##// END OF EJS Templates
Remove a few usage of PromptManager in example...
Matthias Bussonnier -
Show More

The requested changes are too big and content was truncated. Show full diff

1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
@@ -1,160 +1,159 b''
1 """Implementation of configuration-related magic functions.
1 """Implementation of configuration-related magic functions.
2 """
2 """
3 from __future__ import print_function
3 from __future__ import print_function
4 from __future__ import absolute_import
4 from __future__ import absolute_import
5 #-----------------------------------------------------------------------------
5 #-----------------------------------------------------------------------------
6 # Copyright (c) 2012 The IPython Development Team.
6 # Copyright (c) 2012 The IPython Development Team.
7 #
7 #
8 # Distributed under the terms of the Modified BSD License.
8 # Distributed under the terms of the Modified BSD License.
9 #
9 #
10 # The full license is in the file COPYING.txt, distributed with this software.
10 # The full license is in the file COPYING.txt, distributed with this software.
11 #-----------------------------------------------------------------------------
11 #-----------------------------------------------------------------------------
12
12
13 #-----------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
14 # Imports
14 # Imports
15 #-----------------------------------------------------------------------------
15 #-----------------------------------------------------------------------------
16
16
17 # Stdlib
17 # Stdlib
18 import re
18 import re
19
19
20 # Our own packages
20 # Our own packages
21 from IPython.core.error import UsageError
21 from IPython.core.error import UsageError
22 from IPython.core.magic import Magics, magics_class, line_magic
22 from IPython.core.magic import Magics, magics_class, line_magic
23 from logging import error
23 from logging import error
24
24
25 #-----------------------------------------------------------------------------
25 #-----------------------------------------------------------------------------
26 # Magic implementation classes
26 # Magic implementation classes
27 #-----------------------------------------------------------------------------
27 #-----------------------------------------------------------------------------
28
28
29 reg = re.compile('^\w+\.\w+$')
29 reg = re.compile('^\w+\.\w+$')
30 @magics_class
30 @magics_class
31 class ConfigMagics(Magics):
31 class ConfigMagics(Magics):
32
32
33 def __init__(self, shell):
33 def __init__(self, shell):
34 super(ConfigMagics, self).__init__(shell)
34 super(ConfigMagics, self).__init__(shell)
35 self.configurables = []
35 self.configurables = []
36
36
37 @line_magic
37 @line_magic
38 def config(self, s):
38 def config(self, s):
39 """configure IPython
39 """configure IPython
40
40
41 %config Class[.trait=value]
41 %config Class[.trait=value]
42
42
43 This magic exposes most of the IPython config system. Any
43 This magic exposes most of the IPython config system. Any
44 Configurable class should be able to be configured with the simple
44 Configurable class should be able to be configured with the simple
45 line::
45 line::
46
46
47 %config Class.trait=value
47 %config Class.trait=value
48
48
49 Where `value` will be resolved in the user's namespace, if it is an
49 Where `value` will be resolved in the user's namespace, if it is an
50 expression or variable name.
50 expression or variable name.
51
51
52 Examples
52 Examples
53 --------
53 --------
54
54
55 To see what classes are available for config, pass no arguments::
55 To see what classes are available for config, pass no arguments::
56
56
57 In [1]: %config
57 In [1]: %config
58 Available objects for config:
58 Available objects for config:
59 TerminalInteractiveShell
59 TerminalInteractiveShell
60 HistoryManager
60 HistoryManager
61 PrefilterManager
61 PrefilterManager
62 AliasManager
62 AliasManager
63 IPCompleter
63 IPCompleter
64 PromptManager
65 DisplayFormatter
64 DisplayFormatter
66
65
67 To view what is configurable on a given class, just pass the class
66 To view what is configurable on a given class, just pass the class
68 name::
67 name::
69
68
70 In [2]: %config IPCompleter
69 In [2]: %config IPCompleter
71 IPCompleter options
70 IPCompleter options
72 -----------------
71 -----------------
73 IPCompleter.omit__names=<Enum>
72 IPCompleter.omit__names=<Enum>
74 Current: 2
73 Current: 2
75 Choices: (0, 1, 2)
74 Choices: (0, 1, 2)
76 Instruct the completer to omit private method names
75 Instruct the completer to omit private method names
77 Specifically, when completing on ``object.<tab>``.
76 Specifically, when completing on ``object.<tab>``.
78 When 2 [default]: all names that start with '_' will be excluded.
77 When 2 [default]: all names that start with '_' will be excluded.
79 When 1: all 'magic' names (``__foo__``) will be excluded.
78 When 1: all 'magic' names (``__foo__``) will be excluded.
80 When 0: nothing will be excluded.
79 When 0: nothing will be excluded.
81 IPCompleter.merge_completions=<CBool>
80 IPCompleter.merge_completions=<CBool>
82 Current: True
81 Current: True
83 Whether to merge completion results into a single list
82 Whether to merge completion results into a single list
84 If False, only the completion results from the first non-empty
83 If False, only the completion results from the first non-empty
85 completer will be returned.
84 completer will be returned.
86 IPCompleter.limit_to__all__=<CBool>
85 IPCompleter.limit_to__all__=<CBool>
87 Current: False
86 Current: False
88 Instruct the completer to use __all__ for the completion
87 Instruct the completer to use __all__ for the completion
89 Specifically, when completing on ``object.<tab>``.
88 Specifically, when completing on ``object.<tab>``.
90 When True: only those names in obj.__all__ will be included.
89 When True: only those names in obj.__all__ will be included.
91 When False [default]: the __all__ attribute is ignored
90 When False [default]: the __all__ attribute is ignored
92 IPCompleter.greedy=<CBool>
91 IPCompleter.greedy=<CBool>
93 Current: False
92 Current: False
94 Activate greedy completion
93 Activate greedy completion
95 This will enable completion on elements of lists, results of
94 This will enable completion on elements of lists, results of
96 function calls, etc., but can be unsafe because the code is
95 function calls, etc., but can be unsafe because the code is
97 actually evaluated on TAB.
96 actually evaluated on TAB.
98
97
99 but the real use is in setting values::
98 but the real use is in setting values::
100
99
101 In [3]: %config IPCompleter.greedy = True
100 In [3]: %config IPCompleter.greedy = True
102
101
103 and these values are read from the user_ns if they are variables::
102 and these values are read from the user_ns if they are variables::
104
103
105 In [4]: feeling_greedy=False
104 In [4]: feeling_greedy=False
106
105
107 In [5]: %config IPCompleter.greedy = feeling_greedy
106 In [5]: %config IPCompleter.greedy = feeling_greedy
108
107
109 """
108 """
110 from traitlets.config.loader import Config
109 from traitlets.config.loader import Config
111 # some IPython objects are Configurable, but do not yet have
110 # some IPython objects are Configurable, but do not yet have
112 # any configurable traits. Exclude them from the effects of
111 # any configurable traits. Exclude them from the effects of
113 # this magic, as their presence is just noise:
112 # this magic, as their presence is just noise:
114 configurables = [ c for c in self.shell.configurables
113 configurables = [ c for c in self.shell.configurables
115 if c.__class__.class_traits(config=True) ]
114 if c.__class__.class_traits(config=True) ]
116 classnames = [ c.__class__.__name__ for c in configurables ]
115 classnames = [ c.__class__.__name__ for c in configurables ]
117
116
118 line = s.strip()
117 line = s.strip()
119 if not line:
118 if not line:
120 # print available configurable names
119 # print available configurable names
121 print("Available objects for config:")
120 print("Available objects for config:")
122 for name in classnames:
121 for name in classnames:
123 print(" ", name)
122 print(" ", name)
124 return
123 return
125 elif line in classnames:
124 elif line in classnames:
126 # `%config TerminalInteractiveShell` will print trait info for
125 # `%config TerminalInteractiveShell` will print trait info for
127 # TerminalInteractiveShell
126 # TerminalInteractiveShell
128 c = configurables[classnames.index(line)]
127 c = configurables[classnames.index(line)]
129 cls = c.__class__
128 cls = c.__class__
130 help = cls.class_get_help(c)
129 help = cls.class_get_help(c)
131 # strip leading '--' from cl-args:
130 # strip leading '--' from cl-args:
132 help = re.sub(re.compile(r'^--', re.MULTILINE), '', help)
131 help = re.sub(re.compile(r'^--', re.MULTILINE), '', help)
133 print(help)
132 print(help)
134 return
133 return
135 elif reg.match(line):
134 elif reg.match(line):
136 cls, attr = line.split('.')
135 cls, attr = line.split('.')
137 return getattr(configurables[classnames.index(cls)],attr)
136 return getattr(configurables[classnames.index(cls)],attr)
138 elif '=' not in line:
137 elif '=' not in line:
139 msg = "Invalid config statement: %r, "\
138 msg = "Invalid config statement: %r, "\
140 "should be `Class.trait = value`."
139 "should be `Class.trait = value`."
141
140
142 ll = line.lower()
141 ll = line.lower()
143 for classname in classnames:
142 for classname in classnames:
144 if ll == classname.lower():
143 if ll == classname.lower():
145 msg = msg + '\nDid you mean %s (note the case)?' % classname
144 msg = msg + '\nDid you mean %s (note the case)?' % classname
146 break
145 break
147
146
148 raise UsageError( msg % line)
147 raise UsageError( msg % line)
149
148
150 # otherwise, assume we are setting configurables.
149 # otherwise, assume we are setting configurables.
151 # leave quotes on args when splitting, because we want
150 # leave quotes on args when splitting, because we want
152 # unquoted args to eval in user_ns
151 # unquoted args to eval in user_ns
153 cfg = Config()
152 cfg = Config()
154 exec("cfg."+line, locals(), self.shell.user_ns)
153 exec("cfg."+line, locals(), self.shell.user_ns)
155
154
156 for configurable in configurables:
155 for configurable in configurables:
157 try:
156 try:
158 configurable.update_config(cfg)
157 configurable.update_config(cfg)
159 except Exception as e:
158 except Exception as e:
160 error(e)
159 error(e)
@@ -1,509 +1,512 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 Defines a variety of Pygments lexers for highlighting IPython code.
3 Defines a variety of Pygments lexers for highlighting IPython code.
4
4
5 This includes:
5 This includes:
6
6
7 IPythonLexer, IPython3Lexer
7 IPythonLexer, IPython3Lexer
8 Lexers for pure IPython (python + magic/shell commands)
8 Lexers for pure IPython (python + magic/shell commands)
9
9
10 IPythonPartialTracebackLexer, IPythonTracebackLexer
10 IPythonPartialTracebackLexer, IPythonTracebackLexer
11 Supports 2.x and 3.x via keyword `python3`. The partial traceback
11 Supports 2.x and 3.x via keyword `python3`. The partial traceback
12 lexer reads everything but the Python code appearing in a traceback.
12 lexer reads everything but the Python code appearing in a traceback.
13 The full lexer combines the partial lexer with an IPython lexer.
13 The full lexer combines the partial lexer with an IPython lexer.
14
14
15 IPythonConsoleLexer
15 IPythonConsoleLexer
16 A lexer for IPython console sessions, with support for tracebacks.
16 A lexer for IPython console sessions, with support for tracebacks.
17
17
18 IPyLexer
18 IPyLexer
19 A friendly lexer which examines the first line of text and from it,
19 A friendly lexer which examines the first line of text and from it,
20 decides whether to use an IPython lexer or an IPython console lexer.
20 decides whether to use an IPython lexer or an IPython console lexer.
21 This is probably the only lexer that needs to be explicitly added
21 This is probably the only lexer that needs to be explicitly added
22 to Pygments.
22 to Pygments.
23
23
24 """
24 """
25 #-----------------------------------------------------------------------------
25 #-----------------------------------------------------------------------------
26 # Copyright (c) 2013, the IPython Development Team.
26 # Copyright (c) 2013, the IPython Development Team.
27 #
27 #
28 # Distributed under the terms of the Modified BSD License.
28 # Distributed under the terms of the Modified BSD License.
29 #
29 #
30 # The full license is in the file COPYING.txt, distributed with this software.
30 # The full license is in the file COPYING.txt, distributed with this software.
31 #-----------------------------------------------------------------------------
31 #-----------------------------------------------------------------------------
32
32
33 # Standard library
33 # Standard library
34 import re
34 import re
35
35
36 # Third party
36 # Third party
37 from pygments.lexers import BashLexer, PythonLexer, Python3Lexer
37 from pygments.lexers import BashLexer, PythonLexer, Python3Lexer
38 from pygments.lexer import (
38 from pygments.lexer import (
39 Lexer, DelegatingLexer, RegexLexer, do_insertions, bygroups, using,
39 Lexer, DelegatingLexer, RegexLexer, do_insertions, bygroups, using,
40 )
40 )
41 from pygments.token import (
41 from pygments.token import (
42 Generic, Keyword, Literal, Name, Operator, Other, Text, Error,
42 Generic, Keyword, Literal, Name, Operator, Other, Text, Error,
43 )
43 )
44 from pygments.util import get_bool_opt
44 from pygments.util import get_bool_opt
45
45
46 # Local
46 # Local
47
47
48 line_re = re.compile('.*?\n')
48 line_re = re.compile('.*?\n')
49
49
50 __all__ = ['build_ipy_lexer', 'IPython3Lexer', 'IPythonLexer',
50 __all__ = ['build_ipy_lexer', 'IPython3Lexer', 'IPythonLexer',
51 'IPythonPartialTracebackLexer', 'IPythonTracebackLexer',
51 'IPythonPartialTracebackLexer', 'IPythonTracebackLexer',
52 'IPythonConsoleLexer', 'IPyLexer']
52 'IPythonConsoleLexer', 'IPyLexer']
53
53
54 ipython_tokens = [
54 ipython_tokens = [
55 (r"(?s)(\s*)(%%)(\w+)(.*)", bygroups(Text, Operator, Keyword, Text)),
55 (r"(?s)(\s*)(%%)(\w+)(.*)", bygroups(Text, Operator, Keyword, Text)),
56 (r'(?s)(^\s*)(%%!)([^\n]*\n)(.*)', bygroups(Text, Operator, Text, using(BashLexer))),
56 (r'(?s)(^\s*)(%%!)([^\n]*\n)(.*)', bygroups(Text, Operator, Text, using(BashLexer))),
57 (r"(%%?)(\w+)(\?\??)$", bygroups(Operator, Keyword, Operator)),
57 (r"(%%?)(\w+)(\?\??)$", bygroups(Operator, Keyword, Operator)),
58 (r"\b(\?\??)(\s*)$", bygroups(Operator, Text)),
58 (r"\b(\?\??)(\s*)$", bygroups(Operator, Text)),
59 (r'(%)(sx|sc|system)(.*)(\n)', bygroups(Operator, Keyword,
59 (r'(%)(sx|sc|system)(.*)(\n)', bygroups(Operator, Keyword,
60 using(BashLexer), Text)),
60 using(BashLexer), Text)),
61 (r'(%)(\w+)(.*\n)', bygroups(Operator, Keyword, Text)),
61 (r'(%)(\w+)(.*\n)', bygroups(Operator, Keyword, Text)),
62 (r'^(!!)(.+)(\n)', bygroups(Operator, using(BashLexer), Text)),
62 (r'^(!!)(.+)(\n)', bygroups(Operator, using(BashLexer), Text)),
63 (r'(!)(?!=)(.+)(\n)', bygroups(Operator, using(BashLexer), Text)),
63 (r'(!)(?!=)(.+)(\n)', bygroups(Operator, using(BashLexer), Text)),
64 (r'^(\s*)(\?\??)(\s*%{0,2}[\w\.\*]*)', bygroups(Text, Operator, Text)),
64 (r'^(\s*)(\?\??)(\s*%{0,2}[\w\.\*]*)', bygroups(Text, Operator, Text)),
65 (r'(\s*%{0,2}[\w\.\*]*)(\?\??)(\s*)$', bygroups(Text, Operator, Text)),
65 (r'(\s*%{0,2}[\w\.\*]*)(\?\??)(\s*)$', bygroups(Text, Operator, Text)),
66 ]
66 ]
67
67
68 def build_ipy_lexer(python3):
68 def build_ipy_lexer(python3):
69 """Builds IPython lexers depending on the value of `python3`.
69 """Builds IPython lexers depending on the value of `python3`.
70
70
71 The lexer inherits from an appropriate Python lexer and then adds
71 The lexer inherits from an appropriate Python lexer and then adds
72 information about IPython specific keywords (i.e. magic commands,
72 information about IPython specific keywords (i.e. magic commands,
73 shell commands, etc.)
73 shell commands, etc.)
74
74
75 Parameters
75 Parameters
76 ----------
76 ----------
77 python3 : bool
77 python3 : bool
78 If `True`, then build an IPython lexer from a Python 3 lexer.
78 If `True`, then build an IPython lexer from a Python 3 lexer.
79
79
80 """
80 """
81 # It would be nice to have a single IPython lexer class which takes
81 # It would be nice to have a single IPython lexer class which takes
82 # a boolean `python3`. But since there are two Python lexer classes,
82 # a boolean `python3`. But since there are two Python lexer classes,
83 # we will also have two IPython lexer classes.
83 # we will also have two IPython lexer classes.
84 if python3:
84 if python3:
85 PyLexer = Python3Lexer
85 PyLexer = Python3Lexer
86 name = 'IPython3'
86 name = 'IPython3'
87 aliases = ['ipython3']
87 aliases = ['ipython3']
88 doc = """IPython3 Lexer"""
88 doc = """IPython3 Lexer"""
89 else:
89 else:
90 PyLexer = PythonLexer
90 PyLexer = PythonLexer
91 name = 'IPython'
91 name = 'IPython'
92 aliases = ['ipython2', 'ipython']
92 aliases = ['ipython2', 'ipython']
93 doc = """IPython Lexer"""
93 doc = """IPython Lexer"""
94
94
95 tokens = PyLexer.tokens.copy()
95 tokens = PyLexer.tokens.copy()
96 tokens['root'] = ipython_tokens + tokens['root']
96 tokens['root'] = ipython_tokens + tokens['root']
97
97
98 attrs = {'name': name, 'aliases': aliases, 'filenames': [],
98 attrs = {'name': name, 'aliases': aliases, 'filenames': [],
99 '__doc__': doc, 'tokens': tokens}
99 '__doc__': doc, 'tokens': tokens}
100
100
101 return type(name, (PyLexer,), attrs)
101 return type(name, (PyLexer,), attrs)
102
102
103
103
104 IPython3Lexer = build_ipy_lexer(python3=True)
104 IPython3Lexer = build_ipy_lexer(python3=True)
105 IPythonLexer = build_ipy_lexer(python3=False)
105 IPythonLexer = build_ipy_lexer(python3=False)
106
106
107
107
108 class IPythonPartialTracebackLexer(RegexLexer):
108 class IPythonPartialTracebackLexer(RegexLexer):
109 """
109 """
110 Partial lexer for IPython tracebacks.
110 Partial lexer for IPython tracebacks.
111
111
112 Handles all the non-python output. This works for both Python 2.x and 3.x.
112 Handles all the non-python output. This works for both Python 2.x and 3.x.
113
113
114 """
114 """
115 name = 'IPython Partial Traceback'
115 name = 'IPython Partial Traceback'
116
116
117 tokens = {
117 tokens = {
118 'root': [
118 'root': [
119 # Tracebacks for syntax errors have a different style.
119 # Tracebacks for syntax errors have a different style.
120 # For both types of tracebacks, we mark the first line with
120 # For both types of tracebacks, we mark the first line with
121 # Generic.Traceback. For syntax errors, we mark the filename
121 # Generic.Traceback. For syntax errors, we mark the filename
122 # as we mark the filenames for non-syntax tracebacks.
122 # as we mark the filenames for non-syntax tracebacks.
123 #
123 #
124 # These two regexps define how IPythonConsoleLexer finds a
124 # These two regexps define how IPythonConsoleLexer finds a
125 # traceback.
125 # traceback.
126 #
126 #
127 ## Non-syntax traceback
127 ## Non-syntax traceback
128 (r'^(\^C)?(-+\n)', bygroups(Error, Generic.Traceback)),
128 (r'^(\^C)?(-+\n)', bygroups(Error, Generic.Traceback)),
129 ## Syntax traceback
129 ## Syntax traceback
130 (r'^( File)(.*)(, line )(\d+\n)',
130 (r'^( File)(.*)(, line )(\d+\n)',
131 bygroups(Generic.Traceback, Name.Namespace,
131 bygroups(Generic.Traceback, Name.Namespace,
132 Generic.Traceback, Literal.Number.Integer)),
132 Generic.Traceback, Literal.Number.Integer)),
133
133
134 # (Exception Identifier)(Whitespace)(Traceback Message)
134 # (Exception Identifier)(Whitespace)(Traceback Message)
135 (r'(?u)(^[^\d\W]\w*)(\s*)(Traceback.*?\n)',
135 (r'(?u)(^[^\d\W]\w*)(\s*)(Traceback.*?\n)',
136 bygroups(Name.Exception, Generic.Whitespace, Text)),
136 bygroups(Name.Exception, Generic.Whitespace, Text)),
137 # (Module/Filename)(Text)(Callee)(Function Signature)
137 # (Module/Filename)(Text)(Callee)(Function Signature)
138 # Better options for callee and function signature?
138 # Better options for callee and function signature?
139 (r'(.*)( in )(.*)(\(.*\)\n)',
139 (r'(.*)( in )(.*)(\(.*\)\n)',
140 bygroups(Name.Namespace, Text, Name.Entity, Name.Tag)),
140 bygroups(Name.Namespace, Text, Name.Entity, Name.Tag)),
141 # Regular line: (Whitespace)(Line Number)(Python Code)
141 # Regular line: (Whitespace)(Line Number)(Python Code)
142 (r'(\s*?)(\d+)(.*?\n)',
142 (r'(\s*?)(\d+)(.*?\n)',
143 bygroups(Generic.Whitespace, Literal.Number.Integer, Other)),
143 bygroups(Generic.Whitespace, Literal.Number.Integer, Other)),
144 # Emphasized line: (Arrow)(Line Number)(Python Code)
144 # Emphasized line: (Arrow)(Line Number)(Python Code)
145 # Using Exception token so arrow color matches the Exception.
145 # Using Exception token so arrow color matches the Exception.
146 (r'(-*>?\s?)(\d+)(.*?\n)',
146 (r'(-*>?\s?)(\d+)(.*?\n)',
147 bygroups(Name.Exception, Literal.Number.Integer, Other)),
147 bygroups(Name.Exception, Literal.Number.Integer, Other)),
148 # (Exception Identifier)(Message)
148 # (Exception Identifier)(Message)
149 (r'(?u)(^[^\d\W]\w*)(:.*?\n)',
149 (r'(?u)(^[^\d\W]\w*)(:.*?\n)',
150 bygroups(Name.Exception, Text)),
150 bygroups(Name.Exception, Text)),
151 # Tag everything else as Other, will be handled later.
151 # Tag everything else as Other, will be handled later.
152 (r'.*\n', Other),
152 (r'.*\n', Other),
153 ],
153 ],
154 }
154 }
155
155
156
156
157 class IPythonTracebackLexer(DelegatingLexer):
157 class IPythonTracebackLexer(DelegatingLexer):
158 """
158 """
159 IPython traceback lexer.
159 IPython traceback lexer.
160
160
161 For doctests, the tracebacks can be snipped as much as desired with the
161 For doctests, the tracebacks can be snipped as much as desired with the
162 exception to the lines that designate a traceback. For non-syntax error
162 exception to the lines that designate a traceback. For non-syntax error
163 tracebacks, this is the line of hyphens. For syntax error tracebacks,
163 tracebacks, this is the line of hyphens. For syntax error tracebacks,
164 this is the line which lists the File and line number.
164 this is the line which lists the File and line number.
165
165
166 """
166 """
167 # The lexer inherits from DelegatingLexer. The "root" lexer is an
167 # The lexer inherits from DelegatingLexer. The "root" lexer is an
168 # appropriate IPython lexer, which depends on the value of the boolean
168 # appropriate IPython lexer, which depends on the value of the boolean
169 # `python3`. First, we parse with the partial IPython traceback lexer.
169 # `python3`. First, we parse with the partial IPython traceback lexer.
170 # Then, any code marked with the "Other" token is delegated to the root
170 # Then, any code marked with the "Other" token is delegated to the root
171 # lexer.
171 # lexer.
172 #
172 #
173 name = 'IPython Traceback'
173 name = 'IPython Traceback'
174 aliases = ['ipythontb']
174 aliases = ['ipythontb']
175
175
176 def __init__(self, **options):
176 def __init__(self, **options):
177 self.python3 = get_bool_opt(options, 'python3', False)
177 self.python3 = get_bool_opt(options, 'python3', False)
178 if self.python3:
178 if self.python3:
179 self.aliases = ['ipython3tb']
179 self.aliases = ['ipython3tb']
180 else:
180 else:
181 self.aliases = ['ipython2tb', 'ipythontb']
181 self.aliases = ['ipython2tb', 'ipythontb']
182
182
183 if self.python3:
183 if self.python3:
184 IPyLexer = IPython3Lexer
184 IPyLexer = IPython3Lexer
185 else:
185 else:
186 IPyLexer = IPythonLexer
186 IPyLexer = IPythonLexer
187
187
188 DelegatingLexer.__init__(self, IPyLexer,
188 DelegatingLexer.__init__(self, IPyLexer,
189 IPythonPartialTracebackLexer, **options)
189 IPythonPartialTracebackLexer, **options)
190
190
191 class IPythonConsoleLexer(Lexer):
191 class IPythonConsoleLexer(Lexer):
192 """
192 """
193 An IPython console lexer for IPython code-blocks and doctests, such as:
193 An IPython console lexer for IPython code-blocks and doctests, such as:
194
194
195 .. code-block:: rst
195 .. code-block:: rst
196
196
197 .. code-block:: ipythonconsole
197 .. code-block:: ipythonconsole
198
198
199 In [1]: a = 'foo'
199 In [1]: a = 'foo'
200
200
201 In [2]: a
201 In [2]: a
202 Out[2]: 'foo'
202 Out[2]: 'foo'
203
203
204 In [3]: print a
204 In [3]: print a
205 foo
205 foo
206
206
207 In [4]: 1 / 0
207 In [4]: 1 / 0
208
208
209
209
210 Support is also provided for IPython exceptions:
210 Support is also provided for IPython exceptions:
211
211
212 .. code-block:: rst
212 .. code-block:: rst
213
213
214 .. code-block:: ipythonconsole
214 .. code-block:: ipythonconsole
215
215
216 In [1]: raise Exception
216 In [1]: raise Exception
217
217
218 ---------------------------------------------------------------------------
218 ---------------------------------------------------------------------------
219 Exception Traceback (most recent call last)
219 Exception Traceback (most recent call last)
220 <ipython-input-1-fca2ab0ca76b> in <module>()
220 <ipython-input-1-fca2ab0ca76b> in <module>()
221 ----> 1 raise Exception
221 ----> 1 raise Exception
222
222
223 Exception:
223 Exception:
224
224
225 """
225 """
226 name = 'IPython console session'
226 name = 'IPython console session'
227 aliases = ['ipythonconsole']
227 aliases = ['ipythonconsole']
228 mimetypes = ['text/x-ipython-console']
228 mimetypes = ['text/x-ipython-console']
229
229
230 # The regexps used to determine what is input and what is output.
230 # The regexps used to determine what is input and what is output.
231 # The default prompts for IPython are:
231 # The default prompts for IPython are:
232 #
232 #
233 # c.PromptManager.in_template = 'In [\#]: '
233 # in = 'In [#]: '
234 # c.PromptManager.in2_template = ' .\D.: '
234 # continuation = ' .D.: '
235 # c.PromptManager.out_template = 'Out[\#]: '
235 # template = 'Out[#]: '
236 #
237 # Where '#' is the 'prompt number' or 'execution count' and 'D'
238 # D is a number of dots matching the width of the execution count
236 #
239 #
237 in1_regex = r'In \[[0-9]+\]: '
240 in1_regex = r'In \[[0-9]+\]: '
238 in2_regex = r' \.\.+\.: '
241 in2_regex = r' \.\.+\.: '
239 out_regex = r'Out\[[0-9]+\]: '
242 out_regex = r'Out\[[0-9]+\]: '
240
243
241 #: The regex to determine when a traceback starts.
244 #: The regex to determine when a traceback starts.
242 ipytb_start = re.compile(r'^(\^C)?(-+\n)|^( File)(.*)(, line )(\d+\n)')
245 ipytb_start = re.compile(r'^(\^C)?(-+\n)|^( File)(.*)(, line )(\d+\n)')
243
246
244 def __init__(self, **options):
247 def __init__(self, **options):
245 """Initialize the IPython console lexer.
248 """Initialize the IPython console lexer.
246
249
247 Parameters
250 Parameters
248 ----------
251 ----------
249 python3 : bool
252 python3 : bool
250 If `True`, then the console inputs are parsed using a Python 3
253 If `True`, then the console inputs are parsed using a Python 3
251 lexer. Otherwise, they are parsed using a Python 2 lexer.
254 lexer. Otherwise, they are parsed using a Python 2 lexer.
252 in1_regex : RegexObject
255 in1_regex : RegexObject
253 The compiled regular expression used to detect the start
256 The compiled regular expression used to detect the start
254 of inputs. Although the IPython configuration setting may have a
257 of inputs. Although the IPython configuration setting may have a
255 trailing whitespace, do not include it in the regex. If `None`,
258 trailing whitespace, do not include it in the regex. If `None`,
256 then the default input prompt is assumed.
259 then the default input prompt is assumed.
257 in2_regex : RegexObject
260 in2_regex : RegexObject
258 The compiled regular expression used to detect the continuation
261 The compiled regular expression used to detect the continuation
259 of inputs. Although the IPython configuration setting may have a
262 of inputs. Although the IPython configuration setting may have a
260 trailing whitespace, do not include it in the regex. If `None`,
263 trailing whitespace, do not include it in the regex. If `None`,
261 then the default input prompt is assumed.
264 then the default input prompt is assumed.
262 out_regex : RegexObject
265 out_regex : RegexObject
263 The compiled regular expression used to detect outputs. If `None`,
266 The compiled regular expression used to detect outputs. If `None`,
264 then the default output prompt is assumed.
267 then the default output prompt is assumed.
265
268
266 """
269 """
267 self.python3 = get_bool_opt(options, 'python3', False)
270 self.python3 = get_bool_opt(options, 'python3', False)
268 if self.python3:
271 if self.python3:
269 self.aliases = ['ipython3console']
272 self.aliases = ['ipython3console']
270 else:
273 else:
271 self.aliases = ['ipython2console', 'ipythonconsole']
274 self.aliases = ['ipython2console', 'ipythonconsole']
272
275
273 in1_regex = options.get('in1_regex', self.in1_regex)
276 in1_regex = options.get('in1_regex', self.in1_regex)
274 in2_regex = options.get('in2_regex', self.in2_regex)
277 in2_regex = options.get('in2_regex', self.in2_regex)
275 out_regex = options.get('out_regex', self.out_regex)
278 out_regex = options.get('out_regex', self.out_regex)
276
279
277 # So that we can work with input and output prompts which have been
280 # So that we can work with input and output prompts which have been
278 # rstrip'd (possibly by editors) we also need rstrip'd variants. If
281 # rstrip'd (possibly by editors) we also need rstrip'd variants. If
279 # we do not do this, then such prompts will be tagged as 'output'.
282 # we do not do this, then such prompts will be tagged as 'output'.
280 # The reason can't just use the rstrip'd variants instead is because
283 # The reason can't just use the rstrip'd variants instead is because
281 # we want any whitespace associated with the prompt to be inserted
284 # we want any whitespace associated with the prompt to be inserted
282 # with the token. This allows formatted code to be modified so as hide
285 # with the token. This allows formatted code to be modified so as hide
283 # the appearance of prompts, with the whitespace included. One example
286 # the appearance of prompts, with the whitespace included. One example
284 # use of this is in copybutton.js from the standard lib Python docs.
287 # use of this is in copybutton.js from the standard lib Python docs.
285 in1_regex_rstrip = in1_regex.rstrip() + '\n'
288 in1_regex_rstrip = in1_regex.rstrip() + '\n'
286 in2_regex_rstrip = in2_regex.rstrip() + '\n'
289 in2_regex_rstrip = in2_regex.rstrip() + '\n'
287 out_regex_rstrip = out_regex.rstrip() + '\n'
290 out_regex_rstrip = out_regex.rstrip() + '\n'
288
291
289 # Compile and save them all.
292 # Compile and save them all.
290 attrs = ['in1_regex', 'in2_regex', 'out_regex',
293 attrs = ['in1_regex', 'in2_regex', 'out_regex',
291 'in1_regex_rstrip', 'in2_regex_rstrip', 'out_regex_rstrip']
294 'in1_regex_rstrip', 'in2_regex_rstrip', 'out_regex_rstrip']
292 for attr in attrs:
295 for attr in attrs:
293 self.__setattr__(attr, re.compile(locals()[attr]))
296 self.__setattr__(attr, re.compile(locals()[attr]))
294
297
295 Lexer.__init__(self, **options)
298 Lexer.__init__(self, **options)
296
299
297 if self.python3:
300 if self.python3:
298 pylexer = IPython3Lexer
301 pylexer = IPython3Lexer
299 tblexer = IPythonTracebackLexer
302 tblexer = IPythonTracebackLexer
300 else:
303 else:
301 pylexer = IPythonLexer
304 pylexer = IPythonLexer
302 tblexer = IPythonTracebackLexer
305 tblexer = IPythonTracebackLexer
303
306
304 self.pylexer = pylexer(**options)
307 self.pylexer = pylexer(**options)
305 self.tblexer = tblexer(**options)
308 self.tblexer = tblexer(**options)
306
309
307 self.reset()
310 self.reset()
308
311
309 def reset(self):
312 def reset(self):
310 self.mode = 'output'
313 self.mode = 'output'
311 self.index = 0
314 self.index = 0
312 self.buffer = u''
315 self.buffer = u''
313 self.insertions = []
316 self.insertions = []
314
317
315 def buffered_tokens(self):
318 def buffered_tokens(self):
316 """
319 """
317 Generator of unprocessed tokens after doing insertions and before
320 Generator of unprocessed tokens after doing insertions and before
318 changing to a new state.
321 changing to a new state.
319
322
320 """
323 """
321 if self.mode == 'output':
324 if self.mode == 'output':
322 tokens = [(0, Generic.Output, self.buffer)]
325 tokens = [(0, Generic.Output, self.buffer)]
323 elif self.mode == 'input':
326 elif self.mode == 'input':
324 tokens = self.pylexer.get_tokens_unprocessed(self.buffer)
327 tokens = self.pylexer.get_tokens_unprocessed(self.buffer)
325 else: # traceback
328 else: # traceback
326 tokens = self.tblexer.get_tokens_unprocessed(self.buffer)
329 tokens = self.tblexer.get_tokens_unprocessed(self.buffer)
327
330
328 for i, t, v in do_insertions(self.insertions, tokens):
331 for i, t, v in do_insertions(self.insertions, tokens):
329 # All token indexes are relative to the buffer.
332 # All token indexes are relative to the buffer.
330 yield self.index + i, t, v
333 yield self.index + i, t, v
331
334
332 # Clear it all
335 # Clear it all
333 self.index += len(self.buffer)
336 self.index += len(self.buffer)
334 self.buffer = u''
337 self.buffer = u''
335 self.insertions = []
338 self.insertions = []
336
339
337 def get_mci(self, line):
340 def get_mci(self, line):
338 """
341 """
339 Parses the line and returns a 3-tuple: (mode, code, insertion).
342 Parses the line and returns a 3-tuple: (mode, code, insertion).
340
343
341 `mode` is the next mode (or state) of the lexer, and is always equal
344 `mode` is the next mode (or state) of the lexer, and is always equal
342 to 'input', 'output', or 'tb'.
345 to 'input', 'output', or 'tb'.
343
346
344 `code` is a portion of the line that should be added to the buffer
347 `code` is a portion of the line that should be added to the buffer
345 corresponding to the next mode and eventually lexed by another lexer.
348 corresponding to the next mode and eventually lexed by another lexer.
346 For example, `code` could be Python code if `mode` were 'input'.
349 For example, `code` could be Python code if `mode` were 'input'.
347
350
348 `insertion` is a 3-tuple (index, token, text) representing an
351 `insertion` is a 3-tuple (index, token, text) representing an
349 unprocessed "token" that will be inserted into the stream of tokens
352 unprocessed "token" that will be inserted into the stream of tokens
350 that are created from the buffer once we change modes. This is usually
353 that are created from the buffer once we change modes. This is usually
351 the input or output prompt.
354 the input or output prompt.
352
355
353 In general, the next mode depends on current mode and on the contents
356 In general, the next mode depends on current mode and on the contents
354 of `line`.
357 of `line`.
355
358
356 """
359 """
357 # To reduce the number of regex match checks, we have multiple
360 # To reduce the number of regex match checks, we have multiple
358 # 'if' blocks instead of 'if-elif' blocks.
361 # 'if' blocks instead of 'if-elif' blocks.
359
362
360 # Check for possible end of input
363 # Check for possible end of input
361 in2_match = self.in2_regex.match(line)
364 in2_match = self.in2_regex.match(line)
362 in2_match_rstrip = self.in2_regex_rstrip.match(line)
365 in2_match_rstrip = self.in2_regex_rstrip.match(line)
363 if (in2_match and in2_match.group().rstrip() == line.rstrip()) or \
366 if (in2_match and in2_match.group().rstrip() == line.rstrip()) or \
364 in2_match_rstrip:
367 in2_match_rstrip:
365 end_input = True
368 end_input = True
366 else:
369 else:
367 end_input = False
370 end_input = False
368 if end_input and self.mode != 'tb':
371 if end_input and self.mode != 'tb':
369 # Only look for an end of input when not in tb mode.
372 # Only look for an end of input when not in tb mode.
370 # An ellipsis could appear within the traceback.
373 # An ellipsis could appear within the traceback.
371 mode = 'output'
374 mode = 'output'
372 code = u''
375 code = u''
373 insertion = (0, Generic.Prompt, line)
376 insertion = (0, Generic.Prompt, line)
374 return mode, code, insertion
377 return mode, code, insertion
375
378
376 # Check for output prompt
379 # Check for output prompt
377 out_match = self.out_regex.match(line)
380 out_match = self.out_regex.match(line)
378 out_match_rstrip = self.out_regex_rstrip.match(line)
381 out_match_rstrip = self.out_regex_rstrip.match(line)
379 if out_match or out_match_rstrip:
382 if out_match or out_match_rstrip:
380 mode = 'output'
383 mode = 'output'
381 if out_match:
384 if out_match:
382 idx = out_match.end()
385 idx = out_match.end()
383 else:
386 else:
384 idx = out_match_rstrip.end()
387 idx = out_match_rstrip.end()
385 code = line[idx:]
388 code = line[idx:]
386 # Use the 'heading' token for output. We cannot use Generic.Error
389 # Use the 'heading' token for output. We cannot use Generic.Error
387 # since it would conflict with exceptions.
390 # since it would conflict with exceptions.
388 insertion = (0, Generic.Heading, line[:idx])
391 insertion = (0, Generic.Heading, line[:idx])
389 return mode, code, insertion
392 return mode, code, insertion
390
393
391
394
392 # Check for input or continuation prompt (non stripped version)
395 # Check for input or continuation prompt (non stripped version)
393 in1_match = self.in1_regex.match(line)
396 in1_match = self.in1_regex.match(line)
394 if in1_match or (in2_match and self.mode != 'tb'):
397 if in1_match or (in2_match and self.mode != 'tb'):
395 # New input or when not in tb, continued input.
398 # New input or when not in tb, continued input.
396 # We do not check for continued input when in tb since it is
399 # We do not check for continued input when in tb since it is
397 # allowable to replace a long stack with an ellipsis.
400 # allowable to replace a long stack with an ellipsis.
398 mode = 'input'
401 mode = 'input'
399 if in1_match:
402 if in1_match:
400 idx = in1_match.end()
403 idx = in1_match.end()
401 else: # in2_match
404 else: # in2_match
402 idx = in2_match.end()
405 idx = in2_match.end()
403 code = line[idx:]
406 code = line[idx:]
404 insertion = (0, Generic.Prompt, line[:idx])
407 insertion = (0, Generic.Prompt, line[:idx])
405 return mode, code, insertion
408 return mode, code, insertion
406
409
407 # Check for input or continuation prompt (stripped version)
410 # Check for input or continuation prompt (stripped version)
408 in1_match_rstrip = self.in1_regex_rstrip.match(line)
411 in1_match_rstrip = self.in1_regex_rstrip.match(line)
409 if in1_match_rstrip or (in2_match_rstrip and self.mode != 'tb'):
412 if in1_match_rstrip or (in2_match_rstrip and self.mode != 'tb'):
410 # New input or when not in tb, continued input.
413 # New input or when not in tb, continued input.
411 # We do not check for continued input when in tb since it is
414 # We do not check for continued input when in tb since it is
412 # allowable to replace a long stack with an ellipsis.
415 # allowable to replace a long stack with an ellipsis.
413 mode = 'input'
416 mode = 'input'
414 if in1_match_rstrip:
417 if in1_match_rstrip:
415 idx = in1_match_rstrip.end()
418 idx = in1_match_rstrip.end()
416 else: # in2_match
419 else: # in2_match
417 idx = in2_match_rstrip.end()
420 idx = in2_match_rstrip.end()
418 code = line[idx:]
421 code = line[idx:]
419 insertion = (0, Generic.Prompt, line[:idx])
422 insertion = (0, Generic.Prompt, line[:idx])
420 return mode, code, insertion
423 return mode, code, insertion
421
424
422 # Check for traceback
425 # Check for traceback
423 if self.ipytb_start.match(line):
426 if self.ipytb_start.match(line):
424 mode = 'tb'
427 mode = 'tb'
425 code = line
428 code = line
426 insertion = None
429 insertion = None
427 return mode, code, insertion
430 return mode, code, insertion
428
431
429 # All other stuff...
432 # All other stuff...
430 if self.mode in ('input', 'output'):
433 if self.mode in ('input', 'output'):
431 # We assume all other text is output. Multiline input that
434 # We assume all other text is output. Multiline input that
432 # does not use the continuation marker cannot be detected.
435 # does not use the continuation marker cannot be detected.
433 # For example, the 3 in the following is clearly output:
436 # For example, the 3 in the following is clearly output:
434 #
437 #
435 # In [1]: print 3
438 # In [1]: print 3
436 # 3
439 # 3
437 #
440 #
438 # But the following second line is part of the input:
441 # But the following second line is part of the input:
439 #
442 #
440 # In [2]: while True:
443 # In [2]: while True:
441 # print True
444 # print True
442 #
445 #
443 # In both cases, the 2nd line will be 'output'.
446 # In both cases, the 2nd line will be 'output'.
444 #
447 #
445 mode = 'output'
448 mode = 'output'
446 else:
449 else:
447 mode = 'tb'
450 mode = 'tb'
448
451
449 code = line
452 code = line
450 insertion = None
453 insertion = None
451
454
452 return mode, code, insertion
455 return mode, code, insertion
453
456
454 def get_tokens_unprocessed(self, text):
457 def get_tokens_unprocessed(self, text):
455 self.reset()
458 self.reset()
456 for match in line_re.finditer(text):
459 for match in line_re.finditer(text):
457 line = match.group()
460 line = match.group()
458 mode, code, insertion = self.get_mci(line)
461 mode, code, insertion = self.get_mci(line)
459
462
460 if mode != self.mode:
463 if mode != self.mode:
461 # Yield buffered tokens before transitioning to new mode.
464 # Yield buffered tokens before transitioning to new mode.
462 for token in self.buffered_tokens():
465 for token in self.buffered_tokens():
463 yield token
466 yield token
464 self.mode = mode
467 self.mode = mode
465
468
466 if insertion:
469 if insertion:
467 self.insertions.append((len(self.buffer), [insertion]))
470 self.insertions.append((len(self.buffer), [insertion]))
468 self.buffer += code
471 self.buffer += code
469
472
470 for token in self.buffered_tokens():
473 for token in self.buffered_tokens():
471 yield token
474 yield token
472
475
473 class IPyLexer(Lexer):
476 class IPyLexer(Lexer):
474 """
477 """
475 Primary lexer for all IPython-like code.
478 Primary lexer for all IPython-like code.
476
479
477 This is a simple helper lexer. If the first line of the text begins with
480 This is a simple helper lexer. If the first line of the text begins with
478 "In \[[0-9]+\]:", then the entire text is parsed with an IPython console
481 "In \[[0-9]+\]:", then the entire text is parsed with an IPython console
479 lexer. If not, then the entire text is parsed with an IPython lexer.
482 lexer. If not, then the entire text is parsed with an IPython lexer.
480
483
481 The goal is to reduce the number of lexers that are registered
484 The goal is to reduce the number of lexers that are registered
482 with Pygments.
485 with Pygments.
483
486
484 """
487 """
485 name = 'IPy session'
488 name = 'IPy session'
486 aliases = ['ipy']
489 aliases = ['ipy']
487
490
488 def __init__(self, **options):
491 def __init__(self, **options):
489 self.python3 = get_bool_opt(options, 'python3', False)
492 self.python3 = get_bool_opt(options, 'python3', False)
490 if self.python3:
493 if self.python3:
491 self.aliases = ['ipy3']
494 self.aliases = ['ipy3']
492 else:
495 else:
493 self.aliases = ['ipy2', 'ipy']
496 self.aliases = ['ipy2', 'ipy']
494
497
495 Lexer.__init__(self, **options)
498 Lexer.__init__(self, **options)
496
499
497 self.IPythonLexer = IPythonLexer(**options)
500 self.IPythonLexer = IPythonLexer(**options)
498 self.IPythonConsoleLexer = IPythonConsoleLexer(**options)
501 self.IPythonConsoleLexer = IPythonConsoleLexer(**options)
499
502
500 def get_tokens_unprocessed(self, text):
503 def get_tokens_unprocessed(self, text):
501 # Search for the input prompt anywhere...this allows code blocks to
504 # Search for the input prompt anywhere...this allows code blocks to
502 # begin with comments as well.
505 # begin with comments as well.
503 if re.match(r'.*(In \[[0-9]+\]:)', text.strip(), re.DOTALL):
506 if re.match(r'.*(In \[[0-9]+\]:)', text.strip(), re.DOTALL):
504 lex = self.IPythonConsoleLexer
507 lex = self.IPythonConsoleLexer
505 else:
508 else:
506 lex = self.IPythonLexer
509 lex = self.IPythonLexer
507 for token in lex.get_tokens_unprocessed(text):
510 for token in lex.get_tokens_unprocessed(text):
508 yield token
511 yield token
509
512
@@ -1,374 +1,372 b''
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2 # encoding: utf-8
2 # encoding: utf-8
3 """
3 """
4 The :class:`~IPython.core.application.Application` object for the command
4 The :class:`~IPython.core.application.Application` object for the command
5 line :command:`ipython` program.
5 line :command:`ipython` program.
6 """
6 """
7
7
8 # Copyright (c) IPython Development Team.
8 # Copyright (c) IPython Development Team.
9 # Distributed under the terms of the Modified BSD License.
9 # Distributed under the terms of the Modified BSD License.
10
10
11 from __future__ import absolute_import
11 from __future__ import absolute_import
12 from __future__ import print_function
12 from __future__ import print_function
13
13
14 import logging
14 import logging
15 import os
15 import os
16 import sys
16 import sys
17 import warnings
17 import warnings
18
18
19 from traitlets.config.loader import Config
19 from traitlets.config.loader import Config
20 from traitlets.config.application import boolean_flag, catch_config_error, Application
20 from traitlets.config.application import boolean_flag, catch_config_error, Application
21 from IPython.core import release
21 from IPython.core import release
22 from IPython.core import usage
22 from IPython.core import usage
23 from IPython.core.completer import IPCompleter
23 from IPython.core.completer import IPCompleter
24 from IPython.core.crashhandler import CrashHandler
24 from IPython.core.crashhandler import CrashHandler
25 from IPython.core.formatters import PlainTextFormatter
25 from IPython.core.formatters import PlainTextFormatter
26 from IPython.core.history import HistoryManager
26 from IPython.core.history import HistoryManager
27 from IPython.core.application import (
27 from IPython.core.application import (
28 ProfileDir, BaseIPythonApplication, base_flags, base_aliases
28 ProfileDir, BaseIPythonApplication, base_flags, base_aliases
29 )
29 )
30 from IPython.core.magics import ScriptMagics
30 from IPython.core.magics import ScriptMagics
31 from IPython.core.shellapp import (
31 from IPython.core.shellapp import (
32 InteractiveShellApp, shell_flags, shell_aliases
32 InteractiveShellApp, shell_flags, shell_aliases
33 )
33 )
34 from IPython.extensions.storemagic import StoreMagics
34 from IPython.extensions.storemagic import StoreMagics
35 from .ptshell import TerminalInteractiveShell
35 from .ptshell import TerminalInteractiveShell
36 from IPython.paths import get_ipython_dir
36 from IPython.paths import get_ipython_dir
37 from traitlets import (
37 from traitlets import (
38 Bool, List, Dict, default, observe,
38 Bool, List, Dict, default, observe,
39 )
39 )
40
40
41 #-----------------------------------------------------------------------------
41 #-----------------------------------------------------------------------------
42 # Globals, utilities and helpers
42 # Globals, utilities and helpers
43 #-----------------------------------------------------------------------------
43 #-----------------------------------------------------------------------------
44
44
45 _examples = """
45 _examples = """
46 ipython --matplotlib # enable matplotlib integration
46 ipython --matplotlib # enable matplotlib integration
47 ipython --matplotlib=qt # enable matplotlib integration with qt4 backend
47 ipython --matplotlib=qt # enable matplotlib integration with qt4 backend
48
48
49 ipython --log-level=DEBUG # set logging to DEBUG
49 ipython --log-level=DEBUG # set logging to DEBUG
50 ipython --profile=foo # start with profile foo
50 ipython --profile=foo # start with profile foo
51
51
52 ipython profile create foo # create profile foo w/ default config files
52 ipython profile create foo # create profile foo w/ default config files
53 ipython help profile # show the help for the profile subcmd
53 ipython help profile # show the help for the profile subcmd
54
54
55 ipython locate # print the path to the IPython directory
55 ipython locate # print the path to the IPython directory
56 ipython locate profile foo # print the path to the directory for profile `foo`
56 ipython locate profile foo # print the path to the directory for profile `foo`
57 """
57 """
58
58
59 #-----------------------------------------------------------------------------
59 #-----------------------------------------------------------------------------
60 # Crash handler for this application
60 # Crash handler for this application
61 #-----------------------------------------------------------------------------
61 #-----------------------------------------------------------------------------
62
62
63 class IPAppCrashHandler(CrashHandler):
63 class IPAppCrashHandler(CrashHandler):
64 """sys.excepthook for IPython itself, leaves a detailed report on disk."""
64 """sys.excepthook for IPython itself, leaves a detailed report on disk."""
65
65
66 def __init__(self, app):
66 def __init__(self, app):
67 contact_name = release.author
67 contact_name = release.author
68 contact_email = release.author_email
68 contact_email = release.author_email
69 bug_tracker = 'https://github.com/ipython/ipython/issues'
69 bug_tracker = 'https://github.com/ipython/ipython/issues'
70 super(IPAppCrashHandler,self).__init__(
70 super(IPAppCrashHandler,self).__init__(
71 app, contact_name, contact_email, bug_tracker
71 app, contact_name, contact_email, bug_tracker
72 )
72 )
73
73
74 def make_report(self,traceback):
74 def make_report(self,traceback):
75 """Return a string containing a crash report."""
75 """Return a string containing a crash report."""
76
76
77 sec_sep = self.section_sep
77 sec_sep = self.section_sep
78 # Start with parent report
78 # Start with parent report
79 report = [super(IPAppCrashHandler, self).make_report(traceback)]
79 report = [super(IPAppCrashHandler, self).make_report(traceback)]
80 # Add interactive-specific info we may have
80 # Add interactive-specific info we may have
81 rpt_add = report.append
81 rpt_add = report.append
82 try:
82 try:
83 rpt_add(sec_sep+"History of session input:")
83 rpt_add(sec_sep+"History of session input:")
84 for line in self.app.shell.user_ns['_ih']:
84 for line in self.app.shell.user_ns['_ih']:
85 rpt_add(line)
85 rpt_add(line)
86 rpt_add('\n*** Last line of input (may not be in above history):\n')
86 rpt_add('\n*** Last line of input (may not be in above history):\n')
87 rpt_add(self.app.shell._last_input_line+'\n')
87 rpt_add(self.app.shell._last_input_line+'\n')
88 except:
88 except:
89 pass
89 pass
90
90
91 return ''.join(report)
91 return ''.join(report)
92
92
93 #-----------------------------------------------------------------------------
93 #-----------------------------------------------------------------------------
94 # Aliases and Flags
94 # Aliases and Flags
95 #-----------------------------------------------------------------------------
95 #-----------------------------------------------------------------------------
96 flags = dict(base_flags)
96 flags = dict(base_flags)
97 flags.update(shell_flags)
97 flags.update(shell_flags)
98 frontend_flags = {}
98 frontend_flags = {}
99 addflag = lambda *args: frontend_flags.update(boolean_flag(*args))
99 addflag = lambda *args: frontend_flags.update(boolean_flag(*args))
100 addflag('autoedit-syntax', 'TerminalInteractiveShell.autoedit_syntax',
100 addflag('autoedit-syntax', 'TerminalInteractiveShell.autoedit_syntax',
101 'Turn on auto editing of files with syntax errors.',
101 'Turn on auto editing of files with syntax errors.',
102 'Turn off auto editing of files with syntax errors.'
102 'Turn off auto editing of files with syntax errors.'
103 )
103 )
104 addflag('simple-prompt', 'TerminalInteractiveShell.simple_prompt',
104 addflag('simple-prompt', 'TerminalInteractiveShell.simple_prompt',
105 "Force simple minimal prompt using `raw_input`",
105 "Force simple minimal prompt using `raw_input`",
106 "Use a rich interactive prompt with prompt_toolkit",
106 "Use a rich interactive prompt with prompt_toolkit",
107 )
107 )
108
108
109 addflag('banner', 'TerminalIPythonApp.display_banner',
109 addflag('banner', 'TerminalIPythonApp.display_banner',
110 "Display a banner upon starting IPython.",
110 "Display a banner upon starting IPython.",
111 "Don't display a banner upon starting IPython."
111 "Don't display a banner upon starting IPython."
112 )
112 )
113 addflag('confirm-exit', 'TerminalInteractiveShell.confirm_exit',
113 addflag('confirm-exit', 'TerminalInteractiveShell.confirm_exit',
114 """Set to confirm when you try to exit IPython with an EOF (Control-D
114 """Set to confirm when you try to exit IPython with an EOF (Control-D
115 in Unix, Control-Z/Enter in Windows). By typing 'exit' or 'quit',
115 in Unix, Control-Z/Enter in Windows). By typing 'exit' or 'quit',
116 you can force a direct exit without any confirmation.""",
116 you can force a direct exit without any confirmation.""",
117 "Don't prompt the user when exiting."
117 "Don't prompt the user when exiting."
118 )
118 )
119 addflag('term-title', 'TerminalInteractiveShell.term_title',
119 addflag('term-title', 'TerminalInteractiveShell.term_title',
120 "Enable auto setting the terminal title.",
120 "Enable auto setting the terminal title.",
121 "Disable auto setting the terminal title."
121 "Disable auto setting the terminal title."
122 )
122 )
123 classic_config = Config()
123 classic_config = Config()
124 classic_config.InteractiveShell.cache_size = 0
124 classic_config.InteractiveShell.cache_size = 0
125 classic_config.PlainTextFormatter.pprint = False
125 classic_config.PlainTextFormatter.pprint = False
126 classic_config.PromptManager.in_template = '>>> '
126 classic_config.TerminalInteractiveShell.prompts_class='IPython.terminal.prompts.ClassicPrompts'
127 classic_config.PromptManager.in2_template = '... '
128 classic_config.PromptManager.out_template = ''
129 classic_config.InteractiveShell.separate_in = ''
127 classic_config.InteractiveShell.separate_in = ''
130 classic_config.InteractiveShell.separate_out = ''
128 classic_config.InteractiveShell.separate_out = ''
131 classic_config.InteractiveShell.separate_out2 = ''
129 classic_config.InteractiveShell.separate_out2 = ''
132 classic_config.InteractiveShell.colors = 'NoColor'
130 classic_config.InteractiveShell.colors = 'NoColor'
133 classic_config.InteractiveShell.xmode = 'Plain'
131 classic_config.InteractiveShell.xmode = 'Plain'
134
132
135 frontend_flags['classic']=(
133 frontend_flags['classic']=(
136 classic_config,
134 classic_config,
137 "Gives IPython a similar feel to the classic Python prompt."
135 "Gives IPython a similar feel to the classic Python prompt."
138 )
136 )
139 # # log doesn't make so much sense this way anymore
137 # # log doesn't make so much sense this way anymore
140 # paa('--log','-l',
138 # paa('--log','-l',
141 # action='store_true', dest='InteractiveShell.logstart',
139 # action='store_true', dest='InteractiveShell.logstart',
142 # help="Start logging to the default log file (./ipython_log.py).")
140 # help="Start logging to the default log file (./ipython_log.py).")
143 #
141 #
144 # # quick is harder to implement
142 # # quick is harder to implement
145 frontend_flags['quick']=(
143 frontend_flags['quick']=(
146 {'TerminalIPythonApp' : {'quick' : True}},
144 {'TerminalIPythonApp' : {'quick' : True}},
147 "Enable quick startup with no config files."
145 "Enable quick startup with no config files."
148 )
146 )
149
147
150 frontend_flags['i'] = (
148 frontend_flags['i'] = (
151 {'TerminalIPythonApp' : {'force_interact' : True}},
149 {'TerminalIPythonApp' : {'force_interact' : True}},
152 """If running code from the command line, become interactive afterwards.
150 """If running code from the command line, become interactive afterwards.
153 It is often useful to follow this with `--` to treat remaining flags as
151 It is often useful to follow this with `--` to treat remaining flags as
154 script arguments.
152 script arguments.
155 """
153 """
156 )
154 )
157 flags.update(frontend_flags)
155 flags.update(frontend_flags)
158
156
159 aliases = dict(base_aliases)
157 aliases = dict(base_aliases)
160 aliases.update(shell_aliases)
158 aliases.update(shell_aliases)
161
159
162 #-----------------------------------------------------------------------------
160 #-----------------------------------------------------------------------------
163 # Main classes and functions
161 # Main classes and functions
164 #-----------------------------------------------------------------------------
162 #-----------------------------------------------------------------------------
165
163
166
164
167 class LocateIPythonApp(BaseIPythonApplication):
165 class LocateIPythonApp(BaseIPythonApplication):
168 description = """print the path to the IPython dir"""
166 description = """print the path to the IPython dir"""
169 subcommands = Dict(dict(
167 subcommands = Dict(dict(
170 profile=('IPython.core.profileapp.ProfileLocate',
168 profile=('IPython.core.profileapp.ProfileLocate',
171 "print the path to an IPython profile directory",
169 "print the path to an IPython profile directory",
172 ),
170 ),
173 ))
171 ))
174 def start(self):
172 def start(self):
175 if self.subapp is not None:
173 if self.subapp is not None:
176 return self.subapp.start()
174 return self.subapp.start()
177 else:
175 else:
178 print(self.ipython_dir)
176 print(self.ipython_dir)
179
177
180
178
181 class TerminalIPythonApp(BaseIPythonApplication, InteractiveShellApp):
179 class TerminalIPythonApp(BaseIPythonApplication, InteractiveShellApp):
182 name = u'ipython'
180 name = u'ipython'
183 description = usage.cl_usage
181 description = usage.cl_usage
184 crash_handler_class = IPAppCrashHandler
182 crash_handler_class = IPAppCrashHandler
185 examples = _examples
183 examples = _examples
186
184
187 flags = Dict(flags)
185 flags = Dict(flags)
188 aliases = Dict(aliases)
186 aliases = Dict(aliases)
189 classes = List()
187 classes = List()
190 @default('classes')
188 @default('classes')
191 def _classes_default(self):
189 def _classes_default(self):
192 """This has to be in a method, for TerminalIPythonApp to be available."""
190 """This has to be in a method, for TerminalIPythonApp to be available."""
193 return [
191 return [
194 InteractiveShellApp, # ShellApp comes before TerminalApp, because
192 InteractiveShellApp, # ShellApp comes before TerminalApp, because
195 self.__class__, # it will also affect subclasses (e.g. QtConsole)
193 self.__class__, # it will also affect subclasses (e.g. QtConsole)
196 TerminalInteractiveShell,
194 TerminalInteractiveShell,
197 HistoryManager,
195 HistoryManager,
198 ProfileDir,
196 ProfileDir,
199 PlainTextFormatter,
197 PlainTextFormatter,
200 IPCompleter,
198 IPCompleter,
201 ScriptMagics,
199 ScriptMagics,
202 StoreMagics,
200 StoreMagics,
203 ]
201 ]
204
202
205 deprecated_subcommands = dict(
203 deprecated_subcommands = dict(
206 qtconsole=('qtconsole.qtconsoleapp.JupyterQtConsoleApp',
204 qtconsole=('qtconsole.qtconsoleapp.JupyterQtConsoleApp',
207 """DEPRECATED, Will be removed in IPython 6.0 : Launch the Jupyter Qt Console."""
205 """DEPRECATED, Will be removed in IPython 6.0 : Launch the Jupyter Qt Console."""
208 ),
206 ),
209 notebook=('notebook.notebookapp.NotebookApp',
207 notebook=('notebook.notebookapp.NotebookApp',
210 """DEPRECATED, Will be removed in IPython 6.0 : Launch the Jupyter HTML Notebook Server."""
208 """DEPRECATED, Will be removed in IPython 6.0 : Launch the Jupyter HTML Notebook Server."""
211 ),
209 ),
212 console=('jupyter_console.app.ZMQTerminalIPythonApp',
210 console=('jupyter_console.app.ZMQTerminalIPythonApp',
213 """DEPRECATED, Will be removed in IPython 6.0 : Launch the Jupyter terminal-based Console."""
211 """DEPRECATED, Will be removed in IPython 6.0 : Launch the Jupyter terminal-based Console."""
214 ),
212 ),
215 nbconvert=('nbconvert.nbconvertapp.NbConvertApp',
213 nbconvert=('nbconvert.nbconvertapp.NbConvertApp',
216 "DEPRECATED, Will be removed in IPython 6.0 : Convert notebooks to/from other formats."
214 "DEPRECATED, Will be removed in IPython 6.0 : Convert notebooks to/from other formats."
217 ),
215 ),
218 trust=('nbformat.sign.TrustNotebookApp',
216 trust=('nbformat.sign.TrustNotebookApp',
219 "DEPRECATED, Will be removed in IPython 6.0 : Sign notebooks to trust their potentially unsafe contents at load."
217 "DEPRECATED, Will be removed in IPython 6.0 : Sign notebooks to trust their potentially unsafe contents at load."
220 ),
218 ),
221 kernelspec=('jupyter_client.kernelspecapp.KernelSpecApp',
219 kernelspec=('jupyter_client.kernelspecapp.KernelSpecApp',
222 "DEPRECATED, Will be removed in IPython 6.0 : Manage Jupyter kernel specifications."
220 "DEPRECATED, Will be removed in IPython 6.0 : Manage Jupyter kernel specifications."
223 ),
221 ),
224 )
222 )
225 subcommands = dict(
223 subcommands = dict(
226 profile = ("IPython.core.profileapp.ProfileApp",
224 profile = ("IPython.core.profileapp.ProfileApp",
227 "Create and manage IPython profiles."
225 "Create and manage IPython profiles."
228 ),
226 ),
229 kernel = ("ipykernel.kernelapp.IPKernelApp",
227 kernel = ("ipykernel.kernelapp.IPKernelApp",
230 "Start a kernel without an attached frontend."
228 "Start a kernel without an attached frontend."
231 ),
229 ),
232 locate=('IPython.terminal.ipapp.LocateIPythonApp',
230 locate=('IPython.terminal.ipapp.LocateIPythonApp',
233 LocateIPythonApp.description
231 LocateIPythonApp.description
234 ),
232 ),
235 history=('IPython.core.historyapp.HistoryApp',
233 history=('IPython.core.historyapp.HistoryApp',
236 "Manage the IPython history database."
234 "Manage the IPython history database."
237 ),
235 ),
238 )
236 )
239 deprecated_subcommands['install-nbextension'] = (
237 deprecated_subcommands['install-nbextension'] = (
240 "notebook.nbextensions.InstallNBExtensionApp",
238 "notebook.nbextensions.InstallNBExtensionApp",
241 "DEPRECATED, Will be removed in IPython 6.0 : Install Jupyter notebook extension files"
239 "DEPRECATED, Will be removed in IPython 6.0 : Install Jupyter notebook extension files"
242 )
240 )
243 subcommands.update(deprecated_subcommands)
241 subcommands.update(deprecated_subcommands)
244
242
245 # *do* autocreate requested profile, but don't create the config file.
243 # *do* autocreate requested profile, but don't create the config file.
246 auto_create=Bool(True)
244 auto_create=Bool(True)
247 # configurables
245 # configurables
248 quick = Bool(False,
246 quick = Bool(False,
249 help="""Start IPython quickly by skipping the loading of config files."""
247 help="""Start IPython quickly by skipping the loading of config files."""
250 ).tag(config=True)
248 ).tag(config=True)
251 @observe('quick')
249 @observe('quick')
252 def _quick_changed(self, change):
250 def _quick_changed(self, change):
253 if change['new']:
251 if change['new']:
254 self.load_config_file = lambda *a, **kw: None
252 self.load_config_file = lambda *a, **kw: None
255
253
256 display_banner = Bool(True,
254 display_banner = Bool(True,
257 help="Whether to display a banner upon starting IPython."
255 help="Whether to display a banner upon starting IPython."
258 ).tag(config=True)
256 ).tag(config=True)
259
257
260 # if there is code of files to run from the cmd line, don't interact
258 # if there is code of files to run from the cmd line, don't interact
261 # unless the --i flag (App.force_interact) is true.
259 # unless the --i flag (App.force_interact) is true.
262 force_interact = Bool(False,
260 force_interact = Bool(False,
263 help="""If a command or file is given via the command-line,
261 help="""If a command or file is given via the command-line,
264 e.g. 'ipython foo.py', start an interactive shell after executing the
262 e.g. 'ipython foo.py', start an interactive shell after executing the
265 file or command."""
263 file or command."""
266 ).tag(config=True)
264 ).tag(config=True)
267 @observe('force_interact')
265 @observe('force_interact')
268 def _force_interact_changed(self, change):
266 def _force_interact_changed(self, change):
269 if change['new']:
267 if change['new']:
270 self.interact = True
268 self.interact = True
271
269
272 @observe('file_to_run', 'code_to_run', 'module_to_run')
270 @observe('file_to_run', 'code_to_run', 'module_to_run')
273 def _file_to_run_changed(self, change):
271 def _file_to_run_changed(self, change):
274 new = change['new']
272 new = change['new']
275 if new:
273 if new:
276 self.something_to_run = True
274 self.something_to_run = True
277 if new and not self.force_interact:
275 if new and not self.force_interact:
278 self.interact = False
276 self.interact = False
279
277
280 # internal, not-configurable
278 # internal, not-configurable
281 something_to_run=Bool(False)
279 something_to_run=Bool(False)
282
280
283 def parse_command_line(self, argv=None):
281 def parse_command_line(self, argv=None):
284 """override to allow old '-pylab' flag with deprecation warning"""
282 """override to allow old '-pylab' flag with deprecation warning"""
285
283
286 argv = sys.argv[1:] if argv is None else argv
284 argv = sys.argv[1:] if argv is None else argv
287
285
288 if '-pylab' in argv:
286 if '-pylab' in argv:
289 # deprecated `-pylab` given,
287 # deprecated `-pylab` given,
290 # warn and transform into current syntax
288 # warn and transform into current syntax
291 argv = argv[:] # copy, don't clobber
289 argv = argv[:] # copy, don't clobber
292 idx = argv.index('-pylab')
290 idx = argv.index('-pylab')
293 warnings.warn("`-pylab` flag has been deprecated.\n"
291 warnings.warn("`-pylab` flag has been deprecated.\n"
294 " Use `--matplotlib <backend>` and import pylab manually.")
292 " Use `--matplotlib <backend>` and import pylab manually.")
295 argv[idx] = '--pylab'
293 argv[idx] = '--pylab'
296
294
297 return super(TerminalIPythonApp, self).parse_command_line(argv)
295 return super(TerminalIPythonApp, self).parse_command_line(argv)
298
296
299 @catch_config_error
297 @catch_config_error
300 def initialize(self, argv=None):
298 def initialize(self, argv=None):
301 """Do actions after construct, but before starting the app."""
299 """Do actions after construct, but before starting the app."""
302 super(TerminalIPythonApp, self).initialize(argv)
300 super(TerminalIPythonApp, self).initialize(argv)
303 if self.subapp is not None:
301 if self.subapp is not None:
304 # don't bother initializing further, starting subapp
302 # don't bother initializing further, starting subapp
305 return
303 return
306 # print self.extra_args
304 # print self.extra_args
307 if self.extra_args and not self.something_to_run:
305 if self.extra_args and not self.something_to_run:
308 self.file_to_run = self.extra_args[0]
306 self.file_to_run = self.extra_args[0]
309 self.init_path()
307 self.init_path()
310 # create the shell
308 # create the shell
311 self.init_shell()
309 self.init_shell()
312 # and draw the banner
310 # and draw the banner
313 self.init_banner()
311 self.init_banner()
314 # Now a variety of things that happen after the banner is printed.
312 # Now a variety of things that happen after the banner is printed.
315 self.init_gui_pylab()
313 self.init_gui_pylab()
316 self.init_extensions()
314 self.init_extensions()
317 self.init_code()
315 self.init_code()
318
316
319 def init_shell(self):
317 def init_shell(self):
320 """initialize the InteractiveShell instance"""
318 """initialize the InteractiveShell instance"""
321 # Create an InteractiveShell instance.
319 # Create an InteractiveShell instance.
322 # shell.display_banner should always be False for the terminal
320 # shell.display_banner should always be False for the terminal
323 # based app, because we call shell.show_banner() by hand below
321 # based app, because we call shell.show_banner() by hand below
324 # so the banner shows *before* all extension loading stuff.
322 # so the banner shows *before* all extension loading stuff.
325 self.shell = TerminalInteractiveShell.instance(parent=self,
323 self.shell = TerminalInteractiveShell.instance(parent=self,
326 profile_dir=self.profile_dir,
324 profile_dir=self.profile_dir,
327 ipython_dir=self.ipython_dir, user_ns=self.user_ns)
325 ipython_dir=self.ipython_dir, user_ns=self.user_ns)
328 self.shell.configurables.append(self)
326 self.shell.configurables.append(self)
329
327
330 def init_banner(self):
328 def init_banner(self):
331 """optionally display the banner"""
329 """optionally display the banner"""
332 if self.display_banner and self.interact:
330 if self.display_banner and self.interact:
333 self.shell.show_banner()
331 self.shell.show_banner()
334 # Make sure there is a space below the banner.
332 # Make sure there is a space below the banner.
335 if self.log_level <= logging.INFO: print()
333 if self.log_level <= logging.INFO: print()
336
334
337 def _pylab_changed(self, name, old, new):
335 def _pylab_changed(self, name, old, new):
338 """Replace --pylab='inline' with --pylab='auto'"""
336 """Replace --pylab='inline' with --pylab='auto'"""
339 if new == 'inline':
337 if new == 'inline':
340 warnings.warn("'inline' not available as pylab backend, "
338 warnings.warn("'inline' not available as pylab backend, "
341 "using 'auto' instead.")
339 "using 'auto' instead.")
342 self.pylab = 'auto'
340 self.pylab = 'auto'
343
341
344 def start(self):
342 def start(self):
345 if self.subapp is not None:
343 if self.subapp is not None:
346 return self.subapp.start()
344 return self.subapp.start()
347 # perform any prexec steps:
345 # perform any prexec steps:
348 if self.interact:
346 if self.interact:
349 self.log.debug("Starting IPython's mainloop...")
347 self.log.debug("Starting IPython's mainloop...")
350 self.shell.mainloop()
348 self.shell.mainloop()
351 else:
349 else:
352 self.log.debug("IPython not interactive...")
350 self.log.debug("IPython not interactive...")
353
351
354 def load_default_config(ipython_dir=None):
352 def load_default_config(ipython_dir=None):
355 """Load the default config file from the default ipython_dir.
353 """Load the default config file from the default ipython_dir.
356
354
357 This is useful for embedded shells.
355 This is useful for embedded shells.
358 """
356 """
359 if ipython_dir is None:
357 if ipython_dir is None:
360 ipython_dir = get_ipython_dir()
358 ipython_dir = get_ipython_dir()
361
359
362 profile_dir = os.path.join(ipython_dir, 'profile_default')
360 profile_dir = os.path.join(ipython_dir, 'profile_default')
363
361
364 config = Config()
362 config = Config()
365 for cf in Application._load_config_files("ipython_config", path=profile_dir):
363 for cf in Application._load_config_files("ipython_config", path=profile_dir):
366 config.update(cf)
364 config.update(cf)
367
365
368 return config
366 return config
369
367
370 launch_new_instance = TerminalIPythonApp.launch_instance
368 launch_new_instance = TerminalIPythonApp.launch_instance
371
369
372
370
373 if __name__ == '__main__':
371 if __name__ == '__main__':
374 launch_new_instance()
372 launch_new_instance()
@@ -1,492 +1,494 b''
1 """IPython terminal interface using prompt_toolkit in place of readline"""
1 """IPython terminal interface using prompt_toolkit in place of readline"""
2 from __future__ import print_function
2 from __future__ import print_function
3
3
4 import os
4 import os
5 import sys
5 import sys
6 import signal
6 import signal
7 from warnings import warn
7 from warnings import warn
8
8
9 from IPython.core.error import TryNext
9 from IPython.core.error import TryNext
10 from IPython.core.interactiveshell import InteractiveShell, InteractiveShellABC
10 from IPython.core.interactiveshell import InteractiveShell, InteractiveShellABC
11 from IPython.utils.py3compat import PY3, cast_unicode_py2, input
11 from IPython.utils.py3compat import PY3, cast_unicode_py2, input
12 from IPython.utils.terminal import toggle_set_term_title, set_term_title
12 from IPython.utils.terminal import toggle_set_term_title, set_term_title
13 from IPython.utils.process import abbrev_cwd
13 from IPython.utils.process import abbrev_cwd
14 from traitlets import Bool, Unicode, Dict, Integer, observe, Instance
14 from traitlets import Bool, Unicode, Dict, Integer, observe, Instance, Type
15
15
16 from prompt_toolkit.enums import DEFAULT_BUFFER, SEARCH_BUFFER, EditingMode
16 from prompt_toolkit.enums import DEFAULT_BUFFER, SEARCH_BUFFER, EditingMode
17 from prompt_toolkit.filters import HasFocus, HasSelection, Condition, ViInsertMode, EmacsInsertMode, IsDone
17 from prompt_toolkit.filters import HasFocus, HasSelection, Condition, ViInsertMode, EmacsInsertMode, IsDone
18 from prompt_toolkit.history import InMemoryHistory
18 from prompt_toolkit.history import InMemoryHistory
19 from prompt_toolkit.shortcuts import create_prompt_application, create_eventloop, create_prompt_layout
19 from prompt_toolkit.shortcuts import create_prompt_application, create_eventloop, create_prompt_layout
20 from prompt_toolkit.interface import CommandLineInterface
20 from prompt_toolkit.interface import CommandLineInterface
21 from prompt_toolkit.key_binding.manager import KeyBindingManager
21 from prompt_toolkit.key_binding.manager import KeyBindingManager
22 from prompt_toolkit.keys import Keys
22 from prompt_toolkit.keys import Keys
23 from prompt_toolkit.layout.processors import ConditionalProcessor, HighlightMatchingBracketProcessor
23 from prompt_toolkit.layout.processors import ConditionalProcessor, HighlightMatchingBracketProcessor
24 from prompt_toolkit.styles import PygmentsStyle, DynamicStyle
24 from prompt_toolkit.styles import PygmentsStyle, DynamicStyle
25
25
26 from pygments.styles import get_style_by_name, get_all_styles
26 from pygments.styles import get_style_by_name, get_all_styles
27 from pygments.token import Token
27 from pygments.token import Token
28
28
29 from .debugger import TerminalPdb, Pdb
29 from .debugger import TerminalPdb, Pdb
30 from .magics import TerminalMagics
30 from .magics import TerminalMagics
31 from .pt_inputhooks import get_inputhook_func
31 from .pt_inputhooks import get_inputhook_func
32 from .prompts import Prompts, ClassicPrompts, RichPromptDisplayHook
32 from .prompts import Prompts, ClassicPrompts, RichPromptDisplayHook
33 from .ptutils import IPythonPTCompleter, IPythonPTLexer
33 from .ptutils import IPythonPTCompleter, IPythonPTLexer
34
34
35
35
36 def get_default_editor():
36 def get_default_editor():
37 try:
37 try:
38 ed = os.environ['EDITOR']
38 ed = os.environ['EDITOR']
39 if not PY3:
39 if not PY3:
40 ed = ed.decode()
40 ed = ed.decode()
41 return ed
41 return ed
42 except KeyError:
42 except KeyError:
43 pass
43 pass
44 except UnicodeError:
44 except UnicodeError:
45 warn("$EDITOR environment variable is not pure ASCII. Using platform "
45 warn("$EDITOR environment variable is not pure ASCII. Using platform "
46 "default editor.")
46 "default editor.")
47
47
48 if os.name == 'posix':
48 if os.name == 'posix':
49 return 'vi' # the only one guaranteed to be there!
49 return 'vi' # the only one guaranteed to be there!
50 else:
50 else:
51 return 'notepad' # same in Windows!
51 return 'notepad' # same in Windows!
52
52
53 _use_simple_prompt = 'IPY_TEST_SIMPLE_PROMPT' in os.environ or not sys.stdin.isatty()
53 _use_simple_prompt = 'IPY_TEST_SIMPLE_PROMPT' in os.environ or not sys.stdin.isatty()
54
54
55 class TerminalInteractiveShell(InteractiveShell):
55 class TerminalInteractiveShell(InteractiveShell):
56 colors_force = True
56 colors_force = True
57
57
58 space_for_menu = Integer(6, help='Number of line at the bottom of the screen '
58 space_for_menu = Integer(6, help='Number of line at the bottom of the screen '
59 'to reserve for the completion menu'
59 'to reserve for the completion menu'
60 ).tag(config=True)
60 ).tag(config=True)
61
61
62 def _space_for_menu_changed(self, old, new):
62 def _space_for_menu_changed(self, old, new):
63 self._update_layout()
63 self._update_layout()
64
64
65 pt_cli = None
65 pt_cli = None
66 debugger_history = None
66 debugger_history = None
67
67
68 simple_prompt = Bool(_use_simple_prompt,
68 simple_prompt = Bool(_use_simple_prompt,
69 help="""Use `raw_input` for the REPL, without completion, multiline input, and prompt colors.
69 help="""Use `raw_input` for the REPL, without completion, multiline input, and prompt colors.
70
70
71 Useful when controlling IPython as a subprocess, and piping STDIN/OUT/ERR. Known usage are:
71 Useful when controlling IPython as a subprocess, and piping STDIN/OUT/ERR. Known usage are:
72 IPython own testing machinery, and emacs inferior-shell integration through elpy.
72 IPython own testing machinery, and emacs inferior-shell integration through elpy.
73
73
74 This mode default to `True` if the `IPY_TEST_SIMPLE_PROMPT`
74 This mode default to `True` if the `IPY_TEST_SIMPLE_PROMPT`
75 environment variable is set, or the current terminal is not a tty.
75 environment variable is set, or the current terminal is not a tty.
76
76
77 """
77 """
78 ).tag(config=True)
78 ).tag(config=True)
79
79
80 @property
80 @property
81 def debugger_cls(self):
81 def debugger_cls(self):
82 return Pdb if self.simple_prompt else TerminalPdb
82 return Pdb if self.simple_prompt else TerminalPdb
83
83
84 autoedit_syntax = Bool(False,
84 autoedit_syntax = Bool(False,
85 help="auto editing of files with syntax errors.",
85 help="auto editing of files with syntax errors.",
86 ).tag(config=True)
86 ).tag(config=True)
87
87
88
88
89 confirm_exit = Bool(True,
89 confirm_exit = Bool(True,
90 help="""
90 help="""
91 Set to confirm when you try to exit IPython with an EOF (Control-D
91 Set to confirm when you try to exit IPython with an EOF (Control-D
92 in Unix, Control-Z/Enter in Windows). By typing 'exit' or 'quit',
92 in Unix, Control-Z/Enter in Windows). By typing 'exit' or 'quit',
93 you can force a direct exit without any confirmation.""",
93 you can force a direct exit without any confirmation.""",
94 ).tag(config=True)
94 ).tag(config=True)
95
95
96 editing_mode = Unicode('emacs',
96 editing_mode = Unicode('emacs',
97 help="Shortcut style to use at the prompt. 'vi' or 'emacs'.",
97 help="Shortcut style to use at the prompt. 'vi' or 'emacs'.",
98 ).tag(config=True)
98 ).tag(config=True)
99
99
100 mouse_support = Bool(False,
100 mouse_support = Bool(False,
101 help="Enable mouse support in the prompt"
101 help="Enable mouse support in the prompt"
102 ).tag(config=True)
102 ).tag(config=True)
103
103
104 highlighting_style = Unicode('default',
104 highlighting_style = Unicode('default',
105 help="The name of a Pygments style to use for syntax highlighting: \n %s" % ', '.join(get_all_styles())
105 help="The name of a Pygments style to use for syntax highlighting: \n %s" % ', '.join(get_all_styles())
106 ).tag(config=True)
106 ).tag(config=True)
107
107
108
108
109 @observe('highlighting_style')
109 @observe('highlighting_style')
110 def _highlighting_style_changed(self, change):
110 def _highlighting_style_changed(self, change):
111 self._style = self._make_style_from_name(self.highlighting_style)
111 self._style = self._make_style_from_name(self.highlighting_style)
112
112
113 highlighting_style_overrides = Dict(
113 highlighting_style_overrides = Dict(
114 help="Override highlighting format for specific tokens"
114 help="Override highlighting format for specific tokens"
115 ).tag(config=True)
115 ).tag(config=True)
116
116
117 editor = Unicode(get_default_editor(),
117 editor = Unicode(get_default_editor(),
118 help="Set the editor used by IPython (default to $EDITOR/vi/notepad)."
118 help="Set the editor used by IPython (default to $EDITOR/vi/notepad)."
119 ).tag(config=True)
119 ).tag(config=True)
120
120
121 prompts_class = Type(Prompts, config=True, help='Class used to generate Prompt token for prompt_toolkit')
122
121 prompts = Instance(Prompts)
123 prompts = Instance(Prompts)
122
124
123 def _prompts_default(self):
125 def _prompts_default(self):
124 return Prompts(self)
126 return self.prompts_class(self)
125
127
126 @observe('prompts')
128 @observe('prompts')
127 def _(self, change):
129 def _(self, change):
128 self._update_layout()
130 self._update_layout()
129
131
130 def _displayhook_class_default(self):
132 def _displayhook_class_default(self):
131 return RichPromptDisplayHook
133 return RichPromptDisplayHook
132
134
133 term_title = Bool(True,
135 term_title = Bool(True,
134 help="Automatically set the terminal title"
136 help="Automatically set the terminal title"
135 ).tag(config=True)
137 ).tag(config=True)
136
138
137 display_completions_in_columns = Bool(False,
139 display_completions_in_columns = Bool(False,
138 help="Display a multi column completion menu.",
140 help="Display a multi column completion menu.",
139 ).tag(config=True)
141 ).tag(config=True)
140
142
141 highlight_matching_brackets = Bool(True,
143 highlight_matching_brackets = Bool(True,
142 help="Highlight matching brackets .",
144 help="Highlight matching brackets .",
143 ).tag(config=True)
145 ).tag(config=True)
144
146
145 @observe('term_title')
147 @observe('term_title')
146 def init_term_title(self, change=None):
148 def init_term_title(self, change=None):
147 # Enable or disable the terminal title.
149 # Enable or disable the terminal title.
148 if self.term_title:
150 if self.term_title:
149 toggle_set_term_title(True)
151 toggle_set_term_title(True)
150 set_term_title('IPython: ' + abbrev_cwd())
152 set_term_title('IPython: ' + abbrev_cwd())
151 else:
153 else:
152 toggle_set_term_title(False)
154 toggle_set_term_title(False)
153
155
154 def init_prompt_toolkit_cli(self):
156 def init_prompt_toolkit_cli(self):
155 self._app = None
157 self._app = None
156 if self.simple_prompt:
158 if self.simple_prompt:
157 # Fall back to plain non-interactive output for tests.
159 # Fall back to plain non-interactive output for tests.
158 # This is very limited, and only accepts a single line.
160 # This is very limited, and only accepts a single line.
159 def prompt():
161 def prompt():
160 return cast_unicode_py2(input('In [%d]: ' % self.execution_count))
162 return cast_unicode_py2(input('In [%d]: ' % self.execution_count))
161 self.prompt_for_code = prompt
163 self.prompt_for_code = prompt
162 return
164 return
163
165
164 kbmanager = KeyBindingManager.for_prompt()
166 kbmanager = KeyBindingManager.for_prompt()
165 insert_mode = ViInsertMode() | EmacsInsertMode()
167 insert_mode = ViInsertMode() | EmacsInsertMode()
166 # Ctrl+J == Enter, seemingly
168 # Ctrl+J == Enter, seemingly
167 @kbmanager.registry.add_binding(Keys.ControlJ,
169 @kbmanager.registry.add_binding(Keys.ControlJ,
168 filter=(HasFocus(DEFAULT_BUFFER)
170 filter=(HasFocus(DEFAULT_BUFFER)
169 & ~HasSelection()
171 & ~HasSelection()
170 & insert_mode
172 & insert_mode
171 ))
173 ))
172 def _(event):
174 def _(event):
173 b = event.current_buffer
175 b = event.current_buffer
174 d = b.document
176 d = b.document
175 if not (d.on_last_line or d.cursor_position_row >= d.line_count
177 if not (d.on_last_line or d.cursor_position_row >= d.line_count
176 - d.empty_line_count_at_the_end()):
178 - d.empty_line_count_at_the_end()):
177 b.newline()
179 b.newline()
178 return
180 return
179
181
180 status, indent = self.input_splitter.check_complete(d.text)
182 status, indent = self.input_splitter.check_complete(d.text)
181
183
182 if (status != 'incomplete') and b.accept_action.is_returnable:
184 if (status != 'incomplete') and b.accept_action.is_returnable:
183 b.accept_action.validate_and_handle(event.cli, b)
185 b.accept_action.validate_and_handle(event.cli, b)
184 else:
186 else:
185 b.insert_text('\n' + (' ' * (indent or 0)))
187 b.insert_text('\n' + (' ' * (indent or 0)))
186
188
187 @kbmanager.registry.add_binding(Keys.ControlC, filter=HasFocus(DEFAULT_BUFFER))
189 @kbmanager.registry.add_binding(Keys.ControlC, filter=HasFocus(DEFAULT_BUFFER))
188 def _reset_buffer(event):
190 def _reset_buffer(event):
189 event.current_buffer.reset()
191 event.current_buffer.reset()
190
192
191 @kbmanager.registry.add_binding(Keys.ControlC, filter=HasFocus(SEARCH_BUFFER))
193 @kbmanager.registry.add_binding(Keys.ControlC, filter=HasFocus(SEARCH_BUFFER))
192 def _reset_search_buffer(event):
194 def _reset_search_buffer(event):
193 if event.current_buffer.document.text:
195 if event.current_buffer.document.text:
194 event.current_buffer.reset()
196 event.current_buffer.reset()
195 else:
197 else:
196 event.cli.push_focus(DEFAULT_BUFFER)
198 event.cli.push_focus(DEFAULT_BUFFER)
197
199
198 supports_suspend = Condition(lambda cli: hasattr(signal, 'SIGTSTP'))
200 supports_suspend = Condition(lambda cli: hasattr(signal, 'SIGTSTP'))
199
201
200 @kbmanager.registry.add_binding(Keys.ControlZ, filter=supports_suspend)
202 @kbmanager.registry.add_binding(Keys.ControlZ, filter=supports_suspend)
201 def _suspend_to_bg(event):
203 def _suspend_to_bg(event):
202 event.cli.suspend_to_background()
204 event.cli.suspend_to_background()
203
205
204 @Condition
206 @Condition
205 def cursor_in_leading_ws(cli):
207 def cursor_in_leading_ws(cli):
206 before = cli.application.buffer.document.current_line_before_cursor
208 before = cli.application.buffer.document.current_line_before_cursor
207 return (not before) or before.isspace()
209 return (not before) or before.isspace()
208
210
209 # Ctrl+I == Tab
211 # Ctrl+I == Tab
210 @kbmanager.registry.add_binding(Keys.ControlI,
212 @kbmanager.registry.add_binding(Keys.ControlI,
211 filter=(HasFocus(DEFAULT_BUFFER)
213 filter=(HasFocus(DEFAULT_BUFFER)
212 & ~HasSelection()
214 & ~HasSelection()
213 & insert_mode
215 & insert_mode
214 & cursor_in_leading_ws
216 & cursor_in_leading_ws
215 ))
217 ))
216 def _indent_buffer(event):
218 def _indent_buffer(event):
217 event.current_buffer.insert_text(' ' * 4)
219 event.current_buffer.insert_text(' ' * 4)
218
220
219 # Pre-populate history from IPython's history database
221 # Pre-populate history from IPython's history database
220 history = InMemoryHistory()
222 history = InMemoryHistory()
221 last_cell = u""
223 last_cell = u""
222 for __, ___, cell in self.history_manager.get_tail(self.history_load_length,
224 for __, ___, cell in self.history_manager.get_tail(self.history_load_length,
223 include_latest=True):
225 include_latest=True):
224 # Ignore blank lines and consecutive duplicates
226 # Ignore blank lines and consecutive duplicates
225 cell = cell.rstrip()
227 cell = cell.rstrip()
226 if cell and (cell != last_cell):
228 if cell and (cell != last_cell):
227 history.append(cell)
229 history.append(cell)
228
230
229 self._style = self._make_style_from_name(self.highlighting_style)
231 self._style = self._make_style_from_name(self.highlighting_style)
230 style = DynamicStyle(lambda: self._style)
232 style = DynamicStyle(lambda: self._style)
231
233
232 editing_mode = getattr(EditingMode, self.editing_mode.upper())
234 editing_mode = getattr(EditingMode, self.editing_mode.upper())
233
235
234 self._app = create_prompt_application(
236 self._app = create_prompt_application(
235 editing_mode=editing_mode,
237 editing_mode=editing_mode,
236 key_bindings_registry=kbmanager.registry,
238 key_bindings_registry=kbmanager.registry,
237 history=history,
239 history=history,
238 completer=IPythonPTCompleter(self.Completer),
240 completer=IPythonPTCompleter(self.Completer),
239 enable_history_search=True,
241 enable_history_search=True,
240 style=style,
242 style=style,
241 mouse_support=self.mouse_support,
243 mouse_support=self.mouse_support,
242 **self._layout_options()
244 **self._layout_options()
243 )
245 )
244 self._eventloop = create_eventloop(self.inputhook)
246 self._eventloop = create_eventloop(self.inputhook)
245 self.pt_cli = CommandLineInterface(self._app, eventloop=self._eventloop)
247 self.pt_cli = CommandLineInterface(self._app, eventloop=self._eventloop)
246
248
247 def _make_style_from_name(self, name):
249 def _make_style_from_name(self, name):
248 """
250 """
249 Small wrapper that make an IPython compatible style from a style name
251 Small wrapper that make an IPython compatible style from a style name
250
252
251 We need that to add style for prompt ... etc.
253 We need that to add style for prompt ... etc.
252 """
254 """
253 style_cls = get_style_by_name(name)
255 style_cls = get_style_by_name(name)
254 style_overrides = {
256 style_overrides = {
255 Token.Prompt: '#009900',
257 Token.Prompt: '#009900',
256 Token.PromptNum: '#00ff00 bold',
258 Token.PromptNum: '#00ff00 bold',
257 Token.OutPrompt: '#990000',
259 Token.OutPrompt: '#990000',
258 Token.OutPromptNum: '#ff0000 bold',
260 Token.OutPromptNum: '#ff0000 bold',
259 }
261 }
260 if name == 'default':
262 if name == 'default':
261 style_cls = get_style_by_name('default')
263 style_cls = get_style_by_name('default')
262 # The default theme needs to be visible on both a dark background
264 # The default theme needs to be visible on both a dark background
263 # and a light background, because we can't tell what the terminal
265 # and a light background, because we can't tell what the terminal
264 # looks like. These tweaks to the default theme help with that.
266 # looks like. These tweaks to the default theme help with that.
265 style_overrides.update({
267 style_overrides.update({
266 Token.Number: '#007700',
268 Token.Number: '#007700',
267 Token.Operator: 'noinherit',
269 Token.Operator: 'noinherit',
268 Token.String: '#BB6622',
270 Token.String: '#BB6622',
269 Token.Name.Function: '#2080D0',
271 Token.Name.Function: '#2080D0',
270 Token.Name.Class: 'bold #2080D0',
272 Token.Name.Class: 'bold #2080D0',
271 Token.Name.Namespace: 'bold #2080D0',
273 Token.Name.Namespace: 'bold #2080D0',
272 })
274 })
273 style_overrides.update(self.highlighting_style_overrides)
275 style_overrides.update(self.highlighting_style_overrides)
274 style = PygmentsStyle.from_defaults(pygments_style_cls=style_cls,
276 style = PygmentsStyle.from_defaults(pygments_style_cls=style_cls,
275 style_dict=style_overrides)
277 style_dict=style_overrides)
276
278
277 return style
279 return style
278
280
279 def _layout_options(self):
281 def _layout_options(self):
280 """
282 """
281 Return the current layout option for the current Terminal InteractiveShell
283 Return the current layout option for the current Terminal InteractiveShell
282 """
284 """
283 return {
285 return {
284 'lexer':IPythonPTLexer(),
286 'lexer':IPythonPTLexer(),
285 'reserve_space_for_menu':self.space_for_menu,
287 'reserve_space_for_menu':self.space_for_menu,
286 'get_prompt_tokens':self.prompts.in_prompt_tokens,
288 'get_prompt_tokens':self.prompts.in_prompt_tokens,
287 'get_continuation_tokens':self.prompts.continuation_prompt_tokens,
289 'get_continuation_tokens':self.prompts.continuation_prompt_tokens,
288 'multiline':True,
290 'multiline':True,
289 'display_completions_in_columns': self.display_completions_in_columns,
291 'display_completions_in_columns': self.display_completions_in_columns,
290
292
291 # Highlight matching brackets, but only when this setting is
293 # Highlight matching brackets, but only when this setting is
292 # enabled, and only when the DEFAULT_BUFFER has the focus.
294 # enabled, and only when the DEFAULT_BUFFER has the focus.
293 'extra_input_processors': [ConditionalProcessor(
295 'extra_input_processors': [ConditionalProcessor(
294 processor=HighlightMatchingBracketProcessor(chars='[](){}'),
296 processor=HighlightMatchingBracketProcessor(chars='[](){}'),
295 filter=HasFocus(DEFAULT_BUFFER) & ~IsDone() &
297 filter=HasFocus(DEFAULT_BUFFER) & ~IsDone() &
296 Condition(lambda cli: self.highlight_matching_brackets))],
298 Condition(lambda cli: self.highlight_matching_brackets))],
297 }
299 }
298
300
299 def _update_layout(self):
301 def _update_layout(self):
300 """
302 """
301 Ask for a re computation of the application layout, if for example ,
303 Ask for a re computation of the application layout, if for example ,
302 some configuration options have changed.
304 some configuration options have changed.
303 """
305 """
304 if self._app:
306 if getattr(self, '._app', None):
305 self._app.layout = create_prompt_layout(**self._layout_options())
307 self._app.layout = create_prompt_layout(**self._layout_options())
306
308
307 def prompt_for_code(self):
309 def prompt_for_code(self):
308 document = self.pt_cli.run(
310 document = self.pt_cli.run(
309 pre_run=self.pre_prompt, reset_current_buffer=True)
311 pre_run=self.pre_prompt, reset_current_buffer=True)
310 return document.text
312 return document.text
311
313
312 def init_io(self):
314 def init_io(self):
313 if sys.platform not in {'win32', 'cli'}:
315 if sys.platform not in {'win32', 'cli'}:
314 return
316 return
315
317
316 import colorama
318 import colorama
317 colorama.init()
319 colorama.init()
318
320
319 # For some reason we make these wrappers around stdout/stderr.
321 # For some reason we make these wrappers around stdout/stderr.
320 # For now, we need to reset them so all output gets coloured.
322 # For now, we need to reset them so all output gets coloured.
321 # https://github.com/ipython/ipython/issues/8669
323 # https://github.com/ipython/ipython/issues/8669
322 from IPython.utils import io
324 from IPython.utils import io
323 io.stdout = io.IOStream(sys.stdout)
325 io.stdout = io.IOStream(sys.stdout)
324 io.stderr = io.IOStream(sys.stderr)
326 io.stderr = io.IOStream(sys.stderr)
325
327
326 def init_magics(self):
328 def init_magics(self):
327 super(TerminalInteractiveShell, self).init_magics()
329 super(TerminalInteractiveShell, self).init_magics()
328 self.register_magics(TerminalMagics)
330 self.register_magics(TerminalMagics)
329
331
330 def init_alias(self):
332 def init_alias(self):
331 # The parent class defines aliases that can be safely used with any
333 # The parent class defines aliases that can be safely used with any
332 # frontend.
334 # frontend.
333 super(TerminalInteractiveShell, self).init_alias()
335 super(TerminalInteractiveShell, self).init_alias()
334
336
335 # Now define aliases that only make sense on the terminal, because they
337 # Now define aliases that only make sense on the terminal, because they
336 # need direct access to the console in a way that we can't emulate in
338 # need direct access to the console in a way that we can't emulate in
337 # GUI or web frontend
339 # GUI or web frontend
338 if os.name == 'posix':
340 if os.name == 'posix':
339 for cmd in ['clear', 'more', 'less', 'man']:
341 for cmd in ['clear', 'more', 'less', 'man']:
340 self.alias_manager.soft_define_alias(cmd, cmd)
342 self.alias_manager.soft_define_alias(cmd, cmd)
341
343
342
344
343 def __init__(self, *args, **kwargs):
345 def __init__(self, *args, **kwargs):
344 super(TerminalInteractiveShell, self).__init__(*args, **kwargs)
346 super(TerminalInteractiveShell, self).__init__(*args, **kwargs)
345 self.init_prompt_toolkit_cli()
347 self.init_prompt_toolkit_cli()
346 self.init_term_title()
348 self.init_term_title()
347 self.keep_running = True
349 self.keep_running = True
348
350
349 self.debugger_history = InMemoryHistory()
351 self.debugger_history = InMemoryHistory()
350
352
351 def ask_exit(self):
353 def ask_exit(self):
352 self.keep_running = False
354 self.keep_running = False
353
355
354 rl_next_input = None
356 rl_next_input = None
355
357
356 def pre_prompt(self):
358 def pre_prompt(self):
357 if self.rl_next_input:
359 if self.rl_next_input:
358 self.pt_cli.application.buffer.text = cast_unicode_py2(self.rl_next_input)
360 self.pt_cli.application.buffer.text = cast_unicode_py2(self.rl_next_input)
359 self.rl_next_input = None
361 self.rl_next_input = None
360
362
361 def interact(self):
363 def interact(self):
362 while self.keep_running:
364 while self.keep_running:
363 print(self.separate_in, end='')
365 print(self.separate_in, end='')
364
366
365 try:
367 try:
366 code = self.prompt_for_code()
368 code = self.prompt_for_code()
367 except EOFError:
369 except EOFError:
368 if (not self.confirm_exit) \
370 if (not self.confirm_exit) \
369 or self.ask_yes_no('Do you really want to exit ([y]/n)?','y','n'):
371 or self.ask_yes_no('Do you really want to exit ([y]/n)?','y','n'):
370 self.ask_exit()
372 self.ask_exit()
371
373
372 else:
374 else:
373 if code:
375 if code:
374 self.run_cell(code, store_history=True)
376 self.run_cell(code, store_history=True)
375 if self.autoedit_syntax and self.SyntaxTB.last_syntax_error:
377 if self.autoedit_syntax and self.SyntaxTB.last_syntax_error:
376 self.edit_syntax_error()
378 self.edit_syntax_error()
377
379
378 def mainloop(self):
380 def mainloop(self):
379 # An extra layer of protection in case someone mashing Ctrl-C breaks
381 # An extra layer of protection in case someone mashing Ctrl-C breaks
380 # out of our internal code.
382 # out of our internal code.
381 while True:
383 while True:
382 try:
384 try:
383 self.interact()
385 self.interact()
384 break
386 break
385 except KeyboardInterrupt:
387 except KeyboardInterrupt:
386 print("\nKeyboardInterrupt escaped interact()\n")
388 print("\nKeyboardInterrupt escaped interact()\n")
387
389
388 if hasattr(self, '_eventloop'):
390 if hasattr(self, '_eventloop'):
389 self._eventloop.close()
391 self._eventloop.close()
390
392
391 _inputhook = None
393 _inputhook = None
392 def inputhook(self, context):
394 def inputhook(self, context):
393 if self._inputhook is not None:
395 if self._inputhook is not None:
394 self._inputhook(context)
396 self._inputhook(context)
395
397
396 def enable_gui(self, gui=None):
398 def enable_gui(self, gui=None):
397 if gui:
399 if gui:
398 self._inputhook = get_inputhook_func(gui)
400 self._inputhook = get_inputhook_func(gui)
399 else:
401 else:
400 self._inputhook = None
402 self._inputhook = None
401
403
402 # Methods to support auto-editing of SyntaxErrors:
404 # Methods to support auto-editing of SyntaxErrors:
403
405
404 def edit_syntax_error(self):
406 def edit_syntax_error(self):
405 """The bottom half of the syntax error handler called in the main loop.
407 """The bottom half of the syntax error handler called in the main loop.
406
408
407 Loop until syntax error is fixed or user cancels.
409 Loop until syntax error is fixed or user cancels.
408 """
410 """
409
411
410 while self.SyntaxTB.last_syntax_error:
412 while self.SyntaxTB.last_syntax_error:
411 # copy and clear last_syntax_error
413 # copy and clear last_syntax_error
412 err = self.SyntaxTB.clear_err_state()
414 err = self.SyntaxTB.clear_err_state()
413 if not self._should_recompile(err):
415 if not self._should_recompile(err):
414 return
416 return
415 try:
417 try:
416 # may set last_syntax_error again if a SyntaxError is raised
418 # may set last_syntax_error again if a SyntaxError is raised
417 self.safe_execfile(err.filename, self.user_ns)
419 self.safe_execfile(err.filename, self.user_ns)
418 except:
420 except:
419 self.showtraceback()
421 self.showtraceback()
420 else:
422 else:
421 try:
423 try:
422 with open(err.filename) as f:
424 with open(err.filename) as f:
423 # This should be inside a display_trap block and I
425 # This should be inside a display_trap block and I
424 # think it is.
426 # think it is.
425 sys.displayhook(f.read())
427 sys.displayhook(f.read())
426 except:
428 except:
427 self.showtraceback()
429 self.showtraceback()
428
430
429 def _should_recompile(self, e):
431 def _should_recompile(self, e):
430 """Utility routine for edit_syntax_error"""
432 """Utility routine for edit_syntax_error"""
431
433
432 if e.filename in ('<ipython console>', '<input>', '<string>',
434 if e.filename in ('<ipython console>', '<input>', '<string>',
433 '<console>', '<BackgroundJob compilation>',
435 '<console>', '<BackgroundJob compilation>',
434 None):
436 None):
435 return False
437 return False
436 try:
438 try:
437 if (self.autoedit_syntax and
439 if (self.autoedit_syntax and
438 not self.ask_yes_no(
440 not self.ask_yes_no(
439 'Return to editor to correct syntax error? '
441 'Return to editor to correct syntax error? '
440 '[Y/n] ', 'y')):
442 '[Y/n] ', 'y')):
441 return False
443 return False
442 except EOFError:
444 except EOFError:
443 return False
445 return False
444
446
445 def int0(x):
447 def int0(x):
446 try:
448 try:
447 return int(x)
449 return int(x)
448 except TypeError:
450 except TypeError:
449 return 0
451 return 0
450
452
451 # always pass integer line and offset values to editor hook
453 # always pass integer line and offset values to editor hook
452 try:
454 try:
453 self.hooks.fix_error_editor(e.filename,
455 self.hooks.fix_error_editor(e.filename,
454 int0(e.lineno), int0(e.offset),
456 int0(e.lineno), int0(e.offset),
455 e.msg)
457 e.msg)
456 except TryNext:
458 except TryNext:
457 warn('Could not open editor')
459 warn('Could not open editor')
458 return False
460 return False
459 return True
461 return True
460
462
461 # Run !system commands directly, not through pipes, so terminal programs
463 # Run !system commands directly, not through pipes, so terminal programs
462 # work correctly.
464 # work correctly.
463 system = InteractiveShell.system_raw
465 system = InteractiveShell.system_raw
464
466
465 def auto_rewrite_input(self, cmd):
467 def auto_rewrite_input(self, cmd):
466 """Overridden from the parent class to use fancy rewriting prompt"""
468 """Overridden from the parent class to use fancy rewriting prompt"""
467 if not self.show_rewritten_input:
469 if not self.show_rewritten_input:
468 return
470 return
469
471
470 tokens = self.prompts.rewrite_prompt_tokens()
472 tokens = self.prompts.rewrite_prompt_tokens()
471 if self.pt_cli:
473 if self.pt_cli:
472 self.pt_cli.print_tokens(tokens)
474 self.pt_cli.print_tokens(tokens)
473 print(cmd)
475 print(cmd)
474 else:
476 else:
475 prompt = ''.join(s for t, s in tokens)
477 prompt = ''.join(s for t, s in tokens)
476 print(prompt, cmd, sep='')
478 print(prompt, cmd, sep='')
477
479
478 _prompts_before = None
480 _prompts_before = None
479 def switch_doctest_mode(self, mode):
481 def switch_doctest_mode(self, mode):
480 """Switch prompts to classic for %doctest_mode"""
482 """Switch prompts to classic for %doctest_mode"""
481 if mode:
483 if mode:
482 self._prompts_before = self.prompts
484 self._prompts_before = self.prompts
483 self.prompts = ClassicPrompts(self)
485 self.prompts = ClassicPrompts(self)
484 elif self._prompts_before:
486 elif self._prompts_before:
485 self.prompts = self._prompts_before
487 self.prompts = self._prompts_before
486 self._prompts_before = None
488 self._prompts_before = None
487
489
488
490
489 InteractiveShellABC.register(TerminalInteractiveShell)
491 InteractiveShellABC.register(TerminalInteractiveShell)
490
492
491 if __name__ == '__main__':
493 if __name__ == '__main__':
492 TerminalInteractiveShell.instance().interact()
494 TerminalInteractiveShell.instance().interact()
@@ -1,135 +1,146 b''
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2 """An example of how to embed an IPython shell into a running program.
2 """An example of how to embed an IPython shell into a running program.
3
3
4 Please see the documentation in the IPython.Shell module for more details.
4 Please see the documentation in the IPython.Shell module for more details.
5
5
6 The accompanying file embed_class_short.py has quick code fragments for
6 The accompanying file embed_class_short.py has quick code fragments for
7 embedding which you can cut and paste in your code once you understand how
7 embedding which you can cut and paste in your code once you understand how
8 things work.
8 things work.
9
9
10 The code in this file is deliberately extra-verbose, meant for learning."""
10 The code in this file is deliberately extra-verbose, meant for learning."""
11 from __future__ import print_function
11 from __future__ import print_function
12
12
13 # The basics to get you going:
13 # The basics to get you going:
14
14
15 # IPython injects get_ipython into builtins, so you can know if you have nested
15 # IPython injects get_ipython into builtins, so you can know if you have nested
16 # copies running.
16 # copies running.
17
17
18 # Try running this code both at the command line and from inside IPython (with
18 # Try running this code both at the command line and from inside IPython (with
19 # %run example-embed.py)
19 # %run example-embed.py)
20
21 from IPython.terminal.prompts import Prompts, Token
22
23 class CustomPrompt(Prompts):
24
25 def in_prompt_tokens(self, cli=None):
26
27 return [
28 (Token.Prompt, 'In <'),
29 (Token.PromptNum, str(self.shell.execution_count)),
30 (Token.Prompt, '>: '),
31 ]
32
33 def out_prompt_tokens(self):
34 return [
35 (Token.OutPrompt, 'Out<'),
36 (Token.OutPromptNum, str(self.shell.execution_count)),
37 (Token.OutPrompt, '>: '),
38 ]
39
40
20 from traitlets.config.loader import Config
41 from traitlets.config.loader import Config
21 try:
42 try:
22 get_ipython
43 get_ipython
23 except NameError:
44 except NameError:
24 nested = 0
45 nested = 0
25 cfg = Config()
46 cfg = Config()
26 prompt_config = cfg.PromptManager
47 cfg.TerminalInteractiveShell.prompts_class=CustomPrompt
27 prompt_config.in_template = 'In <\\#>: '
28 prompt_config.in2_template = ' .\\D.: '
29 prompt_config.out_template = 'Out<\\#>: '
30 else:
48 else:
31 print("Running nested copies of IPython.")
49 print("Running nested copies of IPython.")
32 print("The prompts for the nested copy have been modified")
50 print("The prompts for the nested copy have been modified")
33 cfg = Config()
51 cfg = Config()
34 nested = 1
52 nested = 1
35
53
36 # First import the embeddable shell class
54 # First import the embeddable shell class
37 from IPython.terminal.embed import InteractiveShellEmbed
55 from IPython.terminal.embed import InteractiveShellEmbed
38
56
39 # Now create an instance of the embeddable shell. The first argument is a
57 # Now create an instance of the embeddable shell. The first argument is a
40 # string with options exactly as you would type them if you were starting
58 # string with options exactly as you would type them if you were starting
41 # IPython at the system command line. Any parameters you want to define for
59 # IPython at the system command line. Any parameters you want to define for
42 # configuration can thus be specified here.
60 # configuration can thus be specified here.
43 ipshell = InteractiveShellEmbed(config=cfg,
61 ipshell = InteractiveShellEmbed(config=cfg,
44 banner1 = 'Dropping into IPython',
62 banner1 = 'Dropping into IPython',
45 exit_msg = 'Leaving Interpreter, back to program.')
63 exit_msg = 'Leaving Interpreter, back to program.')
46
64
47 # Make a second instance, you can have as many as you want.
65 # Make a second instance, you can have as many as you want.
48 cfg2 = cfg.copy()
49 prompt_config = cfg2.PromptManager
50 prompt_config.in_template = 'In2<\\#>: '
51 if not nested:
52 prompt_config.in_template = 'In2<\\#>: '
53 prompt_config.in2_template = ' .\\D.: '
54 prompt_config.out_template = 'Out<\\#>: '
55 ipshell2 = InteractiveShellEmbed(config=cfg,
66 ipshell2 = InteractiveShellEmbed(config=cfg,
56 banner1 = 'Second IPython instance.')
67 banner1 = 'Second IPython instance.')
57
68
58 print('\nHello. This is printed from the main controller program.\n')
69 print('\nHello. This is printed from the main controller program.\n')
59
70
60 # You can then call ipshell() anywhere you need it (with an optional
71 # You can then call ipshell() anywhere you need it (with an optional
61 # message):
72 # message):
62 ipshell('***Called from top level. '
73 ipshell('***Called from top level. '
63 'Hit Ctrl-D to exit interpreter and continue program.\n'
74 'Hit Ctrl-D to exit interpreter and continue program.\n'
64 'Note that if you use %kill_embedded, you can fully deactivate\n'
75 'Note that if you use %kill_embedded, you can fully deactivate\n'
65 'This embedded instance so it will never turn on again')
76 'This embedded instance so it will never turn on again')
66
77
67 print('\nBack in caller program, moving along...\n')
78 print('\nBack in caller program, moving along...\n')
68
79
69 #---------------------------------------------------------------------------
80 #---------------------------------------------------------------------------
70 # More details:
81 # More details:
71
82
72 # InteractiveShellEmbed instances don't print the standard system banner and
83 # InteractiveShellEmbed instances don't print the standard system banner and
73 # messages. The IPython banner (which actually may contain initialization
84 # messages. The IPython banner (which actually may contain initialization
74 # messages) is available as get_ipython().banner in case you want it.
85 # messages) is available as get_ipython().banner in case you want it.
75
86
76 # InteractiveShellEmbed instances print the following information everytime they
87 # InteractiveShellEmbed instances print the following information everytime they
77 # start:
88 # start:
78
89
79 # - A global startup banner.
90 # - A global startup banner.
80
91
81 # - A call-specific header string, which you can use to indicate where in the
92 # - A call-specific header string, which you can use to indicate where in the
82 # execution flow the shell is starting.
93 # execution flow the shell is starting.
83
94
84 # They also print an exit message every time they exit.
95 # They also print an exit message every time they exit.
85
96
86 # Both the startup banner and the exit message default to None, and can be set
97 # Both the startup banner and the exit message default to None, and can be set
87 # either at the instance constructor or at any other time with the
98 # either at the instance constructor or at any other time with the
88 # by setting the banner and exit_msg attributes.
99 # by setting the banner and exit_msg attributes.
89
100
90 # The shell instance can be also put in 'dummy' mode globally or on a per-call
101 # The shell instance can be also put in 'dummy' mode globally or on a per-call
91 # basis. This gives you fine control for debugging without having to change
102 # basis. This gives you fine control for debugging without having to change
92 # code all over the place.
103 # code all over the place.
93
104
94 # The code below illustrates all this.
105 # The code below illustrates all this.
95
106
96
107
97 # This is how the global banner and exit_msg can be reset at any point
108 # This is how the global banner and exit_msg can be reset at any point
98 ipshell.banner = 'Entering interpreter - New Banner'
109 ipshell.banner2 = 'Entering interpreter - New Banner'
99 ipshell.exit_msg = 'Leaving interpreter - New exit_msg'
110 ipshell.exit_msg = 'Leaving interpreter - New exit_msg'
100
111
101 def foo(m):
112 def foo(m):
102 s = 'spam'
113 s = 'spam'
103 ipshell('***In foo(). Try %whos, or print s or m:')
114 ipshell('***In foo(). Try %whos, or print s or m:')
104 print('foo says m = ',m)
115 print('foo says m = ',m)
105
116
106 def bar(n):
117 def bar(n):
107 s = 'eggs'
118 s = 'eggs'
108 ipshell('***In bar(). Try %whos, or print s or n:')
119 ipshell('***In bar(). Try %whos, or print s or n:')
109 print('bar says n = ',n)
120 print('bar says n = ',n)
110
121
111 # Some calls to the above functions which will trigger IPython:
122 # Some calls to the above functions which will trigger IPython:
112 print('Main program calling foo("eggs")\n')
123 print('Main program calling foo("eggs")\n')
113 foo('eggs')
124 foo('eggs')
114
125
115 # The shell can be put in 'dummy' mode where calls to it silently return. This
126 # The shell can be put in 'dummy' mode where calls to it silently return. This
116 # allows you, for example, to globally turn off debugging for a program with a
127 # allows you, for example, to globally turn off debugging for a program with a
117 # single call.
128 # single call.
118 ipshell.dummy_mode = True
129 ipshell.dummy_mode = True
119 print('\nTrying to call IPython which is now "dummy":')
130 print('\nTrying to call IPython which is now "dummy":')
120 ipshell()
131 ipshell()
121 print('Nothing happened...')
132 print('Nothing happened...')
122 # The global 'dummy' mode can still be overridden for a single call
133 # The global 'dummy' mode can still be overridden for a single call
123 print('\nOverriding dummy mode manually:')
134 print('\nOverriding dummy mode manually:')
124 ipshell(dummy=False)
135 ipshell(dummy=False)
125
136
126 # Reactivate the IPython shell
137 # Reactivate the IPython shell
127 ipshell.dummy_mode = False
138 ipshell.dummy_mode = False
128
139
129 print('You can even have multiple embedded instances:')
140 print('You can even have multiple embedded instances:')
130 ipshell2()
141 ipshell2()
131
142
132 print('\nMain program calling bar("spam")\n')
143 print('\nMain program calling bar("spam")\n')
133 bar('spam')
144 bar('spam')
134
145
135 print('Main program finished. Bye!')
146 print('Main program finished. Bye!')
General Comments 0
You need to be logged in to leave comments. Login now