Skip to content
This repository

Prompts #1083

Merged
merged 4 commits into from over 2 years ago

3 participants

Thomas Kluyver Min RK Fernando Perez
Thomas Kluyver
Collaborator

Building on @minrk's PR #1078.

This makes the rewrite prompt adapt to the size of the previous prompt. The minimum length (by default) is 3 characters: ->. It remains configurable, so if the user wants really short prompts, it can be replaced.

and others added some commits November 30, 2011
Min RK PromptManager fixes
* InteractiveShell.prompt_foo traits show deprecation warning, and map to new PromptManager traits
* PromptManager properly added to IPython App, so it will show up in config
* add helpstrings to PromptManager traits.
* Docs / embed references to Shell.prompt_foo also updated
38572c2
Thomas Kluyver Update pysh profile 77a068c
Thomas Kluyver Make size of rewrite prompt flexible. 7a27b8c
Min RK
Owner

@fperez said in #1078 that rewrite need not be a template at all, and can just be a bool always matching the length of the input prompt.

Fernando Perez
Owner

Yes: because this is a prompt meant to expand/contract dynamically to the length of the input prompt above it, I'm not really sure that template semantics make any sense here. If users give some other string, what are we supposed to grow and what to keep static? I think it's needless flexibility that adds complexity for no real payoff, so the only option we should give here is, "do you want a rewrite prompt at all or not?".

Fernando Perez
Owner

This looks good, I tested the functionality and it works just like 0.10x did, so I think we're ok on that front. Once the changes mentioned above are made, to remove the template for the rewrite prompt and make it a simple boolean, we can test again and should be good to merge.

Thomas Kluyver
Collaborator

By "do you want to see a rewrite prompt", I assume you mean an option to turn off showing rewritten input altogether?

Fernando Perez
Owner

Yes, sorry if it wasn't clear. I probably said it better in #1078:

I'm actually OK with the rewrite prompt not being a template at all, we're simply saying 'the line above got rewritten'. The rewrite prompt instead could be a simple boolean: if True, we rewrite with '---->' as long as it needs to be, if False we don't show any rewrite. There's no need for having a template there.

Does that make sense?

Thomas Kluyver
Collaborator

Done.

Added a show_rewritten_input config to InteractiveShell to turn it off.

Fernando Perez
Owner

Great, looks good now, tests pass, rewrite works correctly. Thanks! merging...

Fernando Perez fperez merged commit 4b8920a into from December 01, 2011
Fernando Perez fperez closed this December 01, 2011
Fernando Perez fperez referenced this pull request from a commit January 10, 2012
Commit has since been removed from the repository and is no longer available.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Showing 4 unique commits by 2 authors.

Nov 30, 2011
Min RK PromptManager fixes
* InteractiveShell.prompt_foo traits show deprecation warning, and map to new PromptManager traits
* PromptManager properly added to IPython App, so it will show up in config
* add helpstrings to PromptManager traits.
* Docs / embed references to Shell.prompt_foo also updated
38572c2
Dec 01, 2011
Thomas Kluyver Update pysh profile 77a068c
Thomas Kluyver Make size of rewrite prompt flexible. 7a27b8c
Thomas Kluyver Make rewrite prompt non-configurable. ff4cb84
This page is out of date. Refresh to see the latest.
42  IPython/core/interactiveshell.py
@@ -315,10 +315,41 @@ def _exiter_default(self):
315 315
         help="Save multi-line entries as one entry in readline history"
316 316
     )
317 317
 
318  
-    prompt_in1 = Unicode('In [\\#]: ', config=True)
319  
-    prompt_in2 = Unicode('   .\\D.: ', config=True)
320  
-    prompt_out = Unicode('Out[\\#]: ', config=True)
321  
-    prompts_pad_left = CBool(True, config=True)
  318
+    # deprecated prompt traits:
  319
+    
  320
+    prompt_in1 = Unicode('In [\\#]: ', config=True,
  321
+        help="Deprecated, use PromptManager.in_template")
  322
+    prompt_in2 = Unicode('   .\\D.: ', config=True,
  323
+        help="Deprecated, use PromptManager.in2_template")
  324
