def add_completer(self, fxn, **kargs): """ adds (and logs the addition of) a completion hook, probably with run-priority mentioned in the kargs """ completion_log.info("adding new completer: {0}".format(fxn)) self.completers[get_caller(2)['class']].append(fxn) get_ipython().set_hook('complete_command', fxn, **kargs)
def smash_env_complete(symbol): completion_log.info("symbol: [{0}]".format(symbol)) symbol = symbol.strip() if not symbol: return if symbol.startswith('$'): symbol = symbol[1:] return [x for x in os.environ if x.startswith(symbol)]
def history_completion_update(self, line): line = line.strip() tokens = smart_split(line) full = len(self.db) > self.MAX_SIZE completion_log.info('eating {0} tokens'.format(len(tokens))) for token in tokens: if len(token) < 4: # too small, dont care continue if token not in self.db: self.db.append(token) if full: self.db.pop(0)
def fabric_cmd_completer(self, event): completion_log.info("event [{0}]".format(event.__dict__)) if event.symbol.startswith("-"): return [] if ope("fabfile.py"): _fabfile = "fabfile.py" elif ope("Fabfile.py"): _fabfile = "Fabfile.py" else: smash_log.info("no fabfile was found") return [] with open(_fabfile, "r") as fhandle: src = fhandle.read() node = ast.parse(src) return list([x.name for x in ast.walk(node) if isinstance(x, ast.FunctionDef)])
def smash_matcher(self, shell, event): completion_log.info('completing event: {0}'.format(event.__dict__)) line = event.line if not line.strip(): raise TryNext() first_word = line.split()[0] # NB: cannot use event.symbol here, it splits on '$' last_word = event.text_until_cursor.split() last_word = last_word[-1] if last_word else '' completion_log.info("first-word, last-word: {0}".format( [first_word, last_word])) if last_word.startswith('$'): return smash_env_complete(last_word) magic_command_alias = first_word.startswith('%') and \ have_command_alias(first_word[1:]) naked_command_alias = have_command_alias(first_word) results = [] if naked_command_alias: completion_log.info('naked command alias detected') results += smash_bash_complete(line)[:self.MAX_MATCH] elif magic_command_alias: completion_log.info('magic command alias detected') results += smash_bash_complete(line[1:])[:self.MAX_MATCH] # can't do anything smarter? look for file matches. # this works by default if the last word contains os.path.sep, # but this doesn't necessarily work with the special "ed" alias # unless this sectiion is executed if not results: completion_log.info(('no results for completion, looking for ' 'file matches with "{0}"'.format(last_word))) results = self.smash.shell.Completer.file_matches(last_word) if results: completion_log.info("returning: {0}".format(results)) return results else: completion_log.info("no results so far, raising trynext ") raise TryNext()
def smash_bash_complete(*args, **kargs): completion_log.info("calling pybcompgen: {0}".format([args, kargs])) result = complete(*args, **kargs) completion_log.info("result: {0}".format(result)) result = [x for x in result if x not in keyword.kwlist] return result
def init(self): completion_log.info("adding fabric completer") self.smash.add_completer(fabric_cmd_completer, re_key="fab") self.smash.add_completer(fabric_opt_completer, re_key="fab -") self.smash.add_completer(fabric_opt_completer, re_key="fab --") return self
def complete(self, text=None, line_buffer=None, cursor_pos=None): completion_log.info("received data: [{0}]".format( [text, line_buffer, cursor_pos])) """Find completions for the given text and line context. Note that both the text and the line_buffer are optional, but at least one of them must be given. Parameters ---------- text : string, optional Text to perform the completion on. If not given, the line buffer is split using the instance's CompletionSplitter object. line_buffer : string, optional If not given, the completer attempts to obtain the current line buffer via readline. This keyword allows clients which are requesting for text completions in non-readline contexts to inform the completer of the entire text. cursor_pos : int, optional Index of the cursor in the full line buffer. Should be provided by remote frontends where kernel has no access to frontend state. Returns ------- text : str Text that was actually used in the completion. matches : list A list of completion matches. """ # io.rprint('\nCOMP1 %r %r %r' % (text, line_buffer, cursor_pos)) # # dbg # if the cursor position isn't given, the only sane assumption we can # make is that it's at the end of the line (the common case) if cursor_pos is None: cursor_pos = len(line_buffer) if text is None else len(text) if PY3: latex_text = text if not line_buffer else line_buffer[:cursor_pos] latex_text, latex_matches = self.latex_matches(latex_text) if latex_matches: return latex_text, latex_matches # if text is either None or an empty string, rely on the line buffer if not text: text = self.splitter.split_line(line_buffer, cursor_pos) # If no line buffer is given, assume the input text is all there was if line_buffer is None: line_buffer = text self.line_buffer = line_buffer self.text_until_cursor = self.line_buffer[:cursor_pos] # io.rprint('COMP2 %r %r %r' % (text, line_buffer, cursor_pos)) # dbg # Start with a clean slate of completions self.matches[:] = [] custom_res = self.dispatch_custom_completer(text) if custom_res: # did custom completers produce something? completion_log.info("custom completers: {0}".format(custom_res)) self.matches = custom_res else: # Extend the list of completions with the results of each # matcher, so we return results to the user from all # namespaces. if self.merge_completions: completion_log.info('merging completions') self.matches = [] for matcher in self.matchers: extra = matcher(text) self.matches.extend(extra) completion_log.info( "extending matches with: {0}".format(extra)) # try: # self.matches.extend(matcher(text)) # except: # Show the ugly traceback if the matcher causes an # exception, but do NOT crash the kernel! # raise # sys.excepthook(*sys.exc_info()) else: for matcher in self.matchers: self.matches = matcher(text) if self.matches: completion_log.info( "returning matches from: {0}".format(matcher)) break # FIXME: we should extend our api to return a dict with completions for # different types of objects. The rlcomplete() method could then # simply collapse the dict into a list for readline, but we'd have # richer completion semantics in other evironments. # use penalize_magics_key to put magics after variables with same name self.matches = sorted(set(self.matches), key=penalize_magics_key) completion_log.info('COMP TEXT, MATCHES: %r, %r' % (text, self.matches)) # dbg return text, self.matches