|
56 | 56 | from pygments import format |
57 | 57 | from pygments.lexers import PythonLexer |
58 | 58 | from pygments.token import Token |
59 | | -from bpython.formatter import BPythonFormatter |
60 | | -from itertools import chain |
| 59 | +from bpython.formatter import BPythonFormatter, Parenthesis |
61 | 60 |
|
62 | 61 | # This for import completion |
63 | 62 | from bpython import importcompletion |
@@ -352,6 +351,7 @@ def __init__(self, scr, interp, statusbar=None, idle=None): |
352 | 351 | self.argspec = None |
353 | 352 | self.s = '' |
354 | 353 | self.inside_string = False |
| 354 | + self.highlighted_paren = None |
355 | 355 | self.list_win_visible = False |
356 | 356 | self._C = {} |
357 | 357 | sys.stdin = FakeStdin(self) |
@@ -1303,9 +1303,13 @@ def p_key(self): |
1303 | 1303 |
|
1304 | 1304 | elif self.c == 'KEY_LEFT': # Cursor Left |
1305 | 1305 | self.mvc(1) |
| 1306 | + # Redraw (as there might have been highlighted parens) |
| 1307 | + self.print_line(self.s) |
1306 | 1308 |
|
1307 | 1309 | elif self.c == 'KEY_RIGHT': # Cursor Right |
1308 | 1310 | self.mvc(-1) |
| 1311 | + # Redraw (as there might have been highlighted parens) |
| 1312 | + self.print_line(self.s) |
1309 | 1313 |
|
1310 | 1314 | elif self.c in ("KEY_HOME", '^A', chr(1)): # home or ^A |
1311 | 1315 | self.mvc(len(self.s) - self.cpos) |
@@ -1442,6 +1446,8 @@ def lf(self): |
1442 | 1446 | self.inside_string = next_token_inside_string(self.s, |
1443 | 1447 | self.inside_string) |
1444 | 1448 |
|
| 1449 | + # Reprint the line (as there was maybe a highlighted paren in it) |
| 1450 | + self.print_line(self.s) |
1445 | 1451 | self.echo("\n") |
1446 | 1452 |
|
1447 | 1453 | def addstr(self, s): |
@@ -1469,9 +1475,75 @@ def print_line(self, s, clr=False): |
1469 | 1475 | tokens = PythonLexer().get_tokens(self.inside_string + s) |
1470 | 1476 | token, value = tokens.next() |
1471 | 1477 | if token is Token.String.Doc: |
1472 | | - tokens = chain([(Token.String, value[3:])], tokens) |
| 1478 | + tokens = [(Token.String, value[3:])] + list(tokens) |
1473 | 1479 | else: |
1474 | | - tokens = PythonLexer().get_tokens(s) |
| 1480 | + tokens = list(PythonLexer().get_tokens(s)) |
| 1481 | + # Highlight matching parentheses |
| 1482 | + def reprint_line(lineno, s, to_replace=[]): |
| 1483 | + if lineno < 0: |
| 1484 | + return |
| 1485 | + t = list(PythonLexer().get_tokens(s)) |
| 1486 | + for (i, token) in to_replace: |
| 1487 | + t[i] = token |
| 1488 | + o = format(t, BPythonFormatter(OPTS.color_scheme)) |
| 1489 | + self.scr.move(lineno, 4) |
| 1490 | + map(self.echo, o.split('\x04')) |
| 1491 | + if self.highlighted_paren: |
| 1492 | + # Clear previous highlighted paren |
| 1493 | + reprint_line(*self.highlighted_paren) |
| 1494 | + self.highlighted_paren = None |
| 1495 | + stack = list() |
| 1496 | + source = '\n'.join(self.buffer) + '\n%s' % (s, ) |
| 1497 | + i = line = 0 |
| 1498 | + pos = 3 |
| 1499 | + y, x = self.scr.getyx() |
| 1500 | + for (token, value) in PythonLexer().get_tokens(source): |
| 1501 | + pos += len(value) |
| 1502 | + under_cursor = (line == len(self.buffer) and pos == x) |
| 1503 | + if token is Token.Punctuation: |
| 1504 | + if value == '(': |
| 1505 | + if under_cursor: |
| 1506 | + tokens[i] = (Parenthesis, '(') |
| 1507 | + # Push marker on the stack |
| 1508 | + stack.append(Parenthesis) |
| 1509 | + else: |
| 1510 | + stack.append((line, i)) |
| 1511 | + elif value == ')': |
| 1512 | + try: |
| 1513 | + value = stack.pop() |
| 1514 | + except IndexError: |
| 1515 | + # SyntaxError.. more closed parentheses than |
| 1516 | + # opened |
| 1517 | + break |
| 1518 | + if value is Parenthesis: |
| 1519 | + # Marker found |
| 1520 | + tokens[i] = (Parenthesis, ')') |
| 1521 | + break |
| 1522 | + elif under_cursor: |
| 1523 | + tokens[i] = (Parenthesis, ')') |
| 1524 | + (line, i) = value |
| 1525 | + screen_line = y - len(self.buffer) + line |
| 1526 | + if line == len(self.buffer): |
| 1527 | + self.highlighted_paren = (screen_line, s) |
| 1528 | + tokens[i] = (Parenthesis, '(') |
| 1529 | + else: |
| 1530 | + self.highlighted_paren = (screen_line, |
| 1531 | + self.buffer[line]) |
| 1532 | + # We need to redraw a line |
| 1533 | + reprint_line( |
| 1534 | + screen_line, |
| 1535 | + self.buffer[line], |
| 1536 | + [(i, (Parenthesis, '('))] |
| 1537 | + ) |
| 1538 | + elif under_cursor: |
| 1539 | + break |
| 1540 | + elif under_cursor: |
| 1541 | + break |
| 1542 | + elif token is Token.Text and value == '\n': |
| 1543 | + line += 1 |
| 1544 | + i = -1 |
| 1545 | + pos = 3 |
| 1546 | + i += 1 |
1475 | 1547 | o = format(tokens, BPythonFormatter(OPTS.color_scheme)) |
1476 | 1548 | else: |
1477 | 1549 | o = s |
|
0 commit comments