Show More
@@ -5,11 +5,11 app = c.InteractiveShellApp | |||||
5 | # and merge it into the current one. |
|
5 | # and merge it into the current one. | |
6 | load_subconfig('ipython_config.py', profile='default') |
|
6 | load_subconfig('ipython_config.py', profile='default') | |
7 |
|
7 | |||
8 |
c. |
|
8 | c.PromptManager.in_template = r'{color.LightGreen}\u@\h{color.LightBlue}[{color.LightCyan}\Y1{color.LightBlue}]{color.Green}|\#> ' | |
9 | c.InteractiveShell.prompt_in2 = r'\C_Green|\C_LightGreen\D\C_Green> ' |
|
9 | c.PromptManager.in2_template = r'{color.Green}|{color.LightGreen}\D{color.Green}> ' | |
10 | c.InteractiveShell.prompt_out = r'<\#> ' |
|
10 | c.PromptManager.out_template = r'<\#> ' | |
11 |
|
11 | |||
12 | c.InteractiveShell.prompts_pad_left = True |
|
12 | c.PromptManager.justify = True | |
13 |
|
13 | |||
14 | c.InteractiveShell.separate_in = '' |
|
14 | c.InteractiveShell.separate_in = '' | |
15 | c.InteractiveShell.separate_out = '' |
|
15 | c.InteractiveShell.separate_out = '' |
@@ -25,7 +25,6 Authors: | |||||
25 | import __builtin__ |
|
25 | import __builtin__ | |
26 |
|
26 | |||
27 | from IPython.config.configurable import Configurable |
|
27 | from IPython.config.configurable import Configurable | |
28 | from IPython.core import prompts |
|
|||
29 | from IPython.utils import io |
|
28 | from IPython.utils import io | |
30 | from IPython.utils.traitlets import Instance, List |
|
29 | from IPython.utils.traitlets import Instance, List | |
31 | from IPython.utils.warn import warn |
|
30 | from IPython.utils.warn import warn | |
@@ -34,32 +33,20 from IPython.utils.warn import warn | |||||
34 | # Main displayhook class |
|
33 | # Main displayhook class | |
35 | #----------------------------------------------------------------------------- |
|
34 | #----------------------------------------------------------------------------- | |
36 |
|
35 | |||
37 | # TODO: The DisplayHook class should be split into two classes, one that |
|
36 | # TODO: Move the various attributes (cache_size, [others now moved]). Some | |
38 | # manages the prompts and their synchronization and another that just does the |
|
37 | # of these are also attributes of InteractiveShell. They should be on ONE object | |
39 | # displayhook logic and calls into the prompt manager. |
|
38 | # only and the other objects should ask that one object for their values. | |
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. |
|
|||
45 |
|
39 | |||
46 | class DisplayHook(Configurable): |
|
40 | class DisplayHook(Configurable): | |
47 | """The custom IPython displayhook to replace sys.displayhook. |
|
41 | """The custom IPython displayhook to replace sys.displayhook. | |
48 |
|
42 | |||
49 | This class does many things, but the basic idea is that it is a callable |
|
43 | This class does many things, but the basic idea is that it is a callable | |
50 | that gets called anytime user code returns a value. |
|
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 | shell = Instance('IPython.core.interactiveshell.InteractiveShellABC') |
|
47 | shell = Instance('IPython.core.interactiveshell.InteractiveShellABC') | |
57 |
|
48 | |||
58 | def __init__(self, shell=None, cache_size=1000, |
|
49 | def __init__(self, shell=None, cache_size=1000, config=None): | |
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): |
|
|||
63 | super(DisplayHook, self).__init__(shell=shell, config=config) |
|
50 | super(DisplayHook, self).__init__(shell=shell, config=config) | |
64 |
|
51 | |||
65 | cache_size_min = 3 |
|
52 | cache_size_min = 3 | |
@@ -75,36 +62,10 class DisplayHook(Configurable): | |||||
75 | self.do_full_cache = 1 |
|
62 | self.do_full_cache = 1 | |
76 |
|
63 | |||
77 | self.cache_size = cache_size |
|
64 | self.cache_size = cache_size | |
78 | self.input_sep = input_sep |
|
|||
79 |
|
65 | |||
80 | # we need a reference to the user-level namespace |
|
66 | # we need a reference to the user-level namespace | |
81 | self.shell = shell |
|
67 | self.shell = shell | |
82 |
|
68 | |||
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 |
|
|||
108 | self._,self.__,self.___ = '','','' |
|
69 | self._,self.__,self.___ = '','','' | |
109 |
|
70 | |||
110 | # these are deliberately global: |
|
71 | # these are deliberately global: | |
@@ -115,32 +76,6 class DisplayHook(Configurable): | |||||
115 | def prompt_count(self): |
|
76 | def prompt_count(self): | |
116 | return self.shell.execution_count |
|
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 | # Methods used in __call__. Override these methods to modify the behavior |
|
80 | # Methods used in __call__. Override these methods to modify the behavior | |
146 | # of the displayhook. |
|
81 | # of the displayhook. | |
@@ -180,8 +115,8 class DisplayHook(Configurable): | |||||
180 | ``io.stdout``. |
|
115 | ``io.stdout``. | |
181 | """ |
|
116 | """ | |
182 | # Use write, not print which adds an extra space. |
|
117 | # Use write, not print which adds an extra space. | |
183 |
io.stdout.write(self. |
|
118 | io.stdout.write(self.shell.separate_out) | |
184 |
outprompt = |
|
119 | outprompt = self.shell.prompt_manager.render('out') | |
185 | if self.do_full_cache: |
|
120 | if self.do_full_cache: | |
186 | io.stdout.write(outprompt) |
|
121 | io.stdout.write(outprompt) | |
187 |
|
122 | |||
@@ -235,11 +170,12 class DisplayHook(Configurable): | |||||
235 | # So that multi-line strings line up with the left column of |
|
170 | # So that multi-line strings line up with the left column of | |
236 | # the screen, instead of having the output prompt mess up |
|
171 | # the screen, instead of having the output prompt mess up | |
237 | # their first line. |
|
172 | # their first line. | |
238 |
# We use the p |
|
173 | # We use the prompt template instead of the expanded prompt | |
239 | # because the expansion may add ANSI escapes that will interfere |
|
174 | # because the expansion may add ANSI escapes that will interfere | |
240 | # with our ability to determine whether or not we should add |
|
175 | # with our ability to determine whether or not we should add | |
241 | # a newline. |
|
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 | # But avoid extraneous empty lines. |
|
179 | # But avoid extraneous empty lines. | |
244 | result_repr = '\n' + result_repr |
|
180 | result_repr = '\n' + result_repr | |
245 |
|
181 | |||
@@ -286,7 +222,7 class DisplayHook(Configurable): | |||||
286 |
|
222 | |||
287 | def finish_displayhook(self): |
|
223 | def finish_displayhook(self): | |
288 | """Finish up all displayhook activities.""" |
|
224 | """Finish up all displayhook activities.""" | |
289 |
io.stdout.write(self. |
|
225 | io.stdout.write(self.shell.separate_out2) | |
290 | io.stdout.flush() |
|
226 | io.stdout.flush() | |
291 |
|
227 | |||
292 | def __call__(self, result=None): |
|
228 | def __call__(self, result=None): |
@@ -51,7 +51,7 from IPython.core.error import TryNext | |||||
51 |
|
51 | |||
52 | __all__ = ['editor', 'fix_error_editor', 'synchronize_with_editor', |
|
52 | __all__ = ['editor', 'fix_error_editor', 'synchronize_with_editor', | |
53 | 'input_prefilter', 'shutdown_hook', 'late_startup_hook', |
|
53 | 'input_prefilter', 'shutdown_hook', 'late_startup_hook', | |
54 |
|
|
54 | 'show_in_pager','pre_prompt_hook', | |
55 | 'pre_run_code_hook', 'clipboard_get'] |
|
55 | 'pre_run_code_hook', 'clipboard_get'] | |
56 |
|
56 | |||
57 | def editor(self,filename, linenum=None): |
|
57 | def editor(self,filename, linenum=None): | |
@@ -187,13 +187,6 def late_startup_hook(self): | |||||
187 | #print "default startup hook ok" # dbg |
|
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 | def show_in_pager(self,s): |
|
190 | def show_in_pager(self,s): | |
198 | """ Run a string through pager """ |
|
191 | """ Run a string through pager """ | |
199 | # raising TryNext here will use the default paging functionality |
|
192 | # raising TryNext here will use the default paging functionality |
@@ -63,6 +63,7 from IPython.core.plugin import PluginManager | |||||
63 | from IPython.core.prefilter import PrefilterManager, ESC_MAGIC |
|
63 | from IPython.core.prefilter import PrefilterManager, ESC_MAGIC | |
64 | from IPython.core.profiledir import ProfileDir |
|
64 | from IPython.core.profiledir import ProfileDir | |
65 | from IPython.core.pylabtools import pylab_activate |
|
65 | from IPython.core.pylabtools import pylab_activate | |
|
66 | from IPython.core.prompts import PromptManager | |||
66 | from IPython.external.Itpl import ItplNS |
|
67 | from IPython.external.Itpl import ItplNS | |
67 | from IPython.utils import PyColorize |
|
68 | from IPython.utils import PyColorize | |
68 | from IPython.utils import io |
|
69 | from IPython.utils import io | |
@@ -594,10 +595,8 class InteractiveShell(SingletonConfigurable, Magic): | |||||
594 | io.stderr = io.IOStream(sys.stderr) |
|
595 | io.stderr = io.IOStream(sys.stderr) | |
595 |
|
596 | |||
596 | def init_prompts(self): |
|
597 | def init_prompts(self): | |
597 | # TODO: This is a pass for now because the prompts are managed inside |
|
598 | self.prompt_manager = PromptManager(shell=self, config=self.config) | |
598 | # the DisplayHook. Once there is a separate prompt manager, this |
|
599 | self.configurables.append(self.prompt_manager) | |
599 | # will initialize that object and all prompt related information. |
|
|||
600 | pass |
|
|||
601 |
|
600 | |||
602 | def init_display_formatter(self): |
|
601 | def init_display_formatter(self): | |
603 | self.display_formatter = DisplayFormatter(config=self.config) |
|
602 | self.display_formatter = DisplayFormatter(config=self.config) | |
@@ -613,13 +612,6 class InteractiveShell(SingletonConfigurable, Magic): | |||||
613 | config=self.config, |
|
612 | config=self.config, | |
614 | shell=self, |
|
613 | shell=self, | |
615 | cache_size=self.cache_size, |
|
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 | self.configurables.append(self.displayhook) |
|
616 | self.configurables.append(self.displayhook) | |
625 | # This is a context manager that installs/revmoes the displayhook at |
|
617 | # This is a context manager that installs/revmoes the displayhook at | |
@@ -2149,7 +2141,7 class InteractiveShell(SingletonConfigurable, Magic): | |||||
2149 | after the user's input prompt. This helps the user understand that the |
|
2141 | after the user's input prompt. This helps the user understand that the | |
2150 | input line was transformed automatically by IPython. |
|
2142 | input line was transformed automatically by IPython. | |
2151 | """ |
|
2143 | """ | |
2152 |
rw = self. |
|
2144 | rw = self.prompt_manager.render('rewrite') + cmd | |
2153 |
|
2145 | |||
2154 | try: |
|
2146 | try: | |
2155 | # plain ascii works better w/ pyreadline, on some machines, so |
|
2147 | # plain ascii works better w/ pyreadline, on some machines, so |
@@ -2554,12 +2554,12 Defaulting color scheme to 'NoColor'""" | |||||
2554 |
|
2554 | |||
2555 | # Set prompt colors |
|
2555 | # Set prompt colors | |
2556 | try: |
|
2556 | try: | |
2557 |
shell. |
|
2557 | shell.prompt_manager.color_scheme = new_scheme | |
2558 | except: |
|
2558 | except: | |
2559 | color_switch_err('prompt') |
|
2559 | color_switch_err('prompt') | |
2560 | else: |
|
2560 | else: | |
2561 | shell.colors = \ |
|
2561 | shell.colors = \ | |
2562 |
|
|
2562 | shell.prompt_manager.color_scheme_table.active_scheme_name | |
2563 | # Set exception colors |
|
2563 | # Set exception colors | |
2564 | try: |
|
2564 | try: | |
2565 | shell.InteractiveTB.set_colors(scheme = new_scheme) |
|
2565 | shell.InteractiveTB.set_colors(scheme = new_scheme) | |
@@ -3237,7 +3237,7 Defaulting color scheme to 'NoColor'""" | |||||
3237 |
|
3237 | |||
3238 | # Shorthands |
|
3238 | # Shorthands | |
3239 | shell = self.shell |
|
3239 | shell = self.shell | |
3240 |
|
|
3240 | pm = shell.prompt_manager | |
3241 | meta = shell.meta |
|
3241 | meta = shell.meta | |
3242 | disp_formatter = self.shell.display_formatter |
|
3242 | disp_formatter = self.shell.display_formatter | |
3243 | ptformatter = disp_formatter.formatters['text/plain'] |
|
3243 | ptformatter = disp_formatter.formatters['text/plain'] | |
@@ -3252,23 +3252,23 Defaulting color scheme to 'NoColor'""" | |||||
3252 | save_dstore('xmode',shell.InteractiveTB.mode) |
|
3252 | save_dstore('xmode',shell.InteractiveTB.mode) | |
3253 | save_dstore('rc_separate_out',shell.separate_out) |
|
3253 | save_dstore('rc_separate_out',shell.separate_out) | |
3254 | save_dstore('rc_separate_out2',shell.separate_out2) |
|
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 | save_dstore('rc_separate_in',shell.separate_in) |
|
3256 | save_dstore('rc_separate_in',shell.separate_in) | |
3257 | save_dstore('rc_plain_text_only',disp_formatter.plain_text_only) |
|
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 | if mode == False: |
|
3260 | if mode == False: | |
3260 | # turn on |
|
3261 | # turn on | |
3261 |
|
|
3262 | pm.in_template = '>>> ' | |
3262 |
|
|
3263 | pm.in2_template = '... ' | |
3263 |
|
|
3264 | pm.out_template = '' | |
3264 |
|
3265 | |||
3265 | # Prompt separators like plain python |
|
3266 | # Prompt separators like plain python | |
3266 | oc.input_sep = oc.prompt1.sep = '' |
|
3267 | shell.separate_in = '' | |
3267 |
|
|
3268 | shell.separate_out = '' | |
3268 |
|
|
3269 | shell.separate_out2 = '' | |
3269 |
|
3270 | |||
3270 | oc.prompt1.pad_left = oc.prompt2.pad_left = \ |
|
3271 | pm.justify = False | |
3271 | oc.prompt_out.pad_left = False |
|
|||
3272 |
|
3272 | |||
3273 | ptformatter.pprint = False |
|
3273 | ptformatter.pprint = False | |
3274 | disp_formatter.plain_text_only = True |
|
3274 | disp_formatter.plain_text_only = True | |
@@ -3276,17 +3276,14 Defaulting color scheme to 'NoColor'""" | |||||
3276 | shell.magic_xmode('Plain') |
|
3276 | shell.magic_xmode('Plain') | |
3277 | else: |
|
3277 | else: | |
3278 | # turn off |
|
3278 | # turn off | |
3279 | oc.prompt1.p_template = shell.prompt_in1 |
|
3279 | pm.in_template, pm.in2_template, pm.out_template = dstore.prompt_templates | |
3280 | oc.prompt2.p_template = shell.prompt_in2 |
|
|||
3281 | oc.prompt_out.p_template = shell.prompt_out |
|
|||
3282 |
|
3280 | |||
3283 |
|
|
3281 | shell.separate_in = dstore.rc_separate_in | |
3284 |
|
3282 | |||
3285 |
|
|
3283 | shell.separate_out = dstore.rc_separate_out | |
3286 |
|
|
3284 | shell.separate_out2 = dstore.rc_separate_out2 | |
3287 |
|
3285 | |||
3288 | oc.prompt1.pad_left = oc.prompt2.pad_left = \ |
|
3286 | pm.justify = dstore.rc_prompts_pad_left | |
3289 | oc.prompt_out.pad_left = dstore.rc_prompts_pad_left |
|
|||
3290 |
|
3287 | |||
3291 | ptformatter.pprint = dstore.rc_pprint |
|
3288 | ptformatter.pprint = dstore.rc_pprint | |
3292 | disp_formatter.plain_text_only = dstore.rc_plain_text_only |
|
3289 | disp_formatter.plain_text_only = dstore.rc_plain_text_only | |
@@ -3603,6 +3600,7 Defaulting color scheme to 'NoColor'""" | |||||
3603 | PrefilterManager |
|
3600 | PrefilterManager | |
3604 | AliasManager |
|
3601 | AliasManager | |
3605 | IPCompleter |
|
3602 | IPCompleter | |
|
3603 | PromptManager | |||
3606 | DisplayFormatter |
|
3604 | DisplayFormatter | |
3607 |
|
3605 | |||
3608 | To view what is configurable on a given class, just pass the class name:: |
|
3606 | To view what is configurable on a given class, just pass the class name:: |
@@ -5,6 +5,7 Authors: | |||||
5 |
|
5 | |||
6 | * Fernando Perez |
|
6 | * Fernando Perez | |
7 | * Brian Granger |
|
7 | * Brian Granger | |
|
8 | * Thomas Kluyver | |||
8 | """ |
|
9 | """ | |
9 |
|
10 | |||
10 | #----------------------------------------------------------------------------- |
|
11 | #----------------------------------------------------------------------------- | |
@@ -23,20 +24,23 import os | |||||
23 | import re |
|
24 | import re | |
24 | import socket |
|
25 | import socket | |
25 | import sys |
|
26 | import sys | |
|
27 | import time | |||
26 |
|
28 | |||
|
29 | from IPython.config.configurable import Configurable | |||
27 | from IPython.core import release |
|
30 | from IPython.core import release | |
28 | from IPython.external.Itpl import ItplNS |
|
|||
29 | from IPython.utils import coloransi |
|
31 | from IPython.utils import coloransi | |
|
32 | from IPython.utils.traitlets import (Unicode, Instance, Dict, Bool, Int) | |||
30 |
|
33 | |||
31 | #----------------------------------------------------------------------------- |
|
34 | #----------------------------------------------------------------------------- | |
32 | # Color schemes for prompts |
|
35 | # Color schemes for prompts | |
33 | #----------------------------------------------------------------------------- |
|
36 | #----------------------------------------------------------------------------- | |
34 |
|
37 | |||
35 | PromptColors = coloransi.ColorSchemeTable() |
|
|||
36 | InputColors = coloransi.InputTermColors # just a shorthand |
|
38 | InputColors = coloransi.InputTermColors # just a shorthand | |
37 | Colors = coloransi.TermColors # just a shorthand |
|
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 | 'NoColor', |
|
44 | 'NoColor', | |
41 | in_prompt = InputColors.NoColor, # Input prompt |
|
45 | in_prompt = InputColors.NoColor, # Input prompt | |
42 | in_number = InputColors.NoColor, # Input prompt number |
|
46 | in_number = InputColors.NoColor, # Input prompt number | |
@@ -47,10 +51,10 PromptColors.add_scheme(coloransi.ColorScheme( | |||||
47 | out_number = Colors.NoColor, # Output prompt number |
|
51 | out_number = Colors.NoColor, # Output prompt number | |
48 |
|
52 | |||
49 | normal = Colors.NoColor # color off (usu. Colors.Normal) |
|
53 | normal = Colors.NoColor # color off (usu. Colors.Normal) | |
50 |
) |
|
54 | ) | |
51 |
|
55 | |||
52 | # 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: | |
53 |
|
|
57 | PColLinux = coloransi.ColorScheme( | |
54 | 'Linux', |
|
58 | 'Linux', | |
55 | in_prompt = InputColors.Green, |
|
59 | in_prompt = InputColors.Green, | |
56 | in_number = InputColors.LightGreen, |
|
60 | in_number = InputColors.LightGreen, | |
@@ -62,25 +66,35 __PColLinux = coloransi.ColorScheme( | |||||
62 |
|
66 | |||
63 | normal = Colors.Normal |
|
67 | normal = Colors.Normal | |
64 | ) |
|
68 | ) | |
65 | # Don't forget to enter it into the table! |
|
|||
66 | PromptColors.add_scheme(__PColLinux) |
|
|||
67 |
|
69 | |||
68 | # Slightly modified Linux for light backgrounds |
|
70 | # Slightly modified Linux for light backgrounds | |
69 |
|
|
71 | PColLightBG = PColLinux.copy('LightBG') | |
70 |
|
72 | |||
71 |
|
|
73 | PColLightBG.colors.update( | |
72 | in_prompt = InputColors.Blue, |
|
74 | in_prompt = InputColors.Blue, | |
73 | in_number = InputColors.LightBlue, |
|
75 | in_number = InputColors.LightBlue, | |
74 | in_prompt2 = InputColors.Blue |
|
76 | in_prompt2 = InputColors.Blue | |
75 | ) |
|
77 | ) | |
76 | PromptColors.add_scheme(__PColLightBG) |
|
|||
77 |
|
||||
78 | del Colors,InputColors |
|
|||
79 |
|
78 | |||
80 | #----------------------------------------------------------------------------- |
|
79 | #----------------------------------------------------------------------------- | |
81 | # Utilities |
|
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 | def multiple_replace(dict, text): |
|
98 | def multiple_replace(dict, text): | |
85 | """ Replace in 'text' all occurences of any key in the given |
|
99 | """ Replace in 'text' all occurences of any key in the given | |
86 | dictionary by its corresponding value. Returns the new string.""" |
|
100 | dictionary by its corresponding value. Returns the new string.""" | |
@@ -121,51 +135,43 HOME = os.environ.get("HOME","//////:::::ZZZZZ,,,~~~") | |||||
121 | USER = os.environ.get("USER") |
|
135 | USER = os.environ.get("USER") | |
122 | HOSTNAME = socket.gethostname() |
|
136 | HOSTNAME = socket.gethostname() | |
123 | HOSTNAME_SHORT = HOSTNAME.split(".")[0] |
|
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 | # Prompt/history count |
|
141 | # Prompt/history count | |
128 |
'%n' : ' |
|
142 | '%n' : '{color.number}' '{count}' '{color.prompt}', | |
129 |
r'\#': ' |
|
143 | r'\#': '{color.number}' '{count}' '{color.prompt}', | |
130 | # Just the prompt counter number, WITHOUT any coloring wrappers, so users |
|
144 | # Just the prompt counter number, WITHOUT any coloring wrappers, so users | |
131 | # can get numbers displayed in whatever color they want. |
|
145 | # can get numbers displayed in whatever color they want. | |
132 |
r'\N': ' |
|
146 | r'\N': '{count}', | |
133 |
|
147 | |||
134 | # Prompt/history count, with the actual digits replaced by dots. Used |
|
148 | # Prompt/history count, with the actual digits replaced by dots. Used | |
135 | # mainly in continuation prompts (prompt_in2) |
|
149 | # mainly in continuation prompts (prompt_in2) | |
136 | #r'\D': '${"."*len(str(self.cache.prompt_count))}', |
|
150 | r'\D': '{dots}', | |
137 |
|
151 | |||
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))}', |
|
|||
145 |
|
||||
146 | # Current working directory |
|
|||
147 | r'\w': '${os.getcwd()}', |
|
|||
148 | # Current time |
|
152 | # Current time | |
149 |
r'\ |
|
153 | r'\T' : '{time}', | |
|
154 | # Current working directory | |||
|
155 | r'\w': '{cwd}', | |||
150 | # Basename of current working directory. |
|
156 | # Basename of current working directory. | |
151 | # (use os.sep to make this portable across OSes) |
|
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 | # 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 | |
154 | # N terms of the path, after replacing $HOME with '~' |
|
160 | # N terms of the path, after replacing $HOME with '~' | |
155 | r'\X0': '${os.getcwd().replace("%s","~")}' % HOME, |
|
161 | r'\X0': '{cwd_x[0]}', | |
156 |
r'\X1': ' |
|
162 | r'\X1': '{cwd_x[1]}', | |
157 |
r'\X2': ' |
|
163 | r'\X2': '{cwd_x[2]}', | |
158 |
r'\X3': ' |
|
164 | r'\X3': '{cwd_x[3]}', | |
159 |
r'\X4': ' |
|
165 | r'\X4': '{cwd_x[4]}', | |
160 |
r'\X5': ' |
|
166 | r'\X5': '{cwd_x[5]}', | |
161 | # 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 | |
162 | # N+1 in the list. Somewhat like %cN in tcsh. |
|
168 | # N+1 in the list. Somewhat like %cN in tcsh. | |
163 |
r'\Y0': ' |
|
169 | r'\Y0': '{cwd_y[0]}', | |
164 |
r'\Y1': ' |
|
170 | r'\Y1': '{cwd_y[1]}', | |
165 |
r'\Y2': ' |
|
171 | r'\Y2': '{cwd_y[2]}', | |
166 |
r'\Y3': ' |
|
172 | r'\Y3': '{cwd_y[3]}', | |
167 |
r'\Y4': ' |
|
173 | r'\Y4': '{cwd_y[4]}', | |
168 |
r'\Y5': ' |
|
174 | r'\Y5': '{cwd_y[5]}', | |
169 | # Hostname up to first . |
|
175 | # Hostname up to first . | |
170 | r'\h': HOSTNAME_SHORT, |
|
176 | r'\h': HOSTNAME_SHORT, | |
171 | # Full hostname |
|
177 | # Full hostname | |
@@ -184,137 +190,11 prompt_specials_color = { | |||||
184 | r'\$': ROOT_SYMBOL, |
|
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 | # More utilities |
|
194 | # More utilities | |
211 | #----------------------------------------------------------------------------- |
|
195 | #----------------------------------------------------------------------------- | |
212 |
|
196 | |||
213 | def str_safe(arg): |
|
197 | def cwd_filt(depth): | |
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 |
|
|||
232 |
|
||||
233 | #----------------------------------------------------------------------------- |
|
|||
234 | # Prompt classes |
|
|||
235 | #----------------------------------------------------------------------------- |
|
|||
236 |
|
||||
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 '' |
|
|||
296 |
|
||||
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 |
|
|||
314 |
|
||||
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 |
|
|
198 | """Return the last depth elements of the current working directory. | |
319 |
|
199 | |||
320 |
|
|
200 | $HOME is always replaced with '~'. | |
@@ -322,12 +202,9 class BasePrompt(object): | |||||
322 |
|
202 | |||
323 |
|
|
203 | cwd = os.getcwd().replace(HOME,"~") | |
324 |
|
|
204 | out = os.sep.join(cwd.split(os.sep)[-depth:]) | |
325 | if out: |
|
205 | return out or os.sep | |
326 | return out |
|
|||
327 | else: |
|
|||
328 | return os.sep |
|
|||
329 |
|
206 | |||
330 |
|
|
207 | def cwd_filt2(depth): | |
331 |
|
|
208 | """Return the last depth elements of the current working directory. | |
332 |
|
209 | |||
333 |
|
|
210 | $HOME is always replaced with '~'. | |
@@ -342,95 +219,160 class BasePrompt(object): | |||||
342 |
|
|
219 | drivepart = os.path.splitdrive(full_cwd)[0] | |
343 |
|
|
220 | out = drivepart + '/'.join(cwd[-depth:]) | |
344 |
|
221 | |||
345 | if out: |
|
222 | return out or os.sep | |
346 | return out |
|
|||
347 | else: |
|
|||
348 | return os.sep |
|
|||
349 |
|
223 | |||
350 | def __nonzero__(self): |
|
224 | #----------------------------------------------------------------------------- | |
351 | """Implement boolean behavior. |
|
225 | # Prompt classes | |
352 |
|
226 | #----------------------------------------------------------------------------- | ||
353 | Checks whether the p_str attribute is non-empty""" |
|
|||
354 |
|
||||
355 | return bool(self.p_template) |
|
|||
356 |
|
227 | |||
|
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 | } | |||
357 |
|
235 | |||
358 | class Prompt1(BasePrompt): |
|
|||
359 | """Input interactive prompt similar to Mathematica's.""" |
|
|||
360 |
|
236 | |||
361 | def __init__(self, cache, sep='\n', prompt='In [\\#]: ', pad_left=True): |
|
237 | class PromptManager(Configurable): | |
362 | BasePrompt.__init__(self, cache, sep, prompt, pad_left) |
|
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 | |||
363 |
|
308 | |||
364 | def set_colors(self): |
|
309 | def _update_prompt_trait(self, traitname, new_template): | |
365 | self.set_p_str() |
|
310 | name = traitname[:-9] # Cut off '_template' | |
366 | Colors = self.cache.color_table.active_colors # shorthand |
|
311 | self.update_prompt(name, new_template) | |
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 |
|
312 | |||
375 | def __str__(self): |
|
313 | def render(self, name, color=True, just=None, **kwargs): | |
376 | self.cache.last_prompt = str_safe(self.p_str_nocolor).split('\n')[-1] |
|
314 | """ | |
377 | return str_safe(self.p_str) |
|
315 | Render the selected prompt. | |
378 |
|
316 | |||
379 | def auto_rewrite(self): |
|
317 | Parameters | |
380 | """Return a string of the form '--->' which lines up with the previous |
|
318 | ---------- | |
381 | input string. Useful for systems which re-write the user input when |
|
319 | name : str | |
382 | handling automatically special syntaxes.""" |
|
320 | Which prompt to render. One of 'in', 'in2', 'out', 'rewrite' | |
383 |
|
321 | color : bool | ||
384 | curr = str(self.cache.last_prompt) |
|
322 | If True (default), include ANSI escape sequences for a coloured prompt. | |
385 | nrspaces = len(self.rspace.search(curr).group()) |
|
323 | just : bool | |
386 | return '%s%s>%s%s' % (self.col_p_ni,'-'*(len(curr)-nrspaces-1), |
|
324 | If True, justify the prompt to the width of the last prompt. The | |
387 | ' '*nrspaces,self.col_norm_ni) |
|
325 | default is stored in self.justify. | |
388 |
|
326 | **kwargs : | ||
389 |
|
327 | Additional arguments will be passed to the string formatting operation, | ||
390 | class PromptOut(BasePrompt): |
|
328 | so they can override the values that would otherwise fill in the | |
391 | """Output interactive prompt similar to Mathematica's.""" |
|
329 | template. | |
392 |
|
330 | |||
393 | def __init__(self, cache, sep='', prompt='Out[\\#]: ', pad_left=True): |
|
331 | Returns | |
394 | BasePrompt.__init__(self, cache, sep, prompt, pad_left) |
|
332 | ------- | |
395 | if not self.p_template: |
|
333 | A string containing the rendered prompt. | |
396 | self.__str__ = lambda: '' |
|
334 | """ | |
397 |
|
335 | if color: | ||
398 | def set_colors(self): |
|
336 | scheme = self.color_scheme_table.active_colors | |
399 | self.set_p_str() |
|
337 | if name=='out': | |
400 | Colors = self.cache.color_table.active_colors # shorthand |
|
338 | colors = color_lists['normal'] | |
401 | self.col_p = Colors.out_prompt |
|
339 | colors.number, colors.prompt, colors.normal = \ | |
402 | self.col_num = Colors.out_number |
|
340 | scheme.out_number, scheme.out_prompt, scheme.normal | |
403 | self.col_norm = Colors.normal |
|
341 | elif name=='rewrite': | |
404 |
|
342 | colors = color_lists['normal'] | ||
405 |
|
343 | # We need a non-input version of these escapes | ||
406 | class Prompt2(BasePrompt): |
|
344 | colors.number = scheme.in_number.replace("\001","").replace("\002","") | |
407 | """Interactive continuation prompt.""" |
|
345 | colors.prompt = scheme.in_prompt.replace("\001","").replace("\002","") | |
408 |
|
346 | colors.normal = scheme.normal | ||
409 | def __init__(self, cache, prompt=' .\\D.: ', pad_left=True): |
|
347 | else: | |
410 | self.cache = cache |
|
348 | colors = color_lists['inp'] | |
411 | self.p_template = prompt |
|
349 | colors.number, colors.prompt, colors.normal = \ | |
412 | self.pad_left = pad_left |
|
350 | scheme.in_number, scheme.in_prompt, scheme.in_normal | |
413 | self.set_p_str() |
|
351 | if name=='in2': | |
414 |
|
352 | colors.prompt = scheme.in_prompt2 | ||
415 | def set_p_str(self): |
|
353 | else: | |
416 | import os,time # needed in locals for prompt string handling |
|
354 | # No color | |
417 | loc = locals() |
|
355 | colors = color_lists['nocolor'] | |
418 | self.p_str = ItplNS('%s%s%s' % |
|
356 | colors.number, colors.prompt, colors.normal = '', '', '' | |
419 | ('${self.col_p2}', |
|
357 | ||
420 | multiple_replace(prompt_specials, self.p_template), |
|
358 | count = self.shell.execution_count # Shorthand | |
421 | '$self.col_norm'), |
|
359 | # Build the dictionary to be passed to string formatting | |
422 | self.cache.shell.user_ns,loc) |
|
360 | fmtargs = dict(color=colors, count=count, | |
423 | self.p_str_nocolor = ItplNS(multiple_replace(prompt_specials_nocolor, |
|
361 | dots="."*len(str(count)) ) | |
424 | self.p_template), |
|
362 | fmtargs.update(self.lazy_evaluate_fields) | |
425 | self.cache.shell.user_ns,loc) |
|
363 | fmtargs.update(kwargs) | |
426 |
|
364 | |||
427 | def set_colors(self): |
|
365 | # Prepare the prompt | |
428 | self.set_p_str() |
|
366 | prompt = colors.prompt + self.templates[name] + colors.normal | |
429 | Colors = self.cache.color_table.active_colors |
|
367 | ||
430 | self.col_p2 = Colors.in_prompt2 |
|
368 | # Fill in required fields | |
431 | self.col_norm = Colors.in_normal |
|
369 | res = prompt.format(**fmtargs) | |
432 | # FIXME (2004-06-16) HACK: prevent crashes for users who haven't |
|
370 | ||
433 | # updated their prompt_in2 definitions. Remove eventually. |
|
371 | # Handle justification of prompt | |
434 | self.col_p = Colors.out_prompt |
|
372 | invis_chars = self.invisible_chars[name] if color else 0 | |
435 | self.col_num = Colors.out_number |
|
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 class TestMagicRunPass(tt.TempFileMixin): | |||||
148 | """Test that prompts correctly generate after %run""" |
|
148 | """Test that prompts correctly generate after %run""" | |
149 | self.run_tmpfile() |
|
149 | self.run_tmpfile() | |
150 | _ip = get_ipython() |
|
150 | _ip = get_ipython() | |
151 |
p2 = |
|
151 | p2 = _ip.prompt_manager.render('in2').strip() | |
152 | nt.assert_equals(p2[:3], '...') |
|
152 | nt.assert_equals(p2[:3], '...') | |
153 |
|
153 | |||
154 | def test_run_profile( self ): |
|
154 | def test_run_profile( self ): |
@@ -356,7 +356,7 class TerminalInteractiveShell(InteractiveShell): | |||||
356 | self.hooks.pre_prompt_hook() |
|
356 | self.hooks.pre_prompt_hook() | |
357 | if more: |
|
357 | if more: | |
358 | try: |
|
358 | try: | |
359 |
prompt = self. |
|
359 | prompt = self.prompt_manager.render('in2') | |
360 | except: |
|
360 | except: | |
361 | self.showtraceback() |
|
361 | self.showtraceback() | |
362 | if self.autoindent: |
|
362 | if self.autoindent: | |
@@ -364,7 +364,7 class TerminalInteractiveShell(InteractiveShell): | |||||
364 |
|
364 | |||
365 | else: |
|
365 | else: | |
366 | try: |
|
366 | try: | |
367 |
prompt = self. |
|
367 | prompt = self.separate_in + self.prompt_manager.render('in') | |
368 | except: |
|
368 | except: | |
369 | self.showtraceback() |
|
369 | self.showtraceback() | |
370 | try: |
|
370 | try: |
@@ -15,11 +15,6 import os | |||||
15 |
|
15 | |||
16 | from IPython.utils.ipstruct import Struct |
|
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 |
|
|
18 | color_templates = ( | |
24 | # Dark colors |
|
19 | # Dark colors | |
25 | ("Black" , "0;30"), |
|
20 | ("Black" , "0;30"), | |
@@ -50,6 +45,11 def make_color_table(in_class): | |||||
50 | ("BlinkLightGray", "5;37"), |
|
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 | for name,value in color_templates: |
|
53 | for name,value in color_templates: | |
54 | setattr(in_class,name,in_class._base % value) |
|
54 | setattr(in_class,name,in_class._base % value) | |
55 |
|
55 | |||
@@ -98,6 +98,14 class InputTermColors: | |||||
98 | # Build the actual color table as a set of class attributes: |
|
98 | # Build the actual color table as a set of class attributes: | |
99 | make_color_table(InputTermColors) |
|
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 | class ColorScheme: |
|
109 | class ColorScheme: | |
102 | """Generic color scheme class. Just a name and a Struct.""" |
|
110 | """Generic color scheme class. Just a name and a Struct.""" | |
103 | def __init__(self,__scheme_name_,colordict=None,**colormap): |
|
111 | def __init__(self,__scheme_name_,colordict=None,**colormap): |
@@ -76,13 +76,15 def eval_formatter_slicing_check(f): | |||||
76 |
|
76 | |||
77 | nt.assert_raises(SyntaxError, f.format, "{n:x}", **ns) |
|
77 | nt.assert_raises(SyntaxError, f.format, "{n:x}", **ns) | |
78 |
|
78 | |||
79 |
|
||||
80 | def eval_formatter_no_slicing_check(f): |
|
79 | def eval_formatter_no_slicing_check(f): | |
81 | ns = dict(n=12, pi=math.pi, stuff='hello there', os=os) |
|
80 | ns = dict(n=12, pi=math.pi, stuff='hello there', os=os) | |
82 |
|
81 | |||
83 | s = f.format('{n:x} {pi**2:+f}', **ns) |
|
82 | s = f.format('{n:x} {pi**2:+f}', **ns) | |
84 | nt.assert_equals(s, "c +9.869604") |
|
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 | nt.assert_raises(SyntaxError, f.format, "{a[:]}") |
|
88 | nt.assert_raises(SyntaxError, f.format, "{a[:]}") | |
87 |
|
89 | |||
88 | def test_eval_formatter(): |
|
90 | def test_eval_formatter(): |
@@ -133,7 +133,7 class ZMQInteractiveShell(InteractiveShell): | |||||
133 | FIXME: this payload is currently not correctly processed by the |
|
133 | FIXME: this payload is currently not correctly processed by the | |
134 | frontend. |
|
134 | frontend. | |
135 | """ |
|
135 | """ | |
136 |
new = self. |
|
136 | new = self.prompt_manager.render('rewrite') + cmd | |
137 | payload = dict( |
|
137 | payload = dict( | |
138 | source='IPython.zmq.zmqshell.ZMQInteractiveShell.auto_rewrite_input', |
|
138 | source='IPython.zmq.zmqshell.ZMQInteractiveShell.auto_rewrite_input', | |
139 | transformed_input=new, |
|
139 | transformed_input=new, |
@@ -124,12 +124,13 attributes:: | |||||
124 | c.InteractiveShell.confirm_exit = False |
|
124 | c.InteractiveShell.confirm_exit = False | |
125 | c.InteractiveShell.deep_reload = True |
|
125 | c.InteractiveShell.deep_reload = True | |
126 | c.InteractiveShell.editor = 'nano' |
|
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 | c.InteractiveShell.xmode = 'Context' |
|
127 | c.InteractiveShell.xmode = 'Context' | |
132 |
|
128 | |||
|
129 | c.PromptManager.in_template = 'In [\#]: ' | |||
|
130 | c.PromptManager.in2_template = ' .\D.: ' | |||
|
131 | c.PromptManager.out_template = 'Out[\#]: ' | |||
|
132 | c.PromptManager.justify = True | |||
|
133 | ||||
133 | c.PrefilterManager.multi_line_specials = True |
|
134 | c.PrefilterManager.multi_line_specials = True | |
134 |
|
135 | |||
135 | c.AliasManager.user_aliases = [ |
|
136 | c.AliasManager.user_aliases = [ |
@@ -117,6 +117,15 Backwards incompatible changes | |||||
117 | traits, rather than several ip/port pair ``_addr`` traits. This better matches the |
|
117 | traits, rather than several ip/port pair ``_addr`` traits. This better matches the | |
118 | rest of the code, where the ip cannot not be set separately for each channel. |
|
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 | * The class inheritance of the Launchers in :mod:`IPython.parallel.apps.launcher` |
|
129 | * The class inheritance of the Launchers in :mod:`IPython.parallel.apps.launcher` | |
121 | used by ipcluster has changed, so that trait names are more consistent across |
|
130 | used by ipcluster has changed, so that trait names are more consistent across | |
122 | batch systems. This may require a few renames in your config files, if you |
|
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