+    prompt_out = Unicode('Out[\\#]: ', config=True,
  325
+        help="Deprecated, use PromptManager.out_template")
  326
+    prompts_pad_left = CBool(True, config=True,
  327
+        help="Deprecated, use PromptManager.justify")
  328
+    
  329
+    def _prompt_trait_changed(self, name, old, new):
  330
+        table = {
  331
+            'prompt_in1' : 'in_template',
  332
+            'prompt_in2' : 'in2_template',
  333
+            'prompt_out' : 'out_template',
  334
+            'prompts_pad_left' : 'justify',
  335
+        }
  336
+        warn("InteractiveShell.{name} is deprecated, use PromptManager.{newname}\n".format(
  337
+                name=name, newname=table[name])
  338
+        )
  339
+        # protect against weird cases where self.config may not exist:
  340
+        if self.config is not None:
  341
+            # propagate to corresponding PromptManager trait
  342
+            setattr(self.config.PromptManager, table[name], new)
  343
+    
  344
+    _prompt_in1_changed = _prompt_trait_changed
  345
+    _prompt_in2_changed = _prompt_trait_changed
  346
+    _prompt_out_changed = _prompt_trait_changed
  347
+    _prompt_pad_left_changed = _prompt_trait_changed
  348
+    
  349
+    show_rewritten_input = CBool(True, config=True,
  350
+        help="Show rewritten input, e.g. for autocall."
  351
+    )
  352
+    
322 353
     quiet = CBool(False, config=True)
323 354
 
324 355
     history_length = Integer(10000, config=True)
@@ -2141,6 +2172,9 @@ def auto_rewrite_input(self, cmd):
2141 2172
         after the user's input prompt.  This helps the user understand that the
2142 2173
         input line was transformed automatically by IPython.
2143 2174
         """
  2175
+        if not self.show_rewritten_input:
  2176
+            return
  2177
+        
2144 2178
         rw = self.prompt_manager.render('rewrite') + cmd
2145 2179
 
2146 2180
         try:
96  IPython/core/prompts.py
@@ -254,10 +254,12 @@ def _color_scheme_changed(self, name, new_value):
254 254
         """)
255 255
     def _lazy_evaluate_fields_default(self): return lazily_evaluate.copy()
256 256
     
257  
-    in_template = Unicode('In [\\#]: ', config=True)
258  
-    in2_template = Unicode('   .\\D.: ', config=True)
259  
-    out_template = Unicode('Out[\\#]: ', config=True)
260  
-    rewrite_template = Unicode("------> ", config=True)
  257
+    in_template = Unicode('In [\\#]: ', config=True,
  258
+        help="Input prompt.  '\\#' will be transformed to the prompt number")
  259
+    in2_template = Unicode('   .\\D.: ', config=True,
  260
+        help="Continuation prompt.")
  261
+    out_template = Unicode('Out[\\#]: ', config=True,
  262
+        help="Output prompt. '\\#' will be transformed to the prompt number")
261 263
     
