| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -55,6 +55,7 @@ | |||
| 55 | 55 | ||
| 56 | 56 | # These are used for syntax hilighting. | |
| 57 | 57 | from pygments import format | |
| 58 | + from pygments.formatters import TerminalFormatter | ||
| 58 | 59 | from pygments.lexers import PythonLexer | |
| 59 | 60 | from pygments.token import Token | |
| 60 | 61 | from bpython.formatter import BPythonFormatter, Parenthesis | |
@@ -422,6 +423,7 @@ def __init__(self, scr, interp, statusbar=None, idle=None): | |||
| 422 | 423 | self.matches = [] | |
| 423 | 424 | self.matches_iter = MatchesIterator() | |
| 424 | 425 | self.argspec = None | |
| 426 | + self.current_func = None | ||
| 425 | 427 | self.s = '' | |
| 426 | 428 | self.inside_string = False | |
| 427 | 429 | self.highlighted_paren = None | |
@@ -523,6 +525,12 @@ def cw(self): | |||
| 523 | 525 | i += 1 | |
| 524 | 526 | return self.s[-i +1:] | |
| 525 | 527 | ||
| 528 | + def get_object(self, name): | ||
| 529 | + if name in self.interp.locals: | ||
| 530 | + return self.interp.locals[name] | ||
| 531 | + else: | ||
| 532 | + return eval(name, self.interp.locals) | ||
| 533 | + | ||
| 526 | 534 | def get_args(self): | |
| 527 | 535 | """Check if an unclosed parenthesis exists, then attempt to get the | |
| 528 | 536 | argspec() for it. On success, update self.argspec and return True, | |
@@ -533,7 +541,8 @@ def get_args(self): | |||
| 533 | 541 | if not OPTS.arg_spec: | |
| 534 | 542 | return False | |
| 535 | 543 | ||
| 536 | - # Find the name of the current function | ||
| 544 | + # Get the name of the current function and where we are in | ||
| 545 | + # the arguments | ||
| 537 | 546 | stack = [['', 0, '']] | |
| 538 | 547 | try: | |
| 539 | 548 | for (token, value) in PythonLexer().get_tokens(self.s): | |
@@ -560,19 +569,14 @@ def get_args(self): | |||
| 560 | 569 | func, _, _ = stack.pop() | |
| 561 | 570 | except IndexError: | |
| 562 | 571 | return False | |
| 572 | + if not func: | ||
| 573 | + return False | ||
| 563 | 574 | ||
| 564 | - # We found a name, now get a function object | ||
| 565 | 575 | try: | |
| 566 | - if func in self.interp.locals: | ||
| 567 | - f = self.interp.locals[func] | ||
| 568 | - except TypeError: | ||
| 569 | - return None | ||
| 570 | - else: | ||
| 571 | - try: | ||
| 572 | - f = eval(func, self.interp.locals) | ||
| 573 | - except Exception: | ||
| 574 | - # Same deal with the exceptions :( | ||
| 575 | - return None | ||
| 576 | + f = self.get_object(func) | ||
| 577 | + except (AttributeError, NameError): | ||
| 578 | + return False | ||
| 579 | + | ||
| 576 | 580 | if inspect.isclass(f): | |
| 577 | 581 | try: | |
| 578 | 582 | f = f.__init__ | |
@@ -1565,6 +1569,22 @@ def p_key(self, key): | |||
| 1565 | 1569 | page(self.stdout_hist[self.prev_block_finished:-4]) | |
| 1566 | 1570 | return '' | |
| 1567 | 1571 | ||
| 1572 | + elif key in key_dispatch[OPTS.show_source_key]: | ||
| 1573 | + try: | ||
| 1574 | + obj = self.current_func | ||
| 1575 | + if obj is None and inspection.is_eval_safe_name(self.s): | ||
| 1576 | + obj = self.get_object(self.s) | ||
| 1577 | + source = inspect.getsource(obj) | ||
| 1578 | + except (AttributeError, NameError, TypeError): | ||
| 1579 | + self.statusbar.message("Cannot show source.") | ||
| 1580 | + return '' | ||
| 1581 | + else: | ||
| 1582 | + if OPTS.highlight_show_source: | ||
| 1583 | + source = format(PythonLexer().get_tokens(source), | ||
| 1584 | + TerminalFormatter()) | ||
| 1585 | + page(source) | ||
| 1586 | + return '' | ||
| 1587 | + | ||
| 1568 | 1588 | elif key == '\n': | |
| 1569 | 1589 | self.lf() | |
| 1570 | 1590 | return None | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -36,6 +36,7 @@ def loadini(struct, configfile): | |||
| 36 | 36 | 'auto_display_list': True, | |
| 37 | 37 | 'color_scheme': 'default', | |
| 38 | 38 | 'flush_output': True, | |
| 39 | + 'highlight_show_source': True, | ||
| 39 | 40 | 'hist_file': '~/.pythonhist', | |
| 40 | 41 | 'hist_length': 100, | |
| 41 | 42 | 'paste_time': 0.02, | |
@@ -53,6 +54,7 @@ def loadini(struct, configfile): | |||
| 53 | 54 | 'last_output': 'F9', | |
| 54 | 55 | 'pastebin': 'F8', | |
| 55 | 56 | 'save': 'C-s', | |
| 57 | + 'show_source': 'F2', | ||
| 56 | 58 | 'undo': 'C-r', | |
| 57 | 59 | 'up_one_line': 'C-p', | |
| 58 | 60 | 'yank_from_buffer': 'C-y' | |
@@ -66,11 +68,14 @@ def loadini(struct, configfile): | |||
| 66 | 68 | struct.syntax = config.getboolean('general', 'syntax') | |
| 67 | 69 | struct.arg_spec = config.getboolean('general', 'arg_spec') | |
| 68 | 70 | struct.paste_time = config.getfloat('general', 'paste_time') | |
| 71 | + struct.highlight_show_source = config.getboolean('general', | ||
| 72 | + 'highlight_show_source') | ||
| 69 | 73 | struct.hist_file = config.get('general', 'hist_file') | |
| 70 | 74 | struct.hist_length = config.getint('general', 'hist_length') | |
| 71 | 75 | struct.flush_output = config.getboolean('general', 'flush_output') | |
| 72 | 76 | struct.pastebin_key = config.get('keyboard', 'pastebin') | |
| 73 | 77 | struct.save_key = config.get('keyboard', 'save') | |
| 78 | + struct.show_source_key = config.get('keyboard', 'show_source') | ||
| 74 | 79 | struct.undo_key = config.get('keyboard', 'undo') | |
| 75 | 80 | struct.up_one_line_key = config.get('keyboard', 'up_one_line') | |
| 76 | 81 | struct.down_one_line_key = config.get('keyboard', 'down_one_line') | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -34,6 +34,9 @@ | |||
| 34 | 34 | ||
| 35 | 35 | py3 = sys.version_info[0] == 3 | |
| 36 | 36 | ||
| 37 | + if not py3: | ||
| 38 | + _name = re.compile(r'[a-zA-Z_]\w*') | ||
| 39 | + | ||
| 37 | 40 | ||
| 38 | 41 | class AttrCleaner(object): | |
| 39 | 42 | """A context manager that tries to make an object not exhibit side-effects | |
@@ -43,7 +46,7 @@ def __init__(self, obj): | |||
| 43 | 46 | ||
| 44 | 47 | def __enter__(self): | |
| 45 | 48 | """Try to make an object not exhibit side-effects on attribute | |
| 46 | - lookup.""" | ||
| 49 | + lookup.""" | ||
| 47 | 50 | type_ = type(self.obj) | |
| 48 | 51 | __getattribute__ = None | |
| 49 | 52 | __getattr__ = None | |
@@ -198,7 +201,7 @@ def getargspec(func, f): | |||
| 198 | 201 | argspec = inspect.getfullargspec(f) | |
| 199 | 202 | else: | |
| 200 | 203 | argspec = inspect.getargspec(f) | |
| 201 | - | ||
| 204 | + | ||
| 202 | 205 | argspec = list(argspec) | |
| 203 | 206 | fixlongargs(f, argspec) | |
| 204 | 207 | argspec = [func, argspec, is_bound_method] | |
@@ -211,3 +214,10 @@ def getargspec(func, f): | |||
| 211 | 214 | argspec[1][0].insert(0, 'obj') | |
| 212 | 215 | argspec.append(is_bound_method) | |
| 213 | 216 | return argspec | |
| 217 | + | ||
| 218 | + | ||
| 219 | + def is_eval_safe_name(string): | ||
| 220 | + if py3: | ||
| 221 | + return all(part.isidentifier() for part in string.split('.')) | ||
| 222 | + else: | ||
| 223 | + return all(_name.match(part) for part in string.split('.')) | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments