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