262 264
     justify = Bool(True, config=True, help="""
263 265
         If True (default), each prompt will be right-aligned with the
@@ -270,11 +272,12 @@ def _lazy_evaluate_fields_default(self): return lazily_evaluate.copy()
270 272
     # The number of characters in the last prompt rendered, not including
271 273
     # colour characters.
272 274
     width = Int()
  275
+    txtwidth = Int()   # Not including right-justification
273 276
     
274 277
     # The number of characters in each prompt which don't contribute to width
275 278
     invisible_chars = Dict()
276 279
     def _invisible_chars_default(self):
277  
-        return {'in': 0, 'in2': 0, 'out': 0, 'rewrite': 0}
  280
+        return {'in': 0, 'in2': 0, 'out': 0, 'rewrite':0}
278 281
     
279 282
     def __init__(self, shell, config=None):
280 283
         super(PromptManager, self).__init__(shell=shell, config=config)
@@ -283,13 +286,13 @@ def __init__(self, shell, config=None):
283 286
         self.color_scheme_table = coloransi.ColorSchemeTable([PColNoColors,
284 287
                                     PColLinux, PColLightBG], self.color_scheme)
285 288
         
286  
-        # Prepare templates
  289
+        # Prepare templates & numbers of invisible characters
287 290
         self.update_prompt('in', self.in_template)
288 291
         self.update_prompt('in2', self.in2_template)
289 292
         self.update_prompt('out', self.out_template)
290  
-        self.update_prompt('rewrite', self.rewrite_template)
  293
+        self.update_prompt('rewrite')
291 294
         self.on_trait_change(self._update_prompt_trait, ['in_template',
292  
-                            'in2_template', 'out_template', 'rewrite_template'])
  295
+                            'in2_template', 'out_template'])
293 296
     
294 297
     def update_prompt(self, name, new_template=None):
295 298
         """This is called when a prompt template is updated. It processes
@@ -302,48 +305,26 @@ def update_prompt(self, name, new_template=None):
302 305
         """
303 306
         if new_template is not None:
304 307
             self.templates[name] = multiple_replace(prompt_abbreviations, new_template)
305  
-        invis_chars = len(self.render(name, color=True, just=False)) - \
306  
-                            len(self.render(name, color=False, just=False))
  308
+        invis_chars = len(self._render(name, color=True)) - \
  309
+                            len(self._render(name, color=False))
307 310
         self.invisible_chars[name] = invis_chars
308 311
     
309 312
     def _update_prompt_trait(self, traitname, new_template):
310 313
         name = traitname[:-9]   # Cut off '_template'
311 314
         self.update_prompt(name, new_template)
312 315
     
313  
-    def render(self, name, color=True, just=None, **kwargs):
  316
+    def _render(self, name, color=True, **kwargs):
  317
+        """Render but don't justify, or update the width or txtwidth attributes.
314 318
         """
315  
-        Render the selected prompt.
  319
+        if name == 'rewrite':
  320
+            return self._render_rewrite(color=color)
316 321
         
317  
-        Parameters
318  
-        ----------
319  
-        name : str
320  
-          Which prompt to render. One of 'in', 'in2', 'out', 'rewrite'
321  
-        color : bool
322  
-          If True (default), include ANSI escape sequences for a coloured prompt.
323  
-        just : bool
324  
-          If True, justify the prompt to the width of the last prompt. The
325  
-          default is stored in self.justify.
326  
-        **kwargs :
327  
-          Additional arguments will be passed to the string formatting operation,
328  
-          so they can override the values that would otherwise fill in the
329  
-          template.
330  
-        
331  
-        Returns
332  
-        -------
333  
-        A string containing the rendered prompt.
334  
-        """
335 322
         if color:
336 323
             scheme = self.color_scheme_table.active_colors
337 324
             if name=='out':
338 325
                 colors = color_lists['normal']
339 326
                 colors.number, colors.prompt, colors.normal = \
340 327
                         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 328
             else:
348 329
                 colors = color_lists['inp']
349 330
                 colors.number, colors.prompt, colors.normal = \
@@ -358,7 +339,8 @@ def render(self, name, color=True, just=None, **kwargs):
358 339
         count = self.shell.execution_count    # Shorthand
359 340
         # Build the dictionary to be passed to string formatting
360 341
         fmtargs = dict(color=colors, count=count,
361  
-                        dots="."*len(str(count)) )
  342
+                        dots="."*len(str(count)),
  343
+                        width=self.width, txtwidth=self.txtwidth )
362 344
         fmtargs.update(self.lazy_evaluate_fields)
363 345
         fmtargs.update(kwargs)
364 346
         
@@ -366,13 +348,49 @@ def render(self, name, color=True, just=None, **kwargs):
366 348
         prompt = colors.prompt + self.templates[name] + colors.normal
367 349
         
368 350
         # Fill in required fields
369  
-        res = prompt.format(**fmtargs)
  351
+        return prompt.format(**fmtargs)
  352
+    
  353
+    def _render_rewrite(self, color=True):
  354
+        """Render the ---> rewrite prompt."""
  355
+        if color:
  356
+            scheme = self.color_scheme_table.active_colors
  357
+            # We need a non-input version of these escapes
  358
+            color_prompt = scheme.in_prompt.replace("\001","").replace("\002","")
  359
+            color_normal = scheme.normal
  360
+        else:
  361
+            color_prompt, color_normal = '', ''
  362
+
  363
