##// END OF EJS Templates
Fix bug where output prompts were coming *after* output values....
Fernando Perez -
Show More
@@ -1,635 +1,637 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 Classes for handling input/output prompts.
3 Classes for handling input/output prompts.
4 """
4 """
5
5
6 #*****************************************************************************
6 #*****************************************************************************
7 # Copyright (C) 2008-2009 The IPython Development Team
7 # Copyright (C) 2008-2009 The IPython Development Team
8 # Copyright (C) 2001-2007 Fernando Perez <fperez@colorado.edu>
8 # Copyright (C) 2001-2007 Fernando Perez <fperez@colorado.edu>
9 #
9 #
10 # Distributed under the terms of the BSD License. The full license is in
10 # Distributed under the terms of the BSD License. The full license is in
11 # the file COPYING, distributed as part of this software.
11 # the file COPYING, distributed as part of this software.
12 #*****************************************************************************
12 #*****************************************************************************
13
13
14 #****************************************************************************
14 #****************************************************************************
15 # Required modules
15 # Required modules
16 import __builtin__
16 import __builtin__
17 import os
17 import os
18 import socket
18 import socket
19 import sys
19 import sys
20 import time
20 import time
21
21
22 # IPython's own
22 # IPython's own
23 from IPython.utils import coloransi
23 from IPython.utils import coloransi
24 from IPython.core import release
24 from IPython.core import release
25 from IPython.external.Itpl import ItplNS
25 from IPython.external.Itpl import ItplNS
26 from IPython.core.error import TryNext
26 from IPython.core.error import TryNext
27 from IPython.utils.ipstruct import Struct
27 from IPython.utils.ipstruct import Struct
28 from IPython.core.macro import Macro
28 from IPython.core.macro import Macro
29 import IPython.utils.generics
29 import IPython.utils.generics
30
30
31 from IPython.utils.genutils import *
31 from IPython.utils.genutils import *
32
32
33 #****************************************************************************
33 #****************************************************************************
34 #Color schemes for Prompts.
34 #Color schemes for Prompts.
35
35
36 PromptColors = coloransi.ColorSchemeTable()
36 PromptColors = coloransi.ColorSchemeTable()
37 InputColors = coloransi.InputTermColors # just a shorthand
37 InputColors = coloransi.InputTermColors # just a shorthand
38 Colors = coloransi.TermColors # just a shorthand
38 Colors = coloransi.TermColors # just a shorthand
39
39
40 PromptColors.add_scheme(coloransi.ColorScheme(
40 PromptColors.add_scheme(coloransi.ColorScheme(
41 'NoColor',
41 'NoColor',
42 in_prompt = InputColors.NoColor, # Input prompt
42 in_prompt = InputColors.NoColor, # Input prompt
43 in_number = InputColors.NoColor, # Input prompt number
43 in_number = InputColors.NoColor, # Input prompt number
44 in_prompt2 = InputColors.NoColor, # Continuation prompt
44 in_prompt2 = InputColors.NoColor, # Continuation prompt
45 in_normal = InputColors.NoColor, # color off (usu. Colors.Normal)
45 in_normal = InputColors.NoColor, # color off (usu. Colors.Normal)
46
46
47 out_prompt = Colors.NoColor, # Output prompt
47 out_prompt = Colors.NoColor, # Output prompt
48 out_number = Colors.NoColor, # Output prompt number
48 out_number = Colors.NoColor, # Output prompt number
49
49
50 normal = Colors.NoColor # color off (usu. Colors.Normal)
50 normal = Colors.NoColor # color off (usu. Colors.Normal)
51 ))
51 ))
52
52
53 # make some schemes as instances so we can copy them for modification easily:
53 # make some schemes as instances so we can copy them for modification easily:
54 __PColLinux = coloransi.ColorScheme(
54 __PColLinux = coloransi.ColorScheme(
55 'Linux',
55 'Linux',
56 in_prompt = InputColors.Green,
56 in_prompt = InputColors.Green,
57 in_number = InputColors.LightGreen,
57 in_number = InputColors.LightGreen,
58 in_prompt2 = InputColors.Green,
58 in_prompt2 = InputColors.Green,
59 in_normal = InputColors.Normal, # color off (usu. Colors.Normal)
59 in_normal = InputColors.Normal, # color off (usu. Colors.Normal)
60
60
61 out_prompt = Colors.Red,
61 out_prompt = Colors.Red,
62 out_number = Colors.LightRed,
62 out_number = Colors.LightRed,
63
63
64 normal = Colors.Normal
64 normal = Colors.Normal
65 )
65 )
66 # Don't forget to enter it into the table!
66 # Don't forget to enter it into the table!
67 PromptColors.add_scheme(__PColLinux)
67 PromptColors.add_scheme(__PColLinux)
68
68
69 # Slightly modified Linux for light backgrounds
69 # Slightly modified Linux for light backgrounds
70 __PColLightBG = __PColLinux.copy('LightBG')
70 __PColLightBG = __PColLinux.copy('LightBG')
71
71
72 __PColLightBG.colors.update(
72 __PColLightBG.colors.update(
73 in_prompt = InputColors.Blue,
73 in_prompt = InputColors.Blue,
74 in_number = InputColors.LightBlue,
74 in_number = InputColors.LightBlue,
75 in_prompt2 = InputColors.Blue
75 in_prompt2 = InputColors.Blue
76 )
76 )
77 PromptColors.add_scheme(__PColLightBG)
77 PromptColors.add_scheme(__PColLightBG)
78
78
79 del Colors,InputColors
79 del Colors,InputColors
80
80
81 #-----------------------------------------------------------------------------
81 #-----------------------------------------------------------------------------
82 def multiple_replace(dict, text):
82 def multiple_replace(dict, text):
83 """ Replace in 'text' all occurences of any key in the given
83 """ Replace in 'text' all occurences of any key in the given
84 dictionary by its corresponding value. Returns the new string."""
84 dictionary by its corresponding value. Returns the new string."""
85
85
86 # Function by Xavier Defrang, originally found at:
86 # Function by Xavier Defrang, originally found at:
87 # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/81330
87 # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/81330
88
88
89 # Create a regular expression from the dictionary keys
89 # Create a regular expression from the dictionary keys
90 regex = re.compile("(%s)" % "|".join(map(re.escape, dict.keys())))
90 regex = re.compile("(%s)" % "|".join(map(re.escape, dict.keys())))
91 # For each match, look-up corresponding value in dictionary
91 # For each match, look-up corresponding value in dictionary
92 return regex.sub(lambda mo: dict[mo.string[mo.start():mo.end()]], text)
92 return regex.sub(lambda mo: dict[mo.string[mo.start():mo.end()]], text)
93
93
94 #-----------------------------------------------------------------------------
94 #-----------------------------------------------------------------------------
95 # Special characters that can be used in prompt templates, mainly bash-like
95 # Special characters that can be used in prompt templates, mainly bash-like
96
96
97 # If $HOME isn't defined (Windows), make it an absurd string so that it can
97 # If $HOME isn't defined (Windows), make it an absurd string so that it can
98 # never be expanded out into '~'. Basically anything which can never be a
98 # never be expanded out into '~'. Basically anything which can never be a
99 # reasonable directory name will do, we just want the $HOME -> '~' operation
99 # reasonable directory name will do, we just want the $HOME -> '~' operation
100 # to become a no-op. We pre-compute $HOME here so it's not done on every
100 # to become a no-op. We pre-compute $HOME here so it's not done on every
101 # prompt call.
101 # prompt call.
102
102
103 # FIXME:
103 # FIXME:
104
104
105 # - This should be turned into a class which does proper namespace management,
105 # - This should be turned into a class which does proper namespace management,
106 # since the prompt specials need to be evaluated in a certain namespace.
106 # since the prompt specials need to be evaluated in a certain namespace.
107 # Currently it's just globals, which need to be managed manually by code
107 # Currently it's just globals, which need to be managed manually by code
108 # below.
108 # below.
109
109
110 # - I also need to split up the color schemes from the prompt specials
110 # - I also need to split up the color schemes from the prompt specials
111 # somehow. I don't have a clean design for that quite yet.
111 # somehow. I don't have a clean design for that quite yet.
112
112
113 HOME = os.environ.get("HOME","//////:::::ZZZZZ,,,~~~")
113 HOME = os.environ.get("HOME","//////:::::ZZZZZ,,,~~~")
114
114
115 # We precompute a few more strings here for the prompt_specials, which are
115 # We precompute a few more strings here for the prompt_specials, which are
116 # fixed once ipython starts. This reduces the runtime overhead of computing
116 # fixed once ipython starts. This reduces the runtime overhead of computing
117 # prompt strings.
117 # prompt strings.
118 USER = os.environ.get("USER")
118 USER = os.environ.get("USER")
119 HOSTNAME = socket.gethostname()
119 HOSTNAME = socket.gethostname()
120 HOSTNAME_SHORT = HOSTNAME.split(".")[0]
120 HOSTNAME_SHORT = HOSTNAME.split(".")[0]
121 ROOT_SYMBOL = "$#"[os.name=='nt' or os.getuid()==0]
121 ROOT_SYMBOL = "$#"[os.name=='nt' or os.getuid()==0]
122
122
123 prompt_specials_color = {
123 prompt_specials_color = {
124 # Prompt/history count
124 # Prompt/history count
125 '%n' : '${self.col_num}' '${self.cache.prompt_count}' '${self.col_p}',
125 '%n' : '${self.col_num}' '${self.cache.prompt_count}' '${self.col_p}',
126 r'\#': '${self.col_num}' '${self.cache.prompt_count}' '${self.col_p}',
126 r'\#': '${self.col_num}' '${self.cache.prompt_count}' '${self.col_p}',
127 # Just the prompt counter number, WITHOUT any coloring wrappers, so users
127 # Just the prompt counter number, WITHOUT any coloring wrappers, so users
128 # can get numbers displayed in whatever color they want.
128 # can get numbers displayed in whatever color they want.
129 r'\N': '${self.cache.prompt_count}',
129 r'\N': '${self.cache.prompt_count}',
130
130
131 # Prompt/history count, with the actual digits replaced by dots. Used
131 # Prompt/history count, with the actual digits replaced by dots. Used
132 # mainly in continuation prompts (prompt_in2)
132 # mainly in continuation prompts (prompt_in2)
133 #r'\D': '${"."*len(str(self.cache.prompt_count))}',
133 #r'\D': '${"."*len(str(self.cache.prompt_count))}',
134 # More robust form of the above expression, that uses __builtins__
134 # More robust form of the above expression, that uses __builtins__
135 r'\D': '${"."*__builtins__.len(__builtins__.str(self.cache.prompt_count))}',
135 r'\D': '${"."*__builtins__.len(__builtins__.str(self.cache.prompt_count))}',
136
136
137 # Current working directory
137 # Current working directory
138 r'\w': '${os.getcwd()}',
138 r'\w': '${os.getcwd()}',
139 # Current time
139 # Current time
140 r'\t' : '${time.strftime("%H:%M:%S")}',
140 r'\t' : '${time.strftime("%H:%M:%S")}',
141 # Basename of current working directory.
141 # Basename of current working directory.
142 # (use os.sep to make this portable across OSes)
142 # (use os.sep to make this portable across OSes)
143 r'\W' : '${os.getcwd().split("%s")[-1]}' % os.sep,
143 r'\W' : '${os.getcwd().split("%s")[-1]}' % os.sep,
144 # These X<N> are an extension to the normal bash prompts. They return
144 # These X<N> are an extension to the normal bash prompts. They return
145 # N terms of the path, after replacing $HOME with '~'
145 # N terms of the path, after replacing $HOME with '~'
146 r'\X0': '${os.getcwd().replace("%s","~")}' % HOME,
146 r'\X0': '${os.getcwd().replace("%s","~")}' % HOME,
147 r'\X1': '${self.cwd_filt(1)}',
147 r'\X1': '${self.cwd_filt(1)}',
148 r'\X2': '${self.cwd_filt(2)}',
148 r'\X2': '${self.cwd_filt(2)}',
149 r'\X3': '${self.cwd_filt(3)}',
149 r'\X3': '${self.cwd_filt(3)}',
150 r'\X4': '${self.cwd_filt(4)}',
150 r'\X4': '${self.cwd_filt(4)}',
151 r'\X5': '${self.cwd_filt(5)}',
151 r'\X5': '${self.cwd_filt(5)}',
152 # Y<N> are similar to X<N>, but they show '~' if it's the directory
152 # Y<N> are similar to X<N>, but they show '~' if it's the directory
153 # N+1 in the list. Somewhat like %cN in tcsh.
153 # N+1 in the list. Somewhat like %cN in tcsh.
154 r'\Y0': '${self.cwd_filt2(0)}',
154 r'\Y0': '${self.cwd_filt2(0)}',
155 r'\Y1': '${self.cwd_filt2(1)}',
155 r'\Y1': '${self.cwd_filt2(1)}',
156 r'\Y2': '${self.cwd_filt2(2)}',
156 r'\Y2': '${self.cwd_filt2(2)}',
157 r'\Y3': '${self.cwd_filt2(3)}',
157 r'\Y3': '${self.cwd_filt2(3)}',
158 r'\Y4': '${self.cwd_filt2(4)}',
158 r'\Y4': '${self.cwd_filt2(4)}',
159 r'\Y5': '${self.cwd_filt2(5)}',
159 r'\Y5': '${self.cwd_filt2(5)}',
160 # Hostname up to first .
160 # Hostname up to first .
161 r'\h': HOSTNAME_SHORT,
161 r'\h': HOSTNAME_SHORT,
162 # Full hostname
162 # Full hostname
163 r'\H': HOSTNAME,
163 r'\H': HOSTNAME,
164 # Username of current user
164 # Username of current user
165 r'\u': USER,
165 r'\u': USER,
166 # Escaped '\'
166 # Escaped '\'
167 '\\\\': '\\',
167 '\\\\': '\\',
168 # Newline
168 # Newline
169 r'\n': '\n',
169 r'\n': '\n',
170 # Carriage return
170 # Carriage return
171 r'\r': '\r',
171 r'\r': '\r',
172 # Release version
172 # Release version
173 r'\v': release.version,
173 r'\v': release.version,
174 # Root symbol ($ or #)
174 # Root symbol ($ or #)
175 r'\$': ROOT_SYMBOL,
175 r'\$': ROOT_SYMBOL,
176 }
176 }
177
177
178 # A copy of the prompt_specials dictionary but with all color escapes removed,
178 # A copy of the prompt_specials dictionary but with all color escapes removed,
179 # so we can correctly compute the prompt length for the auto_rewrite method.
179 # so we can correctly compute the prompt length for the auto_rewrite method.
180 prompt_specials_nocolor = prompt_specials_color.copy()
180 prompt_specials_nocolor = prompt_specials_color.copy()
181 prompt_specials_nocolor['%n'] = '${self.cache.prompt_count}'
181 prompt_specials_nocolor['%n'] = '${self.cache.prompt_count}'
182 prompt_specials_nocolor[r'\#'] = '${self.cache.prompt_count}'
182 prompt_specials_nocolor[r'\#'] = '${self.cache.prompt_count}'
183
183
184 # Add in all the InputTermColors color escapes as valid prompt characters.
184 # Add in all the InputTermColors color escapes as valid prompt characters.
185 # They all get added as \\C_COLORNAME, so that we don't have any conflicts
185 # They all get added as \\C_COLORNAME, so that we don't have any conflicts
186 # with a color name which may begin with a letter used by any other of the
186 # with a color name which may begin with a letter used by any other of the
187 # allowed specials. This of course means that \\C will never be allowed for
187 # allowed specials. This of course means that \\C will never be allowed for
188 # anything else.
188 # anything else.
189 input_colors = coloransi.InputTermColors
189 input_colors = coloransi.InputTermColors
190 for _color in dir(input_colors):
190 for _color in dir(input_colors):
191 if _color[0] != '_':
191 if _color[0] != '_':
192 c_name = r'\C_'+_color
192 c_name = r'\C_'+_color
193 prompt_specials_color[c_name] = getattr(input_colors,_color)
193 prompt_specials_color[c_name] = getattr(input_colors,_color)
194 prompt_specials_nocolor[c_name] = ''
194 prompt_specials_nocolor[c_name] = ''
195
195
196 # we default to no color for safety. Note that prompt_specials is a global
196 # we default to no color for safety. Note that prompt_specials is a global
197 # variable used by all prompt objects.
197 # variable used by all prompt objects.
198 prompt_specials = prompt_specials_nocolor
198 prompt_specials = prompt_specials_nocolor
199
199
200 #-----------------------------------------------------------------------------
200 #-----------------------------------------------------------------------------
201 def str_safe(arg):
201 def str_safe(arg):
202 """Convert to a string, without ever raising an exception.
202 """Convert to a string, without ever raising an exception.
203
203
204 If str(arg) fails, <ERROR: ... > is returned, where ... is the exception
204 If str(arg) fails, <ERROR: ... > is returned, where ... is the exception
205 error message."""
205 error message."""
206
206
207 try:
207 try:
208 out = str(arg)
208 out = str(arg)
209 except UnicodeError:
209 except UnicodeError:
210 try:
210 try:
211 out = arg.encode('utf_8','replace')
211 out = arg.encode('utf_8','replace')
212 except Exception,msg:
212 except Exception,msg:
213 # let's keep this little duplication here, so that the most common
213 # let's keep this little duplication here, so that the most common
214 # case doesn't suffer from a double try wrapping.
214 # case doesn't suffer from a double try wrapping.
215 out = '<ERROR: %s>' % msg
215 out = '<ERROR: %s>' % msg
216 except Exception,msg:
216 except Exception,msg:
217 out = '<ERROR: %s>' % msg
217 out = '<ERROR: %s>' % msg
218 return out
218 return out
219
219
220 class BasePrompt(object):
220 class BasePrompt(object):
221 """Interactive prompt similar to Mathematica's."""
221 """Interactive prompt similar to Mathematica's."""
222
222
223 def _get_p_template(self):
223 def _get_p_template(self):
224 return self._p_template
224 return self._p_template
225
225
226 def _set_p_template(self,val):
226 def _set_p_template(self,val):
227 self._p_template = val
227 self._p_template = val
228 self.set_p_str()
228 self.set_p_str()
229
229
230 p_template = property(_get_p_template,_set_p_template,
230 p_template = property(_get_p_template,_set_p_template,
231 doc='Template for prompt string creation')
231 doc='Template for prompt string creation')
232
232
233 def __init__(self,cache,sep,prompt,pad_left=False):
233 def __init__(self,cache,sep,prompt,pad_left=False):
234
234
235 # Hack: we access information about the primary prompt through the
235 # Hack: we access information about the primary prompt through the
236 # cache argument. We need this, because we want the secondary prompt
236 # cache argument. We need this, because we want the secondary prompt
237 # to be aligned with the primary one. Color table info is also shared
237 # to be aligned with the primary one. Color table info is also shared
238 # by all prompt classes through the cache. Nice OO spaghetti code!
238 # by all prompt classes through the cache. Nice OO spaghetti code!
239 self.cache = cache
239 self.cache = cache
240 self.sep = sep
240 self.sep = sep
241
241
242 # regexp to count the number of spaces at the end of a prompt
242 # regexp to count the number of spaces at the end of a prompt
243 # expression, useful for prompt auto-rewriting
243 # expression, useful for prompt auto-rewriting
244 self.rspace = re.compile(r'(\s*)$')
244 self.rspace = re.compile(r'(\s*)$')
245 # Flag to left-pad prompt strings to match the length of the primary
245 # Flag to left-pad prompt strings to match the length of the primary
246 # prompt
246 # prompt
247 self.pad_left = pad_left
247 self.pad_left = pad_left
248
248
249 # Set template to create each actual prompt (where numbers change).
249 # Set template to create each actual prompt (where numbers change).
250 # Use a property
250 # Use a property
251 self.p_template = prompt
251 self.p_template = prompt
252 self.set_p_str()
252 self.set_p_str()
253
253
254 def set_p_str(self):
254 def set_p_str(self):
255 """ Set the interpolating prompt strings.
255 """ Set the interpolating prompt strings.
256
256
257 This must be called every time the color settings change, because the
257 This must be called every time the color settings change, because the
258 prompt_specials global may have changed."""
258 prompt_specials global may have changed."""
259
259
260 import os,time # needed in locals for prompt string handling
260 import os,time # needed in locals for prompt string handling
261 loc = locals()
261 loc = locals()
262 try:
262 try:
263 self.p_str = ItplNS('%s%s%s' %
263 self.p_str = ItplNS('%s%s%s' %
264 ('${self.sep}${self.col_p}',
264 ('${self.sep}${self.col_p}',
265 multiple_replace(prompt_specials, self.p_template),
265 multiple_replace(prompt_specials, self.p_template),
266 '${self.col_norm}'),self.cache.user_ns,loc)
266 '${self.col_norm}'),self.cache.user_ns,loc)
267
267
268 self.p_str_nocolor = ItplNS(multiple_replace(prompt_specials_nocolor,
268 self.p_str_nocolor = ItplNS(multiple_replace(prompt_specials_nocolor,
269 self.p_template),
269 self.p_template),
270 self.cache.user_ns,loc)
270 self.cache.user_ns,loc)
271 except:
271 except:
272 print "Illegal prompt template (check $ usage!):",self.p_template
272 print "Illegal prompt template (check $ usage!):",self.p_template
273 self.p_str = self.p_template
273 self.p_str = self.p_template
274 self.p_str_nocolor = self.p_template
274 self.p_str_nocolor = self.p_template
275
275
276 def write(self,msg): # dbg
276 def write(self,msg): # dbg
277 sys.stdout.write(msg)
277 sys.stdout.write(msg)
278 return ''
278 return ''
279
279
280 def __str__(self):
280 def __str__(self):
281 """Return a string form of the prompt.
281 """Return a string form of the prompt.
282
282
283 This for is useful for continuation and output prompts, since it is
283 This for is useful for continuation and output prompts, since it is
284 left-padded to match lengths with the primary one (if the
284 left-padded to match lengths with the primary one (if the
285 self.pad_left attribute is set)."""
285 self.pad_left attribute is set)."""
286
286
287 out_str = str_safe(self.p_str)
287 out_str = str_safe(self.p_str)
288 if self.pad_left:
288 if self.pad_left:
289 # We must find the amount of padding required to match lengths,
289 # We must find the amount of padding required to match lengths,
290 # taking the color escapes (which are invisible on-screen) into
290 # taking the color escapes (which are invisible on-screen) into
291 # account.
291 # account.
292 esc_pad = len(out_str) - len(str_safe(self.p_str_nocolor))
292 esc_pad = len(out_str) - len(str_safe(self.p_str_nocolor))
293 format = '%%%ss' % (len(str(self.cache.last_prompt))+esc_pad)
293 format = '%%%ss' % (len(str(self.cache.last_prompt))+esc_pad)
294 return format % out_str
294 return format % out_str
295 else:
295 else:
296 return out_str
296 return out_str
297
297
298 # these path filters are put in as methods so that we can control the
298 # these path filters are put in as methods so that we can control the
299 # namespace where the prompt strings get evaluated
299 # namespace where the prompt strings get evaluated
300 def cwd_filt(self,depth):
300 def cwd_filt(self,depth):
301 """Return the last depth elements of the current working directory.
301 """Return the last depth elements of the current working directory.
302
302
303 $HOME is always replaced with '~'.
303 $HOME is always replaced with '~'.
304 If depth==0, the full path is returned."""
304 If depth==0, the full path is returned."""
305
305
306 cwd = os.getcwd().replace(HOME,"~")
306 cwd = os.getcwd().replace(HOME,"~")
307 out = os.sep.join(cwd.split(os.sep)[-depth:])
307 out = os.sep.join(cwd.split(os.sep)[-depth:])
308 if out:
308 if out:
309 return out
309 return out
310 else:
310 else:
311 return os.sep
311 return os.sep
312
312
313 def cwd_filt2(self,depth):
313 def cwd_filt2(self,depth):
314 """Return the last depth elements of the current working directory.
314 """Return the last depth elements of the current working directory.
315
315
316 $HOME is always replaced with '~'.
316 $HOME is always replaced with '~'.
317 If depth==0, the full path is returned."""
317 If depth==0, the full path is returned."""
318
318
319 full_cwd = os.getcwd()
319 full_cwd = os.getcwd()
320 cwd = full_cwd.replace(HOME,"~").split(os.sep)
320 cwd = full_cwd.replace(HOME,"~").split(os.sep)
321 if '~' in cwd and len(cwd) == depth+1:
321 if '~' in cwd and len(cwd) == depth+1:
322 depth += 1
322 depth += 1
323 drivepart = ''
323 drivepart = ''
324 if sys.platform == 'win32' and len(cwd) > depth:
324 if sys.platform == 'win32' and len(cwd) > depth:
325 drivepart = os.path.splitdrive(full_cwd)[0]
325 drivepart = os.path.splitdrive(full_cwd)[0]
326 out = drivepart + '/'.join(cwd[-depth:])
326 out = drivepart + '/'.join(cwd[-depth:])
327
327
328 if out:
328 if out:
329 return out
329 return out
330 else:
330 else:
331 return os.sep
331 return os.sep
332
332
333 def __nonzero__(self):
333 def __nonzero__(self):
334 """Implement boolean behavior.
334 """Implement boolean behavior.
335
335
336 Checks whether the p_str attribute is non-empty"""
336 Checks whether the p_str attribute is non-empty"""
337
337
338 return bool(self.p_template)
338 return bool(self.p_template)
339
339
340 class Prompt1(BasePrompt):
340 class Prompt1(BasePrompt):
341 """Input interactive prompt similar to Mathematica's."""
341 """Input interactive prompt similar to Mathematica's."""
342
342
343 def __init__(self,cache,sep='\n',prompt='In [\\#]: ',pad_left=True):
343 def __init__(self,cache,sep='\n',prompt='In [\\#]: ',pad_left=True):
344 BasePrompt.__init__(self,cache,sep,prompt,pad_left)
344 BasePrompt.__init__(self,cache,sep,prompt,pad_left)
345
345
346 def set_colors(self):
346 def set_colors(self):
347 self.set_p_str()
347 self.set_p_str()
348 Colors = self.cache.color_table.active_colors # shorthand
348 Colors = self.cache.color_table.active_colors # shorthand
349 self.col_p = Colors.in_prompt
349 self.col_p = Colors.in_prompt
350 self.col_num = Colors.in_number
350 self.col_num = Colors.in_number
351 self.col_norm = Colors.in_normal
351 self.col_norm = Colors.in_normal
352 # We need a non-input version of these escapes for the '--->'
352 # We need a non-input version of these escapes for the '--->'
353 # auto-call prompts used in the auto_rewrite() method.
353 # auto-call prompts used in the auto_rewrite() method.
354 self.col_p_ni = self.col_p.replace('\001','').replace('\002','')
354 self.col_p_ni = self.col_p.replace('\001','').replace('\002','')
355 self.col_norm_ni = Colors.normal
355 self.col_norm_ni = Colors.normal
356
356
357 def __str__(self):
357 def __str__(self):
358 self.cache.prompt_count += 1
358 self.cache.prompt_count += 1
359 self.cache.last_prompt = str_safe(self.p_str_nocolor).split('\n')[-1]
359 self.cache.last_prompt = str_safe(self.p_str_nocolor).split('\n')[-1]
360 return str_safe(self.p_str)
360 return str_safe(self.p_str)
361
361
362 def auto_rewrite(self):
362 def auto_rewrite(self):
363 """Print a string of the form '--->' which lines up with the previous
363 """Print a string of the form '--->' which lines up with the previous
364 input string. Useful for systems which re-write the user input when
364 input string. Useful for systems which re-write the user input when
365 handling automatically special syntaxes."""
365 handling automatically special syntaxes."""
366
366
367 curr = str(self.cache.last_prompt)
367 curr = str(self.cache.last_prompt)
368 nrspaces = len(self.rspace.search(curr).group())
368 nrspaces = len(self.rspace.search(curr).group())
369 return '%s%s>%s%s' % (self.col_p_ni,'-'*(len(curr)-nrspaces-1),
369 return '%s%s>%s%s' % (self.col_p_ni,'-'*(len(curr)-nrspaces-1),
370 ' '*nrspaces,self.col_norm_ni)
370 ' '*nrspaces,self.col_norm_ni)
371
371
372 class PromptOut(BasePrompt):
372 class PromptOut(BasePrompt):
373 """Output interactive prompt similar to Mathematica's."""
373 """Output interactive prompt similar to Mathematica's."""
374
374
375 def __init__(self,cache,sep='',prompt='Out[\\#]: ',pad_left=True):
375 def __init__(self,cache,sep='',prompt='Out[\\#]: ',pad_left=True):
376 BasePrompt.__init__(self,cache,sep,prompt,pad_left)
376 BasePrompt.__init__(self,cache,sep,prompt,pad_left)
377 if not self.p_template:
377 if not self.p_template:
378 self.__str__ = lambda: ''
378 self.__str__ = lambda: ''
379
379
380 def set_colors(self):
380 def set_colors(self):
381 self.set_p_str()
381 self.set_p_str()
382 Colors = self.cache.color_table.active_colors # shorthand
382 Colors = self.cache.color_table.active_colors # shorthand
383 self.col_p = Colors.out_prompt
383 self.col_p = Colors.out_prompt
384 self.col_num = Colors.out_number
384 self.col_num = Colors.out_number
385 self.col_norm = Colors.normal
385 self.col_norm = Colors.normal
386
386
387 class Prompt2(BasePrompt):
387 class Prompt2(BasePrompt):
388 """Interactive continuation prompt."""
388 """Interactive continuation prompt."""
389
389
390 def __init__(self,cache,prompt=' .\\D.: ',pad_left=True):
390 def __init__(self,cache,prompt=' .\\D.: ',pad_left=True):
391 self.cache = cache
391 self.cache = cache
392 self.p_template = prompt
392 self.p_template = prompt
393 self.pad_left = pad_left
393 self.pad_left = pad_left
394 self.set_p_str()
394 self.set_p_str()
395
395
396 def set_p_str(self):
396 def set_p_str(self):
397 import os,time # needed in locals for prompt string handling
397 import os,time # needed in locals for prompt string handling
398 loc = locals()
398 loc = locals()
399 self.p_str = ItplNS('%s%s%s' %
399 self.p_str = ItplNS('%s%s%s' %
400 ('${self.col_p2}',
400 ('${self.col_p2}',
401 multiple_replace(prompt_specials, self.p_template),
401 multiple_replace(prompt_specials, self.p_template),
402 '$self.col_norm'),
402 '$self.col_norm'),
403 self.cache.user_ns,loc)
403 self.cache.user_ns,loc)
404 self.p_str_nocolor = ItplNS(multiple_replace(prompt_specials_nocolor,
404 self.p_str_nocolor = ItplNS(multiple_replace(prompt_specials_nocolor,
405 self.p_template),
405 self.p_template),
406 self.cache.user_ns,loc)
406 self.cache.user_ns,loc)
407
407
408 def set_colors(self):
408 def set_colors(self):
409 self.set_p_str()
409 self.set_p_str()
410 Colors = self.cache.color_table.active_colors
410 Colors = self.cache.color_table.active_colors
411 self.col_p2 = Colors.in_prompt2
411 self.col_p2 = Colors.in_prompt2
412 self.col_norm = Colors.in_normal
412 self.col_norm = Colors.in_normal
413 # FIXME (2004-06-16) HACK: prevent crashes for users who haven't
413 # FIXME (2004-06-16) HACK: prevent crashes for users who haven't
414 # updated their prompt_in2 definitions. Remove eventually.
414 # updated their prompt_in2 definitions. Remove eventually.
415 self.col_p = Colors.out_prompt
415 self.col_p = Colors.out_prompt
416 self.col_num = Colors.out_number
416 self.col_num = Colors.out_number
417
417
418
418
419 #-----------------------------------------------------------------------------
419 #-----------------------------------------------------------------------------
420 class CachedOutput:
420 class CachedOutput:
421 """Class for printing output from calculations while keeping a cache of
421 """Class for printing output from calculations while keeping a cache of
422 reults. It dynamically creates global variables prefixed with _ which
422 reults. It dynamically creates global variables prefixed with _ which
423 contain these results.
423 contain these results.
424
424
425 Meant to be used as a sys.displayhook replacement, providing numbered
425 Meant to be used as a sys.displayhook replacement, providing numbered
426 prompts and cache services.
426 prompts and cache services.
427
427
428 Initialize with initial and final values for cache counter (this defines
428 Initialize with initial and final values for cache counter (this defines
429 the maximum size of the cache."""
429 the maximum size of the cache."""
430
430
431 def __init__(self,shell,cache_size,Pprint,
431 def __init__(self,shell,cache_size,Pprint,
432 colors='NoColor',input_sep='\n',
432 colors='NoColor',input_sep='\n',
433 output_sep='\n',output_sep2='',
433 output_sep='\n',output_sep2='',
434 ps1 = None, ps2 = None,ps_out = None,pad_left=True):
434 ps1 = None, ps2 = None,ps_out = None,pad_left=True):
435
435
436 cache_size_min = 3
436 cache_size_min = 3
437 if cache_size <= 0:
437 if cache_size <= 0:
438 self.do_full_cache = 0
438 self.do_full_cache = 0
439 cache_size = 0
439 cache_size = 0
440 elif cache_size < cache_size_min:
440 elif cache_size < cache_size_min:
441 self.do_full_cache = 0
441 self.do_full_cache = 0
442 cache_size = 0
442 cache_size = 0
443 warn('caching was disabled (min value for cache size is %s).' %
443 warn('caching was disabled (min value for cache size is %s).' %
444 cache_size_min,level=3)
444 cache_size_min,level=3)
445 else:
445 else:
446 self.do_full_cache = 1
446 self.do_full_cache = 1
447
447
448 self.cache_size = cache_size
448 self.cache_size = cache_size
449 self.input_sep = input_sep
449 self.input_sep = input_sep
450
450
451 # we need a reference to the user-level namespace
451 # we need a reference to the user-level namespace
452 self.shell = shell
452 self.shell = shell
453 self.user_ns = shell.user_ns
453 self.user_ns = shell.user_ns
454 # and to the user's input
454 # and to the user's input
455 self.input_hist = shell.input_hist
455 self.input_hist = shell.input_hist
456 # and to the user's logger, for logging output
456 # and to the user's logger, for logging output
457 self.logger = shell.logger
457 self.logger = shell.logger
458
458
459 # Set input prompt strings and colors
459 # Set input prompt strings and colors
460 if cache_size == 0:
460 if cache_size == 0:
461 if ps1.find('%n') > -1 or ps1.find(r'\#') > -1 \
461 if ps1.find('%n') > -1 or ps1.find(r'\#') > -1 \
462 or ps1.find(r'\N') > -1:
462 or ps1.find(r'\N') > -1:
463 ps1 = '>>> '
463 ps1 = '>>> '
464 if ps2.find('%n') > -1 or ps2.find(r'\#') > -1 \
464 if ps2.find('%n') > -1 or ps2.find(r'\#') > -1 \
465 or ps2.find(r'\N') > -1:
465 or ps2.find(r'\N') > -1:
466 ps2 = '... '
466 ps2 = '... '
467 self.ps1_str = self._set_prompt_str(ps1,'In [\\#]: ','>>> ')
467 self.ps1_str = self._set_prompt_str(ps1,'In [\\#]: ','>>> ')
468 self.ps2_str = self._set_prompt_str(ps2,' .\\D.: ','... ')
468 self.ps2_str = self._set_prompt_str(ps2,' .\\D.: ','... ')
469 self.ps_out_str = self._set_prompt_str(ps_out,'Out[\\#]: ','')
469 self.ps_out_str = self._set_prompt_str(ps_out,'Out[\\#]: ','')
470
470
471 self.color_table = PromptColors
471 self.color_table = PromptColors
472 self.prompt1 = Prompt1(self,sep=input_sep,prompt=self.ps1_str,
472 self.prompt1 = Prompt1(self,sep=input_sep,prompt=self.ps1_str,
473 pad_left=pad_left)
473 pad_left=pad_left)
474 self.prompt2 = Prompt2(self,prompt=self.ps2_str,pad_left=pad_left)
474 self.prompt2 = Prompt2(self,prompt=self.ps2_str,pad_left=pad_left)
475 self.prompt_out = PromptOut(self,sep='',prompt=self.ps_out_str,
475 self.prompt_out = PromptOut(self,sep='',prompt=self.ps_out_str,
476 pad_left=pad_left)
476 pad_left=pad_left)
477 self.set_colors(colors)
477 self.set_colors(colors)
478
478
479 # other more normal stuff
479 # other more normal stuff
480 # b/c each call to the In[] prompt raises it by 1, even the first.
480 # b/c each call to the In[] prompt raises it by 1, even the first.
481 self.prompt_count = 0
481 self.prompt_count = 0
482 # Store the last prompt string each time, we need it for aligning
482 # Store the last prompt string each time, we need it for aligning
483 # continuation and auto-rewrite prompts
483 # continuation and auto-rewrite prompts
484 self.last_prompt = ''
484 self.last_prompt = ''
485 self.Pprint = Pprint
485 self.Pprint = Pprint
486 self.output_sep = output_sep
486 self.output_sep = output_sep
487 self.output_sep2 = output_sep2
487 self.output_sep2 = output_sep2
488 self._,self.__,self.___ = '','',''
488 self._,self.__,self.___ = '','',''
489 self.pprint_types = map(type,[(),[],{}])
489 self.pprint_types = map(type,[(),[],{}])
490
490
491 # these are deliberately global:
491 # these are deliberately global:
492 to_user_ns = {'_':self._,'__':self.__,'___':self.___}
492 to_user_ns = {'_':self._,'__':self.__,'___':self.___}
493 self.user_ns.update(to_user_ns)
493 self.user_ns.update(to_user_ns)
494
494
495 def _set_prompt_str(self,p_str,cache_def,no_cache_def):
495 def _set_prompt_str(self,p_str,cache_def,no_cache_def):
496 if p_str is None:
496 if p_str is None:
497 if self.do_full_cache:
497 if self.do_full_cache:
498 return cache_def
498 return cache_def
499 else:
499 else:
500 return no_cache_def
500 return no_cache_def
501 else:
501 else:
502 return p_str
502 return p_str
503
503
504 def set_colors(self,colors):
504 def set_colors(self,colors):
505 """Set the active color scheme and configure colors for the three
505 """Set the active color scheme and configure colors for the three
506 prompt subsystems."""
506 prompt subsystems."""
507
507
508 # FIXME: the prompt_specials global should be gobbled inside this
508 # FIXME: the prompt_specials global should be gobbled inside this
509 # class instead. Do it when cleaning up the whole 3-prompt system.
509 # class instead. Do it when cleaning up the whole 3-prompt system.
510 global prompt_specials
510 global prompt_specials
511 if colors.lower()=='nocolor':
511 if colors.lower()=='nocolor':
512 prompt_specials = prompt_specials_nocolor
512 prompt_specials = prompt_specials_nocolor
513 else:
513 else:
514 prompt_specials = prompt_specials_color
514 prompt_specials = prompt_specials_color
515
515
516 self.color_table.set_active_scheme(colors)
516 self.color_table.set_active_scheme(colors)
517 self.prompt1.set_colors()
517 self.prompt1.set_colors()
518 self.prompt2.set_colors()
518 self.prompt2.set_colors()
519 self.prompt_out.set_colors()
519 self.prompt_out.set_colors()
520
520
521 def __call__(self,arg=None):
521 def __call__(self,arg=None):
522 """Printing with history cache management.
522 """Printing with history cache management.
523
523
524 This is invoked everytime the interpreter needs to print, and is
524 This is invoked everytime the interpreter needs to print, and is
525 activated by setting the variable sys.displayhook to it."""
525 activated by setting the variable sys.displayhook to it."""
526
526
527 # If something injected a '_' variable in __builtin__, delete
527 # If something injected a '_' variable in __builtin__, delete
528 # ipython's automatic one so we don't clobber that. gettext() in
528 # ipython's automatic one so we don't clobber that. gettext() in
529 # particular uses _, so we need to stay away from it.
529 # particular uses _, so we need to stay away from it.
530 if '_' in __builtin__.__dict__:
530 if '_' in __builtin__.__dict__:
531 try:
531 try:
532 del self.user_ns['_']
532 del self.user_ns['_']
533 except KeyError:
533 except KeyError:
534 pass
534 pass
535 if arg is not None:
535 if arg is not None:
536
537 # and now call a possibly user-defined print mechanism
538 try:
539 manipulated_val = self.display(arg)
540 except TypeError:
541 # If the user's display hook didn't return a string we can
542 # print, we're done. Happens commonly if they return None
543 return
544
545 # user display hooks can change the variable to be stored in
546 # output history
547 if manipulated_val is not None:
548 arg = manipulated_val
549
550 cout_write = Term.cout.write # fast lookup
536 cout_write = Term.cout.write # fast lookup
551 # first handle the cache and counters
537 # first handle the cache and counters
552
538
553 # do not print output if input ends in ';'
539 # do not print output if input ends in ';'
554 try:
540 try:
555 if self.input_hist[self.prompt_count].endswith(';\n'):
541 if self.input_hist[self.prompt_count].endswith(';\n'):
556 return
542 return
557 except IndexError:
543 except IndexError:
558 # some uses of ipshellembed may fail here
544 # some uses of ipshellembed may fail here
559 pass
545 pass
560 # don't use print, puts an extra space
546 # don't use print, puts an extra space
561 cout_write(self.output_sep)
547 cout_write(self.output_sep)
562 outprompt = self.shell.hooks.generate_output_prompt()
548 outprompt = self.shell.hooks.generate_output_prompt()
563 # print "Got prompt: ", outprompt
549 # print "Got prompt: ", outprompt
564 if self.do_full_cache:
550 if self.do_full_cache:
565 cout_write(outprompt)
551 cout_write(outprompt)
566 else:
552 else:
567 print "self.do_full_cache = False"
553 print "self.do_full_cache = False"
568
554
555 # and now call a possibly user-defined print mechanism. Note that
556 # self.display typically prints as a side-effect, we don't do any
557 # printing to stdout here.
558 try:
559 manipulated_val = self.display(arg)
560 except TypeError:
561 # If the user's display hook didn't return a string we can
562 # print, we're done. Happens commonly if they return None
563 cout_write('\n')
564 return
565
566 # user display hooks can change the variable to be stored in
567 # output history
568 if manipulated_val is not None:
569 arg = manipulated_val
570
569 # avoid recursive reference when displaying _oh/Out
571 # avoid recursive reference when displaying _oh/Out
570 if arg is not self.user_ns['_oh']:
572 if arg is not self.user_ns['_oh']:
571 self.update(arg)
573 self.update(arg)
572
574
573 if self.logger.log_output:
575 if self.logger.log_output:
574 self.logger.log_write(repr(arg),'output')
576 self.logger.log_write(repr(arg),'output')
575 cout_write(self.output_sep2)
577 cout_write(self.output_sep2)
576 Term.cout.flush()
578 Term.cout.flush()
577
579
578 def _display(self,arg):
580 def _display(self,arg):
579 """Default printer method, uses pprint.
581 """Default printer method, uses pprint.
580
582
581 Do ip.set_hook("result_display", my_displayhook) for custom result
583 Do ip.set_hook("result_display", my_displayhook) for custom result
582 display, e.g. when your own objects need special formatting.
584 display, e.g. when your own objects need special formatting.
583 """
585 """
584 try:
586 try:
585 return IPython.utils.generics.result_display(arg)
587 return IPython.utils.generics.result_display(arg)
586 except TryNext:
588 except TryNext:
587 return self.shell.hooks.result_display(arg)
589 return self.shell.hooks.result_display(arg)
588
590
589 # Assign the default display method:
591 # Assign the default display method:
590 display = _display
592 display = _display
591
593
592 def update(self,arg):
594 def update(self,arg):
593 #print '***cache_count', self.cache_count # dbg
595 #print '***cache_count', self.cache_count # dbg
594 if len(self.user_ns['_oh']) >= self.cache_size and self.do_full_cache:
596 if len(self.user_ns['_oh']) >= self.cache_size and self.do_full_cache:
595 warn('Output cache limit (currently '+
597 warn('Output cache limit (currently '+
596 `self.cache_size`+' entries) hit.\n'
598 `self.cache_size`+' entries) hit.\n'
597 'Flushing cache and resetting history counter...\n'
599 'Flushing cache and resetting history counter...\n'
598 'The only history variables available will be _,__,___ and _1\n'
600 'The only history variables available will be _,__,___ and _1\n'
599 'with the current result.')
601 'with the current result.')
600
602
601 self.flush()
603 self.flush()
602 # Don't overwrite '_' and friends if '_' is in __builtin__ (otherwise
604 # Don't overwrite '_' and friends if '_' is in __builtin__ (otherwise
603 # we cause buggy behavior for things like gettext).
605 # we cause buggy behavior for things like gettext).
604 if '_' not in __builtin__.__dict__:
606 if '_' not in __builtin__.__dict__:
605 self.___ = self.__
607 self.___ = self.__
606 self.__ = self._
608 self.__ = self._
607 self._ = arg
609 self._ = arg
608 self.user_ns.update({'_':self._,'__':self.__,'___':self.___})
610 self.user_ns.update({'_':self._,'__':self.__,'___':self.___})
609
611
610 # hackish access to top-level namespace to create _1,_2... dynamically
612 # hackish access to top-level namespace to create _1,_2... dynamically
611 to_main = {}
613 to_main = {}
612 if self.do_full_cache:
614 if self.do_full_cache:
613 new_result = '_'+`self.prompt_count`
615 new_result = '_'+`self.prompt_count`
614 to_main[new_result] = arg
616 to_main[new_result] = arg
615 self.user_ns.update(to_main)
617 self.user_ns.update(to_main)
616 self.user_ns['_oh'][self.prompt_count] = arg
618 self.user_ns['_oh'][self.prompt_count] = arg
617
619
618 def flush(self):
620 def flush(self):
619 if not self.do_full_cache:
621 if not self.do_full_cache:
620 raise ValueError,"You shouldn't have reached the cache flush "\
622 raise ValueError,"You shouldn't have reached the cache flush "\
621 "if full caching is not enabled!"
623 "if full caching is not enabled!"
622 # delete auto-generated vars from global namespace
624 # delete auto-generated vars from global namespace
623
625
624 for n in range(1,self.prompt_count + 1):
626 for n in range(1,self.prompt_count + 1):
625 key = '_'+`n`
627 key = '_'+`n`
626 try:
628 try:
627 del self.user_ns[key]
629 del self.user_ns[key]
628 except: pass
630 except: pass
629 self.user_ns['_oh'].clear()
631 self.user_ns['_oh'].clear()
630
632
631 if '_' not in __builtin__.__dict__:
633 if '_' not in __builtin__.__dict__:
632 self.user_ns.update({'_':None,'__':None, '___':None})
634 self.user_ns.update({'_':None,'__':None, '___':None})
633 import gc
635 import gc
634 gc.collect() # xxx needed?
636 gc.collect() # xxx needed?
635
637
@@ -1,40 +1,41 b''
1 # coding: utf-8
1 # coding: utf-8
2 """
2 """
3 A simple class for quitting IPython.
3 A simple class for quitting IPython.
4
4
5 Authors
5 Authors
6 -------
6 -------
7 * Fernando Perez
7 * Fernando Perez
8 * Brian Granger
8 * Brian Granger
9 """
9 """
10
10
11 #-----------------------------------------------------------------------------
11 #-----------------------------------------------------------------------------
12 # Copyright (C) 2008-2009 The IPython Development Team
12 # Copyright (C) 2008-2009 The IPython Development Team
13 #
13 #
14 # Distributed under the terms of the BSD License. The full license is in
14 # Distributed under the terms of the BSD License. The full license is in
15 # the file COPYING, distributed as part of this software.
15 # the file COPYING, distributed as part of this software.
16 #-----------------------------------------------------------------------------
16 #-----------------------------------------------------------------------------
17
17
18 #-----------------------------------------------------------------------------
18 #-----------------------------------------------------------------------------
19 # Imports
19 # Imports
20 #-----------------------------------------------------------------------------
20 #-----------------------------------------------------------------------------
21
21
22 import sys
22 import sys
23
23
24 class Quitter(object):
24 class Quitter(object):
25 """Simple class to handle exit, similar to Python 2.5's.
25 """Simple class to handle exit, similar to Python 2.5's.
26
26
27 It handles exiting in an ipython-safe manner, which the one in Python 2.5
27 It handles exiting in an ipython-safe manner, which the one in Python 2.5
28 doesn't do (obviously, since it doesn't know about ipython)."""
28 doesn't do (obviously, since it doesn't know about ipython)."""
29
29
30 def __init__(self, shell, name):
30 def __init__(self, shell, name):
31 self.shell = shell
31 self.shell = shell
32 self.name = name
32 self.name = name
33
33
34 def __str__(self):
34 def __str__(self):
35 return 'Type %s() to exit.' % self.name
35 return 'Type %s() to exit.' % self.name
36
36
37 def __call__(self):
37 def __call__(self):
38 self.shell.ask_exit()
38 self.shell.ask_exit()
39 return 'Bye.'
39
40
40 __repr__ = __call__
41 __repr__ = __call__
General Comments 0
You need to be logged in to leave comments. Login now