|
27 | 27 | # Debian/Ubuntu: aptitude install python-pyments python-pyparsing |
28 | 28 | # |
29 | 29 |
|
| 30 | +from __future__ import with_statement |
| 31 | + |
| 32 | +import codecs |
30 | 33 | import os |
31 | 34 | import sys |
32 | 35 | import curses |
|
45 | 48 | import socket |
46 | 49 | import pydoc |
47 | 50 | import types |
| 51 | +import unicodedata |
48 | 52 | from cStringIO import StringIO |
| 53 | +from locale import LC_ALL, getpreferredencoding, setlocale |
49 | 54 | from optparse import OptionParser |
50 | 55 | from urlparse import urljoin |
51 | 56 | from xmlrpclib import ServerProxy, Error as XMLRPCError |
@@ -88,6 +93,7 @@ def __init__(self, interface): |
88 | 93 | """Take the curses Repl on init and assume it provides a get_key method |
89 | 94 | which, fortunately, it does.""" |
90 | 95 |
|
| 96 | + self.encoding = getpreferredencoding() |
91 | 97 | self.interface = interface |
92 | 98 |
|
93 | 99 | def readline(self): |
@@ -325,7 +331,9 @@ def __init__(self, scr, interp, statusbar=None, idle=None): |
325 | 331 |
|
326 | 332 | pythonhist = os.path.expanduser('~/.pythonhist') |
327 | 333 | if os.path.exists(pythonhist): |
328 | | - self.rl_hist = open(pythonhist, 'r').readlines() |
| 334 | + with codecs.open(pythonhist, 'r', getpreferredencoding(), |
| 335 | + 'ignore') as hfile: |
| 336 | + self.rl_hist = hfile.readlines() |
329 | 337 |
|
330 | 338 | pexp = Forward() |
331 | 339 | chars = printables.replace('(', '') |
@@ -855,7 +863,10 @@ def push(self, s): |
855 | 863 | self.buffer.append(s) |
856 | 864 |
|
857 | 865 | try: |
858 | | - more = self.interp.runsource("\n".join(self.buffer)) |
| 866 | + encoding = getpreferredencoding() |
| 867 | + source = '# coding: %s\n' % (encoding, ) |
| 868 | + source += '\n'.join(self.buffer).encode(encoding) |
| 869 | + more = self.interp.runsource(source) |
859 | 870 | except SystemExit: |
860 | 871 | # Avoid a traceback on e.g. quit() |
861 | 872 | self.do_exit = True |
@@ -950,7 +961,7 @@ def reevaluate(self): |
950 | 961 |
|
951 | 962 | self.iy, self.ix = self.scr.getyx() |
952 | 963 | for line in self.history: |
953 | | - self.stdout_hist += line + '\n' |
| 964 | + self.stdout_hist += line.encode(getpreferredencoding()) + '\n' |
954 | 965 | self.print_line(line) |
955 | 966 | self.s_hist[-1] += self.f_string |
956 | 967 | # I decided it was easier to just do this manually |
@@ -1024,7 +1035,7 @@ def repl(self): |
1024 | 1035 | self.h_i = 0 |
1025 | 1036 | self.history.append(inp) |
1026 | 1037 | self.s_hist[-1] += self.f_string |
1027 | | - self.stdout_hist += inp + '\n' |
| 1038 | + self.stdout_hist += inp.encode(getpreferredencoding()) + '\n' |
1028 | 1039 | # Keep two copies so you can go up and down in the hist: |
1029 | 1040 | if inp: |
1030 | 1041 | self.rl_hist.append(inp + '\n') |
@@ -1061,8 +1072,7 @@ def write(self, s): |
1061 | 1072 | t = s |
1062 | 1073 |
|
1063 | 1074 | if isinstance(t, unicode): |
1064 | | - t = (t.encode(getattr(orig_stdout, 'encoding', None) or |
1065 | | - sys.getdefaultencoding())) |
| 1075 | + t = t.encode(getpreferredencoding()) |
1066 | 1076 |
|
1067 | 1077 | if not self.stdout_hist: |
1068 | 1078 | self.stdout_hist = t |
@@ -1097,8 +1107,7 @@ def echo(self, s, redraw=True): |
1097 | 1107 | srings. It won't update the screen if it's reevaluating the code (as it |
1098 | 1108 | does with undo).""" |
1099 | 1109 | if isinstance(s, unicode): |
1100 | | - s = (s.encode(getattr(orig_stdout, 'encoding', None) |
1101 | | - or sys.getdefaultencoding())) |
| 1110 | + s = s.encode(getpreferredencoding()) |
1102 | 1111 |
|
1103 | 1112 | a = curses.color_pair(0) |
1104 | 1113 | if '\x01' in s: |
@@ -1322,7 +1331,8 @@ def p_key(self): |
1322 | 1331 | elif self.c == '\t': |
1323 | 1332 | return self.tab() |
1324 | 1333 |
|
1325 | | - elif len(self.c) == 1 and self.c in string.printable: |
| 1334 | + elif (not self.c.startswith('KEY_') |
| 1335 | + and not unicodedata.category(self.c) == 'Cc'): |
1326 | 1336 | self.addstr(self.c) |
1327 | 1337 | self.print_line(self.s) |
1328 | 1338 |
|
@@ -1506,19 +1516,29 @@ def clear_current_line(self): |
1506 | 1516 | self.s = '' |
1507 | 1517 |
|
1508 | 1518 | def get_key(self): |
| 1519 | + key = '' |
1509 | 1520 | while True: |
1510 | 1521 | if self.idle: |
1511 | 1522 | self.idle(self) |
1512 | 1523 | try: |
1513 | | - key = self.scr.getkey() |
| 1524 | + key += self.scr.getkey() |
| 1525 | + key = key.decode(getpreferredencoding()) |
| 1526 | + self.scr.nodelay(False) |
| 1527 | + except UnicodeDecodeError: |
| 1528 | +# Yes, that actually kind of sucks, but I don't see another way to get |
| 1529 | +# input right |
| 1530 | + self.scr.nodelay(True) |
1514 | 1531 | except curses.error: |
1515 | 1532 | # I'm quite annoyed with the ambiguity of this exception handler. I previously |
1516 | 1533 | # caught "curses.error, x" and accessed x.message and checked that it was "no |
1517 | 1534 | # input", which seemed a crappy way of doing it. But then I ran it on a |
1518 | 1535 | # different computer and the exception seems to have entirely different |
1519 | 1536 | # attributes. So let's hope getkey() doesn't raise any other crazy curses |
1520 | 1537 | # exceptions. :) |
1521 | | - continue |
| 1538 | + self.scr.nodelay(False) |
| 1539 | + # XXX What to do here? Raise an exception? |
| 1540 | + if key: |
| 1541 | + return key |
1522 | 1542 | else: |
1523 | 1543 | return key |
1524 | 1544 |
|
@@ -1885,9 +1905,10 @@ def main_curses(scr): |
1885 | 1905 |
|
1886 | 1906 | repl.repl() |
1887 | 1907 | if OPTS.hist_length: |
1888 | | - f = open(os.path.expanduser('~/.pythonhist'), 'w') |
1889 | | - f.writelines(repl.rl_hist[-OPTS.hist_length:]) |
1890 | | - f.close() |
| 1908 | + histfilename = os.path.expanduser('~/.pythonhist') |
| 1909 | + with codecs.open(histfilename, 'w', getpreferredencoding(), |
| 1910 | + 'ignore') as hfile: |
| 1911 | + hfile.writelines(repl.rl_hist[-OPTS.hist_length:]) |
1891 | 1912 |
|
1892 | 1913 | return repl.getstdout() |
1893 | 1914 |
|
@@ -1915,6 +1936,8 @@ def main(args=None): |
1915 | 1936 | interpreter.runsource(sys.stdin.read()) |
1916 | 1937 | return |
1917 | 1938 |
|
| 1939 | + setlocale(LC_ALL, '') |
| 1940 | + |
1918 | 1941 | tb = None |
1919 | 1942 |
|
1920 | 1943 | path = os.path.expanduser('~/.bpythonrc') # migrating old configuration file |
|
0 commit comments