##// END OF EJS Templates
Move most readline code from InteractiveShell to terminal subclass...
Thomas Kluyver -
Show More
@@ -62,6 +62,7 b' from IPython.utils import PyColorize'
62 from IPython.utils import io
62 from IPython.utils import io
63 from IPython.utils import py3compat
63 from IPython.utils import py3compat
64 from IPython.utils import openpy
64 from IPython.utils import openpy
65 from IPython.utils.contexts import NoOpContext
65 from IPython.utils.decorators import undoc
66 from IPython.utils.decorators import undoc
66 from IPython.utils.io import ask_yes_no
67 from IPython.utils.io import ask_yes_no
67 from IPython.utils.ipstruct import Struct
68 from IPython.utils.ipstruct import Struct
@@ -109,11 +110,6 b' def softspace(file, newvalue):'
109 @undoc
110 @undoc
110 def no_op(*a, **kw): pass
111 def no_op(*a, **kw): pass
111
112
112 @undoc
113 class NoOpContext(object):
114 def __enter__(self): pass
115 def __exit__(self, type, value, traceback): pass
116 no_op_context = NoOpContext()
117
113
118 class SpaceInInput(Exception): pass
114 class SpaceInInput(Exception): pass
119
115
@@ -142,52 +138,6 b' class SeparateUnicode(Unicode):'
142 return super(SeparateUnicode, self).validate(obj, value)
138 return super(SeparateUnicode, self).validate(obj, value)
143
139
144
140
145 class ReadlineNoRecord(object):
146 """Context manager to execute some code, then reload readline history
147 so that interactive input to the code doesn't appear when pressing up."""
148 def __init__(self, shell):
149 self.shell = shell
150 self._nested_level = 0
151
152 def __enter__(self):
153 if self._nested_level == 0:
154 try:
155 self.orig_length = self.current_length()
156 self.readline_tail = self.get_readline_tail()
157 except (AttributeError, IndexError): # Can fail with pyreadline
158 self.orig_length, self.readline_tail = 999999, []
159 self._nested_level += 1
160
161 def __exit__(self, type, value, traceback):
162 self._nested_level -= 1
163 if self._nested_level == 0:
164 # Try clipping the end if it's got longer
165 try:
166 e = self.current_length() - self.orig_length
167 if e > 0:
168 for _ in range(e):
169 self.shell.readline.remove_history_item(self.orig_length)
170
171 # If it still doesn't match, just reload readline history.
172 if self.current_length() != self.orig_length \
173 or self.get_readline_tail() != self.readline_tail:
174 self.shell.refill_readline_hist()
175 except (AttributeError, IndexError):
176 pass
177 # Returning False will cause exceptions to propagate
178 return False
179
180 def current_length(self):
181 return self.shell.readline.get_current_history_length()
182
183 def get_readline_tail(self, n=10):
184 """Get the last n items in readline history."""
185 end = self.shell.readline.get_current_history_length() + 1
186 start = max(end-n, 1)
187 ghi = self.shell.readline.get_history_item
188 return [ghi(x) for x in range(start, end)]
189
190
191 @undoc
141 @undoc
192 class DummyMod(object):
142 class DummyMod(object):
193 """A dummy module used for IPython's interactive module when
143 """A dummy module used for IPython's interactive module when
@@ -1934,120 +1884,17 b' class InteractiveShell(SingletonConfigurable):'
1934 #-------------------------------------------------------------------------
1884 #-------------------------------------------------------------------------
1935
1885
1936 def init_readline(self):
1886 def init_readline(self):
1937 """Command history completion/saving/reloading."""
1887 """Moved to terminal subclass, here only to simplify the init logic."""
1938
1888 self.readline = None
1939 if self.readline_use:
1889 # Set a number of methods that depend on readline to be no-op
1940 import IPython.utils.rlineimpl as readline
1890 self.readline_no_record = NoOpContext()
1941
1891 self.set_readline_completer = no_op
1942 self.rl_next_input = None
1892 self.set_custom_completer = no_op
1943 self.rl_do_indent = False
1944
1945 if not self.readline_use or not readline.have_readline:
1946 self.has_readline = False
1947 self.readline = None
1948 # Set a number of methods that depend on readline to be no-op
1949 self.readline_no_record = no_op_context
1950 self.set_readline_completer = no_op
1951 self.set_custom_completer = no_op
1952 if self.readline_use:
1953 warn('Readline services not available or not loaded.')
1954 else:
1955 self.has_readline = True
1956 self.readline = readline
1957 sys.modules['readline'] = readline
1958
1959 # Platform-specific configuration
1960 if os.name == 'nt':
1961 # FIXME - check with Frederick to see if we can harmonize
1962 # naming conventions with pyreadline to avoid this
1963 # platform-dependent check
1964 self.readline_startup_hook = readline.set_pre_input_hook
1965 else:
1966 self.readline_startup_hook = readline.set_startup_hook
1967
1968 # Readline config order:
1969 # - IPython config (default value)
1970 # - custom inputrc
1971 # - IPython config (user customized)
1972
1973 # load IPython config before inputrc if default
1974 # skip if libedit because parse_and_bind syntax is different
1975 if not self._custom_readline_config and not readline.uses_libedit:
1976 for rlcommand in self.readline_parse_and_bind:
1977 readline.parse_and_bind(rlcommand)
1978
1979 # Load user's initrc file (readline config)
1980 # Or if libedit is used, load editrc.
1981 inputrc_name = os.environ.get('INPUTRC')
1982 if inputrc_name is None:
1983 inputrc_name = '.inputrc'
1984 if readline.uses_libedit:
1985 inputrc_name = '.editrc'
1986 inputrc_name = os.path.join(self.home_dir, inputrc_name)
1987 if os.path.isfile(inputrc_name):
1988 try:
1989 readline.read_init_file(inputrc_name)
1990 except:
1991 warn('Problems reading readline initialization file <%s>'
1992 % inputrc_name)
1993
1994 # load IPython config after inputrc if user has customized
1995 if self._custom_readline_config:
1996 for rlcommand in self.readline_parse_and_bind:
1997 readline.parse_and_bind(rlcommand)
1998
1999 # Remove some chars from the delimiters list. If we encounter
2000 # unicode chars, discard them.
2001 delims = readline.get_completer_delims()
2002 if not py3compat.PY3:
2003 delims = delims.encode("ascii", "ignore")
2004 for d in self.readline_remove_delims:
2005 delims = delims.replace(d, "")
2006 delims = delims.replace(ESC_MAGIC, '')
2007 readline.set_completer_delims(delims)
2008 # Store these so we can restore them if something like rpy2 modifies
2009 # them.
2010 self.readline_delims = delims
2011 # otherwise we end up with a monster history after a while:
2012 readline.set_history_length(self.history_length)
2013
2014 self.refill_readline_hist()
2015 self.readline_no_record = ReadlineNoRecord(self)
2016
2017 # Configure auto-indent for all platforms
2018 self.set_autoindent(self.autoindent)
2019
2020 def refill_readline_hist(self):
2021 # Load the last 1000 lines from history
2022 self.readline.clear_history()
2023 stdin_encoding = sys.stdin.encoding or "utf-8"
2024 last_cell = u""
2025 for _, _, cell in self.history_manager.get_tail(self.history_load_length,
2026 include_latest=True):
2027 # Ignore blank lines and consecutive duplicates
2028 cell = cell.rstrip()
2029 if cell and (cell != last_cell):
2030 try:
2031 if self.multiline_history:
2032 self.readline.add_history(py3compat.unicode_to_str(cell,
2033 stdin_encoding))
2034 else:
2035 for line in cell.splitlines():
2036 self.readline.add_history(py3compat.unicode_to_str(line,
2037 stdin_encoding))
2038 last_cell = cell
2039
2040 except TypeError:
2041 # The history DB can get corrupted so it returns strings
2042 # containing null bytes, which readline objects to.
2043 continue
2044
1893
2045 @skip_doctest
1894 @skip_doctest
2046 def set_next_input(self, s, replace=False):
1895 def set_next_input(self, s, replace=False):
2047 """ Sets the 'default' input string for the next command line.
1896 """ Sets the 'default' input string for the next command line.
2048
1897
2049 Requires readline.
2050
2051 Example::
1898 Example::
2052
1899
2053 In [1]: _ip.set_next_input("Hello Word")
1900 In [1]: _ip.set_next_input("Hello Word")
@@ -2055,18 +1902,6 b' class InteractiveShell(SingletonConfigurable):'
2055 """
1902 """
2056 self.rl_next_input = py3compat.cast_bytes_py2(s)
1903 self.rl_next_input = py3compat.cast_bytes_py2(s)
2057
1904
2058 # Maybe move this to the terminal subclass?
2059 def pre_readline(self):
2060 """readline hook to be used at the start of each line.
2061
2062 Currently it handles auto-indent only."""
2063
2064 if self.rl_do_indent:
2065 self.readline.insert_text(self._indent_current_str())
2066 if self.rl_next_input is not None:
2067 self.readline.insert_text(self.rl_next_input)
2068 self.rl_next_input = None
2069
2070 def _indent_current_str(self):
1905 def _indent_current_str(self):
2071 """return the current level of indentation as a string"""
1906 """return the current level of indentation as a string"""
2072 return self.input_splitter.indent_spaces * ' '
1907 return self.input_splitter.indent_spaces * ' '
@@ -2107,11 +1942,6 b' class InteractiveShell(SingletonConfigurable):'
2107 self.set_hook('complete_command', cd_completer, str_key = '%cd')
1942 self.set_hook('complete_command', cd_completer, str_key = '%cd')
2108 self.set_hook('complete_command', reset_completer, str_key = '%reset')
1943 self.set_hook('complete_command', reset_completer, str_key = '%reset')
2109
1944
2110 # Only configure readline if we truly are using readline. IPython can
2111 # do tab-completion over the network, in GUIs, etc, where readline
2112 # itself may be absent
2113 if self.has_readline:
2114 self.set_readline_completer()
2115
1945
2116 def complete(self, text, line=None, cursor_pos=None):
1946 def complete(self, text, line=None, cursor_pos=None):
2117 """Return the completed text and a list of completions.
1947 """Return the completed text and a list of completions.
@@ -2167,10 +1997,6 b' class InteractiveShell(SingletonConfigurable):'
2167 newcomp = types.MethodType(completer,self.Completer)
1997 newcomp = types.MethodType(completer,self.Completer)
2168 self.Completer.matchers.insert(pos,newcomp)
1998 self.Completer.matchers.insert(pos,newcomp)
2169
1999
2170 def set_readline_completer(self):
2171 """Reset readline's completer to be our own."""
2172 self.readline.set_completer(self.Completer.rlcomplete)
2173
2174 def set_completer_frame(self, frame=None):
2000 def set_completer_frame(self, frame=None):
2175 """Set the frame of the completer."""
2001 """Set the frame of the completer."""
2176 if frame:
2002 if frame:
@@ -1,18 +1,9 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Subclass of InteractiveShell for terminal based frontends."""
2 """Subclass of InteractiveShell for terminal based frontends."""
3
3
4 #-----------------------------------------------------------------------------
4 # Copyright (c) IPython Development Team.
5 # Copyright (C) 2001 Janko Hauser <jhauser@zscout.de>
5 # Distributed under the terms of the Modified BSD License.
6 # Copyright (C) 2001-2007 Fernando Perez. <fperez@colorado.edu>
6
7 # Copyright (C) 2008-2011 The IPython Development Team
8 #
9 # Distributed under the terms of the BSD License. The full license is in
10 # the file COPYING, distributed as part of this software.
11 #-----------------------------------------------------------------------------
12
13 #-----------------------------------------------------------------------------
14 # Imports
15 #-----------------------------------------------------------------------------
16 from __future__ import print_function
7 from __future__ import print_function
17
8
18 import bdb
9 import bdb
@@ -21,10 +12,12 b' import sys'
21
12
22 from IPython.core.error import TryNext, UsageError
13 from IPython.core.error import TryNext, UsageError
23 from IPython.core.usage import interactive_usage
14 from IPython.core.usage import interactive_usage
24 from IPython.core.inputsplitter import IPythonInputSplitter
15 from IPython.core.inputsplitter import IPythonInputSplitter, ESC_MAGIC
25 from IPython.core.interactiveshell import InteractiveShell, InteractiveShellABC
16 from IPython.core.interactiveshell import InteractiveShell, InteractiveShellABC
26 from IPython.core.magic import Magics, magics_class, line_magic
17 from IPython.core.magic import Magics, magics_class, line_magic
27 from IPython.lib.clipboard import ClipboardEmpty
18 from IPython.lib.clipboard import ClipboardEmpty
19 from IPython.utils.contexts import NoOpContext
20 from IPython.utils.decorators import undoc
28 from IPython.utils.encoding import get_stream_enc
21 from IPython.utils.encoding import get_stream_enc
29 from IPython.utils import py3compat
22 from IPython.utils import py3compat
30 from IPython.utils.terminal import toggle_set_term_title, set_term_title
23 from IPython.utils.terminal import toggle_set_term_title, set_term_title
@@ -33,9 +26,6 b' from IPython.utils.warn import warn, error'
33 from IPython.utils.text import num_ini_spaces, SList, strip_email_quotes
26 from IPython.utils.text import num_ini_spaces, SList, strip_email_quotes
34 from traitlets import Integer, CBool, Unicode
27 from traitlets import Integer, CBool, Unicode
35
28
36 #-----------------------------------------------------------------------------
37 # Utilities
38 #-----------------------------------------------------------------------------
39
29
40 def get_default_editor():
30 def get_default_editor():
41 try:
31 try:
@@ -74,10 +64,55 b' def get_pasted_lines(sentinel, l_input=py3compat.input, quiet=False):'
74 print('<EOF>')
64 print('<EOF>')
75 return
65 return
76
66
67 @undoc
68 def no_op(*a, **kw): pass
69
70
71 class ReadlineNoRecord(object):
72 """Context manager to execute some code, then reload readline history
73 so that interactive input to the code doesn't appear when pressing up."""
74 def __init__(self, shell):
75 self.shell = shell
76 self._nested_level = 0
77
78 def __enter__(self):
79 if self._nested_level == 0:
80 try:
81 self.orig_length = self.current_length()
82 self.readline_tail = self.get_readline_tail()
83 except (AttributeError, IndexError): # Can fail with pyreadline
84 self.orig_length, self.readline_tail = 999999, []
85 self._nested_level += 1
86
87 def __exit__(self, type, value, traceback):
88 self._nested_level -= 1
89 if self._nested_level == 0:
90 # Try clipping the end if it's got longer
91 try:
92 e = self.current_length() - self.orig_length
93 if e > 0:
94 for _ in range(e):
95 self.shell.readline.remove_history_item(self.orig_length)
96
97 # If it still doesn't match, just reload readline history.
98 if self.current_length() != self.orig_length \
99 or self.get_readline_tail() != self.readline_tail:
100 self.shell.refill_readline_hist()
101 except (AttributeError, IndexError):
102 pass
103 # Returning False will cause exceptions to propagate
104 return False
105
106 def current_length(self):
107 return self.shell.readline.get_current_history_length()
108
109 def get_readline_tail(self, n=10):
110 """Get the last n items in readline history."""
111 end = self.shell.readline.get_current_history_length() + 1
112 start = max(end-n, 1)
113 ghi = self.shell.readline.get_history_item
114 return [ghi(x) for x in range(start, end)]
77
115
78 #------------------------------------------------------------------------
79 # Terminal-specific magics
80 #------------------------------------------------------------------------
81
116
82 @magics_class
117 @magics_class
83 class TerminalMagics(Magics):
118 class TerminalMagics(Magics):
@@ -248,9 +283,6 b' class TerminalMagics(Magics):'
248 """
283 """
249 os.system("cls")
284 os.system("cls")
250
285
251 #-----------------------------------------------------------------------------
252 # Main class
253 #-----------------------------------------------------------------------------
254
286
255 class TerminalInteractiveShell(InteractiveShell):
287 class TerminalInteractiveShell(InteractiveShell):
256
288
@@ -320,6 +352,141 b' class TerminalInteractiveShell(InteractiveShell):'
320 self.display_formatter.active_types = ['text/plain']
352 self.display_formatter.active_types = ['text/plain']
321
353
322 #-------------------------------------------------------------------------
354 #-------------------------------------------------------------------------
355 # Things related to readline
356 #-------------------------------------------------------------------------
357
358 def init_readline(self):
359 """Command history completion/saving/reloading."""
360
361 if self.readline_use:
362 import IPython.utils.rlineimpl as readline
363
364 self.rl_next_input = None
365 self.rl_do_indent = False
366
367 if not self.readline_use or not readline.have_readline:
368 self.readline = None
369 # Set a number of methods that depend on readline to be no-op
370 self.readline_no_record = NoOpContext()
371 self.set_readline_completer = no_op
372 self.set_custom_completer = no_op
373 if self.readline_use:
374 warn('Readline services not available or not loaded.')
375 else:
376 self.has_readline = True
377 self.readline = readline
378 sys.modules['readline'] = readline
379
380 # Platform-specific configuration
381 if os.name == 'nt':
382 # FIXME - check with Frederick to see if we can harmonize
383 # naming conventions with pyreadline to avoid this
384 # platform-dependent check
385 self.readline_startup_hook = readline.set_pre_input_hook
386 else:
387 self.readline_startup_hook = readline.set_startup_hook
388
389 # Readline config order:
390 # - IPython config (default value)
391 # - custom inputrc
392 # - IPython config (user customized)
393
394 # load IPython config before inputrc if default
395 # skip if libedit because parse_and_bind syntax is different
396 if not self._custom_readline_config and not readline.uses_libedit:
397 for rlcommand in self.readline_parse_and_bind:
398 readline.parse_and_bind(rlcommand)
399
400 # Load user's initrc file (readline config)
401 # Or if libedit is used, load editrc.
402 inputrc_name = os.environ.get('INPUTRC')
403 if inputrc_name is None:
404 inputrc_name = '.inputrc'
405 if readline.uses_libedit:
406 inputrc_name = '.editrc'
407 inputrc_name = os.path.join(self.home_dir, inputrc_name)
408 if os.path.isfile(inputrc_name):
409 try:
410 readline.read_init_file(inputrc_name)
411 except:
412 warn('Problems reading readline initialization file <%s>'
413 % inputrc_name)
414
415 # load IPython config after inputrc if user has customized
416 if self._custom_readline_config:
417 for rlcommand in self.readline_parse_and_bind:
418 readline.parse_and_bind(rlcommand)
419
420 # Remove some chars from the delimiters list. If we encounter
421 # unicode chars, discard them.
422 delims = readline.get_completer_delims()
423 if not py3compat.PY3:
424 delims = delims.encode("ascii", "ignore")
425 for d in self.readline_remove_delims:
426 delims = delims.replace(d, "")
427 delims = delims.replace(ESC_MAGIC, '')
428 readline.set_completer_delims(delims)
429 # Store these so we can restore them if something like rpy2 modifies
430 # them.
431 self.readline_delims = delims
432 # otherwise we end up with a monster history after a while:
433 readline.set_history_length(self.history_length)
434
435 self.refill_readline_hist()
436 self.readline_no_record = ReadlineNoRecord(self)
437
438 # Configure auto-indent for all platforms
439 self.set_autoindent(self.autoindent)
440
441 def init_completer(self):
442 super(TerminalInteractiveShell, self).init_completer()
443
444 # Only configure readline if we truly are using readline.
445 if self.has_readline:
446 self.set_readline_completer()
447
448 def set_readline_completer(self):
449 """Reset readline's completer to be our own."""
450 self.readline.set_completer(self.Completer.rlcomplete)
451
452
453 def pre_readline(self):
454 """readline hook to be used at the start of each line.
455
456 It handles auto-indent and text from set_next_input."""
457
458 if self.rl_do_indent:
459 self.readline.insert_text(self._indent_current_str())
460 if self.rl_next_input is not None:
461 self.readline.insert_text(self.rl_next_input)
462 self.rl_next_input = None
463
464 def refill_readline_hist(self):
465 # Load the last 1000 lines from history
466 self.readline.clear_history()
467 stdin_encoding = sys.stdin.encoding or "utf-8"
468 last_cell = u""
469 for _, _, cell in self.history_manager.get_tail(self.history_load_length,
470 include_latest=True):
471 # Ignore blank lines and consecutive duplicates
472 cell = cell.rstrip()
473 if cell and (cell != last_cell):
474 try:
475 if self.multiline_history:
476 self.readline.add_history(py3compat.unicode_to_str(cell,
477 stdin_encoding))
478 else:
479 for line in cell.splitlines():
480 self.readline.add_history(py3compat.unicode_to_str(line,
481 stdin_encoding))
482 last_cell = cell
483
484 except TypeError:
485 # The history DB can get corrupted so it returns strings
486 # containing null bytes, which readline objects to.
487 continue
488
489 #-------------------------------------------------------------------------
323 # Things related to the terminal
490 # Things related to the terminal
324 #-------------------------------------------------------------------------
491 #-------------------------------------------------------------------------
325
492
@@ -1,22 +1,9 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """Miscellaneous context managers.
2 """
3 """
3 Context managers for temporarily updating dictionaries.
4
4
5 Authors:
5 # Copyright (c) IPython Development Team.
6
6 # Distributed under the terms of the Modified BSD License.
7 * Bradley Froehle
8 """
9
10 #-----------------------------------------------------------------------------
11 # Copyright (C) 2012 The IPython Development Team
12 #
13 # Distributed under the terms of the BSD License. The full license is in
14 # the file COPYING, distributed as part of this software.
15 #-----------------------------------------------------------------------------
16
17 #-----------------------------------------------------------------------------
18 # Code
19 #-----------------------------------------------------------------------------
20
7
21 class preserve_keys(object):
8 class preserve_keys(object):
22 """Preserve a set of keys in a dictionary.
9 """Preserve a set of keys in a dictionary.
@@ -69,3 +56,9 b' class preserve_keys(object):'
69 for k in self.to_delete:
56 for k in self.to_delete:
70 d.pop(k, None)
57 d.pop(k, None)
71 d.update(self.to_update)
58 d.update(self.to_update)
59
60
61 class NoOpContext(object):
62 """Context manager that does nothing."""
63 def __enter__(self): pass
64 def __exit__(self, type, value, traceback): pass
General Comments 0
You need to be logged in to leave comments. Login now