+        return color_prompt + "-> ".rjust(self.txtwidth, "-") + color_normal
  364
+    
  365
+    def render(self, name, color=True, just=None, **kwargs):
  366
+        """
  367
+        Render the selected prompt.
  368
+        
  369
+        Parameters
  370
+        ----------
  371
+        name : str
  372
+          Which prompt to render. One of 'in', 'in2', 'out', 'rewrite'
  373
+        color : bool
  374
+          If True (default), include ANSI escape sequences for a coloured prompt.
  375
+        just : bool
  376
+          If True, justify the prompt to the width of the last prompt. The
  377
+          default is stored in self.justify.
  378
+        **kwargs :
  379
+          Additional arguments will be passed to the string formatting operation,
  380
+          so they can override the values that would otherwise fill in the
  381
+          template.
  382
+        
  383
+        Returns
  384
+        -------
  385
+        A string containing the rendered prompt.
  386
+        """
  387
+        res = self._render(name, color=color, **kwargs)
370 388
         
371 389
         # Handle justification of prompt
372 390
         invis_chars = self.invisible_chars[name] if color else 0
  391
+        self.txtwidth = len(res) - invis_chars
373 392
         just = self.justify if (just is None) else just
374 393
         if just:
375 394
             res = res.rjust(self.width + invis_chars)
376 395
         self.width = len(res) - invis_chars
377 396
         return res
378  
-
8  IPython/frontend/terminal/ipapp.py
@@ -38,6 +38,7 @@
38 38
 from IPython.core.completer import IPCompleter
39 39
 from IPython.core.crashhandler import CrashHandler
40 40
 from IPython.core.formatters import PlainTextFormatter
  41
+from IPython.core.prompts import PromptManager
41 42
 from IPython.core.application import (
42 43
     ProfileDir, BaseIPythonApplication, base_flags, base_aliases
43 44
 )
@@ -133,9 +134,9 @@ def make_report(self,traceback):
133 134
 classic_config = Config()
134 135
 classic_config.InteractiveShell.cache_size = 0
135 136
 classic_config.PlainTextFormatter.pprint = False
136  
-classic_config.InteractiveShell.prompt_in1 = '>>> '
137  
-classic_config.InteractiveShell.prompt_in2 = '... '
138  
-classic_config.InteractiveShell.prompt_out = ''
  137
+classic_config.PromptManager.in_template = '>>> '
  138
+classic_config.PromptManager.in2_template = '... '
  139
+classic_config.PromptManager.out_template = ''
139 140
 classic_config.InteractiveShell.separate_in = ''
140 141
 classic_config.InteractiveShell.separate_out = ''
141 142
 classic_config.InteractiveShell.separate_out2 = ''
@@ -197,6 +198,7 @@ def _classes_default(self):
197 198
             InteractiveShellApp, # ShellApp comes before TerminalApp, because
198 199
             self.__class__,      # it will also affect subclasses (e.g. QtConsole)
199 200
             TerminalInteractiveShell,
  201
+            PromptManager,
200 202
             ProfileDir,
201 203
             PlainTextFormatter,
202 204
             IPCompleter,
6  IPython/testing/tools.py
@@ -202,9 +202,9 @@ def ipexec(fname, options=None):
202 202
 
203 203
     # For these subprocess calls, eliminate all prompt printing so we only see
204 204
     # output from script execution
