##// END OF EJS Templates
Backport PR #9848: Allow to pass a pygments class to highlighting_style....
Matthias Bussonnier -
Show More
@@ -1,488 +1,493 b''
1 1 """IPython terminal interface using prompt_toolkit"""
2 2 from __future__ import print_function
3 3
4 4 import os
5 5 import sys
6 6 import warnings
7 7 from warnings import warn
8 8
9 9 from IPython.core.interactiveshell import InteractiveShell, InteractiveShellABC
10 10 from IPython.utils import io
11 from IPython.utils.py3compat import PY3, cast_unicode_py2, input
11 from IPython.utils.py3compat import PY3, cast_unicode_py2, input, string_types
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, Type, default, Enum
14 from traitlets import Bool, Unicode, Dict, Integer, observe, Instance, Type, default, Enum, Union
15 15
16 16 from prompt_toolkit.enums import DEFAULT_BUFFER, EditingMode
17 17 from prompt_toolkit.filters import (HasFocus, Condition, IsDone)
18 18 from prompt_toolkit.history import InMemoryHistory
19 19 from prompt_toolkit.shortcuts import create_prompt_application, create_eventloop, create_prompt_layout, create_output
20 20 from prompt_toolkit.interface import CommandLineInterface
21 21 from prompt_toolkit.key_binding.manager import KeyBindingManager
22 22 from prompt_toolkit.layout.processors import ConditionalProcessor, HighlightMatchingBracketProcessor
23 23 from prompt_toolkit.styles import PygmentsStyle, DynamicStyle
24 24
25 25 from pygments.styles import get_style_by_name, get_all_styles
26 from pygments.style import Style
26 27 from pygments.token import Token
27 28
28 29 from .debugger import TerminalPdb, Pdb
29 30 from .magics import TerminalMagics
30 31 from .pt_inputhooks import get_inputhook_func
31 32 from .prompts import Prompts, ClassicPrompts, RichPromptDisplayHook
32 33 from .ptutils import IPythonPTCompleter, IPythonPTLexer
33 34 from .shortcuts import register_ipython_shortcuts
34 35
35 36 DISPLAY_BANNER_DEPRECATED = object()
36 37
37 38
38 39 from pygments.style import Style
39 40
40 41 class _NoStyle(Style): pass
41 42
42 43
43 44
44 45 _style_overrides_light_bg = {
45 46 Token.Prompt: '#0000ff',
46 47 Token.PromptNum: '#0000ee bold',
47 48 Token.OutPrompt: '#cc0000',
48 49 Token.OutPromptNum: '#bb0000 bold',
49 50 }
50 51
51 52 _style_overrides_linux = {
52 53 Token.Prompt: '#00cc00',
53 54 Token.PromptNum: '#00bb00 bold',
54 55 Token.OutPrompt: '#cc0000',
55 56 Token.OutPromptNum: '#bb0000 bold',
56 57 }
57 58
58 59
59 60
60 61 def get_default_editor():
61 62 try:
62 63 ed = os.environ['EDITOR']
63 64 if not PY3:
64 65 ed = ed.decode()
65 66 return ed
66 67 except KeyError:
67 68 pass
68 69 except UnicodeError:
69 70 warn("$EDITOR environment variable is not pure ASCII. Using platform "
70 71 "default editor.")
71 72
72 73 if os.name == 'posix':
73 74 return 'vi' # the only one guaranteed to be there!
74 75 else:
75 76 return 'notepad' # same in Windows!
76 77
77 78 # conservatively check for tty
78 79 # overridden streams can result in things like:
79 80 # - sys.stdin = None
80 81 # - no isatty method
81 82 for _name in ('stdin', 'stdout', 'stderr'):
82 83 _stream = getattr(sys, _name)
83 84 if not _stream or not hasattr(_stream, 'isatty') or not _stream.isatty():
84 85 _is_tty = False
85 86 break
86 87 else:
87 88 _is_tty = True
88 89
89 90
90 91 _use_simple_prompt = ('IPY_TEST_SIMPLE_PROMPT' in os.environ) or (not _is_tty)
91 92
92 93 class TerminalInteractiveShell(InteractiveShell):
93 94 space_for_menu = Integer(6, help='Number of line at the bottom of the screen '
94 95 'to reserve for the completion menu'
95 96 ).tag(config=True)
96 97
97 98 def _space_for_menu_changed(self, old, new):
98 99 self._update_layout()
99 100
100 101 pt_cli = None
101 102 debugger_history = None
102 103 _pt_app = None
103 104
104 105 simple_prompt = Bool(_use_simple_prompt,
105 106 help="""Use `raw_input` for the REPL, without completion, multiline input, and prompt colors.
106 107
107 108 Useful when controlling IPython as a subprocess, and piping STDIN/OUT/ERR. Known usage are:
108 109 IPython own testing machinery, and emacs inferior-shell integration through elpy.
109 110
110 111 This mode default to `True` if the `IPY_TEST_SIMPLE_PROMPT`
111 112 environment variable is set, or the current terminal is not a tty.
112 113
113 114 """
114 115 ).tag(config=True)
115 116
116 117 @property
117 118 def debugger_cls(self):
118 119 return Pdb if self.simple_prompt else TerminalPdb
119 120
120 121 confirm_exit = Bool(True,
121 122 help="""
122 123 Set to confirm when you try to exit IPython with an EOF (Control-D
123 124 in Unix, Control-Z/Enter in Windows). By typing 'exit' or 'quit',
124 125 you can force a direct exit without any confirmation.""",
125 126 ).tag(config=True)
126 127
127 128 editing_mode = Unicode('emacs',
128 129 help="Shortcut style to use at the prompt. 'vi' or 'emacs'.",
129 130 ).tag(config=True)
130 131
131 132 mouse_support = Bool(False,
132 133 help="Enable mouse support in the prompt"
133 134 ).tag(config=True)
134 135
135 highlighting_style = Unicode('legacy',
136 help="The name of a Pygments style to use for syntax highlighting: \n %s" % ', '.join(get_all_styles())
136 highlighting_style = Union([Unicode('legacy'), Type(klass=Style)],
137 help="""The name or class of a Pygments style to use for syntax
138 highlighting: \n %s""" % ', '.join(get_all_styles())
137 139 ).tag(config=True)
138 140
139 141
140 142 @observe('highlighting_style')
141 143 @observe('colors')
142 144 def _highlighting_style_changed(self, change):
143 145 self.refresh_style()
144 146
145 147 def refresh_style(self):
146 self._style = self._make_style_from_name(self.highlighting_style)
148 self._style = self._make_style_from_name_or_cls(self.highlighting_style)
147 149
148 150
149 151 highlighting_style_overrides = Dict(
150 152 help="Override highlighting format for specific tokens"
151 153 ).tag(config=True)
152 154
153 155 true_color = Bool(False,
154 156 help=("Use 24bit colors instead of 256 colors in prompt highlighting. "
155 157 "If your terminal supports true color, the following command "
156 158 "should print 'TRUECOLOR' in orange: "
157 159 "printf \"\\x1b[38;2;255;100;0mTRUECOLOR\\x1b[0m\\n\"")
158 160 ).tag(config=True)
159 161
160 162 editor = Unicode(get_default_editor(),
161 163 help="Set the editor used by IPython (default to $EDITOR/vi/notepad)."
162 164 ).tag(config=True)
163 165
164 166 prompts_class = Type(Prompts, help='Class used to generate Prompt token for prompt_toolkit').tag(config=True)
165 167
166 168 prompts = Instance(Prompts)
167 169
168 170 @default('prompts')
169 171 def _prompts_default(self):
170 172 return self.prompts_class(self)
171 173
172 174 @observe('prompts')
173 175 def _(self, change):
174 176 self._update_layout()
175 177
176 178 @default('displayhook_class')
177 179 def _displayhook_class_default(self):
178 180 return RichPromptDisplayHook
179 181
180 182 term_title = Bool(True,
181 183 help="Automatically set the terminal title"
182 184 ).tag(config=True)
183 185
184 186 display_completions = Enum(('column', 'multicolumn','readlinelike'),
185 187 help= ( "Options for displaying tab completions, 'column', 'multicolumn', and "
186 188 "'readlinelike'. These options are for `prompt_toolkit`, see "
187 189 "`prompt_toolkit` documentation for more information."
188 190 ),
189 191 default_value='multicolumn').tag(config=True)
190 192
191 193 highlight_matching_brackets = Bool(True,
192 194 help="Highlight matching brackets .",
193 195 ).tag(config=True)
194 196
195 197 @observe('term_title')
196 198 def init_term_title(self, change=None):
197 199 # Enable or disable the terminal title.
198 200 if self.term_title:
199 201 toggle_set_term_title(True)
200 202 set_term_title('IPython: ' + abbrev_cwd())
201 203 else:
202 204 toggle_set_term_title(False)
203 205
204 206 def init_display_formatter(self):
205 207 super(TerminalInteractiveShell, self).init_display_formatter()
206 208 # terminal only supports plain text
207 209 self.display_formatter.active_types = ['text/plain']
208 210
209 211 def init_prompt_toolkit_cli(self):
210 212 if self.simple_prompt:
211 213 # Fall back to plain non-interactive output for tests.
212 214 # This is very limited, and only accepts a single line.
213 215 def prompt():
214 216 return cast_unicode_py2(input('In [%d]: ' % self.execution_count))
215 217 self.prompt_for_code = prompt
216 218 return
217 219
218 220 # Set up keyboard shortcuts
219 221 kbmanager = KeyBindingManager.for_prompt()
220 222 register_ipython_shortcuts(kbmanager.registry, self)
221 223
222 224 # Pre-populate history from IPython's history database
223 225 history = InMemoryHistory()
224 226 last_cell = u""
225 227 for __, ___, cell in self.history_manager.get_tail(self.history_load_length,
226 228 include_latest=True):
227 229 # Ignore blank lines and consecutive duplicates
228 230 cell = cell.rstrip()
229 231 if cell and (cell != last_cell):
230 232 history.append(cell)
231 233
232 self._style = self._make_style_from_name(self.highlighting_style)
234 self._style = self._make_style_from_name_or_cls(self.highlighting_style)
233 235 style = DynamicStyle(lambda: self._style)
234 236
235 237 editing_mode = getattr(EditingMode, self.editing_mode.upper())
236 238
237 239 self._pt_app = create_prompt_application(
238 240 editing_mode=editing_mode,
239 241 key_bindings_registry=kbmanager.registry,
240 242 history=history,
241 243 completer=IPythonPTCompleter(shell=self),
242 244 enable_history_search=True,
243 245 style=style,
244 246 mouse_support=self.mouse_support,
245 247 **self._layout_options()
246 248 )
247 249 self._eventloop = create_eventloop(self.inputhook)
248 250 self.pt_cli = CommandLineInterface(
249 251 self._pt_app, eventloop=self._eventloop,
250 252 output=create_output(true_color=self.true_color))
251 253
252 def _make_style_from_name(self, name):
254 def _make_style_from_name_or_cls(self, name_or_cls):
253 255 """
254 256 Small wrapper that make an IPython compatible style from a style name
255 257
256 258 We need that to add style for prompt ... etc.
257 259 """
258 260 style_overrides = {}
259 if name == 'legacy':
261 if name_or_cls == 'legacy':
260 262 legacy = self.colors.lower()
261 263 if legacy == 'linux':
262 264 style_cls = get_style_by_name('monokai')
263 265 style_overrides = _style_overrides_linux
264 266 elif legacy == 'lightbg':
265 267 style_overrides = _style_overrides_light_bg
266 268 style_cls = get_style_by_name('pastie')
267 269 elif legacy == 'neutral':
268 270 # The default theme needs to be visible on both a dark background
269 271 # and a light background, because we can't tell what the terminal
270 272 # looks like. These tweaks to the default theme help with that.
271 273 style_cls = get_style_by_name('default')
272 274 style_overrides.update({
273 275 Token.Number: '#007700',
274 276 Token.Operator: 'noinherit',
275 277 Token.String: '#BB6622',
276 278 Token.Name.Function: '#2080D0',
277 279 Token.Name.Class: 'bold #2080D0',
278 280 Token.Name.Namespace: 'bold #2080D0',
279 281 Token.Prompt: '#009900',
280 282 Token.PromptNum: '#00ff00 bold',
281 283 Token.OutPrompt: '#990000',
282 284 Token.OutPromptNum: '#ff0000 bold',
283 285 })
284 286 elif legacy =='nocolor':
285 287 style_cls=_NoStyle
286 288 style_overrides = {}
287 289 else :
288 290 raise ValueError('Got unknown colors: ', legacy)
289 291 else :
290 style_cls = get_style_by_name(name)
292 if isinstance(name_or_cls, string_types):
293 style_cls = get_style_by_name(name_or_cls)
294 else:
295 style_cls = name_or_cls
291 296 style_overrides = {
292 297 Token.Prompt: '#009900',
293 298 Token.PromptNum: '#00ff00 bold',
294 299 Token.OutPrompt: '#990000',
295 300 Token.OutPromptNum: '#ff0000 bold',
296 301 }
297 302 style_overrides.update(self.highlighting_style_overrides)
298 303 style = PygmentsStyle.from_defaults(pygments_style_cls=style_cls,
299 304 style_dict=style_overrides)
300 305
301 306 return style
302 307
303 308 def _layout_options(self):
304 309 """
305 310 Return the current layout option for the current Terminal InteractiveShell
306 311 """
307 312 return {
308 313 'lexer':IPythonPTLexer(),
309 314 'reserve_space_for_menu':self.space_for_menu,
310 315 'get_prompt_tokens':self.prompts.in_prompt_tokens,
311 316 'get_continuation_tokens':self.prompts.continuation_prompt_tokens,
312 317 'multiline':True,
313 318 'display_completions_in_columns': (self.display_completions == 'multicolumn'),
314 319
315 320 # Highlight matching brackets, but only when this setting is
316 321 # enabled, and only when the DEFAULT_BUFFER has the focus.
317 322 'extra_input_processors': [ConditionalProcessor(
318 323 processor=HighlightMatchingBracketProcessor(chars='[](){}'),
319 324 filter=HasFocus(DEFAULT_BUFFER) & ~IsDone() &
320 325 Condition(lambda cli: self.highlight_matching_brackets))],
321 326 }
322 327
323 328 def _update_layout(self):
324 329 """
325 330 Ask for a re computation of the application layout, if for example ,
326 331 some configuration options have changed.
327 332 """
328 333 if self._pt_app:
329 334 self._pt_app.layout = create_prompt_layout(**self._layout_options())
330 335
331 336 def prompt_for_code(self):
332 337 document = self.pt_cli.run(
333 338 pre_run=self.pre_prompt, reset_current_buffer=True)
334 339 return document.text
335 340
336 341 def enable_win_unicode_console(self):
337 342 import win_unicode_console
338 343
339 344 if PY3:
340 345 win_unicode_console.enable()
341 346 else:
342 347 # https://github.com/ipython/ipython/issues/9768
343 348 from win_unicode_console.streams import (TextStreamWrapper,
344 349 stdout_text_transcoded, stderr_text_transcoded)
345 350
346 351 class LenientStrStreamWrapper(TextStreamWrapper):
347 352 def write(self, s):
348 353 if isinstance(s, bytes):
349 354 s = s.decode(self.encoding, 'replace')
350 355
351 356 self.base.write(s)
352 357
353 358 stdout_text_str = LenientStrStreamWrapper(stdout_text_transcoded)
354 359 stderr_text_str = LenientStrStreamWrapper(stderr_text_transcoded)
355 360
356 361 win_unicode_console.enable(stdout=stdout_text_str,
357 362 stderr=stderr_text_str)
358 363
359 364 def init_io(self):
360 365 if sys.platform not in {'win32', 'cli'}:
361 366 return
362 367
363 368 self.enable_win_unicode_console()
364 369
365 370 import colorama
366 371 colorama.init()
367 372
368 373 # For some reason we make these wrappers around stdout/stderr.
369 374 # For now, we need to reset them so all output gets coloured.
370 375 # https://github.com/ipython/ipython/issues/8669
371 376 # io.std* are deprecated, but don't show our own deprecation warnings
372 377 # during initialization of the deprecated API.
373 378 with warnings.catch_warnings():
374 379 warnings.simplefilter('ignore', DeprecationWarning)
375 380 io.stdout = io.IOStream(sys.stdout)
376 381 io.stderr = io.IOStream(sys.stderr)
377 382
378 383 def init_magics(self):
379 384 super(TerminalInteractiveShell, self).init_magics()
380 385 self.register_magics(TerminalMagics)
381 386
382 387 def init_alias(self):
383 388 # The parent class defines aliases that can be safely used with any
384 389 # frontend.
385 390 super(TerminalInteractiveShell, self).init_alias()
386 391
387 392 # Now define aliases that only make sense on the terminal, because they
388 393 # need direct access to the console in a way that we can't emulate in
389 394 # GUI or web frontend
390 395 if os.name == 'posix':
391 396 for cmd in ['clear', 'more', 'less', 'man']:
392 397 self.alias_manager.soft_define_alias(cmd, cmd)
393 398
394 399
395 400 def __init__(self, *args, **kwargs):
396 401 super(TerminalInteractiveShell, self).__init__(*args, **kwargs)
397 402 self.init_prompt_toolkit_cli()
398 403 self.init_term_title()
399 404 self.keep_running = True
400 405
401 406 self.debugger_history = InMemoryHistory()
402 407
403 408 def ask_exit(self):
404 409 self.keep_running = False
405 410
406 411 rl_next_input = None
407 412
408 413 def pre_prompt(self):
409 414 if self.rl_next_input:
410 415 self.pt_cli.application.buffer.text = cast_unicode_py2(self.rl_next_input)
411 416 self.rl_next_input = None
412 417
413 418 def interact(self, display_banner=DISPLAY_BANNER_DEPRECATED):
414 419
415 420 if display_banner is not DISPLAY_BANNER_DEPRECATED:
416 421 warn('interact `display_banner` argument is deprecated since IPython 5.0. Call `show_banner()` if needed.', DeprecationWarning, stacklevel=2)
417 422
418 423 self.keep_running = True
419 424 while self.keep_running:
420 425 print(self.separate_in, end='')
421 426
422 427 try:
423 428 code = self.prompt_for_code()
424 429 except EOFError:
425 430 if (not self.confirm_exit) \
426 431 or self.ask_yes_no('Do you really want to exit ([y]/n)?','y','n'):
427 432 self.ask_exit()
428 433
429 434 else:
430 435 if code:
431 436 self.run_cell(code, store_history=True)
432 437
433 438 def mainloop(self, display_banner=DISPLAY_BANNER_DEPRECATED):
434 439 # An extra layer of protection in case someone mashing Ctrl-C breaks
435 440 # out of our internal code.
436 441 if display_banner is not DISPLAY_BANNER_DEPRECATED:
437 442 warn('mainloop `display_banner` argument is deprecated since IPython 5.0. Call `show_banner()` if needed.', DeprecationWarning, stacklevel=2)
438 443 while True:
439 444 try:
440 445 self.interact()
441 446 break
442 447 except KeyboardInterrupt:
443 448 print("\nKeyboardInterrupt escaped interact()\n")
444 449
445 450 _inputhook = None
446 451 def inputhook(self, context):
447 452 if self._inputhook is not None:
448 453 self._inputhook(context)
449 454
450 455 def enable_gui(self, gui=None):
451 456 if gui:
452 457 self._inputhook = get_inputhook_func(gui)
453 458 else:
454 459 self._inputhook = None
455 460
456 461 # Run !system commands directly, not through pipes, so terminal programs
457 462 # work correctly.
458 463 system = InteractiveShell.system_raw
459 464
460 465 def auto_rewrite_input(self, cmd):
461 466 """Overridden from the parent class to use fancy rewriting prompt"""
462 467 if not self.show_rewritten_input:
463 468 return
464 469
465 470 tokens = self.prompts.rewrite_prompt_tokens()
466 471 if self.pt_cli:
467 472 self.pt_cli.print_tokens(tokens)
468 473 print(cmd)
469 474 else:
470 475 prompt = ''.join(s for t, s in tokens)
471 476 print(prompt, cmd, sep='')
472 477
473 478 _prompts_before = None
474 479 def switch_doctest_mode(self, mode):
475 480 """Switch prompts to classic for %doctest_mode"""
476 481 if mode:
477 482 self._prompts_before = self.prompts
478 483 self.prompts = ClassicPrompts(self)
479 484 elif self._prompts_before:
480 485 self.prompts = self._prompts_before
481 486 self._prompts_before = None
482 487 self._update_layout()
483 488
484 489
485 490 InteractiveShellABC.register(TerminalInteractiveShell)
486 491
487 492 if __name__ == '__main__':
488 493 TerminalInteractiveShell.instance().interact()
@@ -1,229 +1,230 b''
1 1 =======================
2 2 Specific config details
3 3 =======================
4 4
5 5 .. _custom_prompts:
6 6
7 7 Custom Prompts
8 8 ==============
9 9
10 10 .. versionchanged:: 5.0
11 11
12 12 From IPython 5, prompts are produced as a list of Pygments tokens, which are
13 13 tuples of (token_type, text). You can customise prompts by writing a method
14 14 which generates a list of tokens.
15 15
16 16 There are four kinds of prompt:
17 17
18 18 * The **in** prompt is shown before the first line of input
19 19 (default like ``In [1]:``).
20 20 * The **continuation** prompt is shown before further lines of input
21 21 (default like ``...:``).
22 22 * The **rewrite** prompt is shown to highlight how special syntax has been
23 23 interpreted (default like ``----->``).
24 24 * The **out** prompt is shown before the result from evaluating the input
25 25 (default like ``Out[1]:``).
26 26
27 27 Custom prompts are supplied together as a class. If you want to customise only
28 28 some of the prompts, inherit from :class:`IPython.terminal.prompts.Prompts`,
29 29 which defines the defaults. The required interface is like this:
30 30
31 31 .. class:: MyPrompts(shell)
32 32
33 33 Prompt style definition. *shell* is a reference to the
34 34 :class:`~.TerminalInteractiveShell` instance.
35 35
36 36 .. method:: in_prompt_tokens(cli=None)
37 37 continuation_prompt_tokens(self, cli=None, width=None)
38 38 rewrite_prompt_tokens()
39 39 out_prompt_tokens()
40 40
41 41 Return the respective prompts as lists of ``(token_type, text)`` tuples.
42 42
43 43 For continuation prompts, *width* is an integer representing the width of
44 44 the prompt area in terminal columns.
45 45
46 46 *cli*, where used, is the prompt_toolkit ``CommandLineInterface`` instance.
47 47 This is mainly for compatibility with the API prompt_toolkit expects.
48 48
49 49 Here is an example Prompt class that will show the current working directory
50 50 in the input prompt:
51 51
52 52 .. code-block:: python
53 53
54 54 from IPython.terminal.prompts import Prompts, Token
55 55 import os
56 56
57 57 class MyPrompt(Prompts):
58 58 def in_prompt_tokens(self, cli=None):
59 59 return [(Token, os.getcwd()),
60 60 (Token.Prompt, ' >>>')]
61 61
62 62 To set the new prompt, assign it to the ``prompts`` attribute of the IPython
63 63 shell:
64 64
65 65 .. code-block:: python
66 66
67 67 In [2]: ip = get_ipython()
68 68 ...: ip.prompts = MyPrompt(ip)
69 69
70 70 /home/bob >>> # it works
71 71
72 72 See ``IPython/example/utils/cwd_prompt.py`` for an example of how to write an
73 73 extensions to customise prompts.
74 74
75 75 Inside IPython or in a startup script, you can use a custom prompts class
76 76 by setting ``get_ipython().prompts`` to an *instance* of the class.
77 77 In configuration, ``TerminalInteractiveShell.prompts_class`` may be set to
78 78 either the class object, or a string of its full importable name.
79 79
80 80 To include invisible terminal control sequences in a prompt, use
81 81 ``Token.ZeroWidthEscape`` as the token type. Tokens with this type are ignored
82 82 when calculating the width.
83 83
84 84 Colours in the prompt are determined by the token types and the highlighting
85 85 style; see below for more details. The tokens used in the default prompts are
86 86 ``Prompt``, ``PromptNum``, ``OutPrompt`` and ``OutPromptNum``.
87 87
88 88 .. _termcolour:
89 89
90 90 Terminal Colors
91 91 ===============
92 92
93 93 .. versionchanged:: 5.0
94 94
95 95 There are two main configuration options controlling colours.
96 96
97 97 ``InteractiveShell.colors`` sets the colour of tracebacks and object info (the
98 98 output from e.g. ``zip?``). It may also affect other things if the option below
99 99 is set to ``'legacy'``. It has four case-insensitive values:
100 100 ``'nocolor', 'neutral', 'linux', 'lightbg'``. The default is *neutral*, which
101 101 should be legible on either dark or light terminal backgrounds. *linux* is
102 102 optimised for dark backgrounds and *lightbg* for light ones.
103 103
104 ``TerminalInteractiveShell.highlighting_style`` determines prompt colours and syntax
105 highlighting. It takes the name of a Pygments style as a string, or the special
106 value ``'legacy'`` to pick a style in accordance with ``InteractiveShell.colors``.
104 ``TerminalInteractiveShell.highlighting_style`` determines prompt colours and
105 syntax highlighting. It takes the name (as a string) or class (as a subclass of
106 ``pygments.style.Style``) of a Pygments style, or the special value ``'legacy'``
107 to pick a style in accordance with ``InteractiveShell.colors``.
107 108
108 109 You can see the Pygments styles available on your system by running::
109 110
110 111 import pygments
111 112 list(pygments.styles.get_all_styles())
112 113
113 114 Additionally, ``TerminalInteractiveShell.highlighting_style_overrides`` can override
114 115 specific styles in the highlighting. It should be a dictionary mapping Pygments
115 116 token types to strings defining the style. See `Pygments' documentation
116 117 <http://pygments.org/docs/styles/#creating-own-styles>`__ for the language used
117 118 to define styles.
118 119
119 120 Colors in the pager
120 121 -------------------
121 122
122 123 On some systems, the default pager has problems with ANSI colour codes.
123 124 To configure your default pager to allow these:
124 125
125 126 1. Set the environment PAGER variable to ``less``.
126 127 2. Set the environment LESS variable to ``-r`` (plus any other options
127 128 you always want to pass to less by default). This tells less to
128 129 properly interpret control sequences, which is how color
129 130 information is given to your terminal.
130 131
131 132 .. _editors:
132 133
133 134 Editor configuration
134 135 ====================
135 136
136 137 IPython can integrate with text editors in a number of different ways:
137 138
138 139 * Editors (such as `(X)Emacs`_, vim_ and TextMate_) can
139 140 send code to IPython for execution.
140 141
141 142 * IPython's ``%edit`` magic command can open an editor of choice to edit
142 143 a code block.
143 144
144 145 The %edit command (and its alias %ed) will invoke the editor set in your
145 146 environment as :envvar:`EDITOR`. If this variable is not set, it will default
146 147 to vi under Linux/Unix and to notepad under Windows. You may want to set this
147 148 variable properly and to a lightweight editor which doesn't take too long to
148 149 start (that is, something other than a new instance of Emacs). This way you
149 150 can edit multi-line code quickly and with the power of a real editor right
150 151 inside IPython.
151 152
152 153 You can also control the editor by setting :attr:`TerminalInteractiveShell.editor`
153 154 in :file:`ipython_config.py`.
154 155
155 156 Vim
156 157 ---
157 158
158 159 Paul Ivanov's `vim-ipython <https://github.com/ivanov/vim-ipython>`_ provides
159 160 powerful IPython integration for vim.
160 161
161 162 .. _emacs:
162 163
163 164 (X)Emacs
164 165 --------
165 166
166 167 If you are a dedicated Emacs user, and want to use Emacs when IPython's
167 168 ``%edit`` magic command is called you should set up the Emacs server so that
168 169 new requests are handled by the original process. This means that almost no
169 170 time is spent in handling the request (assuming an Emacs process is already
170 171 running). For this to work, you need to set your EDITOR environment variable
171 172 to 'emacsclient'. The code below, supplied by Francois Pinard, can then be
172 173 used in your :file:`.emacs` file to enable the server:
173 174
174 175 .. code-block:: common-lisp
175 176
176 177 (defvar server-buffer-clients)
177 178 (when (and (fboundp 'server-start) (string-equal (getenv "TERM") 'xterm))
178 179 (server-start)
179 180 (defun fp-kill-server-with-buffer-routine ()
180 181 (and server-buffer-clients (server-done)))
181 182 (add-hook 'kill-buffer-hook 'fp-kill-server-with-buffer-routine))
182 183
183 184 Thanks to the work of Alexander Schmolck and Prabhu Ramachandran,
184 185 currently (X)Emacs and IPython get along very well in other ways.
185 186
186 187 With (X)EMacs >= 24, You can enable IPython in python-mode with:
187 188
188 189 .. code-block:: common-lisp
189 190
190 191 (require 'python)
191 192 (setq python-shell-interpreter "ipython")
192 193
193 194 .. _`(X)Emacs`: http://www.gnu.org/software/emacs/
194 195 .. _TextMate: http://macromates.com/
195 196 .. _vim: http://www.vim.org/
196 197
197 198 .. _custom_keyboard_shortcuts
198 199
199 200 Keyboard Shortcuts
200 201 ==================
201 202
202 203 .. versionchanged:: 5.0
203 204
204 205 You can customise keyboard shortcuts for terminal IPython. Put code like this in
205 206 a :ref:`startup file <startup_files>`::
206 207
207 208 from IPython import get_ipython
208 209 from prompt_toolkit.enums import DEFAULT_BUFFER
209 210 from prompt_toolkit.keys import Keys
210 211 from prompt_toolkit.filters import HasFocus, HasSelection, ViInsertMode, EmacsInsertMode
211 212
212 213 ip = get_ipython()
213 214 insert_mode = ViInsertMode() | EmacsInsertMode()
214 215
215 216 def insert_unexpected(event):
216 217 buf = event.current_buffer
217 218 buf.insert_text('The Spanish Inquisition')
218 219
219 220 # Register the shortcut if IPython is using prompt_toolkit
220 221 if getattr(ip, 'pt_cli'):
221 222 registry = ip.pt_cli.application.key_bindings_registry
222 223 registry.add_binding(Keys.ControlN,
223 224 filter=(HasFocus(DEFAULT_BUFFER)
224 225 & ~HasSelection()
225 226 & insert_mode))(insert_unexpected)
226 227
227 228 For more information on filters and what you can do with the ``event`` object,
228 229 `see the prompt_toolkit docs
229 230 <http://python-prompt-toolkit.readthedocs.io/en/latest/pages/building_prompts.html#adding-custom-key-bindings>`__.
General Comments 0
You need to be logged in to leave comments. Login now