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