##// END OF EJS Templates
Further cleanup of prompts code - docstrings, etc.
Thomas Kluyver -
Show More
@@ -1,378 +1,378 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Classes for handling input/output prompts.
2 """Classes for handling input/output prompts.
3
3
4 Authors:
4 Authors:
5
5
6 * Fernando Perez
6 * Fernando Perez
7 * Brian Granger
7 * Brian Granger
8 * Thomas Kluyver
8 """
9 """
9
10
10 #-----------------------------------------------------------------------------
11 #-----------------------------------------------------------------------------
11 # Copyright (C) 2008-2011 The IPython Development Team
12 # Copyright (C) 2008-2011 The IPython Development Team
12 # Copyright (C) 2001-2007 Fernando Perez <fperez@colorado.edu>
13 # Copyright (C) 2001-2007 Fernando Perez <fperez@colorado.edu>
13 #
14 #
14 # Distributed under the terms of the BSD License. The full license is in
15 # Distributed under the terms of the BSD License. The full license is in
15 # the file COPYING, distributed as part of this software.
16 # the file COPYING, distributed as part of this software.
16 #-----------------------------------------------------------------------------
17 #-----------------------------------------------------------------------------
17
18
18 #-----------------------------------------------------------------------------
19 #-----------------------------------------------------------------------------
19 # Imports
20 # Imports
20 #-----------------------------------------------------------------------------
21 #-----------------------------------------------------------------------------
21
22
22 import os
23 import os
23 import re
24 import re
24 import socket
25 import socket
25 import sys
26 import sys
26 import time
27 import time
27
28
28 from IPython.config.configurable import Configurable
29 from IPython.config.configurable import Configurable
29 from IPython.core import release
30 from IPython.core import release
30 from IPython.utils import coloransi
31 from IPython.utils import coloransi
31 from IPython.utils.traitlets import (Unicode, Instance, Dict, Bool, Int)
32 from IPython.utils.traitlets import (Unicode, Instance, Dict, Bool, Int)
32
33
33 #-----------------------------------------------------------------------------
34 #-----------------------------------------------------------------------------
34 # Color schemes for prompts
35 # Color schemes for prompts
35 #-----------------------------------------------------------------------------
36 #-----------------------------------------------------------------------------
36
37
37 InputColors = coloransi.InputTermColors # just a shorthand
38 InputColors = coloransi.InputTermColors # just a shorthand
38 Colors = coloransi.TermColors # just a shorthand
39 Colors = coloransi.TermColors # just a shorthand
39
40
40 color_lists = dict(normal=Colors(), inp=InputColors(), nocolor=coloransi.NoColors())
41 color_lists = dict(normal=Colors(), inp=InputColors(), nocolor=coloransi.NoColors())
41
42
42 PColNoColors = coloransi.ColorScheme(
43 PColNoColors = coloransi.ColorScheme(
43 'NoColor',
44 'NoColor',
44 in_prompt = InputColors.NoColor, # Input prompt
45 in_prompt = InputColors.NoColor, # Input prompt
45 in_number = InputColors.NoColor, # Input prompt number
46 in_number = InputColors.NoColor, # Input prompt number
46 in_prompt2 = InputColors.NoColor, # Continuation prompt
47 in_prompt2 = InputColors.NoColor, # Continuation prompt
47 in_normal = InputColors.NoColor, # color off (usu. Colors.Normal)
48 in_normal = InputColors.NoColor, # color off (usu. Colors.Normal)
48
49
49 out_prompt = Colors.NoColor, # Output prompt
50 out_prompt = Colors.NoColor, # Output prompt
50 out_number = Colors.NoColor, # Output prompt number
51 out_number = Colors.NoColor, # Output prompt number
51
52
52 normal = Colors.NoColor # color off (usu. Colors.Normal)
53 normal = Colors.NoColor # color off (usu. Colors.Normal)
53 )
54 )
54
55
55 # make some schemes as instances so we can copy them for modification easily:
56 # make some schemes as instances so we can copy them for modification easily:
56 PColLinux = coloransi.ColorScheme(
57 PColLinux = coloransi.ColorScheme(
57 'Linux',
58 'Linux',
58 in_prompt = InputColors.Green,
59 in_prompt = InputColors.Green,
59 in_number = InputColors.LightGreen,
60 in_number = InputColors.LightGreen,
60 in_prompt2 = InputColors.Green,
61 in_prompt2 = InputColors.Green,
61 in_normal = InputColors.Normal, # color off (usu. Colors.Normal)
62 in_normal = InputColors.Normal, # color off (usu. Colors.Normal)
62
63
63 out_prompt = Colors.Red,
64 out_prompt = Colors.Red,
64 out_number = Colors.LightRed,
65 out_number = Colors.LightRed,
65
66
66 normal = Colors.Normal
67 normal = Colors.Normal
67 )
68 )
68
69
69 # Slightly modified Linux for light backgrounds
70 # Slightly modified Linux for light backgrounds
70 PColLightBG = PColLinux.copy('LightBG')
71 PColLightBG = PColLinux.copy('LightBG')
71
72
72 PColLightBG.colors.update(
73 PColLightBG.colors.update(
73 in_prompt = InputColors.Blue,
74 in_prompt = InputColors.Blue,
74 in_number = InputColors.LightBlue,
75 in_number = InputColors.LightBlue,
75 in_prompt2 = InputColors.Blue
76 in_prompt2 = InputColors.Blue
76 )
77 )
77
78
78 #-----------------------------------------------------------------------------
79 #-----------------------------------------------------------------------------
79 # Utilities
80 # Utilities
80 #-----------------------------------------------------------------------------
81 #-----------------------------------------------------------------------------
81
82
82 class LazyEvaluate(object):
83 class LazyEvaluate(object):
83 """This is used for formatting strings with values that need to be updated
84 """This is used for formatting strings with values that need to be updated
84 at that time, such as the current time or line number."""
85 at that time, such as the current time or working directory."""
85 def __init__(self, func, *args, **kwargs):
86 def __init__(self, func, *args, **kwargs):
86 self.func = func
87 self.func = func
87 self.args = args
88 self.args = args
88 self.kwargs = kwargs
89 self.kwargs = kwargs
89
90
90 def __call__(self, **kwargs):
91 def __call__(self, **kwargs):
91 self.kwargs.update(kwargs)
92 self.kwargs.update(kwargs)
92 return self.func(*self.args, **self.kwargs)
93 return self.func(*self.args, **self.kwargs)
93
94
94 def __str__(self):
95 def __str__(self):
95 return str(self())
96 return str(self())
96
97
97 def multiple_replace(dict, text):
98 def multiple_replace(dict, text):
98 """ Replace in 'text' all occurences of any key in the given
99 """ Replace in 'text' all occurences of any key in the given
99 dictionary by its corresponding value. Returns the new string."""
100 dictionary by its corresponding value. Returns the new string."""
100
101
101 # Function by Xavier Defrang, originally found at:
102 # Function by Xavier Defrang, originally found at:
102 # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/81330
103 # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/81330
103
104
104 # Create a regular expression from the dictionary keys
105 # Create a regular expression from the dictionary keys
105 regex = re.compile("(%s)" % "|".join(map(re.escape, dict.keys())))
106 regex = re.compile("(%s)" % "|".join(map(re.escape, dict.keys())))
106 # For each match, look-up corresponding value in dictionary
107 # For each match, look-up corresponding value in dictionary
107 return regex.sub(lambda mo: dict[mo.string[mo.start():mo.end()]], text)
108 return regex.sub(lambda mo: dict[mo.string[mo.start():mo.end()]], text)
108
109
109 #-----------------------------------------------------------------------------
110 #-----------------------------------------------------------------------------
110 # Special characters that can be used in prompt templates, mainly bash-like
111 # Special characters that can be used in prompt templates, mainly bash-like
111 #-----------------------------------------------------------------------------
112 #-----------------------------------------------------------------------------
112
113
113 # If $HOME isn't defined (Windows), make it an absurd string so that it can
114 # If $HOME isn't defined (Windows), make it an absurd string so that it can
114 # never be expanded out into '~'. Basically anything which can never be a
115 # never be expanded out into '~'. Basically anything which can never be a
115 # reasonable directory name will do, we just want the $HOME -> '~' operation
116 # reasonable directory name will do, we just want the $HOME -> '~' operation
116 # to become a no-op. We pre-compute $HOME here so it's not done on every
117 # to become a no-op. We pre-compute $HOME here so it's not done on every
117 # prompt call.
118 # prompt call.
118
119
119 # FIXME:
120 # FIXME:
120
121
121 # - This should be turned into a class which does proper namespace management,
122 # - This should be turned into a class which does proper namespace management,
122 # since the prompt specials need to be evaluated in a certain namespace.
123 # since the prompt specials need to be evaluated in a certain namespace.
123 # Currently it's just globals, which need to be managed manually by code
124 # Currently it's just globals, which need to be managed manually by code
124 # below.
125 # below.
125
126
126 # - I also need to split up the color schemes from the prompt specials
127 # - I also need to split up the color schemes from the prompt specials
127 # somehow. I don't have a clean design for that quite yet.
128 # somehow. I don't have a clean design for that quite yet.
128
129
129 HOME = os.environ.get("HOME","//////:::::ZZZZZ,,,~~~")
130 HOME = os.environ.get("HOME","//////:::::ZZZZZ,,,~~~")
130
131
131 # We precompute a few more strings here for the prompt_specials, which are
132 # We precompute a few more strings here for the prompt_specials, which are
132 # fixed once ipython starts. This reduces the runtime overhead of computing
133 # fixed once ipython starts. This reduces the runtime overhead of computing
133 # prompt strings.
134 # prompt strings.
134 USER = os.environ.get("USER")
135 USER = os.environ.get("USER")
135 HOSTNAME = socket.gethostname()
136 HOSTNAME = socket.gethostname()
136 HOSTNAME_SHORT = HOSTNAME.split(".")[0]
137 HOSTNAME_SHORT = HOSTNAME.split(".")[0]
137 ROOT_SYMBOL = "#" if (os.name=='nt' or os.getuid()==0) else "$"
138 ROOT_SYMBOL = "#" if (os.name=='nt' or os.getuid()==0) else "$"
138
139
139 prompt_abbreviations = {
140 prompt_abbreviations = {
140 # Prompt/history count
141 # Prompt/history count
141 '%n' : '{color.number}' '{count}' '{color.prompt}',
142 '%n' : '{color.number}' '{count}' '{color.prompt}',
142 r'\#': '{color.number}' '{count}' '{color.prompt}',
143 r'\#': '{color.number}' '{count}' '{color.prompt}',
143 # Just the prompt counter number, WITHOUT any coloring wrappers, so users
144 # Just the prompt counter number, WITHOUT any coloring wrappers, so users
144 # can get numbers displayed in whatever color they want.
145 # can get numbers displayed in whatever color they want.
145 r'\N': '{count}',
146 r'\N': '{count}',
146
147
147 # Prompt/history count, with the actual digits replaced by dots. Used
148 # Prompt/history count, with the actual digits replaced by dots. Used
148 # mainly in continuation prompts (prompt_in2)
149 # mainly in continuation prompts (prompt_in2)
149 r'\D': '{dots}',
150 r'\D': '{dots}',
150
151
151 # Current time
152 # Current time
152 r'\t' : '{time}',
153 r'\t' : '{time}',
153 # Current working directory
154 # Current working directory
154 r'\w': '{cwd}',
155 r'\w': '{cwd}',
155 # Basename of current working directory.
156 # Basename of current working directory.
156 # (use os.sep to make this portable across OSes)
157 # (use os.sep to make this portable across OSes)
157 r'\W' : '{cwd_last}',
158 r'\W' : '{cwd_last}',
158 # These X<N> are an extension to the normal bash prompts. They return
159 # These X<N> are an extension to the normal bash prompts. They return
159 # N terms of the path, after replacing $HOME with '~'
160 # N terms of the path, after replacing $HOME with '~'
160 r'\X0': '{cwd_x[0])}',
161 r'\X0': '{cwd_x[0])}',
161 r'\X1': '{cwd_x[1])}',
162 r'\X1': '{cwd_x[1])}',
162 r'\X2': '{cwd_x[2])}',
163 r'\X2': '{cwd_x[2])}',
163 r'\X3': '{cwd_x[3])}',
164 r'\X3': '{cwd_x[3])}',
164 r'\X4': '{cwd_x[4])}',
165 r'\X4': '{cwd_x[4])}',
165 r'\X5': '{cwd_x[5])}',
166 r'\X5': '{cwd_x[5])}',
166 # Y<N> are similar to X<N>, but they show '~' if it's the directory
167 # Y<N> are similar to X<N>, but they show '~' if it's the directory
167 # N+1 in the list. Somewhat like %cN in tcsh.
168 # N+1 in the list. Somewhat like %cN in tcsh.
168 r'\Y0': '{cwd_y[0])}',
169 r'\Y0': '{cwd_y[0])}',
169 r'\Y1': '{cwd_y[1])}',
170 r'\Y1': '{cwd_y[1])}',
170 r'\Y2': '{cwd_y[2])}',
171 r'\Y2': '{cwd_y[2])}',
171 r'\Y3': '{cwd_y[3])}',
172 r'\Y3': '{cwd_y[3])}',
172 r'\Y4': '{cwd_y[4])}',
173 r'\Y4': '{cwd_y[4])}',
173 r'\Y5': '{cwd_y[5])}',
174 r'\Y5': '{cwd_y[5])}',
174 # Hostname up to first .
175 # Hostname up to first .
175 r'\h': HOSTNAME_SHORT,
176 r'\h': HOSTNAME_SHORT,
176 # Full hostname
177 # Full hostname
177 r'\H': HOSTNAME,
178 r'\H': HOSTNAME,
178 # Username of current user
179 # Username of current user
179 r'\u': USER,
180 r'\u': USER,
180 # Escaped '\'
181 # Escaped '\'
181 '\\\\': '\\',
182 '\\\\': '\\',
182 # Newline
183 # Newline
183 r'\n': '\n',
184 r'\n': '\n',
184 # Carriage return
185 # Carriage return
185 r'\r': '\r',
186 r'\r': '\r',
186 # Release version
187 # Release version
187 r'\v': release.version,
188 r'\v': release.version,
188 # Root symbol ($ or #)
189 # Root symbol ($ or #)
189 r'\$': ROOT_SYMBOL,
190 r'\$': ROOT_SYMBOL,
190 }
191 }
191
192
192 #-----------------------------------------------------------------------------
193 #-----------------------------------------------------------------------------
193 # More utilities
194 # More utilities
194 #-----------------------------------------------------------------------------
195 #-----------------------------------------------------------------------------
195
196
196 def str_safe(arg):
197 """Convert to a string, without ever raising an exception.
198
199 If str(arg) fails, <ERROR: ... > is returned, where ... is the exception
200 error message."""
201
202 try:
203 out = str(arg)
204 except UnicodeError:
205 try:
206 out = arg.encode('utf_8','replace')
207 except Exception,msg:
208 # let's keep this little duplication here, so that the most common
209 # case doesn't suffer from a double try wrapping.
210 out = '<ERROR: %s>' % msg
211 except Exception,msg:
212 out = '<ERROR: %s>' % msg
213 #raise # dbg
214 return out
215
216 def cwd_filt(self, depth):
197 def cwd_filt(self, depth):
217 """Return the last depth elements of the current working directory.
198 """Return the last depth elements of the current working directory.
218
199
219 $HOME is always replaced with '~'.
200 $HOME is always replaced with '~'.
220 If depth==0, the full path is returned."""
201 If depth==0, the full path is returned."""
221
202
222 cwd = os.getcwd().replace(HOME,"~")
203 cwd = os.getcwd().replace(HOME,"~")
223 out = os.sep.join(cwd.split(os.sep)[-depth:])
204 out = os.sep.join(cwd.split(os.sep)[-depth:])
224 return out or os.sep
205 return out or os.sep
225
206
226 def cwd_filt2(self, depth):
207 def cwd_filt2(self, depth):
227 """Return the last depth elements of the current working directory.
208 """Return the last depth elements of the current working directory.
228
209
229 $HOME is always replaced with '~'.
210 $HOME is always replaced with '~'.
230 If depth==0, the full path is returned."""
211 If depth==0, the full path is returned."""
231
212
232 full_cwd = os.getcwd()
213 full_cwd = os.getcwd()
233 cwd = full_cwd.replace(HOME,"~").split(os.sep)
214 cwd = full_cwd.replace(HOME,"~").split(os.sep)
234 if '~' in cwd and len(cwd) == depth+1:
215 if '~' in cwd and len(cwd) == depth+1:
235 depth += 1
216 depth += 1
236 drivepart = ''
217 drivepart = ''
237 if sys.platform == 'win32' and len(cwd) > depth:
218 if sys.platform == 'win32' and len(cwd) > depth:
238 drivepart = os.path.splitdrive(full_cwd)[0]
219 drivepart = os.path.splitdrive(full_cwd)[0]
239 out = drivepart + '/'.join(cwd[-depth:])
220 out = drivepart + '/'.join(cwd[-depth:])
240
221
241 return out or os.sep
222 return out or os.sep
242
223
243 #-----------------------------------------------------------------------------
224 #-----------------------------------------------------------------------------
244 # Prompt classes
225 # Prompt classes
245 #-----------------------------------------------------------------------------
226 #-----------------------------------------------------------------------------
246
227
247 lazily_evaluate = {'time': LazyEvaluate(time.strftime, "%H:%M:%S"),
228 lazily_evaluate = {'time': LazyEvaluate(time.strftime, "%H:%M:%S"),
248 'cwd': LazyEvaluate(os.getcwd),
229 'cwd': LazyEvaluate(os.getcwd),
249 'cwd_last': LazyEvaluate(lambda: os.getcwd().split(os.sep)[-1]),
230 'cwd_last': LazyEvaluate(lambda: os.getcwd().split(os.sep)[-1]),
250 'cwd_x': [LazyEvaluate(lambda: os.getcwd().replace("%s","~"))] +\
231 'cwd_x': [LazyEvaluate(lambda: os.getcwd().replace("%s","~"))] +\
251 [LazyEvaluate(cwd_filt, x) for x in range(1,6)],
232 [LazyEvaluate(cwd_filt, x) for x in range(1,6)],
252 'cwd_y': [LazyEvaluate(cwd_filt2, x) for x in range(6)]
233 'cwd_y': [LazyEvaluate(cwd_filt2, x) for x in range(6)]
253 }
234 }
254
235
255
236
256 class PromptManager(Configurable):
237 class PromptManager(Configurable):
238 """This is the primary interface for producing IPython's prompts."""
257 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
239 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
258
240
259 color_scheme_table = Instance(coloransi.ColorSchemeTable)
241 color_scheme_table = Instance(coloransi.ColorSchemeTable)
260 color_scheme = Unicode('Linux')
242 color_scheme = Unicode('Linux', config=True)
261 def _color_scheme_changed(self, name, new_value):
243 def _color_scheme_changed(self, name, new_value):
262 self.color_scheme_table.set_active_scheme(new_value)
244 self.color_scheme_table.set_active_scheme(new_value)
263 for pname in ['in', 'in2', 'out', 'rewrite']:
245 for pname in ['in', 'in2', 'out', 'rewrite']:
264 # We need to recalculate the number of invisible characters
246 # We need to recalculate the number of invisible characters
265 self.update_prompt(pname)
247 self.update_prompt(pname)
266
248
267 # These fields can be referenced in prompt templates, and are evaluated
249 lazy_evaluate_fields = Dict(help="""
268 # when the prompt is generated - for things like timestamps. They are only
250 This maps field names used in the prompt templates to functions which
269 # evaluated if a prompt uses them.
251 will be called when the prompt is rendered. This allows us to include
270 lazy_evaluate_fields = Dict()
252 things like the current time in the prompts. Functions are only called
253 if they are used in the prompt.
254 """)
271 def _lazy_evaluate_fields_default(self): return lazily_evaluate.copy()
255 def _lazy_evaluate_fields_default(self): return lazily_evaluate.copy()
272
256
273 in_template = Unicode('In [\\#]: ', config=True)
257 in_template = Unicode('In [\\#]: ', config=True)
274 in2_template = Unicode(' .\\D.: ', config=True)
258 in2_template = Unicode(' .\\D.: ', config=True)
275 out_template = Unicode('Out[\\#]: ', config=True)
259 out_template = Unicode('Out[\\#]: ', config=True)
276 rewrite_template = Unicode("------> ", config=True)
260 rewrite_template = Unicode("------> ", config=True)
277
261
278 # Justify prompts by default?
262 justify = Bool(True, config=True, help="""
279 justify = Bool(True)
263 If True (default), each prompt will be right-aligned with the
264 preceding one.
265 """)
280
266
281 # We actually store the expanded templates here:
267 # We actually store the expanded templates here:
282 templates = Dict()
268 templates = Dict()
283
269
284 # The number of characters in the last prompt rendered, not including
270 # The number of characters in the last prompt rendered, not including
285 # colour characters.
271 # colour characters.
286 width = Int()
272 width = Int()
287
273
288 # The number of characters in each prompt which don't contribute to width
274 # The number of characters in each prompt which don't contribute to width
289 invisible_chars = Dict()
275 invisible_chars = Dict()
290 def _invisible_chars_default(self):
276 def _invisible_chars_default(self):
291 return {'in': 0, 'in2': 0, 'out': 0, 'rewrite': 0}
277 return {'in': 0, 'in2': 0, 'out': 0, 'rewrite': 0}
292
278
293 def __init__(self, shell, config=None):
279 def __init__(self, shell, config=None):
294 super(PromptManager, self).__init__(shell=shell, config=config)
280 super(PromptManager, self).__init__(shell=shell, config=config)
295
281
296 # Prepare colour scheme table
282 # Prepare colour scheme table
297 self.color_scheme_table = coloransi.ColorSchemeTable([PColNoColors,
283 self.color_scheme_table = coloransi.ColorSchemeTable([PColNoColors,
298 PColLinux, PColLightBG], self.color_scheme)
284 PColLinux, PColLightBG], self.color_scheme)
299
285
300 # Prepare templates
286 # Prepare templates
301 self.update_prompt('in', self.in_template)
287 self.update_prompt('in', self.in_template)
302 self.update_prompt('in2', self.in2_template)
288 self.update_prompt('in2', self.in2_template)
303 self.update_prompt('out', self.out_template)
289 self.update_prompt('out', self.out_template)
304 self.update_prompt('rewrite', self.rewrite_template)
290 self.update_prompt('rewrite', self.rewrite_template)
305 self.on_trait_change(self._update_prompt_trait, ['in_template',
291 self.on_trait_change(self._update_prompt_trait, ['in_template',
306 'in2_template', 'out_template', 'rewrite_template'])
292 'in2_template', 'out_template', 'rewrite_template'])
307
293
308 def update_prompt(self, name, new_template=None):
294 def update_prompt(self, name, new_template=None):
295 """This is called when a prompt template is updated. It processes
296 abbreviations used in the prompt template (like \#) and calculates how
297 many invisible characters (ANSI colour escapes) the resulting prompt
298 contains.
299
300 It is also called for each prompt on changing the colour scheme. In both
301 cases, traitlets should take care of calling this automatically.
302 """
309 if new_template is not None:
303 if new_template is not None:
310 self.templates[name] = multiple_replace(prompt_abbreviations, new_template)
304 self.templates[name] = multiple_replace(prompt_abbreviations, new_template)
311 invis_chars = len(self.render(name, color=True, just=False)) - \
305 invis_chars = len(self.render(name, color=True, just=False)) - \
312 len(self.render(name, color=False, just=False))
306 len(self.render(name, color=False, just=False))
313 self.invisible_chars[name] = invis_chars
307 self.invisible_chars[name] = invis_chars
314
308
315 def _update_prompt_trait(self, traitname, new_template):
309 def _update_prompt_trait(self, traitname, new_template):
316 name = traitname[:-9] # Cut off '_template'
310 name = traitname[:-9] # Cut off '_template'
317 self.update_prompt(name, new_template)
311 self.update_prompt(name, new_template)
318
312
319 def render(self, name, color=True, just=None, **kwargs):
313 def render(self, name, color=True, just=None, **kwargs):
320 """
314 """
321 Render the selected prompt.
315 Render the selected prompt.
322
316
323 Parameters
317 Parameters
324 ----------
318 ----------
325 name : str
319 name : str
326 Which prompt to render. One of 'in', 'in2', 'out', 'rewrite'
320 Which prompt to render. One of 'in', 'in2', 'out', 'rewrite'
327 color : bool
321 color : bool
328 If True (default), include ANSI escape sequences for a coloured prompt.
322 If True (default), include ANSI escape sequences for a coloured prompt.
329 just : bool
323 just : bool
330 If True, justify the prompt to the width of the last prompt. The
324 If True, justify the prompt to the width of the last prompt. The
331 default is stored in self.justify.
325 default is stored in self.justify.
332 **kwargs :
326 **kwargs :
333 Additional arguments will be passed to the string formatting operation,
327 Additional arguments will be passed to the string formatting operation,
334 so they can override the values that would otherwise fill in the
328 so they can override the values that would otherwise fill in the
335 template.
329 template.
336
330
337 Returns
331 Returns
338 -------
332 -------
339 A string containing the rendered prompt.
333 A string containing the rendered prompt.
340 """
334 """
341 if color:
335 if color:
342 scheme = self.color_scheme_table.active_colors
336 scheme = self.color_scheme_table.active_colors
343 if name=='out':
337 if name=='out':
344 colors = color_lists['normal']
338 colors = color_lists['normal']
345 colors.number, colors.prompt, colors.normal = \
339 colors.number, colors.prompt, colors.normal = \
346 scheme.out_number, scheme.out_prompt, scheme.normal
340 scheme.out_number, scheme.out_prompt, scheme.normal
341 elif name=='rewrite':
342 colors = color_lists['normal']
343 # We need a non-input version of these escapes
344 colors.number = scheme.in_number.replace("\001","").replace("\002","")
345 colors.prompt = scheme.in_prompt.replace("\001","").replace("\002","")
346 colors.normal = scheme.normal
347 else:
347 else:
348 colors = color_lists['inp']
348 colors = color_lists['inp']
349 colors.number, colors.prompt, colors.normal = \
349 colors.number, colors.prompt, colors.normal = \
350 scheme.in_number, scheme.in_prompt, scheme.in_normal
350 scheme.in_number, scheme.in_prompt, scheme.in_normal
351 if name=='in2':
351 if name=='in2':
352 colors.prompt = scheme.in_prompt2
352 colors.prompt = scheme.in_prompt2
353 else:
353 else:
354 # No color
354 # No color
355 colors = color_lists['nocolor']
355 colors = color_lists['nocolor']
356 colors.number, colors.prompt, colors.normal = '', '', ''
356 colors.number, colors.prompt, colors.normal = '', '', ''
357
357
358 count = self.shell.execution_count # Shorthand
358 count = self.shell.execution_count # Shorthand
359 # Build the dictionary to be passed to string formatting
359 # Build the dictionary to be passed to string formatting
360 fmtargs = dict(color=colors, count=count,
360 fmtargs = dict(color=colors, count=count,
361 dots="."*len(str(count)) )
361 dots="."*len(str(count)) )
362 fmtargs.update(self.lazy_evaluate_fields)
362 fmtargs.update(self.lazy_evaluate_fields)
363 fmtargs.update(kwargs)
363 fmtargs.update(kwargs)
364
364
365 # Prepare the prompt
365 # Prepare the prompt
366 prompt = colors.prompt + self.templates[name] + colors.normal
366 prompt = colors.prompt + self.templates[name] + colors.normal
367
367
368 # Fill in required fields
368 # Fill in required fields
369 res = prompt.format(**fmtargs)
369 res = prompt.format(**fmtargs)
370
370
371 # Handle justification of prompt
371 # Handle justification of prompt
372 invis_chars = self.invisible_chars[name] if color else 0
372 invis_chars = self.invisible_chars[name] if color else 0
373 just = self.justify if (just is None) else just
373 just = self.justify if (just is None) else just
374 if just:
374 if just:
375 res = res.rjust(self.width + invis_chars)
375 res = res.rjust(self.width + invis_chars)
376 self.width = len(res) - invis_chars
376 self.width = len(res) - invis_chars
377 return res
377 return res
378
378
General Comments 0
You need to be logged in to leave comments. Login now