]> git.phdru.name Git - dotfiles.git/blob - lib/python/init.py
Fix(lib/python/init.py): Fix stdout for readline
[dotfiles.git] / lib / python / init.py
1 # This is startup file for interactive python.
2 # It is not automatically loaded by python interpreter.
3 # To instruct the interpreter to load it insert the following commands
4 # into your .profile (use whatever syntax and initialization file
5 # is appropriate for your shell):
6 #
7 # PYTHONSTARTUP=$HOME/init.py  # or where you really put it
8 # export PYTHONSTARTUP
9
10
11 def init():
12     try:
13         import __builtin__ as builtins
14     except ImportError:
15         import builtins
16     import os
17     import sys
18
19     # readline/pyreadline
20
21     pyreadlinew32_startup = os.path.join(
22         sys.prefix, 'lib', 'site-packages',
23         'pyreadline', 'configuration', 'startup.py')
24
25     if os.path.exists(pyreadlinew32_startup):
26         execfile(pyreadlinew32_startup)
27
28     else:
29         # From Bruce Edge:
30         # https://mail.python.org/pipermail/python-list/2001-March/062888.html
31
32         try:
33             import rlcompleter  # noqa: need for completion
34             import readline
35             initfile = os.environ.get('INPUTRC') \
36                 or os.path.expanduser('~/.inputrc')
37             readline.read_init_file(initfile)
38
39             histfile = os.path.expanduser('~/.python_history')
40             try:
41                 readline.read_history_file(histfile)
42             except IOError:
43                 pass  # No such file
44
45             def savehist():
46                 histsize = os.environ.get('HISTSIZE')
47                 if histsize:
48                     try:
49                         histsize = int(histsize)
50                     except ValueError:
51                         pass
52                     else:
53                         readline.set_history_length(histsize)
54                 readline.write_history_file(histfile)
55
56             import atexit
57             atexit.register(savehist)
58
59         except (ImportError, AttributeError):
60             # no readline or atexit, or readline doesn't have
61             # {read,write}_history_file - ignore the error
62             pass
63
64     # terminal
65
66     term = os.environ.get('TERM', '')
67     if 'linux' in term:
68         background = 'dark'
69     else:
70         background = os.environ.get('BACKGROUND', 'light').lower()
71
72     # From Randall Hopper:
73     # https://mail.python.org/pipermail/python-list/2001-March/112696.html
74
75     for _term in ['linux', 'rxvt', 'screen', 'term', 'vt100']:
76         if _term not in term:
77             continue
78
79         if background == 'dark':
80             ps1_color = '3'  # yellow
81             stdout_color = '7'  # bold white
82         else:
83             ps1_color = '4'  # blue
84             stdout_color = '0'  # bold black
85
86         sys.ps1 = '\001\033[3%sm\002>>>\001\033[0m\002 ' % ps1_color
87         sys.ps2 = '\001\033[1;32m\002...\001\033[0m\002 '  # bold green
88
89         # From Denis Otkidach
90
91         class ColoredFile:
92             def __init__(self, fp, begin,
93                          end='\033[0m'):  # reset all attributes
94                 self.__fp = fp
95                 self.__begin = begin
96                 self.__end = end
97
98             def write(self, s):
99                 self.__fp.write(self.__begin+s+self.__end)
100
101             def writelines(self, lines):
102                 map(self.write, lines)
103
104             def __getattr__(self, attr):
105                 return getattr(self.__fp, attr)
106
107         sys.stdout = ColoredFile(sys.stdout, '\033[1;3%sm' % stdout_color)
108         sys.stderr = ColoredFile(sys.stderr, '\033[31m')  # red
109
110         def myinput(prompt=None):
111             save_stdout = sys.stdout
112             sys.stdout = sys.__stdout__
113             result = builtin_input(prompt)
114             sys.stdout = save_stdout
115             return result
116
117         try:
118             builtins.raw_input
119         except AttributeError: # PY3
120             builtin_input = builtins.input
121             builtins.input = myinput
122         else:
123             builtin_input = builtins.raw_input
124             builtins.raw_input = myinput
125
126         break
127
128     try:
129         import locale
130     except ImportError:
131         pass  # locale was not compiled
132     else:
133         try:
134             locale.setlocale(locale.LC_ALL, '')
135         except (ImportError, locale.Error):
136             pass  # no locale support or unsupported locale
137
138     # set displayhook and excepthook
139
140     from pprint import pprint
141     from traceback import format_exception, print_exc
142
143     pager = os.environ.get("PAGER") or 'more'
144
145     # if your pager is 'less', options '-F' and '-R' must be passed to it,
146     # and option '-X' is very much recommended
147     if pager == 'less':
148         less = os.environ.get("LESS") or ''
149         for opt in 'X', 'R', 'F':
150             if opt not in less:
151                 less = opt + less
152         os.environ["LESS"] = less
153
154     class BasePager:
155         def write(self, value):
156             self.stdout.write(value)
157
158         def pprint(self, value):
159             pprint(value,
160                    stream=ColoredFile(self.stdout,
161                                       '\033[1;3%sm' % stdout_color))
162
163         def close(self):
164             self.stdout.close()
165
166     try:
167         from subprocess import Popen, PIPE
168     except ImportError:
169         class Pager(BasePager):
170             def __init__(self):
171                 self.stdout = os.popen(pager, 'w')
172     else:
173         class Pager(BasePager):
174             def __init__(self):
175                 self.pipe = Popen(pager, shell=True, stdin=PIPE,
176                                   universal_newlines=True)
177                 self.stdout = self.pipe.stdin
178
179             def close(self):
180                 BasePager.close(self)
181                 self.pipe.wait()
182
183     def displayhook(value):
184         if value is not None:
185             builtins._ = value
186         pager = Pager()
187         try:
188             pager.pprint(value)
189         except:
190             pager.stdout = ColoredFile(pager.stdout, '\033[31m')  # red
191             print_exc(file=pager)
192         pager.close()
193
194     sys.displayhook = displayhook
195
196     def excepthook(etype, evalue, etraceback):
197         lines = format_exception(etype, evalue, etraceback)
198         pager = Pager()
199         pager.stdout = ColoredFile(pager.stdout, '\033[31m')  # red
200         for line in lines:
201             pager.write(line)
202         pager.close()
203
204     sys.excepthook = excepthook
205
206     #try:
207     #    import cgitb
208     #except ImportError:
209     #    pass
210     #else:
211     #    # cgitb.enable() overrides sys.excepthook
212     #    cgitb.enable(format='text')
213
214     # From Thomas Heller:
215     # https://mail.python.org/pipermail/python-list/2001-April/099020.html
216
217     # import pdb
218     #
219     # def info(*args):
220     #    pdb.pm()
221     # sys.excepthook = info
222
223     # utilities
224
225     # From: Paul Magwene:
226     # https://mail.python.org/pipermail/python-list/2001-March/086191.html
227     # With a lot of my fixes:
228
229     class DirLister:
230         def __getitem__(self, key):
231             s = os.listdir(os.curdir)
232             return s[key]
233
234         def __getslice__(self, i, j):
235             s = os.listdir(os.curdir)
236             return s[i:j]
237
238         def __repr__(self):
239             return str(os.listdir(os.curdir))
240
241         def __call__(self, path=None):
242             if path:
243                 path = os.path.expanduser(os.path.expandvars(path))
244             else:
245                 path = os.curdir
246             return os.listdir(path)
247
248     class DirChanger:
249         def __repr__(self):
250             self()
251             return os.getcwd()
252
253         def __call__(self, path=None):
254             path = os.path.expanduser(os.path.expandvars(path or '~'))
255             os.chdir(path)
256
257     builtins.ls = DirLister()
258     builtins.cd = DirChanger()
259
260     # print working directory
261
262     class Pwd:
263         def __repr__(self):
264             return os.getcwd()
265
266         def __call__(self):
267             return repr(self)
268
269     builtins.pwd = Pwd()
270
271     # exit REPL with 'exit', 'quit' or simple 'x'
272
273     class _Exit:
274         def __repr__(self):
275             sys.exit()
276
277         def __call__(self, msg=None):
278             sys.exit(msg)
279
280     builtins.x = _Exit()
281
282     # print conten of a file
283
284     class _Cat:
285         def __repr__(self):
286             return "Usage: cat('filename')"
287
288         def __call__(self, filename):
289             fp = open(filename, 'rU')
290             text = fp.read()
291             fp.close()
292             print(text)
293
294     builtins.cat = _Cat()
295
296     # call shell
297
298     class _Sh:
299         def __repr__(self):
300             os.system(os.environ["SHELL"])
301             return ''
302
303         def __call__(self, cmdline):
304             os.system(cmdline)
305
306     builtins.sh = _Sh()
307
308     # paginate a file
309
310     class _Pager:
311         def __repr__(self):
312             return "Usage: pager('filename')"
313
314         def __call__(self, filename):
315             os.system("%s '%s'" % (pager, filename.replace("'", '"\'"')))
316
317     builtins.pager = _Pager()
318
319     # edit a file
320
321     class _Editor:
322         def __repr__(self):
323             return "Usage: edit('filename')"
324
325         def __call__(self, filename):
326             editor = os.environ.get("VISUAL") \
327                 or os.environ.get("EDITOR") or 'vi'
328             os.system("%s '%s'" % (editor, filename.replace("'", '"\'"')))
329
330     builtins.edit = builtins.editor = _Editor()
331
332
333 init()
334 del init