205  
-    prompt_opts = [ '--InteractiveShell.prompt_in1=""',
206  
-                    '--InteractiveShell.prompt_in2=""',
207  
-                    '--InteractiveShell.prompt_out=""'
  205
+    prompt_opts = [ '--PromptManager.in_template=""',
  206
+                    '--PromptManager.in2_template=""',
  207
+                    '--PromptManager.out_template=""'
208 208
     ]
209 209
     cmdargs = ' '.join(default_argv() + prompt_opts + options)
210 210
 
18  docs/examples/core/example-embed.py
@@ -23,10 +23,10 @@
23 23
 except NameError:
24 24
     nested = 0
25 25
     cfg = Config()
26  
-    shell_config = cfg.InteractiveShellEmbed
27  
-    shell_config.prompt_in1 = 'In <\\#>: '
28  
-    shell_config.prompt_in2 = '   .\\D.: '
29  
-    shell_config.prompt_out = 'Out<\\#>: '
  26
+    prompt_config = cfg.PromptManager
  27
+    prompt_config.in_template = 'In <\\#>: '
  28
+    prompt_config.in2_template = '   .\\D.: '
  29
+    prompt_config.out_template = 'Out<\\#>: '
30 30
 else:
31 31
     print "Running nested copies of IPython."
32 32
     print "The prompts for the nested copy have been modified"
@@ -46,12 +46,12 @@
46 46
 
47 47
 # Make a second instance, you can have as many as you want.
48 48
 cfg2 = cfg.copy()
49  
-shell_config = cfg2.InteractiveShellEmbed
50  
-shell_config.prompt_in1 = 'In2<\\#>: '
  49
+prompt_config = cfg2.PromptManager
  50
+prompt_config.in_template = 'In2<\\#>: '
51 51
 if not nested:
52  
-    shell_config.prompt_in1 = 'In2<\\#>: '
53  
-    shell_config.prompt_in2 = '   .\\D.: '
54  
-    shell_config.prompt_out = 'Out<\\#>: '
  52
+    prompt_config.in_template = 'In2<\\#>: '
  53
+    prompt_config.in2_template = '   .\\D.: '
  54
+    prompt_config.out_template = 'Out<\\#>: '
55 55
 ipshell2 = InteractiveShellEmbed(config=cfg,
56 56
                         banner1 = 'Second IPython instance.')
57 57
 
8  docs/source/interactive/reference.txt
@@ -227,7 +227,7 @@ All options with a [no] prepended can be specified in negated form
227 227
 	circular file inclusions, IPython will stop if it reaches 15
228 228
 	recursive inclusions.
229 229
 
230  
-    ``InteractiveShell.prompt_in1=<string>``
  230
+    ``PromptManager.in_template=<string>``
231 231
 
232 232
 	Specify the string used for input prompts. Note that if you are using
233 233
 	numbered prompts, the number is represented with a '\#' in the
@@ -236,7 +236,7 @@ All options with a [no] prepended can be specified in negated form
236 236
 	discusses in detail all the available escapes to customize your
237 237
 	prompts.
238 238
 
239  
-    ``InteractiveShell.prompt_in2=<string>``
  239
+    ``PromptManager.in2_template=<string>``
240 240
 	Similar to the previous option, but used for the continuation
241 241
 	prompts. The special sequence '\D' is similar to '\#', but
242 242
 	with all digits replaced dots (so you can have your
@@ -244,9 +244,9 @@ All options with a [no] prepended can be specified in negated form
244 244
 	' .\D.:' (note three spaces at the start for alignment with
245 245
 	'In [\#]').
246 246
 
247  
-    ``InteractiveShell.prompt_out=<string>``
  247
+    ``PromptManager.out_template=<string>``
248 248
 	String used for output prompts, also uses numbers like
249  
-	prompt_in1. Default: 'Out[\#]:'
  249
+	in_template. Default: 'Out[\#]:'
250 250
 
251 251
     ``--quick``
252 252
         start in bare bones mode (no config file loaded).
5  docs/source/interactive/shell.txt
@@ -155,8 +155,9 @@ Prompt customization
155 155
 
156 156
 The sh profile uses the following prompt configurations::
157 157
 
158  
-    o.prompt_in1= r'\C_LightBlue[\C_LightCyan\Y2\C_LightBlue]\C_Green|\#>'
159  
-    o.prompt_in2= r'\C_Green|\C_LightGreen\D\C_Green>'
  158
+    c.PromptManager.in_template = r'{color.LightGreen}\u@\h{color.LightBlue}[{color.LightCyan}\Y1{color.LightBlue}]{color.Green}|\#> '
  159
+    c.PromptManager.in2_template = r'{color.Green}|{color.LightGreen}\D{color.Green}> '
  160
+    c.PromptManager.out_template = r'<\#> '
160 161
 
161 162
 You can change the prompt configuration to your liking by editing
162 163
 ipython_config.py.
Commit_comment_tip

Tip: You can add notes to lines in a file. Hover to the left of a line to make a note

Something went wrong with that request. Please try again.