| Tor Norbye | 3a2425a | 2013-11-04 10:16:08 -0800 | [diff] [blame^] | 1 | |
| 2 | try: |
| 3 | import __builtin__ |
| 4 | except ImportError: |
| 5 | import builtins as __builtin__ |
| 6 | |
| 7 | try: |
| 8 | False |
| 9 | True |
| 10 | except NameError: # version < 2.3 -- didn't have the True/False builtins |
| 11 | setattr(__builtin__, 'True', 1) |
| 12 | setattr(__builtin__, 'False', 0) |
| 13 | |
| 14 | try: |
| 15 | import java.lang #@UnusedImport |
| 16 | import jyimportsTipper #as importsTipper #changed to be backward compatible with 1.5 |
| 17 | importsTipper = jyimportsTipper |
| 18 | except ImportError: |
| 19 | IS_JYTHON = False |
| 20 | import importsTipper |
| 21 | |
| 22 | dir2 = importsTipper.GenerateImportsTipForModule |
| 23 | |
| 24 | |
| 25 | #======================================================================================================================= |
| 26 | # _StartsWithFilter |
| 27 | #======================================================================================================================= |
| 28 | class _StartsWithFilter: |
| 29 | ''' |
| 30 | Used because we can't create a lambda that'll use an outer scope in jython 2.1 |
| 31 | ''' |
| 32 | |
| 33 | |
| 34 | def __init__(self, start_with): |
| 35 | self.start_with = start_with.lower() |
| 36 | |
| 37 | def __call__(self, name): |
| 38 | return name.lower().startswith(self.start_with) |
| 39 | |
| 40 | #======================================================================================================================= |
| 41 | # Completer |
| 42 | # |
| 43 | # This class was gotten from IPython.completer (dir2 was replaced with the completer already in pydev) |
| 44 | #======================================================================================================================= |
| 45 | class Completer: |
| 46 | |
| 47 | def __init__(self, namespace=None, global_namespace=None): |
| 48 | """Create a new completer for the command line. |
| 49 | |
| 50 | Completer([namespace,global_namespace]) -> completer instance. |
| 51 | |
| 52 | If unspecified, the default namespace where completions are performed |
| 53 | is __main__ (technically, __main__.__dict__). Namespaces should be |
| 54 | given as dictionaries. |
| 55 | |
| 56 | An optional second namespace can be given. This allows the completer |
| 57 | to handle cases where both the local and global scopes need to be |
| 58 | distinguished. |
| 59 | |
| 60 | Completer instances should be used as the completion mechanism of |
| 61 | readline via the set_completer() call: |
| 62 | |
| 63 | readline.set_completer(Completer(my_namespace).complete) |
| 64 | """ |
| 65 | |
| 66 | # Don't bind to namespace quite yet, but flag whether the user wants a |
| 67 | # specific namespace or to use __main__.__dict__. This will allow us |
| 68 | # to bind to __main__.__dict__ at completion time, not now. |
| 69 | if namespace is None: |
| 70 | self.use_main_ns = 1 |
| 71 | else: |
| 72 | self.use_main_ns = 0 |
| 73 | self.namespace = namespace |
| 74 | |
| 75 | # The global namespace, if given, can be bound directly |
| 76 | if global_namespace is None: |
| 77 | self.global_namespace = {} |
| 78 | else: |
| 79 | self.global_namespace = global_namespace |
| 80 | |
| 81 | def complete(self, text): |
| 82 | """Return the next possible completion for 'text'. |
| 83 | |
| 84 | This is called successively with state == 0, 1, 2, ... until it |
| 85 | returns None. The completion should begin with 'text'. |
| 86 | |
| 87 | """ |
| 88 | if self.use_main_ns: |
| 89 | #In pydev this option should never be used |
| 90 | raise RuntimeError('Namespace must be provided!') |
| 91 | self.namespace = __main__.__dict__ #@UndefinedVariable |
| 92 | |
| 93 | if "." in text: |
| 94 | return self.attr_matches(text) |
| 95 | else: |
| 96 | return self.global_matches(text) |
| 97 | |
| 98 | def global_matches(self, text): |
| 99 | """Compute matches when text is a simple name. |
| 100 | |
| 101 | Return a list of all keywords, built-in functions and names currently |
| 102 | defined in self.namespace or self.global_namespace that match. |
| 103 | |
| 104 | """ |
| 105 | |
| 106 | |
| 107 | def get_item(obj, attr): |
| 108 | return obj[attr] |
| 109 | |
| 110 | a = {} |
| 111 | |
| 112 | for dict_with_comps in [__builtin__.__dict__, self.namespace, self.global_namespace]: #@UndefinedVariable |
| 113 | a.update(dict_with_comps) |
| 114 | |
| 115 | filter = _StartsWithFilter(text) |
| 116 | |
| 117 | return dir2(a, a.keys(), get_item, filter) |
| 118 | |
| 119 | def attr_matches(self, text): |
| 120 | """Compute matches when text contains a dot. |
| 121 | |
| 122 | Assuming the text is of the form NAME.NAME....[NAME], and is |
| 123 | evaluatable in self.namespace or self.global_namespace, it will be |
| 124 | evaluated and its attributes (as revealed by dir()) are used as |
| 125 | possible completions. (For class instances, class members are are |
| 126 | also considered.) |
| 127 | |
| 128 | WARNING: this can still invoke arbitrary C code, if an object |
| 129 | with a __getattr__ hook is evaluated. |
| 130 | |
| 131 | """ |
| 132 | import re |
| 133 | |
| 134 | # Another option, seems to work great. Catches things like ''.<tab> |
| 135 | m = re.match(r"(\S+(\.\w+)*)\.(\w*)$", text) #@UndefinedVariable |
| 136 | |
| 137 | if not m: |
| 138 | return [] |
| 139 | |
| 140 | expr, attr = m.group(1, 3) |
| 141 | try: |
| 142 | obj = eval(expr, self.namespace) |
| 143 | except: |
| 144 | try: |
| 145 | obj = eval(expr, self.global_namespace) |
| 146 | except: |
| 147 | return [] |
| 148 | |
| 149 | filter = _StartsWithFilter(attr) |
| 150 | |
| 151 | words = dir2(obj, filter=filter) |
| 152 | |
| 153 | return words |
| 154 | |
| 155 | |