Show More
@@ -5,11 +5,11 b' app = c.InteractiveShellApp' | |||
|
5 | 5 | # and merge it into the current one. |
|
6 | 6 | load_subconfig('ipython_config.py', profile='default') |
|
7 | 7 | |
|
8 |
c. |
|
|
9 | c.InteractiveShell.prompt_in2 = r'\C_Green|\C_LightGreen\D\C_Green> ' | |
|
10 | c.InteractiveShell.prompt_out = r'<\#> ' | |
|
8 | c.PromptManager.in_template = r'{color.LightGreen}\u@\h{color.LightBlue}[{color.LightCyan}\Y1{color.LightBlue}]{color.Green}|\#> ' | |
|
9 | c.PromptManager.in2_template = r'{color.Green}|{color.LightGreen}\D{color.Green}> ' | |
|
10 | c.PromptManager.out_template = r'<\#> ' | |
|
11 | 11 | |
|
12 | c.InteractiveShell.prompts_pad_left = True | |
|
12 | c.PromptManager.justify = True | |
|
13 | 13 | |
|
14 | 14 | c.InteractiveShell.separate_in = '' |
|
15 | 15 | c.InteractiveShell.separate_out = '' |
@@ -25,7 +25,6 b' Authors:' | |||
|
25 | 25 | import __builtin__ |
|
26 | 26 | |
|
27 | 27 | from IPython.config.configurable import Configurable |
|
28 | from IPython.core import prompts | |
|
29 | 28 | from IPython.utils import io |
|
30 | 29 | from IPython.utils.traitlets import Instance, List |
|
31 | 30 | from IPython.utils.warn import warn |
@@ -34,32 +33,20 b' from IPython.utils.warn import warn' | |||
|
34 | 33 | # Main displayhook class |
|
35 | 34 | #----------------------------------------------------------------------------- |
|
36 | 35 | |
|
37 | # TODO: The DisplayHook class should be split into two classes, one that | |
|
38 | # manages the prompts and their synchronization and another that just does the | |
|
39 | # displayhook logic and calls into the prompt manager. | |
|
40 | ||
|
41 | # TODO: Move the various attributes (cache_size, colors, input_sep, | |
|
42 | # output_sep, output_sep2, ps1, ps2, ps_out, pad_left). Some of these are also | |
|
43 | # attributes of InteractiveShell. They should be on ONE object only and the | |
|
44 | # other objects should ask that one object for their values. | |
|
36 | # TODO: Move the various attributes (cache_size, [others now moved]). Some | |
|
37 | # of these are also attributes of InteractiveShell. They should be on ONE object | |
|
38 | # only and the other objects should ask that one object for their values. | |
|
45 | 39 | |
|
46 | 40 | class DisplayHook(Configurable): |
|
47 | 41 | """The custom IPython displayhook to replace sys.displayhook. |
|
48 | 42 | |
|
49 | 43 | This class does many things, but the basic idea is that it is a callable |
|
50 | 44 | that gets called anytime user code returns a value. |
|
51 | ||
|
52 | Currently this class does more than just the displayhook logic and that | |
|
53 | extra logic should eventually be moved out of here. | |
|
54 | 45 | """ |
|
55 | 46 | |
|
56 | 47 | shell = Instance('IPython.core.interactiveshell.InteractiveShellABC') |
|
57 | 48 | |
|
58 | def __init__(self, shell=None, cache_size=1000, | |
|
59 | colors='NoColor', input_sep='\n', | |
|
60 | output_sep='\n', output_sep2='', | |
|
61 | ps1 = None, ps2 = None, ps_out = None, pad_left=True, | |
|
62 | config=None): | |
|
49 | def __init__(self, shell=None, cache_size=1000, config=None): | |
|
63 | 50 | super(DisplayHook, self).__init__(shell=shell, config=config) |
|
64 | 51 | |
|
65 | 52 | cache_size_min = 3 |
@@ -75,36 +62,10 b' class DisplayHook(Configurable):' | |||
|
75 | 62 | self.do_full_cache = 1 |
|
76 | 63 | |
|
77 | 64 | self.cache_size = cache_size |
|
78 | self.input_sep = input_sep | |
|
79 | 65 | |
|
80 | 66 | # we need a reference to the user-level namespace |
|
81 | 67 | self.shell = shell |
|
82 | ||
|
83 | # Set input prompt strings and colors | |
|
84 | if cache_size == 0: | |
|
85 | if ps1.find('%n') > -1 or ps1.find(r'\#') > -1 \ | |
|
86 | or ps1.find(r'\N') > -1: | |
|
87 | ps1 = '>>> ' | |
|
88 | if ps2.find('%n') > -1 or ps2.find(r'\#') > -1 \ | |
|
89 | or ps2.find(r'\N') > -1: | |
|
90 | ps2 = '... ' | |
|
91 | self.ps1_str = self._set_prompt_str(ps1,'In [\\#]: ','>>> ') | |
|
92 | self.ps2_str = self._set_prompt_str(ps2,' .\\D.: ','... ') | |
|
93 | self.ps_out_str = self._set_prompt_str(ps_out,'Out[\\#]: ','') | |
|
94 | ||
|
95 | self.color_table = prompts.PromptColors | |
|
96 | self.prompt1 = prompts.Prompt1(self,sep=input_sep,prompt=self.ps1_str, | |
|
97 | pad_left=pad_left) | |
|
98 | self.prompt2 = prompts.Prompt2(self,prompt=self.ps2_str,pad_left=pad_left) | |
|
99 | self.prompt_out = prompts.PromptOut(self,sep='',prompt=self.ps_out_str, | |
|
100 | pad_left=pad_left) | |
|
101 | self.set_colors(colors) | |
|
102 | ||
|
103 | # Store the last prompt string each time, we need it for aligning | |
|
104 | # continuation and auto-rewrite prompts | |
|
105 | self.last_prompt = '' | |
|
106 | self.output_sep = output_sep | |
|
107 | self.output_sep2 = output_sep2 | |
|
68 | ||
|
108 | 69 | self._,self.__,self.___ = '','','' |
|
109 | 70 | |
|
110 | 71 | # these are deliberately global: |
@@ -115,32 +76,6 b' class DisplayHook(Configurable):' | |||
|
115 | 76 | def prompt_count(self): |
|
116 | 77 | return self.shell.execution_count |
|
117 | 78 | |
|
118 | def _set_prompt_str(self,p_str,cache_def,no_cache_def): | |
|
119 | if p_str is None: | |
|
120 | if self.do_full_cache: | |
|
121 | return cache_def | |
|
122 | else: | |
|
123 | return no_cache_def | |
|
124 | else: | |
|
125 | return p_str | |
|
126 | ||
|
127 | def set_colors(self, colors): | |
|
128 | """Set the active color scheme and configure colors for the three | |
|
129 | prompt subsystems.""" | |
|
130 | ||
|
131 | # FIXME: This modifying of the global prompts.prompt_specials needs | |
|
132 | # to be fixed. We need to refactor all of the prompts stuff to use | |
|
133 | # proper configuration and traits notifications. | |
|
134 | if colors.lower()=='nocolor': | |
|
135 | prompts.prompt_specials = prompts.prompt_specials_nocolor | |
|
136 | else: | |
|
137 | prompts.prompt_specials = prompts.prompt_specials_color | |
|
138 | ||
|
139 | self.color_table.set_active_scheme(colors) | |
|
140 | self.prompt1.set_colors() | |
|
141 | self.prompt2.set_colors() | |
|
142 | self.prompt_out.set_colors() | |
|
143 | ||
|
144 | 79 | #------------------------------------------------------------------------- |
|
145 | 80 | # Methods used in __call__. Override these methods to modify the behavior |
|
146 | 81 | # of the displayhook. |
@@ -180,8 +115,8 b' class DisplayHook(Configurable):' | |||
|
180 | 115 | ``io.stdout``. |
|
181 | 116 | """ |
|
182 | 117 | # Use write, not print which adds an extra space. |
|
183 |
io.stdout.write(self. |
|
|
184 |
outprompt = |
|
|
118 | io.stdout.write(self.shell.separate_out) | |
|
119 | outprompt = self.shell.prompt_manager.render('out') | |
|
185 | 120 | if self.do_full_cache: |
|
186 | 121 | io.stdout.write(outprompt) |
|
187 | 122 | |
@@ -235,11 +170,12 b' class DisplayHook(Configurable):' | |||
|
235 | 170 | # So that multi-line strings line up with the left column of |
|
236 | 171 | # the screen, instead of having the output prompt mess up |
|
237 | 172 | # their first line. |
|
238 |
# We use the p |
|
|
173 | # We use the prompt template instead of the expanded prompt | |
|
239 | 174 | # because the expansion may add ANSI escapes that will interfere |
|
240 | 175 | # with our ability to determine whether or not we should add |
|
241 | 176 | # a newline. |
|
242 | if self.ps_out_str and not self.ps_out_str.endswith('\n'): | |
|
177 | prompt_template = self.shell.prompt_manager.out_template | |
|
178 | if prompt_template and not prompt_template.endswith('\n'): | |
|
243 | 179 | # But avoid extraneous empty lines. |
|
244 | 180 | result_repr = '\n' + result_repr |
|
245 | 181 | |
@@ -286,7 +222,7 b' class DisplayHook(Configurable):' | |||
|
286 | 222 | |
|
287 | 223 | def finish_displayhook(self): |
|
288 | 224 | """Finish up all displayhook activities.""" |
|
289 |
io.stdout.write(self. |
|
|
225 | io.stdout.write(self.shell.separate_out2) | |
|
290 | 226 | io.stdout.flush() |
|
291 | 227 | |
|
292 | 228 | def __call__(self, result=None): |
@@ -51,7 +51,7 b' from IPython.core.error import TryNext' | |||
|
51 | 51 | |
|
52 | 52 | __all__ = ['editor', 'fix_error_editor', 'synchronize_with_editor', |
|
53 | 53 | 'input_prefilter', 'shutdown_hook', 'late_startup_hook', |
|
54 |
|
|
|
54 | 'show_in_pager','pre_prompt_hook', | |
|
55 | 55 | 'pre_run_code_hook', 'clipboard_get'] |
|
56 | 56 | |
|
57 | 57 | def editor(self,filename, linenum=None): |
@@ -187,13 +187,6 b' def late_startup_hook(self):' | |||
|
187 | 187 | #print "default startup hook ok" # dbg |
|
188 | 188 | |
|
189 | 189 | |
|
190 | def generate_prompt(self, is_continuation): | |
|
191 | """ calculate and return a string with the prompt to display """ | |
|
192 | if is_continuation: | |
|
193 | return str(self.displayhook.prompt2) | |
|
194 | return str(self.displayhook.prompt1) | |
|
195 | ||
|
196 | ||
|
197 | 190 | def show_in_pager(self,s): |
|
198 | 191 | """ Run a string through pager """ |
|
199 | 192 | # raising TryNext here will use the default paging functionality |
@@ -63,6 +63,7 b' from IPython.core.plugin import PluginManager' | |||
|
63 | 63 | from IPython.core.prefilter import PrefilterManager, ESC_MAGIC |
|
64 | 64 | from IPython.core.profiledir import ProfileDir |
|
65 | 65 | from IPython.core.pylabtools import pylab_activate |
|
66 | from IPython.core.prompts import PromptManager | |
|
66 | 67 | from IPython.external.Itpl import ItplNS |
|
67 | 68 | from IPython.utils import PyColorize |
|
68 | 69 | from IPython.utils import io |
@@ -594,10 +595,8 b' class InteractiveShell(SingletonConfigurable, Magic):' | |||
|
594 | 595 | io.stderr = io.IOStream(sys.stderr) |
|
595 | 596 | |
|
596 | 597 | def init_prompts(self): |
|
597 | # TODO: This is a pass for now because the prompts are managed inside | |
|
598 | # the DisplayHook. Once there is a separate prompt manager, this | |
|
599 | # will initialize that object and all prompt related information. | |
|
600 | pass | |
|
598 | self.prompt_manager = PromptManager(shell=self, config=self.config) | |
|
599 | self.configurables.append(self.prompt_manager) | |
|
601 | 600 | |
|
602 | 601 | def init_display_formatter(self): |
|
603 | 602 | self.display_formatter = DisplayFormatter(config=self.config) |
@@ -613,13 +612,6 b' class InteractiveShell(SingletonConfigurable, Magic):' | |||
|
613 | 612 | config=self.config, |
|
614 | 613 | shell=self, |
|
615 | 614 | cache_size=self.cache_size, |
|
616 | input_sep = self.separate_in, | |
|
617 | output_sep = self.separate_out, | |
|
618 | output_sep2 = self.separate_out2, | |
|
619 | ps1 = self.prompt_in1, | |
|
620 | ps2 = self.prompt_in2, | |
|
621 | ps_out = self.prompt_out, | |
|
622 | pad_left = self.prompts_pad_left | |
|
623 | 615 | ) |
|
624 | 616 | self.configurables.append(self.displayhook) |
|
625 | 617 | # This is a context manager that installs/revmoes the displayhook at |
@@ -2149,7 +2141,7 b' class InteractiveShell(SingletonConfigurable, Magic):' | |||
|
2149 | 2141 | after the user's input prompt. This helps the user understand that the |
|
2150 | 2142 | input line was transformed automatically by IPython. |
|
2151 | 2143 | """ |
|
2152 |
rw = self. |
|
|
2144 | rw = self.prompt_manager.render('rewrite') + cmd | |
|
2153 | 2145 | |
|
2154 | 2146 | try: |
|
2155 | 2147 | # plain ascii works better w/ pyreadline, on some machines, so |
@@ -2554,12 +2554,12 b' Defaulting color scheme to \'NoColor\'"""' | |||
|
2554 | 2554 | |
|
2555 | 2555 | # Set prompt colors |
|
2556 | 2556 | try: |
|
2557 |
shell. |
|
|
2557 | shell.prompt_manager.color_scheme = new_scheme | |
|
2558 | 2558 | except: |
|
2559 | 2559 | color_switch_err('prompt') |
|
2560 | 2560 | else: |
|
2561 | 2561 | shell.colors = \ |
|
2562 |
|
|
|
2562 | shell.prompt_manager.color_scheme_table.active_scheme_name | |
|
2563 | 2563 | # Set exception colors |
|
2564 | 2564 | try: |
|
2565 | 2565 | shell.InteractiveTB.set_colors(scheme = new_scheme) |
@@ -3237,7 +3237,7 b' Defaulting color scheme to \'NoColor\'"""' | |||
|
3237 | 3237 | |
|
3238 | 3238 | # Shorthands |
|
3239 | 3239 | shell = self.shell |
|
3240 |
|
|
|
3240 | pm = shell.prompt_manager | |
|
3241 | 3241 | meta = shell.meta |
|
3242 | 3242 | disp_formatter = self.shell.display_formatter |
|
3243 | 3243 | ptformatter = disp_formatter.formatters['text/plain'] |
@@ -3252,23 +3252,23 b' Defaulting color scheme to \'NoColor\'"""' | |||
|
3252 | 3252 | save_dstore('xmode',shell.InteractiveTB.mode) |
|
3253 | 3253 | save_dstore('rc_separate_out',shell.separate_out) |
|
3254 | 3254 | save_dstore('rc_separate_out2',shell.separate_out2) |
|
3255 |
save_dstore('rc_prompts_pad_left', |
|
|
3255 | save_dstore('rc_prompts_pad_left',pm.justify) | |
|
3256 | 3256 | save_dstore('rc_separate_in',shell.separate_in) |
|
3257 | 3257 | save_dstore('rc_plain_text_only',disp_formatter.plain_text_only) |
|
3258 | save_dstore('prompt_templates',(pm.in_template, pm.in2_template, pm.out_template)) | |
|
3258 | 3259 | |
|
3259 | 3260 | if mode == False: |
|
3260 | 3261 | # turn on |
|
3261 |
|
|
|
3262 |
|
|
|
3263 |
|
|
|
3262 | pm.in_template = '>>> ' | |
|
3263 | pm.in2_template = '... ' | |
|
3264 | pm.out_template = '' | |
|
3264 | 3265 | |
|
3265 | 3266 | # Prompt separators like plain python |
|
3266 | oc.input_sep = oc.prompt1.sep = '' | |
|
3267 |
|
|
|
3268 |
|
|
|
3267 | shell.separate_in = '' | |
|
3268 | shell.separate_out = '' | |
|
3269 | shell.separate_out2 = '' | |
|
3269 | 3270 | |
|
3270 | oc.prompt1.pad_left = oc.prompt2.pad_left = \ | |
|
3271 | oc.prompt_out.pad_left = False | |
|
3271 | pm.justify = False | |
|
3272 | 3272 | |
|
3273 | 3273 | ptformatter.pprint = False |
|
3274 | 3274 | disp_formatter.plain_text_only = True |
@@ -3276,17 +3276,14 b' Defaulting color scheme to \'NoColor\'"""' | |||
|
3276 | 3276 | shell.magic_xmode('Plain') |
|
3277 | 3277 | else: |
|
3278 | 3278 | # turn off |
|
3279 | oc.prompt1.p_template = shell.prompt_in1 | |
|
3280 | oc.prompt2.p_template = shell.prompt_in2 | |
|
3281 | oc.prompt_out.p_template = shell.prompt_out | |
|
3279 | pm.in_template, pm.in2_template, pm.out_template = dstore.prompt_templates | |
|
3282 | 3280 | |
|
3283 |
|
|
|
3281 | shell.separate_in = dstore.rc_separate_in | |
|
3284 | 3282 | |
|
3285 |
|
|
|
3286 |
|
|
|
3283 | shell.separate_out = dstore.rc_separate_out | |
|
3284 | shell.separate_out2 = dstore.rc_separate_out2 | |
|
3287 | 3285 | |
|
3288 | oc.prompt1.pad_left = oc.prompt2.pad_left = \ | |
|
3289 | oc.prompt_out.pad_left = dstore.rc_prompts_pad_left | |
|
3286 | pm.justify = dstore.rc_prompts_pad_left | |
|
3290 | 3287 | |
|
3291 | 3288 | ptformatter.pprint = dstore.rc_pprint |
|
3292 | 3289 | disp_formatter.plain_text_only = dstore.rc_plain_text_only |
@@ -3603,6 +3600,7 b' Defaulting color scheme to \'NoColor\'"""' | |||
|
3603 | 3600 | PrefilterManager |
|
3604 | 3601 | AliasManager |
|
3605 | 3602 | IPCompleter |
|
3603 | PromptManager | |
|
3606 | 3604 | DisplayFormatter |
|
3607 | 3605 | |
|
3608 | 3606 | To view what is configurable on a given class, just pass the class name:: |
@@ -5,6 +5,7 b' Authors:' | |||
|
5 | 5 | |
|
6 | 6 | * Fernando Perez |
|
7 | 7 | * Brian Granger |
|
8 | * Thomas Kluyver | |
|
8 | 9 | """ |
|
9 | 10 | |
|
10 | 11 | #----------------------------------------------------------------------------- |
@@ -23,20 +24,23 b' import os' | |||
|
23 | 24 | import re |
|
24 | 25 | import socket |
|
25 | 26 | import sys |
|
27 | import time | |
|
26 | 28 | |
|
29 | from IPython.config.configurable import Configurable | |
|
27 | 30 | from IPython.core import release |
|
28 | from IPython.external.Itpl import ItplNS | |
|
29 | 31 | from IPython.utils import coloransi |
|
32 | from IPython.utils.traitlets import (Unicode, Instance, Dict, Bool, Int) | |
|
30 | 33 | |
|
31 | 34 | #----------------------------------------------------------------------------- |
|
32 | 35 | # Color schemes for prompts |
|
33 | 36 | #----------------------------------------------------------------------------- |
|
34 | 37 | |
|
35 | PromptColors = coloransi.ColorSchemeTable() | |
|
36 | 38 | InputColors = coloransi.InputTermColors # just a shorthand |
|
37 | 39 | Colors = coloransi.TermColors # just a shorthand |
|
38 | 40 | |
|
39 | PromptColors.add_scheme(coloransi.ColorScheme( | |
|
41 | color_lists = dict(normal=Colors(), inp=InputColors(), nocolor=coloransi.NoColors()) | |
|
42 | ||
|
43 | PColNoColors = coloransi.ColorScheme( | |
|
40 | 44 | 'NoColor', |
|
41 | 45 | in_prompt = InputColors.NoColor, # Input prompt |
|
42 | 46 | in_number = InputColors.NoColor, # Input prompt number |
@@ -47,10 +51,10 b' PromptColors.add_scheme(coloransi.ColorScheme(' | |||
|
47 | 51 | out_number = Colors.NoColor, # Output prompt number |
|
48 | 52 | |
|
49 | 53 | normal = Colors.NoColor # color off (usu. Colors.Normal) |
|
50 |
) |
|
|
54 | ) | |
|
51 | 55 | |
|
52 | 56 | # make some schemes as instances so we can copy them for modification easily: |
|
53 |
|
|
|
57 | PColLinux = coloransi.ColorScheme( | |
|
54 | 58 | 'Linux', |
|
55 | 59 | in_prompt = InputColors.Green, |
|
56 | 60 | in_number = InputColors.LightGreen, |
@@ -62,25 +66,35 b' __PColLinux = coloransi.ColorScheme(' | |||
|
62 | 66 | |
|
63 | 67 | normal = Colors.Normal |
|
64 | 68 | ) |
|
65 | # Don't forget to enter it into the table! | |
|
66 | PromptColors.add_scheme(__PColLinux) | |
|
67 | 69 | |
|
68 | 70 | # Slightly modified Linux for light backgrounds |
|
69 |
|
|
|
71 | PColLightBG = PColLinux.copy('LightBG') | |
|
70 | 72 | |
|
71 |
|
|
|
73 | PColLightBG.colors.update( | |
|
72 | 74 | in_prompt = InputColors.Blue, |
|
73 | 75 | in_number = InputColors.LightBlue, |
|
74 | 76 | in_prompt2 = InputColors.Blue |
|
75 | 77 | ) |
|
76 | PromptColors.add_scheme(__PColLightBG) | |
|
77 | ||
|
78 | del Colors,InputColors | |
|
79 | 78 | |
|
80 | 79 | #----------------------------------------------------------------------------- |
|
81 | 80 | # Utilities |
|
82 | 81 | #----------------------------------------------------------------------------- |
|
83 | 82 | |
|
83 | class LazyEvaluate(object): | |
|
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.""" | |
|
86 | def __init__(self, func, *args, **kwargs): | |
|
87 | self.func = func | |
|
88 | self.args = args | |
|
89 | self.kwargs = kwargs | |
|
90 | ||
|
91 | def __call__(self, **kwargs): | |
|
92 | self.kwargs.update(kwargs) | |
|
93 | return self.func(*self.args, **self.kwargs) | |
|
94 | ||
|
95 | def __str__(self): | |
|
96 | return str(self()) | |
|
97 | ||
|
84 | 98 | def multiple_replace(dict, text): |
|
85 | 99 | """ Replace in 'text' all occurences of any key in the given |
|
86 | 100 | dictionary by its corresponding value. Returns the new string.""" |
@@ -121,51 +135,43 b' HOME = os.environ.get("HOME","//////:::::ZZZZZ,,,~~~")' | |||
|
121 | 135 | USER = os.environ.get("USER") |
|
122 | 136 | HOSTNAME = socket.gethostname() |
|
123 | 137 | HOSTNAME_SHORT = HOSTNAME.split(".")[0] |
|
124 |
ROOT_SYMBOL = " |
|
|
138 | ROOT_SYMBOL = "#" if (os.name=='nt' or os.getuid()==0) else "$" | |
|
125 | 139 | |
|
126 |
prompt_ |
|
|
140 | prompt_abbreviations = { | |
|
127 | 141 | # Prompt/history count |
|
128 |
'%n' : ' |
|
|
129 |
r'\#': ' |
|
|
142 | '%n' : '{color.number}' '{count}' '{color.prompt}', | |
|
143 | r'\#': '{color.number}' '{count}' '{color.prompt}', | |
|
130 | 144 | # Just the prompt counter number, WITHOUT any coloring wrappers, so users |
|
131 | 145 | # can get numbers displayed in whatever color they want. |
|
132 |
r'\N': ' |
|
|
146 | r'\N': '{count}', | |
|
133 | 147 | |
|
134 | 148 | # Prompt/history count, with the actual digits replaced by dots. Used |
|
135 | 149 | # mainly in continuation prompts (prompt_in2) |
|
136 | #r'\D': '${"."*len(str(self.cache.prompt_count))}', | |
|
137 | ||
|
138 | # More robust form of the above expression, that uses the __builtin__ | |
|
139 | # module. Note that we can NOT use __builtins__ (note the 's'), because | |
|
140 | # that can either be a dict or a module, and can even mutate at runtime, | |
|
141 | # depending on the context (Python makes no guarantees on it). In | |
|
142 | # contrast, __builtin__ is always a module object, though it must be | |
|
143 | # explicitly imported. | |
|
144 | r'\D': '${"."*__builtin__.len(__builtin__.str(self.cache.prompt_count))}', | |
|
150 | r'\D': '{dots}', | |
|
145 | 151 | |
|
146 | # Current working directory | |
|
147 | r'\w': '${os.getcwd()}', | |
|
148 | 152 | # Current time |
|
149 |
r'\ |
|
|
153 | r'\T' : '{time}', | |
|
154 | # Current working directory | |
|
155 | r'\w': '{cwd}', | |
|
150 | 156 | # Basename of current working directory. |
|
151 | 157 | # (use os.sep to make this portable across OSes) |
|
152 | r'\W' : '${os.getcwd().split("%s")[-1]}' % os.sep, | |
|
158 | r'\W' : '{cwd_last}', | |
|
153 | 159 | # These X<N> are an extension to the normal bash prompts. They return |
|
154 | 160 | # N terms of the path, after replacing $HOME with '~' |
|
155 | r'\X0': '${os.getcwd().replace("%s","~")}' % HOME, | |
|
156 |
r'\X1': ' |
|
|
157 |
r'\X2': ' |
|
|
158 |
r'\X3': ' |
|
|
159 |
r'\X4': ' |
|
|
160 |
r'\X5': ' |
|
|
161 | r'\X0': '{cwd_x[0]}', | |
|
162 | r'\X1': '{cwd_x[1]}', | |
|
163 | r'\X2': '{cwd_x[2]}', | |
|
164 | r'\X3': '{cwd_x[3]}', | |
|
165 | r'\X4': '{cwd_x[4]}', | |
|
166 | r'\X5': '{cwd_x[5]}', | |
|
161 | 167 | # Y<N> are similar to X<N>, but they show '~' if it's the directory |
|
162 | 168 | # N+1 in the list. Somewhat like %cN in tcsh. |
|
163 |
r'\Y0': ' |
|
|
164 |
r'\Y1': ' |
|
|
165 |
r'\Y2': ' |
|
|
166 |
r'\Y3': ' |
|
|
167 |
r'\Y4': ' |
|
|
168 |
r'\Y5': ' |
|
|
169 | r'\Y0': '{cwd_y[0]}', | |
|
170 | r'\Y1': '{cwd_y[1]}', | |
|
171 | r'\Y2': '{cwd_y[2]}', | |
|
172 | r'\Y3': '{cwd_y[3]}', | |
|
173 | r'\Y4': '{cwd_y[4]}', | |
|
174 | r'\Y5': '{cwd_y[5]}', | |
|
169 | 175 | # Hostname up to first . |
|
170 | 176 | r'\h': HOSTNAME_SHORT, |
|
171 | 177 | # Full hostname |
@@ -184,253 +190,189 b' prompt_specials_color = {' | |||
|
184 | 190 | r'\$': ROOT_SYMBOL, |
|
185 | 191 | } |
|
186 | 192 | |
|
187 | # A copy of the prompt_specials dictionary but with all color escapes removed, | |
|
188 | # so we can correctly compute the prompt length for the auto_rewrite method. | |
|
189 | prompt_specials_nocolor = prompt_specials_color.copy() | |
|
190 | prompt_specials_nocolor['%n'] = '${self.cache.prompt_count}' | |
|
191 | prompt_specials_nocolor[r'\#'] = '${self.cache.prompt_count}' | |
|
192 | ||
|
193 | # Add in all the InputTermColors color escapes as valid prompt characters. | |
|
194 | # They all get added as \\C_COLORNAME, so that we don't have any conflicts | |
|
195 | # with a color name which may begin with a letter used by any other of the | |
|
196 | # allowed specials. This of course means that \\C will never be allowed for | |
|
197 | # anything else. | |
|
198 | input_colors = coloransi.InputTermColors | |
|
199 | for _color in dir(input_colors): | |
|
200 | if _color[0] != '_': | |
|
201 | c_name = r'\C_'+_color | |
|
202 | prompt_specials_color[c_name] = getattr(input_colors,_color) | |
|
203 | prompt_specials_nocolor[c_name] = '' | |
|
204 | ||
|
205 | # we default to no color for safety. Note that prompt_specials is a global | |
|
206 | # variable used by all prompt objects. | |
|
207 | prompt_specials = prompt_specials_nocolor | |
|
208 | ||
|
209 | 193 | #----------------------------------------------------------------------------- |
|
210 | 194 | # More utilities |
|
211 | 195 | #----------------------------------------------------------------------------- |
|
212 | 196 | |
|
213 | def str_safe(arg): | |
|
214 | """Convert to a string, without ever raising an exception. | |
|
215 | ||
|
216 | If str(arg) fails, <ERROR: ... > is returned, where ... is the exception | |
|
217 | error message.""" | |
|
218 | ||
|
219 | try: | |
|
220 | out = str(arg) | |
|
221 | except UnicodeError: | |
|
222 | try: | |
|
223 | out = arg.encode('utf_8','replace') | |
|
224 | except Exception,msg: | |
|
225 | # let's keep this little duplication here, so that the most common | |
|
226 | # case doesn't suffer from a double try wrapping. | |
|
227 | out = '<ERROR: %s>' % msg | |
|
228 | except Exception,msg: | |
|
229 | out = '<ERROR: %s>' % msg | |
|
230 | #raise # dbg | |
|
231 | return out | |
|
197 | def cwd_filt(depth): | |
|
198 | """Return the last depth elements of the current working directory. | |
|
232 | 199 |
|
|
233 | #----------------------------------------------------------------------------- | |
|
234 | # Prompt classes | |
|
235 | #----------------------------------------------------------------------------- | |
|
200 | $HOME is always replaced with '~'. | |
|
201 | If depth==0, the full path is returned.""" | |
|
236 | 202 | |
|
237 | class BasePrompt(object): | |
|
238 | """Interactive prompt similar to Mathematica's.""" | |
|
239 | ||
|
240 | def _get_p_template(self): | |
|
241 | return self._p_template | |
|
242 | ||
|
243 | def _set_p_template(self,val): | |
|
244 | self._p_template = val | |
|
245 | self.set_p_str() | |
|
246 | ||
|
247 | p_template = property(_get_p_template,_set_p_template, | |
|
248 | doc='Template for prompt string creation') | |
|
249 | ||
|
250 | def __init__(self, cache, sep, prompt, pad_left=False): | |
|
251 | ||
|
252 | # Hack: we access information about the primary prompt through the | |
|
253 | # cache argument. We need this, because we want the secondary prompt | |
|
254 | # to be aligned with the primary one. Color table info is also shared | |
|
255 | # by all prompt classes through the cache. Nice OO spaghetti code! | |
|
256 | self.cache = cache | |
|
257 | self.sep = sep | |
|
258 | ||
|
259 | # regexp to count the number of spaces at the end of a prompt | |
|
260 | # expression, useful for prompt auto-rewriting | |
|
261 | self.rspace = re.compile(r'(\s*)$') | |
|
262 | # Flag to left-pad prompt strings to match the length of the primary | |
|
263 | # prompt | |
|
264 | self.pad_left = pad_left | |
|
265 | ||
|
266 | # Set template to create each actual prompt (where numbers change). | |
|
267 | # Use a property | |
|
268 | self.p_template = prompt | |
|
269 | self.set_p_str() | |
|
270 | ||
|
271 | def set_p_str(self): | |
|
272 | """ Set the interpolating prompt strings. | |
|
273 | ||
|
274 | This must be called every time the color settings change, because the | |
|
275 | prompt_specials global may have changed.""" | |
|
276 | ||
|
277 | import os,time # needed in locals for prompt string handling | |
|
278 | loc = locals() | |
|
279 | try: | |
|
280 | self.p_str = ItplNS('%s%s%s' % | |
|
281 | ('${self.sep}${self.col_p}', | |
|
282 | multiple_replace(prompt_specials, self.p_template), | |
|
283 | '${self.col_norm}'),self.cache.shell.user_ns,loc) | |
|
284 | ||
|
285 | self.p_str_nocolor = ItplNS(multiple_replace(prompt_specials_nocolor, | |
|
286 | self.p_template), | |
|
287 | self.cache.shell.user_ns,loc) | |
|
288 | except: | |
|
289 | print "Illegal prompt template (check $ usage!):",self.p_template | |
|
290 | self.p_str = self.p_template | |
|
291 | self.p_str_nocolor = self.p_template | |
|
292 | ||
|
293 | def write(self, msg): | |
|
294 | sys.stdout.write(msg) | |
|
295 | return '' | |
|
203 | cwd = os.getcwd().replace(HOME,"~") | |
|
204 | out = os.sep.join(cwd.split(os.sep)[-depth:]) | |
|
205 | return out or os.sep | |
|
296 | 206 | |
|
297 | def __str__(self): | |
|
298 | """Return a string form of the prompt. | |
|
299 | ||
|
300 | This for is useful for continuation and output prompts, since it is | |
|
301 | left-padded to match lengths with the primary one (if the | |
|
302 | self.pad_left attribute is set).""" | |
|
303 | ||
|
304 | out_str = str_safe(self.p_str) | |
|
305 | if self.pad_left: | |
|
306 | # We must find the amount of padding required to match lengths, | |
|
307 | # taking the color escapes (which are invisible on-screen) into | |
|
308 | # account. | |
|
309 | esc_pad = len(out_str) - len(str_safe(self.p_str_nocolor)) | |
|
310 | format = '%%%ss' % (len(str(self.cache.last_prompt))+esc_pad) | |
|
311 | return format % out_str | |
|
312 | else: | |
|
313 | return out_str | |
|
207 | def cwd_filt2(depth): | |
|
208 | """Return the last depth elements of the current working directory. | |
|
314 | 209 |
|
|
315 | # these path filters are put in as methods so that we can control the | |
|
316 | # namespace where the prompt strings get evaluated | |
|
317 | def cwd_filt(self, depth): | |
|
318 | """Return the last depth elements of the current working directory. | |
|
210 | $HOME is always replaced with '~'. | |
|
211 | If depth==0, the full path is returned.""" | |
|
319 | 212 | |
|
320 | $HOME is always replaced with '~'. | |
|
321 | If depth==0, the full path is returned.""" | |
|
213 | full_cwd = os.getcwd() | |
|
214 | cwd = full_cwd.replace(HOME,"~").split(os.sep) | |
|
215 | if '~' in cwd and len(cwd) == depth+1: | |
|
216 | depth += 1 | |
|
217 | drivepart = '' | |
|
218 | if sys.platform == 'win32' and len(cwd) > depth: | |
|
219 | drivepart = os.path.splitdrive(full_cwd)[0] | |
|
220 | out = drivepart + '/'.join(cwd[-depth:]) | |
|
322 | 221 | |
|
323 | cwd = os.getcwd().replace(HOME,"~") | |
|
324 | out = os.sep.join(cwd.split(os.sep)[-depth:]) | |
|
325 | if out: | |
|
326 | return out | |
|
327 | else: | |
|
328 | return os.sep | |
|
222 | return out or os.sep | |
|
329 | 223 | |
|
330 | def cwd_filt2(self, depth): | |
|
331 | """Return the last depth elements of the current working directory. | |
|
332 | ||
|
333 | $HOME is always replaced with '~'. | |
|
334 | If depth==0, the full path is returned.""" | |
|
335 | ||
|
336 | full_cwd = os.getcwd() | |
|
337 | cwd = full_cwd.replace(HOME,"~").split(os.sep) | |
|
338 | if '~' in cwd and len(cwd) == depth+1: | |
|
339 | depth += 1 | |
|
340 | drivepart = '' | |
|
341 | if sys.platform == 'win32' and len(cwd) > depth: | |
|
342 | drivepart = os.path.splitdrive(full_cwd)[0] | |
|
343 | out = drivepart + '/'.join(cwd[-depth:]) | |
|
224 | #----------------------------------------------------------------------------- | |
|
225 | # Prompt classes | |
|
226 | #----------------------------------------------------------------------------- | |
|
344 | 227 | |
|
345 | if out: | |
|
346 | return out | |
|
228 | lazily_evaluate = {'time': LazyEvaluate(time.strftime, "%H:%M:%S"), | |
|
229 | 'cwd': LazyEvaluate(os.getcwd), | |
|
230 | 'cwd_last': LazyEvaluate(lambda: os.getcwd().split(os.sep)[-1]), | |
|
231 | 'cwd_x': [LazyEvaluate(lambda: os.getcwd().replace("%s","~"))] +\ | |
|
232 | [LazyEvaluate(cwd_filt, x) for x in range(1,6)], | |
|
233 | 'cwd_y': [LazyEvaluate(cwd_filt2, x) for x in range(6)] | |
|
234 | } | |
|
235 | ||
|
236 | ||
|
237 | class PromptManager(Configurable): | |
|
238 | """This is the primary interface for producing IPython's prompts.""" | |
|
239 | shell = Instance('IPython.core.interactiveshell.InteractiveShellABC') | |
|
240 | ||
|
241 | color_scheme_table = Instance(coloransi.ColorSchemeTable) | |
|
242 | color_scheme = Unicode('Linux', config=True) | |
|
243 | def _color_scheme_changed(self, name, new_value): | |
|
244 | self.color_scheme_table.set_active_scheme(new_value) | |
|
245 | for pname in ['in', 'in2', 'out', 'rewrite']: | |
|
246 | # We need to recalculate the number of invisible characters | |
|
247 | self.update_prompt(pname) | |
|
248 | ||
|
249 | lazy_evaluate_fields = Dict(help=""" | |
|
250 | 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 | |
|
252 | things like the current time in the prompts. Functions are only called | |
|
253 | if they are used in the prompt. | |
|
254 | """) | |
|
255 | def _lazy_evaluate_fields_default(self): return lazily_evaluate.copy() | |
|
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) | |
|
261 | ||
|
262 | justify = Bool(True, config=True, help=""" | |
|
263 | If True (default), each prompt will be right-aligned with the | |
|
264 | preceding one. | |
|
265 | """) | |
|
266 | ||
|
267 | # We actually store the expanded templates here: | |
|
268 | templates = Dict() | |
|
269 | ||
|
270 | # The number of characters in the last prompt rendered, not including | |
|
271 | # colour characters. | |
|
272 | width = Int() | |
|
273 | ||
|
274 | # The number of characters in each prompt which don't contribute to width | |
|
275 | invisible_chars = Dict() | |
|
276 | def _invisible_chars_default(self): | |
|
277 | return {'in': 0, 'in2': 0, 'out': 0, 'rewrite': 0} | |
|
278 | ||
|
279 | def __init__(self, shell, config=None): | |
|
280 | super(PromptManager, self).__init__(shell=shell, config=config) | |
|
281 | ||
|
282 | # Prepare colour scheme table | |
|
283 | self.color_scheme_table = coloransi.ColorSchemeTable([PColNoColors, | |
|
284 | PColLinux, PColLightBG], self.color_scheme) | |
|
285 | ||
|
286 | # Prepare templates | |
|
287 | self.update_prompt('in', self.in_template) | |
|
288 | self.update_prompt('in2', self.in2_template) | |
|
289 | self.update_prompt('out', self.out_template) | |
|
290 | self.update_prompt('rewrite', self.rewrite_template) | |
|
291 | self.on_trait_change(self._update_prompt_trait, ['in_template', | |
|
292 | 'in2_template', 'out_template', 'rewrite_template']) | |
|
293 | ||
|
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 | """ | |
|
303 | if new_template is not None: | |
|
304 | 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)) | |
|
307 | self.invisible_chars[name] = invis_chars | |
|
308 | ||
|
309 | def _update_prompt_trait(self, traitname, new_template): | |
|
310 | name = traitname[:-9] # Cut off '_template' | |
|
311 | self.update_prompt(name, new_template) | |
|
312 | ||
|
313 | def render(self, name, color=True, just=None, **kwargs): | |
|
314 | """ | |
|
315 | Render the selected prompt. | |
|
316 | ||
|
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 | if color: | |
|
336 | scheme = self.color_scheme_table.active_colors | |
|
337 | if name=='out': | |
|
338 | colors = color_lists['normal'] | |
|
339 | colors.number, colors.prompt, colors.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: | |
|
348 | colors = color_lists['inp'] | |
|
349 | colors.number, colors.prompt, colors.normal = \ | |
|
350 | scheme.in_number, scheme.in_prompt, scheme.in_normal | |
|
351 | if name=='in2': | |
|
352 | colors.prompt = scheme.in_prompt2 | |
|
347 | 353 | else: |
|
348 | return os.sep | |
|
349 | ||
|
350 | def __nonzero__(self): | |
|
351 | """Implement boolean behavior. | |
|
352 | ||
|
353 | Checks whether the p_str attribute is non-empty""" | |
|
354 | ||
|
355 | return bool(self.p_template) | |
|
356 | ||
|
357 | ||
|
358 | class Prompt1(BasePrompt): | |
|
359 | """Input interactive prompt similar to Mathematica's.""" | |
|
360 | ||
|
361 | def __init__(self, cache, sep='\n', prompt='In [\\#]: ', pad_left=True): | |
|
362 | BasePrompt.__init__(self, cache, sep, prompt, pad_left) | |
|
363 | ||
|
364 | def set_colors(self): | |
|
365 | self.set_p_str() | |
|
366 | Colors = self.cache.color_table.active_colors # shorthand | |
|
367 | self.col_p = Colors.in_prompt | |
|
368 | self.col_num = Colors.in_number | |
|
369 | self.col_norm = Colors.in_normal | |
|
370 | # We need a non-input version of these escapes for the '--->' | |
|
371 | # auto-call prompts used in the auto_rewrite() method. | |
|
372 | self.col_p_ni = self.col_p.replace('\001','').replace('\002','') | |
|
373 | self.col_norm_ni = Colors.normal | |
|
374 | ||
|
375 | def __str__(self): | |
|
376 | self.cache.last_prompt = str_safe(self.p_str_nocolor).split('\n')[-1] | |
|
377 | return str_safe(self.p_str) | |
|
378 | ||
|
379 | def auto_rewrite(self): | |
|
380 | """Return a string of the form '--->' which lines up with the previous | |
|
381 | input string. Useful for systems which re-write the user input when | |
|
382 | handling automatically special syntaxes.""" | |
|
383 | ||
|
384 | curr = str(self.cache.last_prompt) | |
|
385 | nrspaces = len(self.rspace.search(curr).group()) | |
|
386 | return '%s%s>%s%s' % (self.col_p_ni,'-'*(len(curr)-nrspaces-1), | |
|
387 | ' '*nrspaces,self.col_norm_ni) | |
|
388 | ||
|
389 | ||
|
390 | class PromptOut(BasePrompt): | |
|
391 | """Output interactive prompt similar to Mathematica's.""" | |
|
392 | ||
|
393 | def __init__(self, cache, sep='', prompt='Out[\\#]: ', pad_left=True): | |
|
394 | BasePrompt.__init__(self, cache, sep, prompt, pad_left) | |
|
395 | if not self.p_template: | |
|
396 | self.__str__ = lambda: '' | |
|
397 | ||
|
398 | def set_colors(self): | |
|
399 | self.set_p_str() | |
|
400 | Colors = self.cache.color_table.active_colors # shorthand | |
|
401 | self.col_p = Colors.out_prompt | |
|
402 | self.col_num = Colors.out_number | |
|
403 | self.col_norm = Colors.normal | |
|
404 | ||
|
405 | ||
|
406 | class Prompt2(BasePrompt): | |
|
407 | """Interactive continuation prompt.""" | |
|
408 | ||
|
409 | def __init__(self, cache, prompt=' .\\D.: ', pad_left=True): | |
|
410 | self.cache = cache | |
|
411 | self.p_template = prompt | |
|
412 | self.pad_left = pad_left | |
|
413 | self.set_p_str() | |
|
414 | ||
|
415 | def set_p_str(self): | |
|
416 | import os,time # needed in locals for prompt string handling | |
|
417 | loc = locals() | |
|
418 | self.p_str = ItplNS('%s%s%s' % | |
|
419 | ('${self.col_p2}', | |
|
420 | multiple_replace(prompt_specials, self.p_template), | |
|
421 | '$self.col_norm'), | |
|
422 | self.cache.shell.user_ns,loc) | |
|
423 | self.p_str_nocolor = ItplNS(multiple_replace(prompt_specials_nocolor, | |
|
424 | self.p_template), | |
|
425 | self.cache.shell.user_ns,loc) | |
|
426 | ||
|
427 | def set_colors(self): | |
|
428 | self.set_p_str() | |
|
429 | Colors = self.cache.color_table.active_colors | |
|
430 | self.col_p2 = Colors.in_prompt2 | |
|
431 | self.col_norm = Colors.in_normal | |
|
432 | # FIXME (2004-06-16) HACK: prevent crashes for users who haven't | |
|
433 | # updated their prompt_in2 definitions. Remove eventually. | |
|
434 | self.col_p = Colors.out_prompt | |
|
435 | self.col_num = Colors.out_number | |
|
354 | # No color | |
|
355 | colors = color_lists['nocolor'] | |
|
356 | colors.number, colors.prompt, colors.normal = '', '', '' | |
|
357 | ||
|
358 | count = self.shell.execution_count # Shorthand | |
|
359 | # Build the dictionary to be passed to string formatting | |
|
360 | fmtargs = dict(color=colors, count=count, | |
|
361 | dots="."*len(str(count)) ) | |
|
362 | fmtargs.update(self.lazy_evaluate_fields) | |
|
363 | fmtargs.update(kwargs) | |
|
364 | ||
|
365 | # Prepare the prompt | |
|
366 | prompt = colors.prompt + self.templates[name] + colors.normal | |
|
367 | ||
|
368 | # Fill in required fields | |
|
369 | res = prompt.format(**fmtargs) | |
|
370 | ||
|
371 | # Handle justification of prompt | |
|
372 | invis_chars = self.invisible_chars[name] if color else 0 | |
|
373 | just = self.justify if (just is None) else just | |
|
374 | if just: | |
|
375 | res = res.rjust(self.width + invis_chars) | |
|
376 | self.width = len(res) - invis_chars | |
|
377 | return res | |
|
436 | 378 |
@@ -148,7 +148,7 b' class TestMagicRunPass(tt.TempFileMixin):' | |||
|
148 | 148 | """Test that prompts correctly generate after %run""" |
|
149 | 149 | self.run_tmpfile() |
|
150 | 150 | _ip = get_ipython() |
|
151 |
p2 = |
|
|
151 | p2 = _ip.prompt_manager.render('in2').strip() | |
|
152 | 152 | nt.assert_equals(p2[:3], '...') |
|
153 | 153 | |
|
154 | 154 | def test_run_profile( self ): |
@@ -356,7 +356,7 b' class TerminalInteractiveShell(InteractiveShell):' | |||
|
356 | 356 | self.hooks.pre_prompt_hook() |
|
357 | 357 | if more: |
|
358 | 358 | try: |
|
359 |
prompt = self. |
|
|
359 | prompt = self.prompt_manager.render('in2') | |
|
360 | 360 | except: |
|
361 | 361 | self.showtraceback() |
|
362 | 362 | if self.autoindent: |
@@ -364,7 +364,7 b' class TerminalInteractiveShell(InteractiveShell):' | |||
|
364 | 364 | |
|
365 | 365 | else: |
|
366 | 366 | try: |
|
367 |
prompt = self. |
|
|
367 | prompt = self.separate_in + self.prompt_manager.render('in') | |
|
368 | 368 | except: |
|
369 | 369 | self.showtraceback() |
|
370 | 370 | try: |
@@ -15,12 +15,7 b' import os' | |||
|
15 | 15 | |
|
16 | 16 | from IPython.utils.ipstruct import Struct |
|
17 | 17 | |
|
18 | def make_color_table(in_class): | |
|
19 | """Build a set of color attributes in a class. | |
|
20 | ||
|
21 | Helper function for building the *TermColors classes.""" | |
|
22 | ||
|
23 | color_templates = ( | |
|
18 | color_templates = ( | |
|
24 | 19 | # Dark colors |
|
25 | 20 | ("Black" , "0;30"), |
|
26 | 21 | ("Red" , "0;31"), |
@@ -50,6 +45,11 b' def make_color_table(in_class):' | |||
|
50 | 45 | ("BlinkLightGray", "5;37"), |
|
51 | 46 | ) |
|
52 | 47 | |
|
48 | def make_color_table(in_class): | |
|
49 | """Build a set of color attributes in a class. | |
|
50 | ||
|
51 | Helper function for building the *TermColors classes.""" | |
|
52 | ||
|
53 | 53 | for name,value in color_templates: |
|
54 | 54 | setattr(in_class,name,in_class._base % value) |
|
55 | 55 | |
@@ -98,6 +98,14 b' class InputTermColors:' | |||
|
98 | 98 | # Build the actual color table as a set of class attributes: |
|
99 | 99 | make_color_table(InputTermColors) |
|
100 | 100 | |
|
101 | class NoColors: | |
|
102 | """This defines all the same names as the colour classes, but maps them to | |
|
103 | empty strings, so it can easily be substituted to turn off colours.""" | |
|
104 | NoColor = '' | |
|
105 | ||
|
106 | for name, value in color_templates: | |
|
107 | setattr(NoColors, name, '') | |
|
108 | ||
|
101 | 109 | class ColorScheme: |
|
102 | 110 | """Generic color scheme class. Just a name and a Struct.""" |
|
103 | 111 | def __init__(self,__scheme_name_,colordict=None,**colormap): |
@@ -75,7 +75,6 b' def eval_formatter_slicing_check(f):' | |||
|
75 | 75 | nt.assert_equals(s, ns['stuff'][::2]) |
|
76 | 76 | |
|
77 | 77 | nt.assert_raises(SyntaxError, f.format, "{n:x}", **ns) |
|
78 | ||
|
79 | 78 | |
|
80 | 79 | def eval_formatter_no_slicing_check(f): |
|
81 | 80 | ns = dict(n=12, pi=math.pi, stuff='hello there', os=os) |
@@ -83,6 +82,9 b' def eval_formatter_no_slicing_check(f):' | |||
|
83 | 82 | s = f.format('{n:x} {pi**2:+f}', **ns) |
|
84 | 83 | nt.assert_equals(s, "c +9.869604") |
|
85 | 84 | |
|
85 | s = f.format('{stuff[slice(1,4)]}', **ns) | |
|
86 | nt.assert_equals(s, 'ell') | |
|
87 | ||
|
86 | 88 | nt.assert_raises(SyntaxError, f.format, "{a[:]}") |
|
87 | 89 | |
|
88 | 90 | def test_eval_formatter(): |
@@ -133,7 +133,7 b' class ZMQInteractiveShell(InteractiveShell):' | |||
|
133 | 133 | FIXME: this payload is currently not correctly processed by the |
|
134 | 134 | frontend. |
|
135 | 135 | """ |
|
136 |
new = self. |
|
|
136 | new = self.prompt_manager.render('rewrite') + cmd | |
|
137 | 137 | payload = dict( |
|
138 | 138 | source='IPython.zmq.zmqshell.ZMQInteractiveShell.auto_rewrite_input', |
|
139 | 139 | transformed_input=new, |
@@ -124,11 +124,12 b' attributes::' | |||
|
124 | 124 | c.InteractiveShell.confirm_exit = False |
|
125 | 125 | c.InteractiveShell.deep_reload = True |
|
126 | 126 | c.InteractiveShell.editor = 'nano' |
|
127 | c.InteractiveShell.prompt_in1 = 'In [\#]: ' | |
|
128 | c.InteractiveShell.prompt_in2 = ' .\D.: ' | |
|
129 | c.InteractiveShell.prompt_out = 'Out[\#]: ' | |
|
130 | c.InteractiveShell.prompts_pad_left = True | |
|
131 | 127 | c.InteractiveShell.xmode = 'Context' |
|
128 | ||
|
129 | c.PromptManager.in_template = 'In [\#]: ' | |
|
130 | c.PromptManager.in2_template = ' .\D.: ' | |
|
131 | c.PromptManager.out_template = 'Out[\#]: ' | |
|
132 | c.PromptManager.justify = True | |
|
132 | 133 | |
|
133 | 134 | c.PrefilterManager.multi_line_specials = True |
|
134 | 135 |
@@ -117,6 +117,15 b' Backwards incompatible changes' | |||
|
117 | 117 | traits, rather than several ip/port pair ``_addr`` traits. This better matches the |
|
118 | 118 | rest of the code, where the ip cannot not be set separately for each channel. |
|
119 | 119 | |
|
120 | * Custom prompts are now configured using a new class, | |
|
121 | :class:`~IPython.core.prompts.PromptManager`, which has traits for :attr:`in_template`, | |
|
122 | :attr:`in2_template` (the ``...:`` continuation prompt), :attr:`out_template` | |
|
123 | and :attr:`rewrite_template`. This uses Python's string formatting system, so | |
|
124 | you can use ``{time}`` and ``{cwd}``, although we have preserved the abbreviations | |
|
125 | from previous versions, e.g. ``\#`` (prompt number) and ``\w`` (working | |
|
126 | directory). For the list of available fields, refer to the source of | |
|
127 | :file:`IPython/core/prompts.py`. | |
|
128 | ||
|
120 | 129 | * The class inheritance of the Launchers in :mod:`IPython.parallel.apps.launcher` |
|
121 | 130 | used by ipcluster has changed, so that trait names are more consistent across |
|
122 | 131 | batch systems. This may require a few renames in your config files, if you |
General Comments 0
You need to be logged in to leave comments.
Login now