##// END OF EJS Templates
Fix the rest of the colors used on Windows so they are more visible...
Segev Finer -
Show More
@@ -1,177 +1,184 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 Color schemes for exception handling code in IPython.
3 Color schemes for exception handling code in IPython.
4 """
4 """
5
5
6 import os
6 import warnings
7 import warnings
7
8
8 #*****************************************************************************
9 #*****************************************************************************
9 # Copyright (C) 2005-2006 Fernando Perez <fperez@colorado.edu>
10 # Copyright (C) 2005-2006 Fernando Perez <fperez@colorado.edu>
10 #
11 #
11 # Distributed under the terms of the BSD License. The full license is in
12 # Distributed under the terms of the BSD License. The full license is in
12 # the file COPYING, distributed as part of this software.
13 # the file COPYING, distributed as part of this software.
13 #*****************************************************************************
14 #*****************************************************************************
14
15
15 from IPython.utils.coloransi import ColorSchemeTable, TermColors, ColorScheme
16 from IPython.utils.coloransi import ColorSchemeTable, TermColors, ColorScheme
16
17
17 def exception_colors():
18 def exception_colors():
18 """Return a color table with fields for exception reporting.
19 """Return a color table with fields for exception reporting.
19
20
20 The table is an instance of ColorSchemeTable with schemes added for
21 The table is an instance of ColorSchemeTable with schemes added for
21 'Neutral', 'Linux', 'LightBG' and 'NoColor' and fields for exception handling filled
22 'Neutral', 'Linux', 'LightBG' and 'NoColor' and fields for exception handling filled
22 in.
23 in.
23
24
24 Examples:
25 Examples:
25
26
26 >>> ec = exception_colors()
27 >>> ec = exception_colors()
27 >>> ec.active_scheme_name
28 >>> ec.active_scheme_name
28 ''
29 ''
29 >>> print(ec.active_colors)
30 >>> print(ec.active_colors)
30 None
31 None
31
32
32 Now we activate a color scheme:
33 Now we activate a color scheme:
33 >>> ec.set_active_scheme('NoColor')
34 >>> ec.set_active_scheme('NoColor')
34 >>> ec.active_scheme_name
35 >>> ec.active_scheme_name
35 'NoColor'
36 'NoColor'
36 >>> sorted(ec.active_colors.keys())
37 >>> sorted(ec.active_colors.keys())
37 ['Normal', 'caret', 'em', 'excName', 'filename', 'filenameEm', 'line',
38 ['Normal', 'caret', 'em', 'excName', 'filename', 'filenameEm', 'line',
38 'lineno', 'linenoEm', 'name', 'nameEm', 'normalEm', 'topline', 'vName',
39 'lineno', 'linenoEm', 'name', 'nameEm', 'normalEm', 'topline', 'vName',
39 'val', 'valEm']
40 'val', 'valEm']
40 """
41 """
41
42
42 ex_colors = ColorSchemeTable()
43 ex_colors = ColorSchemeTable()
43
44
44 # Populate it with color schemes
45 # Populate it with color schemes
45 C = TermColors # shorthand and local lookup
46 C = TermColors # shorthand and local lookup
46 ex_colors.add_scheme(ColorScheme(
47 ex_colors.add_scheme(ColorScheme(
47 'NoColor',
48 'NoColor',
48 # The color to be used for the top line
49 # The color to be used for the top line
49 topline = C.NoColor,
50 topline = C.NoColor,
50
51
51 # The colors to be used in the traceback
52 # The colors to be used in the traceback
52 filename = C.NoColor,
53 filename = C.NoColor,
53 lineno = C.NoColor,
54 lineno = C.NoColor,
54 name = C.NoColor,
55 name = C.NoColor,
55 vName = C.NoColor,
56 vName = C.NoColor,
56 val = C.NoColor,
57 val = C.NoColor,
57 em = C.NoColor,
58 em = C.NoColor,
58
59
59 # Emphasized colors for the last frame of the traceback
60 # Emphasized colors for the last frame of the traceback
60 normalEm = C.NoColor,
61 normalEm = C.NoColor,
61 filenameEm = C.NoColor,
62 filenameEm = C.NoColor,
62 linenoEm = C.NoColor,
63 linenoEm = C.NoColor,
63 nameEm = C.NoColor,
64 nameEm = C.NoColor,
64 valEm = C.NoColor,
65 valEm = C.NoColor,
65
66
66 # Colors for printing the exception
67 # Colors for printing the exception
67 excName = C.NoColor,
68 excName = C.NoColor,
68 line = C.NoColor,
69 line = C.NoColor,
69 caret = C.NoColor,
70 caret = C.NoColor,
70 Normal = C.NoColor
71 Normal = C.NoColor
71 ))
72 ))
72
73
73 # make some schemes as instances so we can copy them for modification easily
74 # make some schemes as instances so we can copy them for modification easily
74 ex_colors.add_scheme(ColorScheme(
75 ex_colors.add_scheme(ColorScheme(
75 'Linux',
76 'Linux',
76 # The color to be used for the top line
77 # The color to be used for the top line
77 topline = C.LightRed,
78 topline = C.LightRed,
78
79
79 # The colors to be used in the traceback
80 # The colors to be used in the traceback
80 filename = C.Green,
81 filename = C.Green,
81 lineno = C.Green,
82 lineno = C.Green,
82 name = C.Purple,
83 name = C.Purple,
83 vName = C.Cyan,
84 vName = C.Cyan,
84 val = C.Green,
85 val = C.Green,
85 em = C.LightCyan,
86 em = C.LightCyan,
86
87
87 # Emphasized colors for the last frame of the traceback
88 # Emphasized colors for the last frame of the traceback
88 normalEm = C.LightCyan,
89 normalEm = C.LightCyan,
89 filenameEm = C.LightGreen,
90 filenameEm = C.LightGreen,
90 linenoEm = C.LightGreen,
91 linenoEm = C.LightGreen,
91 nameEm = C.LightPurple,
92 nameEm = C.LightPurple,
92 valEm = C.LightBlue,
93 valEm = C.LightBlue,
93
94
94 # Colors for printing the exception
95 # Colors for printing the exception
95 excName = C.LightRed,
96 excName = C.LightRed,
96 line = C.Yellow,
97 line = C.Yellow,
97 caret = C.White,
98 caret = C.White,
98 Normal = C.Normal
99 Normal = C.Normal
99 ))
100 ))
100
101
101 # For light backgrounds, swap dark/light colors
102 # For light backgrounds, swap dark/light colors
102 ex_colors.add_scheme(ColorScheme(
103 ex_colors.add_scheme(ColorScheme(
103 'LightBG',
104 'LightBG',
104 # The color to be used for the top line
105 # The color to be used for the top line
105 topline = C.Red,
106 topline = C.Red,
106
107
107 # The colors to be used in the traceback
108 # The colors to be used in the traceback
108 filename = C.LightGreen,
109 filename = C.LightGreen,
109 lineno = C.LightGreen,
110 lineno = C.LightGreen,
110 name = C.LightPurple,
111 name = C.LightPurple,
111 vName = C.Cyan,
112 vName = C.Cyan,
112 val = C.LightGreen,
113 val = C.LightGreen,
113 em = C.Cyan,
114 em = C.Cyan,
114
115
115 # Emphasized colors for the last frame of the traceback
116 # Emphasized colors for the last frame of the traceback
116 normalEm = C.Cyan,
117 normalEm = C.Cyan,
117 filenameEm = C.Green,
118 filenameEm = C.Green,
118 linenoEm = C.Green,
119 linenoEm = C.Green,
119 nameEm = C.Purple,
120 nameEm = C.Purple,
120 valEm = C.Blue,
121 valEm = C.Blue,
121
122
122 # Colors for printing the exception
123 # Colors for printing the exception
123 excName = C.Red,
124 excName = C.Red,
124 #line = C.Brown, # brown often is displayed as yellow
125 #line = C.Brown, # brown often is displayed as yellow
125 line = C.Red,
126 line = C.Red,
126 caret = C.Normal,
127 caret = C.Normal,
127 Normal = C.Normal,
128 Normal = C.Normal,
128 ))
129 ))
129
130
130 ex_colors.add_scheme(ColorScheme(
131 ex_colors.add_scheme(ColorScheme(
131 'Neutral',
132 'Neutral',
132 # The color to be used for the top line
133 # The color to be used for the top line
133 topline = C.Red,
134 topline = C.Red,
134
135
135 # The colors to be used in the traceback
136 # The colors to be used in the traceback
136 filename = C.LightGreen,
137 filename = C.LightGreen,
137 lineno = C.LightGreen,
138 lineno = C.LightGreen,
138 name = C.LightPurple,
139 name = C.LightPurple,
139 vName = C.Cyan,
140 vName = C.Cyan,
140 val = C.LightGreen,
141 val = C.LightGreen,
141 em = C.Cyan,
142 em = C.Cyan,
142
143
143 # Emphasized colors for the last frame of the traceback
144 # Emphasized colors for the last frame of the traceback
144 normalEm = C.Cyan,
145 normalEm = C.Cyan,
145 filenameEm = C.Green,
146 filenameEm = C.Green,
146 linenoEm = C.Green,
147 linenoEm = C.Green,
147 nameEm = C.Purple,
148 nameEm = C.Purple,
148 valEm = C.Blue,
149 valEm = C.Blue,
149
150
150 # Colors for printing the exception
151 # Colors for printing the exception
151 excName = C.Red,
152 excName = C.Red,
152 #line = C.Brown, # brown often is displayed as yellow
153 #line = C.Brown, # brown often is displayed as yellow
153 line = C.Red,
154 line = C.Red,
154 caret = C.Normal,
155 caret = C.Normal,
155 Normal = C.Normal,
156 Normal = C.Normal,
156 ))
157 ))
157
158
159 # Hack: the 'neutral' colours are not very visible on a dark background on
160 # Windows. Since Windows command prompts have a dark background by default, and
161 # relatively few users are likely to alter that, we will use the 'Linux' colours,
162 # designed for a dark background, as the default on Windows.
163 if os.name == "nt":
164 ex_colors.add_scheme(ex_colors['Linux'].copy('Neutral'))
158
165
159 return ex_colors
166 return ex_colors
160
167
161 class Deprec(object):
168 class Deprec(object):
162
169
163 def __init__(self, wrapped_obj):
170 def __init__(self, wrapped_obj):
164 self.wrapped=wrapped_obj
171 self.wrapped=wrapped_obj
165
172
166 def __getattr__(self, name):
173 def __getattr__(self, name):
167 val = getattr(self.wrapped, name)
174 val = getattr(self.wrapped, name)
168 warnings.warn("Using ExceptionColors global is deprecated and will be removed in IPython 6.0",
175 warnings.warn("Using ExceptionColors global is deprecated and will be removed in IPython 6.0",
169 DeprecationWarning, stacklevel=2)
176 DeprecationWarning, stacklevel=2)
170 # using getattr after warnings break ipydoctest in weird way for 3.5
177 # using getattr after warnings break ipydoctest in weird way for 3.5
171 return val
178 return val
172
179
173 # For backwards compatibility, keep around a single global object. Note that
180 # For backwards compatibility, keep around a single global object. Note that
174 # this should NOT be used, the factory function should be used instead, since
181 # this should NOT be used, the factory function should be used instead, since
175 # these objects are stateful and it's very easy to get strange bugs if any code
182 # these objects are stateful and it's very easy to get strange bugs if any code
176 # modifies the module-level object's state.
183 # modifies the module-level object's state.
177 ExceptionColors = Deprec(exception_colors())
184 ExceptionColors = Deprec(exception_colors())
@@ -1,491 +1,501 b''
1 """IPython terminal interface using prompt_toolkit"""
1 """IPython terminal interface using prompt_toolkit"""
2
2
3 import os
3 import os
4 import sys
4 import sys
5 import warnings
5 import warnings
6 from warnings import warn
6 from warnings import warn
7
7
8 from IPython.core.interactiveshell import InteractiveShell, InteractiveShellABC
8 from IPython.core.interactiveshell import InteractiveShell, InteractiveShellABC
9 from IPython.utils import io
9 from IPython.utils import io
10 from IPython.utils.py3compat import cast_unicode_py2, input
10 from IPython.utils.py3compat import cast_unicode_py2, input
11 from IPython.utils.terminal import toggle_set_term_title, set_term_title
11 from IPython.utils.terminal import toggle_set_term_title, set_term_title
12 from IPython.utils.process import abbrev_cwd
12 from IPython.utils.process import abbrev_cwd
13 from traitlets import Bool, Unicode, Dict, Integer, observe, Instance, Type, default, Enum, Union
13 from traitlets import Bool, Unicode, Dict, Integer, observe, Instance, Type, default, Enum, Union
14
14
15 from prompt_toolkit.enums import DEFAULT_BUFFER, EditingMode
15 from prompt_toolkit.enums import DEFAULT_BUFFER, EditingMode
16 from prompt_toolkit.filters import (HasFocus, Condition, IsDone)
16 from prompt_toolkit.filters import (HasFocus, Condition, IsDone)
17 from prompt_toolkit.history import InMemoryHistory
17 from prompt_toolkit.history import InMemoryHistory
18 from prompt_toolkit.shortcuts import create_prompt_application, create_eventloop, create_prompt_layout, create_output
18 from prompt_toolkit.shortcuts import create_prompt_application, create_eventloop, create_prompt_layout, create_output
19 from prompt_toolkit.interface import CommandLineInterface
19 from prompt_toolkit.interface import CommandLineInterface
20 from prompt_toolkit.key_binding.manager import KeyBindingManager
20 from prompt_toolkit.key_binding.manager import KeyBindingManager
21 from prompt_toolkit.layout.processors import ConditionalProcessor, HighlightMatchingBracketProcessor
21 from prompt_toolkit.layout.processors import ConditionalProcessor, HighlightMatchingBracketProcessor
22 from prompt_toolkit.styles import PygmentsStyle, DynamicStyle
22 from prompt_toolkit.styles import PygmentsStyle, DynamicStyle
23
23
24 from pygments.styles import get_style_by_name, get_all_styles
24 from pygments.styles import get_style_by_name, get_all_styles
25 from pygments.style import Style
25 from pygments.style import Style
26 from pygments.token import Token
26 from pygments.token import Token
27
27
28 from .debugger import TerminalPdb, Pdb
28 from .debugger import TerminalPdb, Pdb
29 from .magics import TerminalMagics
29 from .magics import TerminalMagics
30 from .pt_inputhooks import get_inputhook_name_and_func
30 from .pt_inputhooks import get_inputhook_name_and_func
31 from .prompts import Prompts, ClassicPrompts, RichPromptDisplayHook
31 from .prompts import Prompts, ClassicPrompts, RichPromptDisplayHook
32 from .ptutils import IPythonPTCompleter, IPythonPTLexer
32 from .ptutils import IPythonPTCompleter, IPythonPTLexer
33 from .shortcuts import register_ipython_shortcuts
33 from .shortcuts import register_ipython_shortcuts
34
34
35 DISPLAY_BANNER_DEPRECATED = object()
35 DISPLAY_BANNER_DEPRECATED = object()
36
36
37
37
38 from pygments.style import Style
38 from pygments.style import Style
39
39
40 class _NoStyle(Style): pass
40 class _NoStyle(Style): pass
41
41
42
42
43
43
44 _style_overrides_light_bg = {
44 _style_overrides_light_bg = {
45 Token.Prompt: '#0000ff',
45 Token.Prompt: '#0000ff',
46 Token.PromptNum: '#0000ee bold',
46 Token.PromptNum: '#0000ee bold',
47 Token.OutPrompt: '#cc0000',
47 Token.OutPrompt: '#cc0000',
48 Token.OutPromptNum: '#bb0000 bold',
48 Token.OutPromptNum: '#bb0000 bold',
49 }
49 }
50
50
51 _style_overrides_linux = {
51 _style_overrides_linux = {
52 Token.Prompt: '#00cc00',
52 Token.Prompt: '#00cc00',
53 Token.PromptNum: '#00bb00 bold',
53 Token.PromptNum: '#00bb00 bold',
54 Token.OutPrompt: '#cc0000',
54 Token.OutPrompt: '#cc0000',
55 Token.OutPromptNum: '#bb0000 bold',
55 Token.OutPromptNum: '#bb0000 bold',
56 }
56 }
57
57
58
58
59
59
60 def get_default_editor():
60 def get_default_editor():
61 try:
61 try:
62 return os.environ['EDITOR']
62 return os.environ['EDITOR']
63 except KeyError:
63 except KeyError:
64 pass
64 pass
65 except UnicodeError:
65 except UnicodeError:
66 warn("$EDITOR environment variable is not pure ASCII. Using platform "
66 warn("$EDITOR environment variable is not pure ASCII. Using platform "
67 "default editor.")
67 "default editor.")
68
68
69 if os.name == 'posix':
69 if os.name == 'posix':
70 return 'vi' # the only one guaranteed to be there!
70 return 'vi' # the only one guaranteed to be there!
71 else:
71 else:
72 return 'notepad' # same in Windows!
72 return 'notepad' # same in Windows!
73
73
74 # conservatively check for tty
74 # conservatively check for tty
75 # overridden streams can result in things like:
75 # overridden streams can result in things like:
76 # - sys.stdin = None
76 # - sys.stdin = None
77 # - no isatty method
77 # - no isatty method
78 for _name in ('stdin', 'stdout', 'stderr'):
78 for _name in ('stdin', 'stdout', 'stderr'):
79 _stream = getattr(sys, _name)
79 _stream = getattr(sys, _name)
80 if not _stream or not hasattr(_stream, 'isatty') or not _stream.isatty():
80 if not _stream or not hasattr(_stream, 'isatty') or not _stream.isatty():
81 _is_tty = False
81 _is_tty = False
82 break
82 break
83 else:
83 else:
84 _is_tty = True
84 _is_tty = True
85
85
86
86
87 _use_simple_prompt = ('IPY_TEST_SIMPLE_PROMPT' in os.environ) or (not _is_tty)
87 _use_simple_prompt = ('IPY_TEST_SIMPLE_PROMPT' in os.environ) or (not _is_tty)
88
88
89 class TerminalInteractiveShell(InteractiveShell):
89 class TerminalInteractiveShell(InteractiveShell):
90 space_for_menu = Integer(6, help='Number of line at the bottom of the screen '
90 space_for_menu = Integer(6, help='Number of line at the bottom of the screen '
91 'to reserve for the completion menu'
91 'to reserve for the completion menu'
92 ).tag(config=True)
92 ).tag(config=True)
93
93
94 def _space_for_menu_changed(self, old, new):
94 def _space_for_menu_changed(self, old, new):
95 self._update_layout()
95 self._update_layout()
96
96
97 pt_cli = None
97 pt_cli = None
98 debugger_history = None
98 debugger_history = None
99 _pt_app = None
99 _pt_app = None
100
100
101 simple_prompt = Bool(_use_simple_prompt,
101 simple_prompt = Bool(_use_simple_prompt,
102 help="""Use `raw_input` for the REPL, without completion, multiline input, and prompt colors.
102 help="""Use `raw_input` for the REPL, without completion, multiline input, and prompt colors.
103
103
104 Useful when controlling IPython as a subprocess, and piping STDIN/OUT/ERR. Known usage are:
104 Useful when controlling IPython as a subprocess, and piping STDIN/OUT/ERR. Known usage are:
105 IPython own testing machinery, and emacs inferior-shell integration through elpy.
105 IPython own testing machinery, and emacs inferior-shell integration through elpy.
106
106
107 This mode default to `True` if the `IPY_TEST_SIMPLE_PROMPT`
107 This mode default to `True` if the `IPY_TEST_SIMPLE_PROMPT`
108 environment variable is set, or the current terminal is not a tty.
108 environment variable is set, or the current terminal is not a tty.
109
109
110 """
110 """
111 ).tag(config=True)
111 ).tag(config=True)
112
112
113 @property
113 @property
114 def debugger_cls(self):
114 def debugger_cls(self):
115 return Pdb if self.simple_prompt else TerminalPdb
115 return Pdb if self.simple_prompt else TerminalPdb
116
116
117 confirm_exit = Bool(True,
117 confirm_exit = Bool(True,
118 help="""
118 help="""
119 Set to confirm when you try to exit IPython with an EOF (Control-D
119 Set to confirm when you try to exit IPython with an EOF (Control-D
120 in Unix, Control-Z/Enter in Windows). By typing 'exit' or 'quit',
120 in Unix, Control-Z/Enter in Windows). By typing 'exit' or 'quit',
121 you can force a direct exit without any confirmation.""",
121 you can force a direct exit without any confirmation.""",
122 ).tag(config=True)
122 ).tag(config=True)
123
123
124 editing_mode = Unicode('emacs',
124 editing_mode = Unicode('emacs',
125 help="Shortcut style to use at the prompt. 'vi' or 'emacs'.",
125 help="Shortcut style to use at the prompt. 'vi' or 'emacs'.",
126 ).tag(config=True)
126 ).tag(config=True)
127
127
128 mouse_support = Bool(False,
128 mouse_support = Bool(False,
129 help="Enable mouse support in the prompt"
129 help="Enable mouse support in the prompt"
130 ).tag(config=True)
130 ).tag(config=True)
131
131
132 highlighting_style = Union([Unicode('legacy'), Type(klass=Style)],
132 highlighting_style = Union([Unicode('legacy'), Type(klass=Style)],
133 help="""The name or class of a Pygments style to use for syntax
133 help="""The name or class of a Pygments style to use for syntax
134 highlighting: \n %s""" % ', '.join(get_all_styles())
134 highlighting: \n %s""" % ', '.join(get_all_styles())
135 ).tag(config=True)
135 ).tag(config=True)
136
136
137
137
138 @observe('highlighting_style')
138 @observe('highlighting_style')
139 @observe('colors')
139 @observe('colors')
140 def _highlighting_style_changed(self, change):
140 def _highlighting_style_changed(self, change):
141 self.refresh_style()
141 self.refresh_style()
142
142
143 def refresh_style(self):
143 def refresh_style(self):
144 self._style = self._make_style_from_name_or_cls(self.highlighting_style)
144 self._style = self._make_style_from_name_or_cls(self.highlighting_style)
145
145
146
146
147 highlighting_style_overrides = Dict(
147 highlighting_style_overrides = Dict(
148 help="Override highlighting format for specific tokens"
148 help="Override highlighting format for specific tokens"
149 ).tag(config=True)
149 ).tag(config=True)
150
150
151 true_color = Bool(False,
151 true_color = Bool(False,
152 help=("Use 24bit colors instead of 256 colors in prompt highlighting. "
152 help=("Use 24bit colors instead of 256 colors in prompt highlighting. "
153 "If your terminal supports true color, the following command "
153 "If your terminal supports true color, the following command "
154 "should print 'TRUECOLOR' in orange: "
154 "should print 'TRUECOLOR' in orange: "
155 "printf \"\\x1b[38;2;255;100;0mTRUECOLOR\\x1b[0m\\n\"")
155 "printf \"\\x1b[38;2;255;100;0mTRUECOLOR\\x1b[0m\\n\"")
156 ).tag(config=True)
156 ).tag(config=True)
157
157
158 editor = Unicode(get_default_editor(),
158 editor = Unicode(get_default_editor(),
159 help="Set the editor used by IPython (default to $EDITOR/vi/notepad)."
159 help="Set the editor used by IPython (default to $EDITOR/vi/notepad)."
160 ).tag(config=True)
160 ).tag(config=True)
161
161
162 prompts_class = Type(Prompts, help='Class used to generate Prompt token for prompt_toolkit').tag(config=True)
162 prompts_class = Type(Prompts, help='Class used to generate Prompt token for prompt_toolkit').tag(config=True)
163
163
164 prompts = Instance(Prompts)
164 prompts = Instance(Prompts)
165
165
166 @default('prompts')
166 @default('prompts')
167 def _prompts_default(self):
167 def _prompts_default(self):
168 return self.prompts_class(self)
168 return self.prompts_class(self)
169
169
170 @observe('prompts')
170 @observe('prompts')
171 def _(self, change):
171 def _(self, change):
172 self._update_layout()
172 self._update_layout()
173
173
174 @default('displayhook_class')
174 @default('displayhook_class')
175 def _displayhook_class_default(self):
175 def _displayhook_class_default(self):
176 return RichPromptDisplayHook
176 return RichPromptDisplayHook
177
177
178 term_title = Bool(True,
178 term_title = Bool(True,
179 help="Automatically set the terminal title"
179 help="Automatically set the terminal title"
180 ).tag(config=True)
180 ).tag(config=True)
181
181
182 display_completions = Enum(('column', 'multicolumn','readlinelike'),
182 display_completions = Enum(('column', 'multicolumn','readlinelike'),
183 help= ( "Options for displaying tab completions, 'column', 'multicolumn', and "
183 help= ( "Options for displaying tab completions, 'column', 'multicolumn', and "
184 "'readlinelike'. These options are for `prompt_toolkit`, see "
184 "'readlinelike'. These options are for `prompt_toolkit`, see "
185 "`prompt_toolkit` documentation for more information."
185 "`prompt_toolkit` documentation for more information."
186 ),
186 ),
187 default_value='multicolumn').tag(config=True)
187 default_value='multicolumn').tag(config=True)
188
188
189 highlight_matching_brackets = Bool(True,
189 highlight_matching_brackets = Bool(True,
190 help="Highlight matching brackets .",
190 help="Highlight matching brackets .",
191 ).tag(config=True)
191 ).tag(config=True)
192
192
193 @observe('term_title')
193 @observe('term_title')
194 def init_term_title(self, change=None):
194 def init_term_title(self, change=None):
195 # Enable or disable the terminal title.
195 # Enable or disable the terminal title.
196 if self.term_title:
196 if self.term_title:
197 toggle_set_term_title(True)
197 toggle_set_term_title(True)
198 set_term_title('IPython: ' + abbrev_cwd())
198 set_term_title('IPython: ' + abbrev_cwd())
199 else:
199 else:
200 toggle_set_term_title(False)
200 toggle_set_term_title(False)
201
201
202 def init_display_formatter(self):
202 def init_display_formatter(self):
203 super(TerminalInteractiveShell, self).init_display_formatter()
203 super(TerminalInteractiveShell, self).init_display_formatter()
204 # terminal only supports plain text
204 # terminal only supports plain text
205 self.display_formatter.active_types = ['text/plain']
205 self.display_formatter.active_types = ['text/plain']
206 # disable `_ipython_display_`
206 # disable `_ipython_display_`
207 self.display_formatter.ipython_display_formatter.enabled = False
207 self.display_formatter.ipython_display_formatter.enabled = False
208
208
209 def init_prompt_toolkit_cli(self):
209 def init_prompt_toolkit_cli(self):
210 if self.simple_prompt:
210 if self.simple_prompt:
211 # Fall back to plain non-interactive output for tests.
211 # Fall back to plain non-interactive output for tests.
212 # This is very limited, and only accepts a single line.
212 # This is very limited, and only accepts a single line.
213 def prompt():
213 def prompt():
214 return cast_unicode_py2(input('In [%d]: ' % self.execution_count))
214 return cast_unicode_py2(input('In [%d]: ' % self.execution_count))
215 self.prompt_for_code = prompt
215 self.prompt_for_code = prompt
216 return
216 return
217
217
218 # Set up keyboard shortcuts
218 # Set up keyboard shortcuts
219 kbmanager = KeyBindingManager.for_prompt()
219 kbmanager = KeyBindingManager.for_prompt()
220 register_ipython_shortcuts(kbmanager.registry, self)
220 register_ipython_shortcuts(kbmanager.registry, self)
221
221
222 # Pre-populate history from IPython's history database
222 # Pre-populate history from IPython's history database
223 history = InMemoryHistory()
223 history = InMemoryHistory()
224 last_cell = u""
224 last_cell = u""
225 for __, ___, cell in self.history_manager.get_tail(self.history_load_length,
225 for __, ___, cell in self.history_manager.get_tail(self.history_load_length,
226 include_latest=True):
226 include_latest=True):
227 # Ignore blank lines and consecutive duplicates
227 # Ignore blank lines and consecutive duplicates
228 cell = cell.rstrip()
228 cell = cell.rstrip()
229 if cell and (cell != last_cell):
229 if cell and (cell != last_cell):
230 history.append(cell)
230 history.append(cell)
231 last_cell = cell
231 last_cell = cell
232
232
233 self._style = self._make_style_from_name_or_cls(self.highlighting_style)
233 self._style = self._make_style_from_name_or_cls(self.highlighting_style)
234 style = DynamicStyle(lambda: self._style)
234 style = DynamicStyle(lambda: self._style)
235
235
236 editing_mode = getattr(EditingMode, self.editing_mode.upper())
236 editing_mode = getattr(EditingMode, self.editing_mode.upper())
237
237
238 def patch_stdout(**kwargs):
238 def patch_stdout(**kwargs):
239 return self.pt_cli.patch_stdout_context(**kwargs)
239 return self.pt_cli.patch_stdout_context(**kwargs)
240
240
241 self._pt_app = create_prompt_application(
241 self._pt_app = create_prompt_application(
242 editing_mode=editing_mode,
242 editing_mode=editing_mode,
243 key_bindings_registry=kbmanager.registry,
243 key_bindings_registry=kbmanager.registry,
244 history=history,
244 history=history,
245 completer=IPythonPTCompleter(shell=self,
245 completer=IPythonPTCompleter(shell=self,
246 patch_stdout=patch_stdout),
246 patch_stdout=patch_stdout),
247 enable_history_search=True,
247 enable_history_search=True,
248 style=style,
248 style=style,
249 mouse_support=self.mouse_support,
249 mouse_support=self.mouse_support,
250 **self._layout_options()
250 **self._layout_options()
251 )
251 )
252 self._eventloop = create_eventloop(self.inputhook)
252 self._eventloop = create_eventloop(self.inputhook)
253 self.pt_cli = CommandLineInterface(
253 self.pt_cli = CommandLineInterface(
254 self._pt_app, eventloop=self._eventloop,
254 self._pt_app, eventloop=self._eventloop,
255 output=create_output(true_color=self.true_color))
255 output=create_output(true_color=self.true_color))
256
256
257 def _make_style_from_name_or_cls(self, name_or_cls):
257 def _make_style_from_name_or_cls(self, name_or_cls):
258 """
258 """
259 Small wrapper that make an IPython compatible style from a style name
259 Small wrapper that make an IPython compatible style from a style name
260
260
261 We need that to add style for prompt ... etc.
261 We need that to add style for prompt ... etc.
262 """
262 """
263 style_overrides = {}
263 style_overrides = {}
264 if name_or_cls == 'legacy':
264 if name_or_cls == 'legacy':
265 legacy = self.colors.lower()
265 legacy = self.colors.lower()
266 if legacy == 'linux':
266 if legacy == 'linux':
267 style_cls = get_style_by_name('monokai')
267 style_cls = get_style_by_name('monokai')
268 style_overrides = _style_overrides_linux
268 style_overrides = _style_overrides_linux
269 elif legacy == 'lightbg':
269 elif legacy == 'lightbg':
270 style_overrides = _style_overrides_light_bg
270 style_overrides = _style_overrides_light_bg
271 style_cls = get_style_by_name('pastie')
271 style_cls = get_style_by_name('pastie')
272 elif legacy == 'neutral':
272 elif legacy == 'neutral':
273 # The default theme needs to be visible on both a dark background
273 # The default theme needs to be visible on both a dark background
274 # and a light background, because we can't tell what the terminal
274 # and a light background, because we can't tell what the terminal
275 # looks like. These tweaks to the default theme help with that.
275 # looks like. These tweaks to the default theme help with that.
276 style_cls = get_style_by_name('default')
276 style_cls = get_style_by_name('default')
277 style_overrides.update({
277 style_overrides.update({
278 Token.Number: '#007700',
278 Token.Number: '#007700',
279 Token.Operator: 'noinherit',
279 Token.Operator: 'noinherit',
280 Token.String: '#BB6622',
280 Token.String: '#BB6622',
281 Token.Name.Function: '#2080D0',
281 Token.Name.Function: '#2080D0',
282 Token.Name.Class: 'bold #2080D0',
282 Token.Name.Class: 'bold #2080D0',
283 Token.Name.Namespace: 'bold #2080D0',
283 Token.Name.Namespace: 'bold #2080D0',
284 Token.Prompt: '#009900',
284 Token.Prompt: '#009900',
285 Token.PromptNum: '#00ff00 bold',
285 Token.PromptNum: '#00ff00 bold',
286 Token.OutPrompt: '#990000',
286 Token.OutPrompt: '#990000',
287 Token.OutPromptNum: '#ff0000 bold',
287 Token.OutPromptNum: '#ff0000 bold',
288 })
288 })
289
290 # Hack: Due to limited color support on the Windows console
291 # the prompt colors will be wrong without this
292 if os.name == 'nt':
293 style_overrides.update({
294 Token.Prompt: '#ansidarkgreen',
295 Token.PromptNum: '#ansigreen bold',
296 Token.OutPrompt: '#ansidarkred',
297 Token.OutPromptNum: '#ansired bold',
298 })
289 elif legacy =='nocolor':
299 elif legacy =='nocolor':
290 style_cls=_NoStyle
300 style_cls=_NoStyle
291 style_overrides = {}
301 style_overrides = {}
292 else :
302 else :
293 raise ValueError('Got unknown colors: ', legacy)
303 raise ValueError('Got unknown colors: ', legacy)
294 else :
304 else :
295 if isinstance(name_or_cls, str):
305 if isinstance(name_or_cls, str):
296 style_cls = get_style_by_name(name_or_cls)
306 style_cls = get_style_by_name(name_or_cls)
297 else:
307 else:
298 style_cls = name_or_cls
308 style_cls = name_or_cls
299 style_overrides = {
309 style_overrides = {
300 Token.Prompt: '#009900',
310 Token.Prompt: '#009900',
301 Token.PromptNum: '#00ff00 bold',
311 Token.PromptNum: '#00ff00 bold',
302 Token.OutPrompt: '#990000',
312 Token.OutPrompt: '#990000',
303 Token.OutPromptNum: '#ff0000 bold',
313 Token.OutPromptNum: '#ff0000 bold',
304 }
314 }
305 style_overrides.update(self.highlighting_style_overrides)
315 style_overrides.update(self.highlighting_style_overrides)
306 style = PygmentsStyle.from_defaults(pygments_style_cls=style_cls,
316 style = PygmentsStyle.from_defaults(pygments_style_cls=style_cls,
307 style_dict=style_overrides)
317 style_dict=style_overrides)
308
318
309 return style
319 return style
310
320
311 def _layout_options(self):
321 def _layout_options(self):
312 """
322 """
313 Return the current layout option for the current Terminal InteractiveShell
323 Return the current layout option for the current Terminal InteractiveShell
314 """
324 """
315 return {
325 return {
316 'lexer':IPythonPTLexer(),
326 'lexer':IPythonPTLexer(),
317 'reserve_space_for_menu':self.space_for_menu,
327 'reserve_space_for_menu':self.space_for_menu,
318 'get_prompt_tokens':self.prompts.in_prompt_tokens,
328 'get_prompt_tokens':self.prompts.in_prompt_tokens,
319 'get_continuation_tokens':self.prompts.continuation_prompt_tokens,
329 'get_continuation_tokens':self.prompts.continuation_prompt_tokens,
320 'multiline':True,
330 'multiline':True,
321 'display_completions_in_columns': (self.display_completions == 'multicolumn'),
331 'display_completions_in_columns': (self.display_completions == 'multicolumn'),
322
332
323 # Highlight matching brackets, but only when this setting is
333 # Highlight matching brackets, but only when this setting is
324 # enabled, and only when the DEFAULT_BUFFER has the focus.
334 # enabled, and only when the DEFAULT_BUFFER has the focus.
325 'extra_input_processors': [ConditionalProcessor(
335 'extra_input_processors': [ConditionalProcessor(
326 processor=HighlightMatchingBracketProcessor(chars='[](){}'),
336 processor=HighlightMatchingBracketProcessor(chars='[](){}'),
327 filter=HasFocus(DEFAULT_BUFFER) & ~IsDone() &
337 filter=HasFocus(DEFAULT_BUFFER) & ~IsDone() &
328 Condition(lambda cli: self.highlight_matching_brackets))],
338 Condition(lambda cli: self.highlight_matching_brackets))],
329 }
339 }
330
340
331 def _update_layout(self):
341 def _update_layout(self):
332 """
342 """
333 Ask for a re computation of the application layout, if for example ,
343 Ask for a re computation of the application layout, if for example ,
334 some configuration options have changed.
344 some configuration options have changed.
335 """
345 """
336 if self._pt_app:
346 if self._pt_app:
337 self._pt_app.layout = create_prompt_layout(**self._layout_options())
347 self._pt_app.layout = create_prompt_layout(**self._layout_options())
338
348
339 def prompt_for_code(self):
349 def prompt_for_code(self):
340 document = self.pt_cli.run(
350 document = self.pt_cli.run(
341 pre_run=self.pre_prompt, reset_current_buffer=True)
351 pre_run=self.pre_prompt, reset_current_buffer=True)
342 return document.text
352 return document.text
343
353
344 def enable_win_unicode_console(self):
354 def enable_win_unicode_console(self):
345 if sys.version_info >= (3, 6):
355 if sys.version_info >= (3, 6):
346 # Since PEP 528, Python uses the unicode APIs for the Windows
356 # Since PEP 528, Python uses the unicode APIs for the Windows
347 # console by default, so WUC shouldn't be needed.
357 # console by default, so WUC shouldn't be needed.
348 return
358 return
349
359
350 import win_unicode_console
360 import win_unicode_console
351 win_unicode_console.enable()
361 win_unicode_console.enable()
352
362
353 def init_io(self):
363 def init_io(self):
354 if sys.platform not in {'win32', 'cli'}:
364 if sys.platform not in {'win32', 'cli'}:
355 return
365 return
356
366
357 self.enable_win_unicode_console()
367 self.enable_win_unicode_console()
358
368
359 import colorama
369 import colorama
360 colorama.init()
370 colorama.init()
361
371
362 # For some reason we make these wrappers around stdout/stderr.
372 # For some reason we make these wrappers around stdout/stderr.
363 # For now, we need to reset them so all output gets coloured.
373 # For now, we need to reset them so all output gets coloured.
364 # https://github.com/ipython/ipython/issues/8669
374 # https://github.com/ipython/ipython/issues/8669
365 # io.std* are deprecated, but don't show our own deprecation warnings
375 # io.std* are deprecated, but don't show our own deprecation warnings
366 # during initialization of the deprecated API.
376 # during initialization of the deprecated API.
367 with warnings.catch_warnings():
377 with warnings.catch_warnings():
368 warnings.simplefilter('ignore', DeprecationWarning)
378 warnings.simplefilter('ignore', DeprecationWarning)
369 io.stdout = io.IOStream(sys.stdout)
379 io.stdout = io.IOStream(sys.stdout)
370 io.stderr = io.IOStream(sys.stderr)
380 io.stderr = io.IOStream(sys.stderr)
371
381
372 def init_magics(self):
382 def init_magics(self):
373 super(TerminalInteractiveShell, self).init_magics()
383 super(TerminalInteractiveShell, self).init_magics()
374 self.register_magics(TerminalMagics)
384 self.register_magics(TerminalMagics)
375
385
376 def init_alias(self):
386 def init_alias(self):
377 # The parent class defines aliases that can be safely used with any
387 # The parent class defines aliases that can be safely used with any
378 # frontend.
388 # frontend.
379 super(TerminalInteractiveShell, self).init_alias()
389 super(TerminalInteractiveShell, self).init_alias()
380
390
381 # Now define aliases that only make sense on the terminal, because they
391 # Now define aliases that only make sense on the terminal, because they
382 # need direct access to the console in a way that we can't emulate in
392 # need direct access to the console in a way that we can't emulate in
383 # GUI or web frontend
393 # GUI or web frontend
384 if os.name == 'posix':
394 if os.name == 'posix':
385 for cmd in ['clear', 'more', 'less', 'man']:
395 for cmd in ['clear', 'more', 'less', 'man']:
386 self.alias_manager.soft_define_alias(cmd, cmd)
396 self.alias_manager.soft_define_alias(cmd, cmd)
387
397
388
398
389 def __init__(self, *args, **kwargs):
399 def __init__(self, *args, **kwargs):
390 super(TerminalInteractiveShell, self).__init__(*args, **kwargs)
400 super(TerminalInteractiveShell, self).__init__(*args, **kwargs)
391 self.init_prompt_toolkit_cli()
401 self.init_prompt_toolkit_cli()
392 self.init_term_title()
402 self.init_term_title()
393 self.keep_running = True
403 self.keep_running = True
394
404
395 self.debugger_history = InMemoryHistory()
405 self.debugger_history = InMemoryHistory()
396
406
397 def ask_exit(self):
407 def ask_exit(self):
398 self.keep_running = False
408 self.keep_running = False
399
409
400 rl_next_input = None
410 rl_next_input = None
401
411
402 def pre_prompt(self):
412 def pre_prompt(self):
403 if self.rl_next_input:
413 if self.rl_next_input:
404 self.pt_cli.application.buffer.text = cast_unicode_py2(self.rl_next_input)
414 self.pt_cli.application.buffer.text = cast_unicode_py2(self.rl_next_input)
405 self.rl_next_input = None
415 self.rl_next_input = None
406
416
407 def interact(self, display_banner=DISPLAY_BANNER_DEPRECATED):
417 def interact(self, display_banner=DISPLAY_BANNER_DEPRECATED):
408
418
409 if display_banner is not DISPLAY_BANNER_DEPRECATED:
419 if display_banner is not DISPLAY_BANNER_DEPRECATED:
410 warn('interact `display_banner` argument is deprecated since IPython 5.0. Call `show_banner()` if needed.', DeprecationWarning, stacklevel=2)
420 warn('interact `display_banner` argument is deprecated since IPython 5.0. Call `show_banner()` if needed.', DeprecationWarning, stacklevel=2)
411
421
412 self.keep_running = True
422 self.keep_running = True
413 while self.keep_running:
423 while self.keep_running:
414 print(self.separate_in, end='')
424 print(self.separate_in, end='')
415
425
416 try:
426 try:
417 code = self.prompt_for_code()
427 code = self.prompt_for_code()
418 except EOFError:
428 except EOFError:
419 if (not self.confirm_exit) \
429 if (not self.confirm_exit) \
420 or self.ask_yes_no('Do you really want to exit ([y]/n)?','y','n'):
430 or self.ask_yes_no('Do you really want to exit ([y]/n)?','y','n'):
421 self.ask_exit()
431 self.ask_exit()
422
432
423 else:
433 else:
424 if code:
434 if code:
425 self.run_cell(code, store_history=True)
435 self.run_cell(code, store_history=True)
426
436
427 def mainloop(self, display_banner=DISPLAY_BANNER_DEPRECATED):
437 def mainloop(self, display_banner=DISPLAY_BANNER_DEPRECATED):
428 # An extra layer of protection in case someone mashing Ctrl-C breaks
438 # An extra layer of protection in case someone mashing Ctrl-C breaks
429 # out of our internal code.
439 # out of our internal code.
430 if display_banner is not DISPLAY_BANNER_DEPRECATED:
440 if display_banner is not DISPLAY_BANNER_DEPRECATED:
431 warn('mainloop `display_banner` argument is deprecated since IPython 5.0. Call `show_banner()` if needed.', DeprecationWarning, stacklevel=2)
441 warn('mainloop `display_banner` argument is deprecated since IPython 5.0. Call `show_banner()` if needed.', DeprecationWarning, stacklevel=2)
432 while True:
442 while True:
433 try:
443 try:
434 self.interact()
444 self.interact()
435 break
445 break
436 except KeyboardInterrupt as e:
446 except KeyboardInterrupt as e:
437 print("\n%s escaped interact()\n" % type(e).__name__)
447 print("\n%s escaped interact()\n" % type(e).__name__)
438 finally:
448 finally:
439 # An interrupt during the eventloop will mess up the
449 # An interrupt during the eventloop will mess up the
440 # internal state of the prompt_toolkit library.
450 # internal state of the prompt_toolkit library.
441 # Stopping the eventloop fixes this, see
451 # Stopping the eventloop fixes this, see
442 # https://github.com/ipython/ipython/pull/9867
452 # https://github.com/ipython/ipython/pull/9867
443 if hasattr(self, '_eventloop'):
453 if hasattr(self, '_eventloop'):
444 self._eventloop.stop()
454 self._eventloop.stop()
445
455
446 _inputhook = None
456 _inputhook = None
447 def inputhook(self, context):
457 def inputhook(self, context):
448 if self._inputhook is not None:
458 if self._inputhook is not None:
449 self._inputhook(context)
459 self._inputhook(context)
450
460
451 active_eventloop = None
461 active_eventloop = None
452 def enable_gui(self, gui=None):
462 def enable_gui(self, gui=None):
453 if gui:
463 if gui:
454 self.active_eventloop, self._inputhook =\
464 self.active_eventloop, self._inputhook =\
455 get_inputhook_name_and_func(gui)
465 get_inputhook_name_and_func(gui)
456 else:
466 else:
457 self.active_eventloop = self._inputhook = None
467 self.active_eventloop = self._inputhook = None
458
468
459 # Run !system commands directly, not through pipes, so terminal programs
469 # Run !system commands directly, not through pipes, so terminal programs
460 # work correctly.
470 # work correctly.
461 system = InteractiveShell.system_raw
471 system = InteractiveShell.system_raw
462
472
463 def auto_rewrite_input(self, cmd):
473 def auto_rewrite_input(self, cmd):
464 """Overridden from the parent class to use fancy rewriting prompt"""
474 """Overridden from the parent class to use fancy rewriting prompt"""
465 if not self.show_rewritten_input:
475 if not self.show_rewritten_input:
466 return
476 return
467
477
468 tokens = self.prompts.rewrite_prompt_tokens()
478 tokens = self.prompts.rewrite_prompt_tokens()
469 if self.pt_cli:
479 if self.pt_cli:
470 self.pt_cli.print_tokens(tokens)
480 self.pt_cli.print_tokens(tokens)
471 print(cmd)
481 print(cmd)
472 else:
482 else:
473 prompt = ''.join(s for t, s in tokens)
483 prompt = ''.join(s for t, s in tokens)
474 print(prompt, cmd, sep='')
484 print(prompt, cmd, sep='')
475
485
476 _prompts_before = None
486 _prompts_before = None
477 def switch_doctest_mode(self, mode):
487 def switch_doctest_mode(self, mode):
478 """Switch prompts to classic for %doctest_mode"""
488 """Switch prompts to classic for %doctest_mode"""
479 if mode:
489 if mode:
480 self._prompts_before = self.prompts
490 self._prompts_before = self.prompts
481 self.prompts = ClassicPrompts(self)
491 self.prompts = ClassicPrompts(self)
482 elif self._prompts_before:
492 elif self._prompts_before:
483 self.prompts = self._prompts_before
493 self.prompts = self._prompts_before
484 self._prompts_before = None
494 self._prompts_before = None
485 self._update_layout()
495 self._update_layout()
486
496
487
497
488 InteractiveShellABC.register(TerminalInteractiveShell)
498 InteractiveShellABC.register(TerminalInteractiveShell)
489
499
490 if __name__ == '__main__':
500 if __name__ == '__main__':
491 TerminalInteractiveShell.instance().interact()
501 TerminalInteractiveShell.instance().interact()
General Comments 0
You need to be logged in to leave comments. Login now