##// END OF EJS Templates
Minimal changes to import IPython from IronPython
Doug Blank -
Show More
@@ -0,0 +1,61 b''
1 """
2 cli-specific implementation of process utilities.
3
4 cli - Common Language Infrastructure for IronPython. Code
5 can run on any operating system. Check os.name for os-
6 specific settings.
7
8 This file is only meant to be imported by process.py, not by end-users.
9 """
10
11 # Import cli libraries:
12 import clr
13 import System
14
15 # Import Python libraries:
16 import os
17
18 # Import IPython libraries:
19 from IPython.utils import py3compat
20 from ._process_common import arg_split
21
22 def _find_cmd(cmd):
23 """Find the full path to a command using which."""
24 os_path_sep = ":" if os.name == "posix" else ";"
25 paths = System.Environment.GetEnvironmentVariable("PATH").Split(os_path_sep)
26 for path in paths:
27 filename = os.path.join(path, cmd)
28 if System.IO.File.Exists(filename):
29 return py3compat.bytes_to_str(filename)
30 raise OSError("command %r not found" % cmd)
31
32 def system(cmd):
33 """
34 system(cmd) should work in a cli environment on Mac OSX, Linux,
35 and Windows
36 """
37 psi = System.Diagnostics.ProcessStartInfo(cmd)
38 psi.RedirectStandardOutput = True
39 psi.RedirectStandardError = True
40 psi.WindowStyle = System.Diagnostics.ProcessWindowStyle.Normal
41 psi.UseShellExecute = False
42 # Start up process:
43 reg = System.Diagnostics.Process.Start(psi)
44
45 def getoutput(cmd):
46 """
47 getoutput(cmd) should work in a cli environment on Mac OSX, Linux,
48 and Windows
49 """
50 psi = System.Diagnostics.ProcessStartInfo(cmd)
51 psi.RedirectStandardOutput = True
52 psi.RedirectStandardError = True
53 psi.WindowStyle = System.Diagnostics.ProcessWindowStyle.Normal
54 psi.UseShellExecute = False
55 # Start up process:
56 reg = System.Diagnostics.Process.Start(psi)
57 myOutput = reg.StandardOutput
58 output = myOutput.ReadToEnd()
59 myError = reg.StandardError
60 error = myError.ReadToEnd()
61 return output
@@ -1,144 +1,147 b''
1 """Compiler tools with improved interactive support.
1 """Compiler tools with improved interactive support.
2
2
3 Provides compilation machinery similar to codeop, but with caching support so
3 Provides compilation machinery similar to codeop, but with caching support so
4 we can provide interactive tracebacks.
4 we can provide interactive tracebacks.
5
5
6 Authors
6 Authors
7 -------
7 -------
8 * Robert Kern
8 * Robert Kern
9 * Fernando Perez
9 * Fernando Perez
10 * Thomas Kluyver
10 * Thomas Kluyver
11 """
11 """
12
12
13 # Note: though it might be more natural to name this module 'compiler', that
13 # Note: though it might be more natural to name this module 'compiler', that
14 # name is in the stdlib and name collisions with the stdlib tend to produce
14 # name is in the stdlib and name collisions with the stdlib tend to produce
15 # weird problems (often with third-party tools).
15 # weird problems (often with third-party tools).
16
16
17 #-----------------------------------------------------------------------------
17 #-----------------------------------------------------------------------------
18 # Copyright (C) 2010-2011 The IPython Development Team.
18 # Copyright (C) 2010-2011 The IPython Development Team.
19 #
19 #
20 # Distributed under the terms of the BSD License.
20 # Distributed under the terms of the BSD License.
21 #
21 #
22 # The full license is in the file COPYING.txt, distributed with this software.
22 # The full license is in the file COPYING.txt, distributed with this software.
23 #-----------------------------------------------------------------------------
23 #-----------------------------------------------------------------------------
24
24
25 #-----------------------------------------------------------------------------
25 #-----------------------------------------------------------------------------
26 # Imports
26 # Imports
27 #-----------------------------------------------------------------------------
27 #-----------------------------------------------------------------------------
28 from __future__ import print_function
28 from __future__ import print_function
29
29
30 # Stdlib imports
30 # Stdlib imports
31 import __future__
31 import __future__
32 from ast import PyCF_ONLY_AST
32 from ast import PyCF_ONLY_AST
33 import codeop
33 import codeop
34 import functools
34 import functools
35 import hashlib
35 import hashlib
36 import linecache
36 import linecache
37 import operator
37 import operator
38 import time
38 import time
39
39
40 #-----------------------------------------------------------------------------
40 #-----------------------------------------------------------------------------
41 # Constants
41 # Constants
42 #-----------------------------------------------------------------------------
42 #-----------------------------------------------------------------------------
43
43
44 # Roughtly equal to PyCF_MASK | PyCF_MASK_OBSOLETE as defined in pythonrun.h,
44 # Roughtly equal to PyCF_MASK | PyCF_MASK_OBSOLETE as defined in pythonrun.h,
45 # this is used as a bitmask to extract future-related code flags.
45 # this is used as a bitmask to extract future-related code flags.
46 PyCF_MASK = functools.reduce(operator.or_,
46 PyCF_MASK = functools.reduce(operator.or_,
47 (getattr(__future__, fname).compiler_flag
47 (getattr(__future__, fname).compiler_flag
48 for fname in __future__.all_feature_names))
48 for fname in __future__.all_feature_names
49 if (hasattr(__future__, fname) and
50 hasattr(getattr(__future__, fname), "compiler_flag"))),
51 0)
49
52
50 #-----------------------------------------------------------------------------
53 #-----------------------------------------------------------------------------
51 # Local utilities
54 # Local utilities
52 #-----------------------------------------------------------------------------
55 #-----------------------------------------------------------------------------
53
56
54 def code_name(code, number=0):
57 def code_name(code, number=0):
55 """ Compute a (probably) unique name for code for caching.
58 """ Compute a (probably) unique name for code for caching.
56
59
57 This now expects code to be unicode.
60 This now expects code to be unicode.
58 """
61 """
59 hash_digest = hashlib.md5(code.encode("utf-8")).hexdigest()
62 hash_digest = hashlib.md5(code.encode("utf-8")).hexdigest()
60 # Include the number and 12 characters of the hash in the name. It's
63 # Include the number and 12 characters of the hash in the name. It's
61 # pretty much impossible that in a single session we'll have collisions
64 # pretty much impossible that in a single session we'll have collisions
62 # even with truncated hashes, and the full one makes tracebacks too long
65 # even with truncated hashes, and the full one makes tracebacks too long
63 return '<ipython-input-{0}-{1}>'.format(number, hash_digest[:12])
66 return '<ipython-input-{0}-{1}>'.format(number, hash_digest[:12])
64
67
65 #-----------------------------------------------------------------------------
68 #-----------------------------------------------------------------------------
66 # Classes and functions
69 # Classes and functions
67 #-----------------------------------------------------------------------------
70 #-----------------------------------------------------------------------------
68
71
69 class CachingCompiler(codeop.Compile):
72 class CachingCompiler(codeop.Compile):
70 """A compiler that caches code compiled from interactive statements.
73 """A compiler that caches code compiled from interactive statements.
71 """
74 """
72
75
73 def __init__(self):
76 def __init__(self):
74 codeop.Compile.__init__(self)
77 codeop.Compile.__init__(self)
75
78
76 # This is ugly, but it must be done this way to allow multiple
79 # This is ugly, but it must be done this way to allow multiple
77 # simultaneous ipython instances to coexist. Since Python itself
80 # simultaneous ipython instances to coexist. Since Python itself
78 # directly accesses the data structures in the linecache module, and
81 # directly accesses the data structures in the linecache module, and
79 # the cache therein is global, we must work with that data structure.
82 # the cache therein is global, we must work with that data structure.
80 # We must hold a reference to the original checkcache routine and call
83 # We must hold a reference to the original checkcache routine and call
81 # that in our own check_cache() below, but the special IPython cache
84 # that in our own check_cache() below, but the special IPython cache
82 # must also be shared by all IPython instances. If we were to hold
85 # must also be shared by all IPython instances. If we were to hold
83 # separate caches (one in each CachingCompiler instance), any call made
86 # separate caches (one in each CachingCompiler instance), any call made
84 # by Python itself to linecache.checkcache() would obliterate the
87 # by Python itself to linecache.checkcache() would obliterate the
85 # cached data from the other IPython instances.
88 # cached data from the other IPython instances.
86 if not hasattr(linecache, '_ipython_cache'):
89 if not hasattr(linecache, '_ipython_cache'):
87 linecache._ipython_cache = {}
90 linecache._ipython_cache = {}
88 if not hasattr(linecache, '_checkcache_ori'):
91 if not hasattr(linecache, '_checkcache_ori'):
89 linecache._checkcache_ori = linecache.checkcache
92 linecache._checkcache_ori = linecache.checkcache
90 # Now, we must monkeypatch the linecache directly so that parts of the
93 # Now, we must monkeypatch the linecache directly so that parts of the
91 # stdlib that call it outside our control go through our codepath
94 # stdlib that call it outside our control go through our codepath
92 # (otherwise we'd lose our tracebacks).
95 # (otherwise we'd lose our tracebacks).
93 linecache.checkcache = check_linecache_ipython
96 linecache.checkcache = check_linecache_ipython
94
97
95 def ast_parse(self, source, filename='<unknown>', symbol='exec'):
98 def ast_parse(self, source, filename='<unknown>', symbol='exec'):
96 """Parse code to an AST with the current compiler flags active.
99 """Parse code to an AST with the current compiler flags active.
97
100
98 Arguments are exactly the same as ast.parse (in the standard library),
101 Arguments are exactly the same as ast.parse (in the standard library),
99 and are passed to the built-in compile function."""
102 and are passed to the built-in compile function."""
100 return compile(source, filename, symbol, self.flags | PyCF_ONLY_AST, 1)
103 return compile(source, filename, symbol, self.flags | PyCF_ONLY_AST, 1)
101
104
102 def reset_compiler_flags(self):
105 def reset_compiler_flags(self):
103 """Reset compiler flags to default state."""
106 """Reset compiler flags to default state."""
104 # This value is copied from codeop.Compile.__init__, so if that ever
107 # This value is copied from codeop.Compile.__init__, so if that ever
105 # changes, it will need to be updated.
108 # changes, it will need to be updated.
106 self.flags = codeop.PyCF_DONT_IMPLY_DEDENT
109 self.flags = codeop.PyCF_DONT_IMPLY_DEDENT
107
110
108 @property
111 @property
109 def compiler_flags(self):
112 def compiler_flags(self):
110 """Flags currently active in the compilation process.
113 """Flags currently active in the compilation process.
111 """
114 """
112 return self.flags
115 return self.flags
113
116
114 def cache(self, code, number=0):
117 def cache(self, code, number=0):
115 """Make a name for a block of code, and cache the code.
118 """Make a name for a block of code, and cache the code.
116
119
117 Parameters
120 Parameters
118 ----------
121 ----------
119 code : str
122 code : str
120 The Python source code to cache.
123 The Python source code to cache.
121 number : int
124 number : int
122 A number which forms part of the code's name. Used for the execution
125 A number which forms part of the code's name. Used for the execution
123 counter.
126 counter.
124
127
125 Returns
128 Returns
126 -------
129 -------
127 The name of the cached code (as a string). Pass this as the filename
130 The name of the cached code (as a string). Pass this as the filename
128 argument to compilation, so that tracebacks are correctly hooked up.
131 argument to compilation, so that tracebacks are correctly hooked up.
129 """
132 """
130 name = code_name(code, number)
133 name = code_name(code, number)
131 entry = (len(code), time.time(),
134 entry = (len(code), time.time(),
132 [line+'\n' for line in code.splitlines()], name)
135 [line+'\n' for line in code.splitlines()], name)
133 linecache.cache[name] = entry
136 linecache.cache[name] = entry
134 linecache._ipython_cache[name] = entry
137 linecache._ipython_cache[name] = entry
135 return name
138 return name
136
139
137 def check_linecache_ipython(*args):
140 def check_linecache_ipython(*args):
138 """Call linecache.checkcache() safely protecting our cached values.
141 """Call linecache.checkcache() safely protecting our cached values.
139 """
142 """
140 # First call the orignal checkcache as intended
143 # First call the orignal checkcache as intended
141 linecache._checkcache_ori(*args)
144 linecache._checkcache_ori(*args)
142 # Then, update back the cache with our data, so that tracebacks related
145 # Then, update back the cache with our data, so that tracebacks related
143 # to our compiled codes can be produced.
146 # to our compiled codes can be produced.
144 linecache.cache.update(linecache._ipython_cache)
147 linecache.cache.update(linecache._ipython_cache)
@@ -1,997 +1,1000 b''
1 """Word completion for IPython.
1 """Word completion for IPython.
2
2
3 This module is a fork of the rlcompleter module in the Python standard
3 This module is a fork of the rlcompleter module in the Python standard
4 library. The original enhancements made to rlcompleter have been sent
4 library. The original enhancements made to rlcompleter have been sent
5 upstream and were accepted as of Python 2.3, but we need a lot more
5 upstream and were accepted as of Python 2.3, but we need a lot more
6 functionality specific to IPython, so this module will continue to live as an
6 functionality specific to IPython, so this module will continue to live as an
7 IPython-specific utility.
7 IPython-specific utility.
8
8
9 Original rlcompleter documentation:
9 Original rlcompleter documentation:
10
10
11 This requires the latest extension to the readline module (the
11 This requires the latest extension to the readline module (the
12 completes keywords, built-ins and globals in __main__; when completing
12 completes keywords, built-ins and globals in __main__; when completing
13 NAME.NAME..., it evaluates (!) the expression up to the last dot and
13 NAME.NAME..., it evaluates (!) the expression up to the last dot and
14 completes its attributes.
14 completes its attributes.
15
15
16 It's very cool to do "import string" type "string.", hit the
16 It's very cool to do "import string" type "string.", hit the
17 completion key (twice), and see the list of names defined by the
17 completion key (twice), and see the list of names defined by the
18 string module!
18 string module!
19
19
20 Tip: to use the tab key as the completion key, call
20 Tip: to use the tab key as the completion key, call
21
21
22 readline.parse_and_bind("tab: complete")
22 readline.parse_and_bind("tab: complete")
23
23
24 Notes:
24 Notes:
25
25
26 - Exceptions raised by the completer function are *ignored* (and
26 - Exceptions raised by the completer function are *ignored* (and
27 generally cause the completion to fail). This is a feature -- since
27 generally cause the completion to fail). This is a feature -- since
28 readline sets the tty device in raw (or cbreak) mode, printing a
28 readline sets the tty device in raw (or cbreak) mode, printing a
29 traceback wouldn't work well without some complicated hoopla to save,
29 traceback wouldn't work well without some complicated hoopla to save,
30 reset and restore the tty state.
30 reset and restore the tty state.
31
31
32 - The evaluation of the NAME.NAME... form may cause arbitrary
32 - The evaluation of the NAME.NAME... form may cause arbitrary
33 application defined code to be executed if an object with a
33 application defined code to be executed if an object with a
34 ``__getattr__`` hook is found. Since it is the responsibility of the
34 ``__getattr__`` hook is found. Since it is the responsibility of the
35 application (or the user) to enable this feature, I consider this an
35 application (or the user) to enable this feature, I consider this an
36 acceptable risk. More complicated expressions (e.g. function calls or
36 acceptable risk. More complicated expressions (e.g. function calls or
37 indexing operations) are *not* evaluated.
37 indexing operations) are *not* evaluated.
38
38
39 - GNU readline is also used by the built-in functions input() and
39 - GNU readline is also used by the built-in functions input() and
40 raw_input(), and thus these also benefit/suffer from the completer
40 raw_input(), and thus these also benefit/suffer from the completer
41 features. Clearly an interactive application can benefit by
41 features. Clearly an interactive application can benefit by
42 specifying its own completer function and using raw_input() for all
42 specifying its own completer function and using raw_input() for all
43 its input.
43 its input.
44
44
45 - When the original stdin is not a tty device, GNU readline is never
45 - When the original stdin is not a tty device, GNU readline is never
46 used, and this module (and the readline module) are silently inactive.
46 used, and this module (and the readline module) are silently inactive.
47 """
47 """
48
48
49 #*****************************************************************************
49 #*****************************************************************************
50 #
50 #
51 # Since this file is essentially a minimally modified copy of the rlcompleter
51 # Since this file is essentially a minimally modified copy of the rlcompleter
52 # module which is part of the standard Python distribution, I assume that the
52 # module which is part of the standard Python distribution, I assume that the
53 # proper procedure is to maintain its copyright as belonging to the Python
53 # proper procedure is to maintain its copyright as belonging to the Python
54 # Software Foundation (in addition to my own, for all new code).
54 # Software Foundation (in addition to my own, for all new code).
55 #
55 #
56 # Copyright (C) 2008 IPython Development Team
56 # Copyright (C) 2008 IPython Development Team
57 # Copyright (C) 2001 Fernando Perez. <fperez@colorado.edu>
57 # Copyright (C) 2001 Fernando Perez. <fperez@colorado.edu>
58 # Copyright (C) 2001 Python Software Foundation, www.python.org
58 # Copyright (C) 2001 Python Software Foundation, www.python.org
59 #
59 #
60 # Distributed under the terms of the BSD License. The full license is in
60 # Distributed under the terms of the BSD License. The full license is in
61 # the file COPYING, distributed as part of this software.
61 # the file COPYING, distributed as part of this software.
62 #
62 #
63 #*****************************************************************************
63 #*****************************************************************************
64
64
65 #-----------------------------------------------------------------------------
65 #-----------------------------------------------------------------------------
66 # Imports
66 # Imports
67 #-----------------------------------------------------------------------------
67 #-----------------------------------------------------------------------------
68
68
69 import __main__
69 try:
70 import __main__
71 except ImportError:
72 pass
70 import glob
73 import glob
71 import inspect
74 import inspect
72 import itertools
75 import itertools
73 import keyword
76 import keyword
74 import os
77 import os
75 import re
78 import re
76 import sys
79 import sys
77
80
78 from IPython.config.configurable import Configurable
81 from IPython.config.configurable import Configurable
79 from IPython.core.error import TryNext
82 from IPython.core.error import TryNext
80 from IPython.core.inputsplitter import ESC_MAGIC
83 from IPython.core.inputsplitter import ESC_MAGIC
81 from IPython.utils import generics
84 from IPython.utils import generics
82 from IPython.utils import io
85 from IPython.utils import io
83 from IPython.utils.dir2 import dir2
86 from IPython.utils.dir2 import dir2
84 from IPython.utils.process import arg_split
87 from IPython.utils.process import arg_split
85 from IPython.utils.py3compat import builtin_mod, string_types
88 from IPython.utils.py3compat import builtin_mod, string_types
86 from IPython.utils.traitlets import CBool, Enum
89 from IPython.utils.traitlets import CBool, Enum
87
90
88 #-----------------------------------------------------------------------------
91 #-----------------------------------------------------------------------------
89 # Globals
92 # Globals
90 #-----------------------------------------------------------------------------
93 #-----------------------------------------------------------------------------
91
94
92 # Public API
95 # Public API
93 __all__ = ['Completer','IPCompleter']
96 __all__ = ['Completer','IPCompleter']
94
97
95 if sys.platform == 'win32':
98 if sys.platform == 'win32':
96 PROTECTABLES = ' '
99 PROTECTABLES = ' '
97 else:
100 else:
98 PROTECTABLES = ' ()[]{}?=\\|;:\'#*"^&'
101 PROTECTABLES = ' ()[]{}?=\\|;:\'#*"^&'
99
102
100 #-----------------------------------------------------------------------------
103 #-----------------------------------------------------------------------------
101 # Main functions and classes
104 # Main functions and classes
102 #-----------------------------------------------------------------------------
105 #-----------------------------------------------------------------------------
103
106
104 def has_open_quotes(s):
107 def has_open_quotes(s):
105 """Return whether a string has open quotes.
108 """Return whether a string has open quotes.
106
109
107 This simply counts whether the number of quote characters of either type in
110 This simply counts whether the number of quote characters of either type in
108 the string is odd.
111 the string is odd.
109
112
110 Returns
113 Returns
111 -------
114 -------
112 If there is an open quote, the quote character is returned. Else, return
115 If there is an open quote, the quote character is returned. Else, return
113 False.
116 False.
114 """
117 """
115 # We check " first, then ', so complex cases with nested quotes will get
118 # We check " first, then ', so complex cases with nested quotes will get
116 # the " to take precedence.
119 # the " to take precedence.
117 if s.count('"') % 2:
120 if s.count('"') % 2:
118 return '"'
121 return '"'
119 elif s.count("'") % 2:
122 elif s.count("'") % 2:
120 return "'"
123 return "'"
121 else:
124 else:
122 return False
125 return False
123
126
124
127
125 def protect_filename(s):
128 def protect_filename(s):
126 """Escape a string to protect certain characters."""
129 """Escape a string to protect certain characters."""
127
130
128 return "".join([(ch in PROTECTABLES and '\\' + ch or ch)
131 return "".join([(ch in PROTECTABLES and '\\' + ch or ch)
129 for ch in s])
132 for ch in s])
130
133
131 def expand_user(path):
134 def expand_user(path):
132 """Expand '~'-style usernames in strings.
135 """Expand '~'-style usernames in strings.
133
136
134 This is similar to :func:`os.path.expanduser`, but it computes and returns
137 This is similar to :func:`os.path.expanduser`, but it computes and returns
135 extra information that will be useful if the input was being used in
138 extra information that will be useful if the input was being used in
136 computing completions, and you wish to return the completions with the
139 computing completions, and you wish to return the completions with the
137 original '~' instead of its expanded value.
140 original '~' instead of its expanded value.
138
141
139 Parameters
142 Parameters
140 ----------
143 ----------
141 path : str
144 path : str
142 String to be expanded. If no ~ is present, the output is the same as the
145 String to be expanded. If no ~ is present, the output is the same as the
143 input.
146 input.
144
147
145 Returns
148 Returns
146 -------
149 -------
147 newpath : str
150 newpath : str
148 Result of ~ expansion in the input path.
151 Result of ~ expansion in the input path.
149 tilde_expand : bool
152 tilde_expand : bool
150 Whether any expansion was performed or not.
153 Whether any expansion was performed or not.
151 tilde_val : str
154 tilde_val : str
152 The value that ~ was replaced with.
155 The value that ~ was replaced with.
153 """
156 """
154 # Default values
157 # Default values
155 tilde_expand = False
158 tilde_expand = False
156 tilde_val = ''
159 tilde_val = ''
157 newpath = path
160 newpath = path
158
161
159 if path.startswith('~'):
162 if path.startswith('~'):
160 tilde_expand = True
163 tilde_expand = True
161 rest = len(path)-1
164 rest = len(path)-1
162 newpath = os.path.expanduser(path)
165 newpath = os.path.expanduser(path)
163 if rest:
166 if rest:
164 tilde_val = newpath[:-rest]
167 tilde_val = newpath[:-rest]
165 else:
168 else:
166 tilde_val = newpath
169 tilde_val = newpath
167
170
168 return newpath, tilde_expand, tilde_val
171 return newpath, tilde_expand, tilde_val
169
172
170
173
171 def compress_user(path, tilde_expand, tilde_val):
174 def compress_user(path, tilde_expand, tilde_val):
172 """Does the opposite of expand_user, with its outputs.
175 """Does the opposite of expand_user, with its outputs.
173 """
176 """
174 if tilde_expand:
177 if tilde_expand:
175 return path.replace(tilde_val, '~')
178 return path.replace(tilde_val, '~')
176 else:
179 else:
177 return path
180 return path
178
181
179
182
180
183
181 def penalize_magics_key(word):
184 def penalize_magics_key(word):
182 """key for sorting that penalizes magic commands in the ordering
185 """key for sorting that penalizes magic commands in the ordering
183
186
184 Normal words are left alone.
187 Normal words are left alone.
185
188
186 Magic commands have the initial % moved to the end, e.g.
189 Magic commands have the initial % moved to the end, e.g.
187 %matplotlib is transformed as follows:
190 %matplotlib is transformed as follows:
188
191
189 %matplotlib -> matplotlib%
192 %matplotlib -> matplotlib%
190
193
191 [The choice of the final % is arbitrary.]
194 [The choice of the final % is arbitrary.]
192
195
193 Since "matplotlib" < "matplotlib%" as strings,
196 Since "matplotlib" < "matplotlib%" as strings,
194 "timeit" will appear before the magic "%timeit" in the ordering
197 "timeit" will appear before the magic "%timeit" in the ordering
195
198
196 For consistency, move "%%" to the end, so cell magics appear *after*
199 For consistency, move "%%" to the end, so cell magics appear *after*
197 line magics with the same name.
200 line magics with the same name.
198
201
199 A check is performed that there are no other "%" in the string;
202 A check is performed that there are no other "%" in the string;
200 if there are, then the string is not a magic command and is left unchanged.
203 if there are, then the string is not a magic command and is left unchanged.
201
204
202 """
205 """
203
206
204 # Move any % signs from start to end of the key
207 # Move any % signs from start to end of the key
205 # provided there are no others elsewhere in the string
208 # provided there are no others elsewhere in the string
206
209
207 if word[:2] == "%%":
210 if word[:2] == "%%":
208 if not "%" in word[2:]:
211 if not "%" in word[2:]:
209 return word[2:] + "%%"
212 return word[2:] + "%%"
210
213
211 if word[:1] == "%":
214 if word[:1] == "%":
212 if not "%" in word[1:]:
215 if not "%" in word[1:]:
213 return word[1:] + "%"
216 return word[1:] + "%"
214
217
215 return word
218 return word
216
219
217
220
218
221
219 class Bunch(object): pass
222 class Bunch(object): pass
220
223
221
224
222 DELIMS = ' \t\n`!@#$^&*()=+[{]}\\|;:\'",<>?'
225 DELIMS = ' \t\n`!@#$^&*()=+[{]}\\|;:\'",<>?'
223 GREEDY_DELIMS = ' =\r\n'
226 GREEDY_DELIMS = ' =\r\n'
224
227
225
228
226 class CompletionSplitter(object):
229 class CompletionSplitter(object):
227 """An object to split an input line in a manner similar to readline.
230 """An object to split an input line in a manner similar to readline.
228
231
229 By having our own implementation, we can expose readline-like completion in
232 By having our own implementation, we can expose readline-like completion in
230 a uniform manner to all frontends. This object only needs to be given the
233 a uniform manner to all frontends. This object only needs to be given the
231 line of text to be split and the cursor position on said line, and it
234 line of text to be split and the cursor position on said line, and it
232 returns the 'word' to be completed on at the cursor after splitting the
235 returns the 'word' to be completed on at the cursor after splitting the
233 entire line.
236 entire line.
234
237
235 What characters are used as splitting delimiters can be controlled by
238 What characters are used as splitting delimiters can be controlled by
236 setting the `delims` attribute (this is a property that internally
239 setting the `delims` attribute (this is a property that internally
237 automatically builds the necessary regular expression)"""
240 automatically builds the necessary regular expression)"""
238
241
239 # Private interface
242 # Private interface
240
243
241 # A string of delimiter characters. The default value makes sense for
244 # A string of delimiter characters. The default value makes sense for
242 # IPython's most typical usage patterns.
245 # IPython's most typical usage patterns.
243 _delims = DELIMS
246 _delims = DELIMS
244
247
245 # The expression (a normal string) to be compiled into a regular expression
248 # The expression (a normal string) to be compiled into a regular expression
246 # for actual splitting. We store it as an attribute mostly for ease of
249 # for actual splitting. We store it as an attribute mostly for ease of
247 # debugging, since this type of code can be so tricky to debug.
250 # debugging, since this type of code can be so tricky to debug.
248 _delim_expr = None
251 _delim_expr = None
249
252
250 # The regular expression that does the actual splitting
253 # The regular expression that does the actual splitting
251 _delim_re = None
254 _delim_re = None
252
255
253 def __init__(self, delims=None):
256 def __init__(self, delims=None):
254 delims = CompletionSplitter._delims if delims is None else delims
257 delims = CompletionSplitter._delims if delims is None else delims
255 self.delims = delims
258 self.delims = delims
256
259
257 @property
260 @property
258 def delims(self):
261 def delims(self):
259 """Return the string of delimiter characters."""
262 """Return the string of delimiter characters."""
260 return self._delims
263 return self._delims
261
264
262 @delims.setter
265 @delims.setter
263 def delims(self, delims):
266 def delims(self, delims):
264 """Set the delimiters for line splitting."""
267 """Set the delimiters for line splitting."""
265 expr = '[' + ''.join('\\'+ c for c in delims) + ']'
268 expr = '[' + ''.join('\\'+ c for c in delims) + ']'
266 self._delim_re = re.compile(expr)
269 self._delim_re = re.compile(expr)
267 self._delims = delims
270 self._delims = delims
268 self._delim_expr = expr
271 self._delim_expr = expr
269
272
270 def split_line(self, line, cursor_pos=None):
273 def split_line(self, line, cursor_pos=None):
271 """Split a line of text with a cursor at the given position.
274 """Split a line of text with a cursor at the given position.
272 """
275 """
273 l = line if cursor_pos is None else line[:cursor_pos]
276 l = line if cursor_pos is None else line[:cursor_pos]
274 return self._delim_re.split(l)[-1]
277 return self._delim_re.split(l)[-1]
275
278
276
279
277 class Completer(Configurable):
280 class Completer(Configurable):
278
281
279 greedy = CBool(False, config=True,
282 greedy = CBool(False, config=True,
280 help="""Activate greedy completion
283 help="""Activate greedy completion
281
284
282 This will enable completion on elements of lists, results of function calls, etc.,
285 This will enable completion on elements of lists, results of function calls, etc.,
283 but can be unsafe because the code is actually evaluated on TAB.
286 but can be unsafe because the code is actually evaluated on TAB.
284 """
287 """
285 )
288 )
286
289
287
290
288 def __init__(self, namespace=None, global_namespace=None, **kwargs):
291 def __init__(self, namespace=None, global_namespace=None, **kwargs):
289 """Create a new completer for the command line.
292 """Create a new completer for the command line.
290
293
291 Completer(namespace=ns,global_namespace=ns2) -> completer instance.
294 Completer(namespace=ns,global_namespace=ns2) -> completer instance.
292
295
293 If unspecified, the default namespace where completions are performed
296 If unspecified, the default namespace where completions are performed
294 is __main__ (technically, __main__.__dict__). Namespaces should be
297 is __main__ (technically, __main__.__dict__). Namespaces should be
295 given as dictionaries.
298 given as dictionaries.
296
299
297 An optional second namespace can be given. This allows the completer
300 An optional second namespace can be given. This allows the completer
298 to handle cases where both the local and global scopes need to be
301 to handle cases where both the local and global scopes need to be
299 distinguished.
302 distinguished.
300
303
301 Completer instances should be used as the completion mechanism of
304 Completer instances should be used as the completion mechanism of
302 readline via the set_completer() call:
305 readline via the set_completer() call:
303
306
304 readline.set_completer(Completer(my_namespace).complete)
307 readline.set_completer(Completer(my_namespace).complete)
305 """
308 """
306
309
307 # Don't bind to namespace quite yet, but flag whether the user wants a
310 # Don't bind to namespace quite yet, but flag whether the user wants a
308 # specific namespace or to use __main__.__dict__. This will allow us
311 # specific namespace or to use __main__.__dict__. This will allow us
309 # to bind to __main__.__dict__ at completion time, not now.
312 # to bind to __main__.__dict__ at completion time, not now.
310 if namespace is None:
313 if namespace is None:
311 self.use_main_ns = 1
314 self.use_main_ns = 1
312 else:
315 else:
313 self.use_main_ns = 0
316 self.use_main_ns = 0
314 self.namespace = namespace
317 self.namespace = namespace
315
318
316 # The global namespace, if given, can be bound directly
319 # The global namespace, if given, can be bound directly
317 if global_namespace is None:
320 if global_namespace is None:
318 self.global_namespace = {}
321 self.global_namespace = {}
319 else:
322 else:
320 self.global_namespace = global_namespace
323 self.global_namespace = global_namespace
321
324
322 super(Completer, self).__init__(**kwargs)
325 super(Completer, self).__init__(**kwargs)
323
326
324 def complete(self, text, state):
327 def complete(self, text, state):
325 """Return the next possible completion for 'text'.
328 """Return the next possible completion for 'text'.
326
329
327 This is called successively with state == 0, 1, 2, ... until it
330 This is called successively with state == 0, 1, 2, ... until it
328 returns None. The completion should begin with 'text'.
331 returns None. The completion should begin with 'text'.
329
332
330 """
333 """
331 if self.use_main_ns:
334 if self.use_main_ns:
332 self.namespace = __main__.__dict__
335 self.namespace = __main__.__dict__
333
336
334 if state == 0:
337 if state == 0:
335 if "." in text:
338 if "." in text:
336 self.matches = self.attr_matches(text)
339 self.matches = self.attr_matches(text)
337 else:
340 else:
338 self.matches = self.global_matches(text)
341 self.matches = self.global_matches(text)
339 try:
342 try:
340 return self.matches[state]
343 return self.matches[state]
341 except IndexError:
344 except IndexError:
342 return None
345 return None
343
346
344 def global_matches(self, text):
347 def global_matches(self, text):
345 """Compute matches when text is a simple name.
348 """Compute matches when text is a simple name.
346
349
347 Return a list of all keywords, built-in functions and names currently
350 Return a list of all keywords, built-in functions and names currently
348 defined in self.namespace or self.global_namespace that match.
351 defined in self.namespace or self.global_namespace that match.
349
352
350 """
353 """
351 #print 'Completer->global_matches, txt=%r' % text # dbg
354 #print 'Completer->global_matches, txt=%r' % text # dbg
352 matches = []
355 matches = []
353 match_append = matches.append
356 match_append = matches.append
354 n = len(text)
357 n = len(text)
355 for lst in [keyword.kwlist,
358 for lst in [keyword.kwlist,
356 builtin_mod.__dict__.keys(),
359 builtin_mod.__dict__.keys(),
357 self.namespace.keys(),
360 self.namespace.keys(),
358 self.global_namespace.keys()]:
361 self.global_namespace.keys()]:
359 for word in lst:
362 for word in lst:
360 if word[:n] == text and word != "__builtins__":
363 if word[:n] == text and word != "__builtins__":
361 match_append(word)
364 match_append(word)
362 return matches
365 return matches
363
366
364 def attr_matches(self, text):
367 def attr_matches(self, text):
365 """Compute matches when text contains a dot.
368 """Compute matches when text contains a dot.
366
369
367 Assuming the text is of the form NAME.NAME....[NAME], and is
370 Assuming the text is of the form NAME.NAME....[NAME], and is
368 evaluatable in self.namespace or self.global_namespace, it will be
371 evaluatable in self.namespace or self.global_namespace, it will be
369 evaluated and its attributes (as revealed by dir()) are used as
372 evaluated and its attributes (as revealed by dir()) are used as
370 possible completions. (For class instances, class members are are
373 possible completions. (For class instances, class members are are
371 also considered.)
374 also considered.)
372
375
373 WARNING: this can still invoke arbitrary C code, if an object
376 WARNING: this can still invoke arbitrary C code, if an object
374 with a __getattr__ hook is evaluated.
377 with a __getattr__ hook is evaluated.
375
378
376 """
379 """
377
380
378 #io.rprint('Completer->attr_matches, txt=%r' % text) # dbg
381 #io.rprint('Completer->attr_matches, txt=%r' % text) # dbg
379 # Another option, seems to work great. Catches things like ''.<tab>
382 # Another option, seems to work great. Catches things like ''.<tab>
380 m = re.match(r"(\S+(\.\w+)*)\.(\w*)$", text)
383 m = re.match(r"(\S+(\.\w+)*)\.(\w*)$", text)
381
384
382 if m:
385 if m:
383 expr, attr = m.group(1, 3)
386 expr, attr = m.group(1, 3)
384 elif self.greedy:
387 elif self.greedy:
385 m2 = re.match(r"(.+)\.(\w*)$", self.line_buffer)
388 m2 = re.match(r"(.+)\.(\w*)$", self.line_buffer)
386 if not m2:
389 if not m2:
387 return []
390 return []
388 expr, attr = m2.group(1,2)
391 expr, attr = m2.group(1,2)
389 else:
392 else:
390 return []
393 return []
391
394
392 try:
395 try:
393 obj = eval(expr, self.namespace)
396 obj = eval(expr, self.namespace)
394 except:
397 except:
395 try:
398 try:
396 obj = eval(expr, self.global_namespace)
399 obj = eval(expr, self.global_namespace)
397 except:
400 except:
398 return []
401 return []
399
402
400 if self.limit_to__all__ and hasattr(obj, '__all__'):
403 if self.limit_to__all__ and hasattr(obj, '__all__'):
401 words = get__all__entries(obj)
404 words = get__all__entries(obj)
402 else:
405 else:
403 words = dir2(obj)
406 words = dir2(obj)
404
407
405 try:
408 try:
406 words = generics.complete_object(obj, words)
409 words = generics.complete_object(obj, words)
407 except TryNext:
410 except TryNext:
408 pass
411 pass
409 except Exception:
412 except Exception:
410 # Silence errors from completion function
413 # Silence errors from completion function
411 #raise # dbg
414 #raise # dbg
412 pass
415 pass
413 # Build match list to return
416 # Build match list to return
414 n = len(attr)
417 n = len(attr)
415 res = ["%s.%s" % (expr, w) for w in words if w[:n] == attr ]
418 res = ["%s.%s" % (expr, w) for w in words if w[:n] == attr ]
416 return res
419 return res
417
420
418
421
419 def get__all__entries(obj):
422 def get__all__entries(obj):
420 """returns the strings in the __all__ attribute"""
423 """returns the strings in the __all__ attribute"""
421 try:
424 try:
422 words = getattr(obj, '__all__')
425 words = getattr(obj, '__all__')
423 except:
426 except:
424 return []
427 return []
425
428
426 return [w for w in words if isinstance(w, string_types)]
429 return [w for w in words if isinstance(w, string_types)]
427
430
428
431
429 class IPCompleter(Completer):
432 class IPCompleter(Completer):
430 """Extension of the completer class with IPython-specific features"""
433 """Extension of the completer class with IPython-specific features"""
431
434
432 def _greedy_changed(self, name, old, new):
435 def _greedy_changed(self, name, old, new):
433 """update the splitter and readline delims when greedy is changed"""
436 """update the splitter and readline delims when greedy is changed"""
434 if new:
437 if new:
435 self.splitter.delims = GREEDY_DELIMS
438 self.splitter.delims = GREEDY_DELIMS
436 else:
439 else:
437 self.splitter.delims = DELIMS
440 self.splitter.delims = DELIMS
438
441
439 if self.readline:
442 if self.readline:
440 self.readline.set_completer_delims(self.splitter.delims)
443 self.readline.set_completer_delims(self.splitter.delims)
441
444
442 merge_completions = CBool(True, config=True,
445 merge_completions = CBool(True, config=True,
443 help="""Whether to merge completion results into a single list
446 help="""Whether to merge completion results into a single list
444
447
445 If False, only the completion results from the first non-empty
448 If False, only the completion results from the first non-empty
446 completer will be returned.
449 completer will be returned.
447 """
450 """
448 )
451 )
449 omit__names = Enum((0,1,2), default_value=2, config=True,
452 omit__names = Enum((0,1,2), default_value=2, config=True,
450 help="""Instruct the completer to omit private method names
453 help="""Instruct the completer to omit private method names
451
454
452 Specifically, when completing on ``object.<tab>``.
455 Specifically, when completing on ``object.<tab>``.
453
456
454 When 2 [default]: all names that start with '_' will be excluded.
457 When 2 [default]: all names that start with '_' will be excluded.
455
458
456 When 1: all 'magic' names (``__foo__``) will be excluded.
459 When 1: all 'magic' names (``__foo__``) will be excluded.
457
460
458 When 0: nothing will be excluded.
461 When 0: nothing will be excluded.
459 """
462 """
460 )
463 )
461 limit_to__all__ = CBool(default_value=False, config=True,
464 limit_to__all__ = CBool(default_value=False, config=True,
462 help="""Instruct the completer to use __all__ for the completion
465 help="""Instruct the completer to use __all__ for the completion
463
466
464 Specifically, when completing on ``object.<tab>``.
467 Specifically, when completing on ``object.<tab>``.
465
468
466 When True: only those names in obj.__all__ will be included.
469 When True: only those names in obj.__all__ will be included.
467
470
468 When False [default]: the __all__ attribute is ignored
471 When False [default]: the __all__ attribute is ignored
469 """
472 """
470 )
473 )
471
474
472 def __init__(self, shell=None, namespace=None, global_namespace=None,
475 def __init__(self, shell=None, namespace=None, global_namespace=None,
473 use_readline=True, config=None, **kwargs):
476 use_readline=True, config=None, **kwargs):
474 """IPCompleter() -> completer
477 """IPCompleter() -> completer
475
478
476 Return a completer object suitable for use by the readline library
479 Return a completer object suitable for use by the readline library
477 via readline.set_completer().
480 via readline.set_completer().
478
481
479 Inputs:
482 Inputs:
480
483
481 - shell: a pointer to the ipython shell itself. This is needed
484 - shell: a pointer to the ipython shell itself. This is needed
482 because this completer knows about magic functions, and those can
485 because this completer knows about magic functions, and those can
483 only be accessed via the ipython instance.
486 only be accessed via the ipython instance.
484
487
485 - namespace: an optional dict where completions are performed.
488 - namespace: an optional dict where completions are performed.
486
489
487 - global_namespace: secondary optional dict for completions, to
490 - global_namespace: secondary optional dict for completions, to
488 handle cases (such as IPython embedded inside functions) where
491 handle cases (such as IPython embedded inside functions) where
489 both Python scopes are visible.
492 both Python scopes are visible.
490
493
491 use_readline : bool, optional
494 use_readline : bool, optional
492 If true, use the readline library. This completer can still function
495 If true, use the readline library. This completer can still function
493 without readline, though in that case callers must provide some extra
496 without readline, though in that case callers must provide some extra
494 information on each call about the current line."""
497 information on each call about the current line."""
495
498
496 self.magic_escape = ESC_MAGIC
499 self.magic_escape = ESC_MAGIC
497 self.splitter = CompletionSplitter()
500 self.splitter = CompletionSplitter()
498
501
499 # Readline configuration, only used by the rlcompleter method.
502 # Readline configuration, only used by the rlcompleter method.
500 if use_readline:
503 if use_readline:
501 # We store the right version of readline so that later code
504 # We store the right version of readline so that later code
502 import IPython.utils.rlineimpl as readline
505 import IPython.utils.rlineimpl as readline
503 self.readline = readline
506 self.readline = readline
504 else:
507 else:
505 self.readline = None
508 self.readline = None
506
509
507 # _greedy_changed() depends on splitter and readline being defined:
510 # _greedy_changed() depends on splitter and readline being defined:
508 Completer.__init__(self, namespace=namespace, global_namespace=global_namespace,
511 Completer.__init__(self, namespace=namespace, global_namespace=global_namespace,
509 config=config, **kwargs)
512 config=config, **kwargs)
510
513
511 # List where completion matches will be stored
514 # List where completion matches will be stored
512 self.matches = []
515 self.matches = []
513 self.shell = shell
516 self.shell = shell
514 # Regexp to split filenames with spaces in them
517 # Regexp to split filenames with spaces in them
515 self.space_name_re = re.compile(r'([^\\] )')
518 self.space_name_re = re.compile(r'([^\\] )')
516 # Hold a local ref. to glob.glob for speed
519 # Hold a local ref. to glob.glob for speed
517 self.glob = glob.glob
520 self.glob = glob.glob
518
521
519 # Determine if we are running on 'dumb' terminals, like (X)Emacs
522 # Determine if we are running on 'dumb' terminals, like (X)Emacs
520 # buffers, to avoid completion problems.
523 # buffers, to avoid completion problems.
521 term = os.environ.get('TERM','xterm')
524 term = os.environ.get('TERM','xterm')
522 self.dumb_terminal = term in ['dumb','emacs']
525 self.dumb_terminal = term in ['dumb','emacs']
523
526
524 # Special handling of backslashes needed in win32 platforms
527 # Special handling of backslashes needed in win32 platforms
525 if sys.platform == "win32":
528 if sys.platform == "win32":
526 self.clean_glob = self._clean_glob_win32
529 self.clean_glob = self._clean_glob_win32
527 else:
530 else:
528 self.clean_glob = self._clean_glob
531 self.clean_glob = self._clean_glob
529
532
530 #regexp to parse docstring for function signature
533 #regexp to parse docstring for function signature
531 self.docstring_sig_re = re.compile(r'^[\w|\s.]+\(([^)]*)\).*')
534 self.docstring_sig_re = re.compile(r'^[\w|\s.]+\(([^)]*)\).*')
532 self.docstring_kwd_re = re.compile(r'[\s|\[]*(\w+)(?:\s*=\s*.*)')
535 self.docstring_kwd_re = re.compile(r'[\s|\[]*(\w+)(?:\s*=\s*.*)')
533 #use this if positional argument name is also needed
536 #use this if positional argument name is also needed
534 #= re.compile(r'[\s|\[]*(\w+)(?:\s*=?\s*.*)')
537 #= re.compile(r'[\s|\[]*(\w+)(?:\s*=?\s*.*)')
535
538
536 # All active matcher routines for completion
539 # All active matcher routines for completion
537 self.matchers = [self.python_matches,
540 self.matchers = [self.python_matches,
538 self.file_matches,
541 self.file_matches,
539 self.magic_matches,
542 self.magic_matches,
540 self.python_func_kw_matches,
543 self.python_func_kw_matches,
541 ]
544 ]
542
545
543 def all_completions(self, text):
546 def all_completions(self, text):
544 """
547 """
545 Wrapper around the complete method for the benefit of emacs
548 Wrapper around the complete method for the benefit of emacs
546 and pydb.
549 and pydb.
547 """
550 """
548 return self.complete(text)[1]
551 return self.complete(text)[1]
549
552
550 def _clean_glob(self,text):
553 def _clean_glob(self,text):
551 return self.glob("%s*" % text)
554 return self.glob("%s*" % text)
552
555
553 def _clean_glob_win32(self,text):
556 def _clean_glob_win32(self,text):
554 return [f.replace("\\","/")
557 return [f.replace("\\","/")
555 for f in self.glob("%s*" % text)]
558 for f in self.glob("%s*" % text)]
556
559
557 def file_matches(self, text):
560 def file_matches(self, text):
558 """Match filenames, expanding ~USER type strings.
561 """Match filenames, expanding ~USER type strings.
559
562
560 Most of the seemingly convoluted logic in this completer is an
563 Most of the seemingly convoluted logic in this completer is an
561 attempt to handle filenames with spaces in them. And yet it's not
564 attempt to handle filenames with spaces in them. And yet it's not
562 quite perfect, because Python's readline doesn't expose all of the
565 quite perfect, because Python's readline doesn't expose all of the
563 GNU readline details needed for this to be done correctly.
566 GNU readline details needed for this to be done correctly.
564
567
565 For a filename with a space in it, the printed completions will be
568 For a filename with a space in it, the printed completions will be
566 only the parts after what's already been typed (instead of the
569 only the parts after what's already been typed (instead of the
567 full completions, as is normally done). I don't think with the
570 full completions, as is normally done). I don't think with the
568 current (as of Python 2.3) Python readline it's possible to do
571 current (as of Python 2.3) Python readline it's possible to do
569 better."""
572 better."""
570
573
571 #io.rprint('Completer->file_matches: <%r>' % text) # dbg
574 #io.rprint('Completer->file_matches: <%r>' % text) # dbg
572
575
573 # chars that require escaping with backslash - i.e. chars
576 # chars that require escaping with backslash - i.e. chars
574 # that readline treats incorrectly as delimiters, but we
577 # that readline treats incorrectly as delimiters, but we
575 # don't want to treat as delimiters in filename matching
578 # don't want to treat as delimiters in filename matching
576 # when escaped with backslash
579 # when escaped with backslash
577 if text.startswith('!'):
580 if text.startswith('!'):
578 text = text[1:]
581 text = text[1:]
579 text_prefix = '!'
582 text_prefix = '!'
580 else:
583 else:
581 text_prefix = ''
584 text_prefix = ''
582
585
583 text_until_cursor = self.text_until_cursor
586 text_until_cursor = self.text_until_cursor
584 # track strings with open quotes
587 # track strings with open quotes
585 open_quotes = has_open_quotes(text_until_cursor)
588 open_quotes = has_open_quotes(text_until_cursor)
586
589
587 if '(' in text_until_cursor or '[' in text_until_cursor:
590 if '(' in text_until_cursor or '[' in text_until_cursor:
588 lsplit = text
591 lsplit = text
589 else:
592 else:
590 try:
593 try:
591 # arg_split ~ shlex.split, but with unicode bugs fixed by us
594 # arg_split ~ shlex.split, but with unicode bugs fixed by us
592 lsplit = arg_split(text_until_cursor)[-1]
595 lsplit = arg_split(text_until_cursor)[-1]
593 except ValueError:
596 except ValueError:
594 # typically an unmatched ", or backslash without escaped char.
597 # typically an unmatched ", or backslash without escaped char.
595 if open_quotes:
598 if open_quotes:
596 lsplit = text_until_cursor.split(open_quotes)[-1]
599 lsplit = text_until_cursor.split(open_quotes)[-1]
597 else:
600 else:
598 return []
601 return []
599 except IndexError:
602 except IndexError:
600 # tab pressed on empty line
603 # tab pressed on empty line
601 lsplit = ""
604 lsplit = ""
602
605
603 if not open_quotes and lsplit != protect_filename(lsplit):
606 if not open_quotes and lsplit != protect_filename(lsplit):
604 # if protectables are found, do matching on the whole escaped name
607 # if protectables are found, do matching on the whole escaped name
605 has_protectables = True
608 has_protectables = True
606 text0,text = text,lsplit
609 text0,text = text,lsplit
607 else:
610 else:
608 has_protectables = False
611 has_protectables = False
609 text = os.path.expanduser(text)
612 text = os.path.expanduser(text)
610
613
611 if text == "":
614 if text == "":
612 return [text_prefix + protect_filename(f) for f in self.glob("*")]
615 return [text_prefix + protect_filename(f) for f in self.glob("*")]
613
616
614 # Compute the matches from the filesystem
617 # Compute the matches from the filesystem
615 m0 = self.clean_glob(text.replace('\\',''))
618 m0 = self.clean_glob(text.replace('\\',''))
616
619
617 if has_protectables:
620 if has_protectables:
618 # If we had protectables, we need to revert our changes to the
621 # If we had protectables, we need to revert our changes to the
619 # beginning of filename so that we don't double-write the part
622 # beginning of filename so that we don't double-write the part
620 # of the filename we have so far
623 # of the filename we have so far
621 len_lsplit = len(lsplit)
624 len_lsplit = len(lsplit)
622 matches = [text_prefix + text0 +
625 matches = [text_prefix + text0 +
623 protect_filename(f[len_lsplit:]) for f in m0]
626 protect_filename(f[len_lsplit:]) for f in m0]
624 else:
627 else:
625 if open_quotes:
628 if open_quotes:
626 # if we have a string with an open quote, we don't need to
629 # if we have a string with an open quote, we don't need to
627 # protect the names at all (and we _shouldn't_, as it
630 # protect the names at all (and we _shouldn't_, as it
628 # would cause bugs when the filesystem call is made).
631 # would cause bugs when the filesystem call is made).
629 matches = m0
632 matches = m0
630 else:
633 else:
631 matches = [text_prefix +
634 matches = [text_prefix +
632 protect_filename(f) for f in m0]
635 protect_filename(f) for f in m0]
633
636
634 #io.rprint('mm', matches) # dbg
637 #io.rprint('mm', matches) # dbg
635
638
636 # Mark directories in input list by appending '/' to their names.
639 # Mark directories in input list by appending '/' to their names.
637 matches = [x+'/' if os.path.isdir(x) else x for x in matches]
640 matches = [x+'/' if os.path.isdir(x) else x for x in matches]
638 return matches
641 return matches
639
642
640 def magic_matches(self, text):
643 def magic_matches(self, text):
641 """Match magics"""
644 """Match magics"""
642 #print 'Completer->magic_matches:',text,'lb',self.text_until_cursor # dbg
645 #print 'Completer->magic_matches:',text,'lb',self.text_until_cursor # dbg
643 # Get all shell magics now rather than statically, so magics loaded at
646 # Get all shell magics now rather than statically, so magics loaded at
644 # runtime show up too.
647 # runtime show up too.
645 lsm = self.shell.magics_manager.lsmagic()
648 lsm = self.shell.magics_manager.lsmagic()
646 line_magics = lsm['line']
649 line_magics = lsm['line']
647 cell_magics = lsm['cell']
650 cell_magics = lsm['cell']
648 pre = self.magic_escape
651 pre = self.magic_escape
649 pre2 = pre+pre
652 pre2 = pre+pre
650
653
651 # Completion logic:
654 # Completion logic:
652 # - user gives %%: only do cell magics
655 # - user gives %%: only do cell magics
653 # - user gives %: do both line and cell magics
656 # - user gives %: do both line and cell magics
654 # - no prefix: do both
657 # - no prefix: do both
655 # In other words, line magics are skipped if the user gives %% explicitly
658 # In other words, line magics are skipped if the user gives %% explicitly
656 bare_text = text.lstrip(pre)
659 bare_text = text.lstrip(pre)
657 comp = [ pre2+m for m in cell_magics if m.startswith(bare_text)]
660 comp = [ pre2+m for m in cell_magics if m.startswith(bare_text)]
658 if not text.startswith(pre2):
661 if not text.startswith(pre2):
659 comp += [ pre+m for m in line_magics if m.startswith(bare_text)]
662 comp += [ pre+m for m in line_magics if m.startswith(bare_text)]
660 return comp
663 return comp
661
664
662 def python_matches(self,text):
665 def python_matches(self,text):
663 """Match attributes or global python names"""
666 """Match attributes or global python names"""
664
667
665 #io.rprint('Completer->python_matches, txt=%r' % text) # dbg
668 #io.rprint('Completer->python_matches, txt=%r' % text) # dbg
666 if "." in text:
669 if "." in text:
667 try:
670 try:
668 matches = self.attr_matches(text)
671 matches = self.attr_matches(text)
669 if text.endswith('.') and self.omit__names:
672 if text.endswith('.') and self.omit__names:
670 if self.omit__names == 1:
673 if self.omit__names == 1:
671 # true if txt is _not_ a __ name, false otherwise:
674 # true if txt is _not_ a __ name, false otherwise:
672 no__name = (lambda txt:
675 no__name = (lambda txt:
673 re.match(r'.*\.__.*?__',txt) is None)
676 re.match(r'.*\.__.*?__',txt) is None)
674 else:
677 else:
675 # true if txt is _not_ a _ name, false otherwise:
678 # true if txt is _not_ a _ name, false otherwise:
676 no__name = (lambda txt:
679 no__name = (lambda txt:
677 re.match(r'.*\._.*?',txt) is None)
680 re.match(r'.*\._.*?',txt) is None)
678 matches = filter(no__name, matches)
681 matches = filter(no__name, matches)
679 except NameError:
682 except NameError:
680 # catches <undefined attributes>.<tab>
683 # catches <undefined attributes>.<tab>
681 matches = []
684 matches = []
682 else:
685 else:
683 matches = self.global_matches(text)
686 matches = self.global_matches(text)
684
687
685 return matches
688 return matches
686
689
687 def _default_arguments_from_docstring(self, doc):
690 def _default_arguments_from_docstring(self, doc):
688 """Parse the first line of docstring for call signature.
691 """Parse the first line of docstring for call signature.
689
692
690 Docstring should be of the form 'min(iterable[, key=func])\n'.
693 Docstring should be of the form 'min(iterable[, key=func])\n'.
691 It can also parse cython docstring of the form
694 It can also parse cython docstring of the form
692 'Minuit.migrad(self, int ncall=10000, resume=True, int nsplit=1)'.
695 'Minuit.migrad(self, int ncall=10000, resume=True, int nsplit=1)'.
693 """
696 """
694 if doc is None:
697 if doc is None:
695 return []
698 return []
696
699
697 #care only the firstline
700 #care only the firstline
698 line = doc.lstrip().splitlines()[0]
701 line = doc.lstrip().splitlines()[0]
699
702
700 #p = re.compile(r'^[\w|\s.]+\(([^)]*)\).*')
703 #p = re.compile(r'^[\w|\s.]+\(([^)]*)\).*')
701 #'min(iterable[, key=func])\n' -> 'iterable[, key=func]'
704 #'min(iterable[, key=func])\n' -> 'iterable[, key=func]'
702 sig = self.docstring_sig_re.search(line)
705 sig = self.docstring_sig_re.search(line)
703 if sig is None:
706 if sig is None:
704 return []
707 return []
705 # iterable[, key=func]' -> ['iterable[' ,' key=func]']
708 # iterable[, key=func]' -> ['iterable[' ,' key=func]']
706 sig = sig.groups()[0].split(',')
709 sig = sig.groups()[0].split(',')
707 ret = []
710 ret = []
708 for s in sig:
711 for s in sig:
709 #re.compile(r'[\s|\[]*(\w+)(?:\s*=\s*.*)')
712 #re.compile(r'[\s|\[]*(\w+)(?:\s*=\s*.*)')
710 ret += self.docstring_kwd_re.findall(s)
713 ret += self.docstring_kwd_re.findall(s)
711 return ret
714 return ret
712
715
713 def _default_arguments(self, obj):
716 def _default_arguments(self, obj):
714 """Return the list of default arguments of obj if it is callable,
717 """Return the list of default arguments of obj if it is callable,
715 or empty list otherwise."""
718 or empty list otherwise."""
716 call_obj = obj
719 call_obj = obj
717 ret = []
720 ret = []
718 if inspect.isbuiltin(obj):
721 if inspect.isbuiltin(obj):
719 pass
722 pass
720 elif not (inspect.isfunction(obj) or inspect.ismethod(obj)):
723 elif not (inspect.isfunction(obj) or inspect.ismethod(obj)):
721 if inspect.isclass(obj):
724 if inspect.isclass(obj):
722 #for cython embededsignature=True the constructor docstring
725 #for cython embededsignature=True the constructor docstring
723 #belongs to the object itself not __init__
726 #belongs to the object itself not __init__
724 ret += self._default_arguments_from_docstring(
727 ret += self._default_arguments_from_docstring(
725 getattr(obj, '__doc__', ''))
728 getattr(obj, '__doc__', ''))
726 # for classes, check for __init__,__new__
729 # for classes, check for __init__,__new__
727 call_obj = (getattr(obj, '__init__', None) or
730 call_obj = (getattr(obj, '__init__', None) or
728 getattr(obj, '__new__', None))
731 getattr(obj, '__new__', None))
729 # for all others, check if they are __call__able
732 # for all others, check if they are __call__able
730 elif hasattr(obj, '__call__'):
733 elif hasattr(obj, '__call__'):
731 call_obj = obj.__call__
734 call_obj = obj.__call__
732
735
733 ret += self._default_arguments_from_docstring(
736 ret += self._default_arguments_from_docstring(
734 getattr(call_obj, '__doc__', ''))
737 getattr(call_obj, '__doc__', ''))
735
738
736 try:
739 try:
737 args,_,_1,defaults = inspect.getargspec(call_obj)
740 args,_,_1,defaults = inspect.getargspec(call_obj)
738 if defaults:
741 if defaults:
739 ret+=args[-len(defaults):]
742 ret+=args[-len(defaults):]
740 except TypeError:
743 except TypeError:
741 pass
744 pass
742
745
743 return list(set(ret))
746 return list(set(ret))
744
747
745 def python_func_kw_matches(self,text):
748 def python_func_kw_matches(self,text):
746 """Match named parameters (kwargs) of the last open function"""
749 """Match named parameters (kwargs) of the last open function"""
747
750
748 if "." in text: # a parameter cannot be dotted
751 if "." in text: # a parameter cannot be dotted
749 return []
752 return []
750 try: regexp = self.__funcParamsRegex
753 try: regexp = self.__funcParamsRegex
751 except AttributeError:
754 except AttributeError:
752 regexp = self.__funcParamsRegex = re.compile(r'''
755 regexp = self.__funcParamsRegex = re.compile(r'''
753 '.*?(?<!\\)' | # single quoted strings or
756 '.*?(?<!\\)' | # single quoted strings or
754 ".*?(?<!\\)" | # double quoted strings or
757 ".*?(?<!\\)" | # double quoted strings or
755 \w+ | # identifier
758 \w+ | # identifier
756 \S # other characters
759 \S # other characters
757 ''', re.VERBOSE | re.DOTALL)
760 ''', re.VERBOSE | re.DOTALL)
758 # 1. find the nearest identifier that comes before an unclosed
761 # 1. find the nearest identifier that comes before an unclosed
759 # parenthesis before the cursor
762 # parenthesis before the cursor
760 # e.g. for "foo (1+bar(x), pa<cursor>,a=1)", the candidate is "foo"
763 # e.g. for "foo (1+bar(x), pa<cursor>,a=1)", the candidate is "foo"
761 tokens = regexp.findall(self.text_until_cursor)
764 tokens = regexp.findall(self.text_until_cursor)
762 tokens.reverse()
765 tokens.reverse()
763 iterTokens = iter(tokens); openPar = 0
766 iterTokens = iter(tokens); openPar = 0
764
767
765 for token in iterTokens:
768 for token in iterTokens:
766 if token == ')':
769 if token == ')':
767 openPar -= 1
770 openPar -= 1
768 elif token == '(':
771 elif token == '(':
769 openPar += 1
772 openPar += 1
770 if openPar > 0:
773 if openPar > 0:
771 # found the last unclosed parenthesis
774 # found the last unclosed parenthesis
772 break
775 break
773 else:
776 else:
774 return []
777 return []
775 # 2. Concatenate dotted names ("foo.bar" for "foo.bar(x, pa" )
778 # 2. Concatenate dotted names ("foo.bar" for "foo.bar(x, pa" )
776 ids = []
779 ids = []
777 isId = re.compile(r'\w+$').match
780 isId = re.compile(r'\w+$').match
778
781
779 while True:
782 while True:
780 try:
783 try:
781 ids.append(next(iterTokens))
784 ids.append(next(iterTokens))
782 if not isId(ids[-1]):
785 if not isId(ids[-1]):
783 ids.pop(); break
786 ids.pop(); break
784 if not next(iterTokens) == '.':
787 if not next(iterTokens) == '.':
785 break
788 break
786 except StopIteration:
789 except StopIteration:
787 break
790 break
788 # lookup the candidate callable matches either using global_matches
791 # lookup the candidate callable matches either using global_matches
789 # or attr_matches for dotted names
792 # or attr_matches for dotted names
790 if len(ids) == 1:
793 if len(ids) == 1:
791 callableMatches = self.global_matches(ids[0])
794 callableMatches = self.global_matches(ids[0])
792 else:
795 else:
793 callableMatches = self.attr_matches('.'.join(ids[::-1]))
796 callableMatches = self.attr_matches('.'.join(ids[::-1]))
794 argMatches = []
797 argMatches = []
795 for callableMatch in callableMatches:
798 for callableMatch in callableMatches:
796 try:
799 try:
797 namedArgs = self._default_arguments(eval(callableMatch,
800 namedArgs = self._default_arguments(eval(callableMatch,
798 self.namespace))
801 self.namespace))
799 except:
802 except:
800 continue
803 continue
801
804
802 for namedArg in namedArgs:
805 for namedArg in namedArgs:
803 if namedArg.startswith(text):
806 if namedArg.startswith(text):
804 argMatches.append("%s=" %namedArg)
807 argMatches.append("%s=" %namedArg)
805 return argMatches
808 return argMatches
806
809
807 def dispatch_custom_completer(self, text):
810 def dispatch_custom_completer(self, text):
808 #io.rprint("Custom! '%s' %s" % (text, self.custom_completers)) # dbg
811 #io.rprint("Custom! '%s' %s" % (text, self.custom_completers)) # dbg
809 line = self.line_buffer
812 line = self.line_buffer
810 if not line.strip():
813 if not line.strip():
811 return None
814 return None
812
815
813 # Create a little structure to pass all the relevant information about
816 # Create a little structure to pass all the relevant information about
814 # the current completion to any custom completer.
817 # the current completion to any custom completer.
815 event = Bunch()
818 event = Bunch()
816 event.line = line
819 event.line = line
817 event.symbol = text
820 event.symbol = text
818 cmd = line.split(None,1)[0]
821 cmd = line.split(None,1)[0]
819 event.command = cmd
822 event.command = cmd
820 event.text_until_cursor = self.text_until_cursor
823 event.text_until_cursor = self.text_until_cursor
821
824
822 #print "\ncustom:{%s]\n" % event # dbg
825 #print "\ncustom:{%s]\n" % event # dbg
823
826
824 # for foo etc, try also to find completer for %foo
827 # for foo etc, try also to find completer for %foo
825 if not cmd.startswith(self.magic_escape):
828 if not cmd.startswith(self.magic_escape):
826 try_magic = self.custom_completers.s_matches(
829 try_magic = self.custom_completers.s_matches(
827 self.magic_escape + cmd)
830 self.magic_escape + cmd)
828 else:
831 else:
829 try_magic = []
832 try_magic = []
830
833
831 for c in itertools.chain(self.custom_completers.s_matches(cmd),
834 for c in itertools.chain(self.custom_completers.s_matches(cmd),
832 try_magic,
835 try_magic,
833 self.custom_completers.flat_matches(self.text_until_cursor)):
836 self.custom_completers.flat_matches(self.text_until_cursor)):
834 #print "try",c # dbg
837 #print "try",c # dbg
835 try:
838 try:
836 res = c(event)
839 res = c(event)
837 if res:
840 if res:
838 # first, try case sensitive match
841 # first, try case sensitive match
839 withcase = [r for r in res if r.startswith(text)]
842 withcase = [r for r in res if r.startswith(text)]
840 if withcase:
843 if withcase:
841 return withcase
844 return withcase
842 # if none, then case insensitive ones are ok too
845 # if none, then case insensitive ones are ok too
843 text_low = text.lower()
846 text_low = text.lower()
844 return [r for r in res if r.lower().startswith(text_low)]
847 return [r for r in res if r.lower().startswith(text_low)]
845 except TryNext:
848 except TryNext:
846 pass
849 pass
847
850
848 return None
851 return None
849
852
850 def complete(self, text=None, line_buffer=None, cursor_pos=None):
853 def complete(self, text=None, line_buffer=None, cursor_pos=None):
851 """Find completions for the given text and line context.
854 """Find completions for the given text and line context.
852
855
853 This is called successively with state == 0, 1, 2, ... until it
856 This is called successively with state == 0, 1, 2, ... until it
854 returns None. The completion should begin with 'text'.
857 returns None. The completion should begin with 'text'.
855
858
856 Note that both the text and the line_buffer are optional, but at least
859 Note that both the text and the line_buffer are optional, but at least
857 one of them must be given.
860 one of them must be given.
858
861
859 Parameters
862 Parameters
860 ----------
863 ----------
861 text : string, optional
864 text : string, optional
862 Text to perform the completion on. If not given, the line buffer
865 Text to perform the completion on. If not given, the line buffer
863 is split using the instance's CompletionSplitter object.
866 is split using the instance's CompletionSplitter object.
864
867
865 line_buffer : string, optional
868 line_buffer : string, optional
866 If not given, the completer attempts to obtain the current line
869 If not given, the completer attempts to obtain the current line
867 buffer via readline. This keyword allows clients which are
870 buffer via readline. This keyword allows clients which are
868 requesting for text completions in non-readline contexts to inform
871 requesting for text completions in non-readline contexts to inform
869 the completer of the entire text.
872 the completer of the entire text.
870
873
871 cursor_pos : int, optional
874 cursor_pos : int, optional
872 Index of the cursor in the full line buffer. Should be provided by
875 Index of the cursor in the full line buffer. Should be provided by
873 remote frontends where kernel has no access to frontend state.
876 remote frontends where kernel has no access to frontend state.
874
877
875 Returns
878 Returns
876 -------
879 -------
877 text : str
880 text : str
878 Text that was actually used in the completion.
881 Text that was actually used in the completion.
879
882
880 matches : list
883 matches : list
881 A list of completion matches.
884 A list of completion matches.
882 """
885 """
883 #io.rprint('\nCOMP1 %r %r %r' % (text, line_buffer, cursor_pos)) # dbg
886 #io.rprint('\nCOMP1 %r %r %r' % (text, line_buffer, cursor_pos)) # dbg
884
887
885 # if the cursor position isn't given, the only sane assumption we can
888 # if the cursor position isn't given, the only sane assumption we can
886 # make is that it's at the end of the line (the common case)
889 # make is that it's at the end of the line (the common case)
887 if cursor_pos is None:
890 if cursor_pos is None:
888 cursor_pos = len(line_buffer) if text is None else len(text)
891 cursor_pos = len(line_buffer) if text is None else len(text)
889
892
890 # if text is either None or an empty string, rely on the line buffer
893 # if text is either None or an empty string, rely on the line buffer
891 if not text:
894 if not text:
892 text = self.splitter.split_line(line_buffer, cursor_pos)
895 text = self.splitter.split_line(line_buffer, cursor_pos)
893
896
894 # If no line buffer is given, assume the input text is all there was
897 # If no line buffer is given, assume the input text is all there was
895 if line_buffer is None:
898 if line_buffer is None:
896 line_buffer = text
899 line_buffer = text
897
900
898 self.line_buffer = line_buffer
901 self.line_buffer = line_buffer
899 self.text_until_cursor = self.line_buffer[:cursor_pos]
902 self.text_until_cursor = self.line_buffer[:cursor_pos]
900 #io.rprint('COMP2 %r %r %r' % (text, line_buffer, cursor_pos)) # dbg
903 #io.rprint('COMP2 %r %r %r' % (text, line_buffer, cursor_pos)) # dbg
901
904
902 # Start with a clean slate of completions
905 # Start with a clean slate of completions
903 self.matches[:] = []
906 self.matches[:] = []
904 custom_res = self.dispatch_custom_completer(text)
907 custom_res = self.dispatch_custom_completer(text)
905 if custom_res is not None:
908 if custom_res is not None:
906 # did custom completers produce something?
909 # did custom completers produce something?
907 self.matches = custom_res
910 self.matches = custom_res
908 else:
911 else:
909 # Extend the list of completions with the results of each
912 # Extend the list of completions with the results of each
910 # matcher, so we return results to the user from all
913 # matcher, so we return results to the user from all
911 # namespaces.
914 # namespaces.
912 if self.merge_completions:
915 if self.merge_completions:
913 self.matches = []
916 self.matches = []
914 for matcher in self.matchers:
917 for matcher in self.matchers:
915 try:
918 try:
916 self.matches.extend(matcher(text))
919 self.matches.extend(matcher(text))
917 except:
920 except:
918 # Show the ugly traceback if the matcher causes an
921 # Show the ugly traceback if the matcher causes an
919 # exception, but do NOT crash the kernel!
922 # exception, but do NOT crash the kernel!
920 sys.excepthook(*sys.exc_info())
923 sys.excepthook(*sys.exc_info())
921 else:
924 else:
922 for matcher in self.matchers:
925 for matcher in self.matchers:
923 self.matches = matcher(text)
926 self.matches = matcher(text)
924 if self.matches:
927 if self.matches:
925 break
928 break
926 # FIXME: we should extend our api to return a dict with completions for
929 # FIXME: we should extend our api to return a dict with completions for
927 # different types of objects. The rlcomplete() method could then
930 # different types of objects. The rlcomplete() method could then
928 # simply collapse the dict into a list for readline, but we'd have
931 # simply collapse the dict into a list for readline, but we'd have
929 # richer completion semantics in other evironments.
932 # richer completion semantics in other evironments.
930
933
931 # use penalize_magics_key to put magics after variables with same name
934 # use penalize_magics_key to put magics after variables with same name
932 self.matches = sorted(set(self.matches), key=penalize_magics_key)
935 self.matches = sorted(set(self.matches), key=penalize_magics_key)
933
936
934 #io.rprint('COMP TEXT, MATCHES: %r, %r' % (text, self.matches)) # dbg
937 #io.rprint('COMP TEXT, MATCHES: %r, %r' % (text, self.matches)) # dbg
935 return text, self.matches
938 return text, self.matches
936
939
937 def rlcomplete(self, text, state):
940 def rlcomplete(self, text, state):
938 """Return the state-th possible completion for 'text'.
941 """Return the state-th possible completion for 'text'.
939
942
940 This is called successively with state == 0, 1, 2, ... until it
943 This is called successively with state == 0, 1, 2, ... until it
941 returns None. The completion should begin with 'text'.
944 returns None. The completion should begin with 'text'.
942
945
943 Parameters
946 Parameters
944 ----------
947 ----------
945 text : string
948 text : string
946 Text to perform the completion on.
949 Text to perform the completion on.
947
950
948 state : int
951 state : int
949 Counter used by readline.
952 Counter used by readline.
950 """
953 """
951 if state==0:
954 if state==0:
952
955
953 self.line_buffer = line_buffer = self.readline.get_line_buffer()
956 self.line_buffer = line_buffer = self.readline.get_line_buffer()
954 cursor_pos = self.readline.get_endidx()
957 cursor_pos = self.readline.get_endidx()
955
958
956 #io.rprint("\nRLCOMPLETE: %r %r %r" %
959 #io.rprint("\nRLCOMPLETE: %r %r %r" %
957 # (text, line_buffer, cursor_pos) ) # dbg
960 # (text, line_buffer, cursor_pos) ) # dbg
958
961
959 # if there is only a tab on a line with only whitespace, instead of
962 # if there is only a tab on a line with only whitespace, instead of
960 # the mostly useless 'do you want to see all million completions'
963 # the mostly useless 'do you want to see all million completions'
961 # message, just do the right thing and give the user his tab!
964 # message, just do the right thing and give the user his tab!
962 # Incidentally, this enables pasting of tabbed text from an editor
965 # Incidentally, this enables pasting of tabbed text from an editor
963 # (as long as autoindent is off).
966 # (as long as autoindent is off).
964
967
965 # It should be noted that at least pyreadline still shows file
968 # It should be noted that at least pyreadline still shows file
966 # completions - is there a way around it?
969 # completions - is there a way around it?
967
970
968 # don't apply this on 'dumb' terminals, such as emacs buffers, so
971 # don't apply this on 'dumb' terminals, such as emacs buffers, so
969 # we don't interfere with their own tab-completion mechanism.
972 # we don't interfere with their own tab-completion mechanism.
970 if not (self.dumb_terminal or line_buffer.strip()):
973 if not (self.dumb_terminal or line_buffer.strip()):
971 self.readline.insert_text('\t')
974 self.readline.insert_text('\t')
972 sys.stdout.flush()
975 sys.stdout.flush()
973 return None
976 return None
974
977
975 # Note: debugging exceptions that may occur in completion is very
978 # Note: debugging exceptions that may occur in completion is very
976 # tricky, because readline unconditionally silences them. So if
979 # tricky, because readline unconditionally silences them. So if
977 # during development you suspect a bug in the completion code, turn
980 # during development you suspect a bug in the completion code, turn
978 # this flag on temporarily by uncommenting the second form (don't
981 # this flag on temporarily by uncommenting the second form (don't
979 # flip the value in the first line, as the '# dbg' marker can be
982 # flip the value in the first line, as the '# dbg' marker can be
980 # automatically detected and is used elsewhere).
983 # automatically detected and is used elsewhere).
981 DEBUG = False
984 DEBUG = False
982 #DEBUG = True # dbg
985 #DEBUG = True # dbg
983 if DEBUG:
986 if DEBUG:
984 try:
987 try:
985 self.complete(text, line_buffer, cursor_pos)
988 self.complete(text, line_buffer, cursor_pos)
986 except:
989 except:
987 import traceback; traceback.print_exc()
990 import traceback; traceback.print_exc()
988 else:
991 else:
989 # The normal production version is here
992 # The normal production version is here
990
993
991 # This method computes the self.matches array
994 # This method computes the self.matches array
992 self.complete(text, line_buffer, cursor_pos)
995 self.complete(text, line_buffer, cursor_pos)
993
996
994 try:
997 try:
995 return self.matches[state]
998 return self.matches[state]
996 except IndexError:
999 except IndexError:
997 return None
1000 return None
@@ -1,439 +1,440 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Classes for handling input/output prompts.
2 """Classes for handling input/output prompts.
3
3
4 Authors:
4 Authors:
5
5
6 * Fernando Perez
6 * Fernando Perez
7 * Brian Granger
7 * Brian Granger
8 * Thomas Kluyver
8 * Thomas Kluyver
9 """
9 """
10
10
11 #-----------------------------------------------------------------------------
11 #-----------------------------------------------------------------------------
12 # Copyright (C) 2008-2011 The IPython Development Team
12 # Copyright (C) 2008-2011 The IPython Development Team
13 # Copyright (C) 2001-2007 Fernando Perez <fperez@colorado.edu>
13 # Copyright (C) 2001-2007 Fernando Perez <fperez@colorado.edu>
14 #
14 #
15 # Distributed under the terms of the BSD License. The full license is in
15 # Distributed under the terms of the BSD License. The full license is in
16 # the file COPYING, distributed as part of this software.
16 # the file COPYING, distributed as part of this software.
17 #-----------------------------------------------------------------------------
17 #-----------------------------------------------------------------------------
18
18
19 #-----------------------------------------------------------------------------
19 #-----------------------------------------------------------------------------
20 # Imports
20 # Imports
21 #-----------------------------------------------------------------------------
21 #-----------------------------------------------------------------------------
22
22
23 import os
23 import os
24 import re
24 import re
25 import socket
25 import socket
26 import sys
26 import sys
27 import time
27 import time
28
28
29 from string import Formatter
29 from string import Formatter
30
30
31 from IPython.config.configurable import Configurable
31 from IPython.config.configurable import Configurable
32 from IPython.core import release
32 from IPython.core import release
33 from IPython.utils import coloransi, py3compat
33 from IPython.utils import coloransi, py3compat
34 from IPython.utils.traitlets import (Unicode, Instance, Dict, Bool, Int)
34 from IPython.utils.traitlets import (Unicode, Instance, Dict, Bool, Int)
35
35
36 #-----------------------------------------------------------------------------
36 #-----------------------------------------------------------------------------
37 # Color schemes for prompts
37 # Color schemes for prompts
38 #-----------------------------------------------------------------------------
38 #-----------------------------------------------------------------------------
39
39
40 InputColors = coloransi.InputTermColors # just a shorthand
40 InputColors = coloransi.InputTermColors # just a shorthand
41 Colors = coloransi.TermColors # just a shorthand
41 Colors = coloransi.TermColors # just a shorthand
42
42
43 color_lists = dict(normal=Colors(), inp=InputColors(), nocolor=coloransi.NoColors())
43 color_lists = dict(normal=Colors(), inp=InputColors(), nocolor=coloransi.NoColors())
44
44
45 PColNoColors = coloransi.ColorScheme(
45 PColNoColors = coloransi.ColorScheme(
46 'NoColor',
46 'NoColor',
47 in_prompt = InputColors.NoColor, # Input prompt
47 in_prompt = InputColors.NoColor, # Input prompt
48 in_number = InputColors.NoColor, # Input prompt number
48 in_number = InputColors.NoColor, # Input prompt number
49 in_prompt2 = InputColors.NoColor, # Continuation prompt
49 in_prompt2 = InputColors.NoColor, # Continuation prompt
50 in_normal = InputColors.NoColor, # color off (usu. Colors.Normal)
50 in_normal = InputColors.NoColor, # color off (usu. Colors.Normal)
51
51
52 out_prompt = Colors.NoColor, # Output prompt
52 out_prompt = Colors.NoColor, # Output prompt
53 out_number = Colors.NoColor, # Output prompt number
53 out_number = Colors.NoColor, # Output prompt number
54
54
55 normal = Colors.NoColor # color off (usu. Colors.Normal)
55 normal = Colors.NoColor # color off (usu. Colors.Normal)
56 )
56 )
57
57
58 # make some schemes as instances so we can copy them for modification easily:
58 # make some schemes as instances so we can copy them for modification easily:
59 PColLinux = coloransi.ColorScheme(
59 PColLinux = coloransi.ColorScheme(
60 'Linux',
60 'Linux',
61 in_prompt = InputColors.Green,
61 in_prompt = InputColors.Green,
62 in_number = InputColors.LightGreen,
62 in_number = InputColors.LightGreen,
63 in_prompt2 = InputColors.Green,
63 in_prompt2 = InputColors.Green,
64 in_normal = InputColors.Normal, # color off (usu. Colors.Normal)
64 in_normal = InputColors.Normal, # color off (usu. Colors.Normal)
65
65
66 out_prompt = Colors.Red,
66 out_prompt = Colors.Red,
67 out_number = Colors.LightRed,
67 out_number = Colors.LightRed,
68
68
69 normal = Colors.Normal
69 normal = Colors.Normal
70 )
70 )
71
71
72 # Slightly modified Linux for light backgrounds
72 # Slightly modified Linux for light backgrounds
73 PColLightBG = PColLinux.copy('LightBG')
73 PColLightBG = PColLinux.copy('LightBG')
74
74
75 PColLightBG.colors.update(
75 PColLightBG.colors.update(
76 in_prompt = InputColors.Blue,
76 in_prompt = InputColors.Blue,
77 in_number = InputColors.LightBlue,
77 in_number = InputColors.LightBlue,
78 in_prompt2 = InputColors.Blue
78 in_prompt2 = InputColors.Blue
79 )
79 )
80
80
81 #-----------------------------------------------------------------------------
81 #-----------------------------------------------------------------------------
82 # Utilities
82 # Utilities
83 #-----------------------------------------------------------------------------
83 #-----------------------------------------------------------------------------
84
84
85 class LazyEvaluate(object):
85 class LazyEvaluate(object):
86 """This is used for formatting strings with values that need to be updated
86 """This is used for formatting strings with values that need to be updated
87 at that time, such as the current time or working directory."""
87 at that time, such as the current time or working directory."""
88 def __init__(self, func, *args, **kwargs):
88 def __init__(self, func, *args, **kwargs):
89 self.func = func
89 self.func = func
90 self.args = args
90 self.args = args
91 self.kwargs = kwargs
91 self.kwargs = kwargs
92
92
93 def __call__(self, **kwargs):
93 def __call__(self, **kwargs):
94 self.kwargs.update(kwargs)
94 self.kwargs.update(kwargs)
95 return self.func(*self.args, **self.kwargs)
95 return self.func(*self.args, **self.kwargs)
96
96
97 def __str__(self):
97 def __str__(self):
98 return str(self())
98 return str(self())
99
99
100 def __unicode__(self):
100 def __unicode__(self):
101 return py3compat.unicode_type(self())
101 return py3compat.unicode_type(self())
102
102
103 def __format__(self, format_spec):
103 def __format__(self, format_spec):
104 return format(self(), format_spec)
104 return format(self(), format_spec)
105
105
106 def multiple_replace(dict, text):
106 def multiple_replace(dict, text):
107 """ Replace in 'text' all occurences of any key in the given
107 """ Replace in 'text' all occurences of any key in the given
108 dictionary by its corresponding value. Returns the new string."""
108 dictionary by its corresponding value. Returns the new string."""
109
109
110 # Function by Xavier Defrang, originally found at:
110 # Function by Xavier Defrang, originally found at:
111 # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/81330
111 # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/81330
112
112
113 # Create a regular expression from the dictionary keys
113 # Create a regular expression from the dictionary keys
114 regex = re.compile("(%s)" % "|".join(map(re.escape, dict.keys())))
114 regex = re.compile("(%s)" % "|".join(map(re.escape, dict.keys())))
115 # For each match, look-up corresponding value in dictionary
115 # For each match, look-up corresponding value in dictionary
116 return regex.sub(lambda mo: dict[mo.string[mo.start():mo.end()]], text)
116 return regex.sub(lambda mo: dict[mo.string[mo.start():mo.end()]], text)
117
117
118 #-----------------------------------------------------------------------------
118 #-----------------------------------------------------------------------------
119 # Special characters that can be used in prompt templates, mainly bash-like
119 # Special characters that can be used in prompt templates, mainly bash-like
120 #-----------------------------------------------------------------------------
120 #-----------------------------------------------------------------------------
121
121
122 # If $HOME isn't defined (Windows), make it an absurd string so that it can
122 # If $HOME isn't defined (Windows), make it an absurd string so that it can
123 # never be expanded out into '~'. Basically anything which can never be a
123 # never be expanded out into '~'. Basically anything which can never be a
124 # reasonable directory name will do, we just want the $HOME -> '~' operation
124 # reasonable directory name will do, we just want the $HOME -> '~' operation
125 # to become a no-op. We pre-compute $HOME here so it's not done on every
125 # to become a no-op. We pre-compute $HOME here so it's not done on every
126 # prompt call.
126 # prompt call.
127
127
128 # FIXME:
128 # FIXME:
129
129
130 # - This should be turned into a class which does proper namespace management,
130 # - This should be turned into a class which does proper namespace management,
131 # since the prompt specials need to be evaluated in a certain namespace.
131 # since the prompt specials need to be evaluated in a certain namespace.
132 # Currently it's just globals, which need to be managed manually by code
132 # Currently it's just globals, which need to be managed manually by code
133 # below.
133 # below.
134
134
135 # - I also need to split up the color schemes from the prompt specials
135 # - I also need to split up the color schemes from the prompt specials
136 # somehow. I don't have a clean design for that quite yet.
136 # somehow. I don't have a clean design for that quite yet.
137
137
138 HOME = py3compat.str_to_unicode(os.environ.get("HOME","//////:::::ZZZZZ,,,~~~"))
138 HOME = py3compat.str_to_unicode(os.environ.get("HOME","//////:::::ZZZZZ,,,~~~"))
139
139
140 # This is needed on FreeBSD, and maybe other systems which symlink /home to
140 # This is needed on FreeBSD, and maybe other systems which symlink /home to
141 # /usr/home, but retain the $HOME variable as pointing to /home
141 # /usr/home, but retain the $HOME variable as pointing to /home
142 HOME = os.path.realpath(HOME)
142 HOME = os.path.realpath(HOME)
143
143
144 # We precompute a few more strings here for the prompt_specials, which are
144 # We precompute a few more strings here for the prompt_specials, which are
145 # fixed once ipython starts. This reduces the runtime overhead of computing
145 # fixed once ipython starts. This reduces the runtime overhead of computing
146 # prompt strings.
146 # prompt strings.
147 USER = py3compat.str_to_unicode(os.environ.get("USER",''))
147 USER = py3compat.str_to_unicode(os.environ.get("USER",''))
148 HOSTNAME = py3compat.str_to_unicode(socket.gethostname())
148 HOSTNAME = py3compat.str_to_unicode(socket.gethostname())
149 HOSTNAME_SHORT = HOSTNAME.split(".")[0]
149 HOSTNAME_SHORT = HOSTNAME.split(".")[0]
150 ROOT_SYMBOL = "#" if (os.name=='nt' or os.getuid()==0) else "$"
150
151 ROOT_SYMBOL = "#" if (os.name=='nt' or sys.platform=='cli' or os.getuid()==0) else "$"
151
152
152 prompt_abbreviations = {
153 prompt_abbreviations = {
153 # Prompt/history count
154 # Prompt/history count
154 '%n' : '{color.number}' '{count}' '{color.prompt}',
155 '%n' : '{color.number}' '{count}' '{color.prompt}',
155 r'\#': '{color.number}' '{count}' '{color.prompt}',
156 r'\#': '{color.number}' '{count}' '{color.prompt}',
156 # Just the prompt counter number, WITHOUT any coloring wrappers, so users
157 # Just the prompt counter number, WITHOUT any coloring wrappers, so users
157 # can get numbers displayed in whatever color they want.
158 # can get numbers displayed in whatever color they want.
158 r'\N': '{count}',
159 r'\N': '{count}',
159
160
160 # Prompt/history count, with the actual digits replaced by dots. Used
161 # Prompt/history count, with the actual digits replaced by dots. Used
161 # mainly in continuation prompts (prompt_in2)
162 # mainly in continuation prompts (prompt_in2)
162 r'\D': '{dots}',
163 r'\D': '{dots}',
163
164
164 # Current time
165 # Current time
165 r'\T' : '{time}',
166 r'\T' : '{time}',
166 # Current working directory
167 # Current working directory
167 r'\w': '{cwd}',
168 r'\w': '{cwd}',
168 # Basename of current working directory.
169 # Basename of current working directory.
169 # (use os.sep to make this portable across OSes)
170 # (use os.sep to make this portable across OSes)
170 r'\W' : '{cwd_last}',
171 r'\W' : '{cwd_last}',
171 # These X<N> are an extension to the normal bash prompts. They return
172 # These X<N> are an extension to the normal bash prompts. They return
172 # N terms of the path, after replacing $HOME with '~'
173 # N terms of the path, after replacing $HOME with '~'
173 r'\X0': '{cwd_x[0]}',
174 r'\X0': '{cwd_x[0]}',
174 r'\X1': '{cwd_x[1]}',
175 r'\X1': '{cwd_x[1]}',
175 r'\X2': '{cwd_x[2]}',
176 r'\X2': '{cwd_x[2]}',
176 r'\X3': '{cwd_x[3]}',
177 r'\X3': '{cwd_x[3]}',
177 r'\X4': '{cwd_x[4]}',
178 r'\X4': '{cwd_x[4]}',
178 r'\X5': '{cwd_x[5]}',
179 r'\X5': '{cwd_x[5]}',
179 # Y<N> are similar to X<N>, but they show '~' if it's the directory
180 # Y<N> are similar to X<N>, but they show '~' if it's the directory
180 # N+1 in the list. Somewhat like %cN in tcsh.
181 # N+1 in the list. Somewhat like %cN in tcsh.
181 r'\Y0': '{cwd_y[0]}',
182 r'\Y0': '{cwd_y[0]}',
182 r'\Y1': '{cwd_y[1]}',
183 r'\Y1': '{cwd_y[1]}',
183 r'\Y2': '{cwd_y[2]}',
184 r'\Y2': '{cwd_y[2]}',
184 r'\Y3': '{cwd_y[3]}',
185 r'\Y3': '{cwd_y[3]}',
185 r'\Y4': '{cwd_y[4]}',
186 r'\Y4': '{cwd_y[4]}',
186 r'\Y5': '{cwd_y[5]}',
187 r'\Y5': '{cwd_y[5]}',
187 # Hostname up to first .
188 # Hostname up to first .
188 r'\h': HOSTNAME_SHORT,
189 r'\h': HOSTNAME_SHORT,
189 # Full hostname
190 # Full hostname
190 r'\H': HOSTNAME,
191 r'\H': HOSTNAME,
191 # Username of current user
192 # Username of current user
192 r'\u': USER,
193 r'\u': USER,
193 # Escaped '\'
194 # Escaped '\'
194 '\\\\': '\\',
195 '\\\\': '\\',
195 # Newline
196 # Newline
196 r'\n': '\n',
197 r'\n': '\n',
197 # Carriage return
198 # Carriage return
198 r'\r': '\r',
199 r'\r': '\r',
199 # Release version
200 # Release version
200 r'\v': release.version,
201 r'\v': release.version,
201 # Root symbol ($ or #)
202 # Root symbol ($ or #)
202 r'\$': ROOT_SYMBOL,
203 r'\$': ROOT_SYMBOL,
203 }
204 }
204
205
205 #-----------------------------------------------------------------------------
206 #-----------------------------------------------------------------------------
206 # More utilities
207 # More utilities
207 #-----------------------------------------------------------------------------
208 #-----------------------------------------------------------------------------
208
209
209 def cwd_filt(depth):
210 def cwd_filt(depth):
210 """Return the last depth elements of the current working directory.
211 """Return the last depth elements of the current working directory.
211
212
212 $HOME is always replaced with '~'.
213 $HOME is always replaced with '~'.
213 If depth==0, the full path is returned."""
214 If depth==0, the full path is returned."""
214
215
215 cwd = py3compat.getcwd().replace(HOME,"~")
216 cwd = py3compat.getcwd().replace(HOME,"~")
216 out = os.sep.join(cwd.split(os.sep)[-depth:])
217 out = os.sep.join(cwd.split(os.sep)[-depth:])
217 return out or os.sep
218 return out or os.sep
218
219
219 def cwd_filt2(depth):
220 def cwd_filt2(depth):
220 """Return the last depth elements of the current working directory.
221 """Return the last depth elements of the current working directory.
221
222
222 $HOME is always replaced with '~'.
223 $HOME is always replaced with '~'.
223 If depth==0, the full path is returned."""
224 If depth==0, the full path is returned."""
224
225
225 full_cwd = py3compat.getcwd()
226 full_cwd = py3compat.getcwd()
226 cwd = full_cwd.replace(HOME,"~").split(os.sep)
227 cwd = full_cwd.replace(HOME,"~").split(os.sep)
227 if '~' in cwd and len(cwd) == depth+1:
228 if '~' in cwd and len(cwd) == depth+1:
228 depth += 1
229 depth += 1
229 drivepart = ''
230 drivepart = ''
230 if sys.platform == 'win32' and len(cwd) > depth:
231 if sys.platform == 'win32' and len(cwd) > depth:
231 drivepart = os.path.splitdrive(full_cwd)[0]
232 drivepart = os.path.splitdrive(full_cwd)[0]
232 out = drivepart + '/'.join(cwd[-depth:])
233 out = drivepart + '/'.join(cwd[-depth:])
233
234
234 return out or os.sep
235 return out or os.sep
235
236
236 #-----------------------------------------------------------------------------
237 #-----------------------------------------------------------------------------
237 # Prompt classes
238 # Prompt classes
238 #-----------------------------------------------------------------------------
239 #-----------------------------------------------------------------------------
239
240
240 lazily_evaluate = {'time': LazyEvaluate(time.strftime, "%H:%M:%S"),
241 lazily_evaluate = {'time': LazyEvaluate(time.strftime, "%H:%M:%S"),
241 'cwd': LazyEvaluate(py3compat.getcwd),
242 'cwd': LazyEvaluate(py3compat.getcwd),
242 'cwd_last': LazyEvaluate(lambda: py3compat.getcwd().split(os.sep)[-1]),
243 'cwd_last': LazyEvaluate(lambda: py3compat.getcwd().split(os.sep)[-1]),
243 'cwd_x': [LazyEvaluate(lambda: py3compat.getcwd().replace(HOME,"~"))] +\
244 'cwd_x': [LazyEvaluate(lambda: py3compat.getcwd().replace(HOME,"~"))] +\
244 [LazyEvaluate(cwd_filt, x) for x in range(1,6)],
245 [LazyEvaluate(cwd_filt, x) for x in range(1,6)],
245 'cwd_y': [LazyEvaluate(cwd_filt2, x) for x in range(6)]
246 'cwd_y': [LazyEvaluate(cwd_filt2, x) for x in range(6)]
246 }
247 }
247
248
248 def _lenlastline(s):
249 def _lenlastline(s):
249 """Get the length of the last line. More intelligent than
250 """Get the length of the last line. More intelligent than
250 len(s.splitlines()[-1]).
251 len(s.splitlines()[-1]).
251 """
252 """
252 if not s or s.endswith(('\n', '\r')):
253 if not s or s.endswith(('\n', '\r')):
253 return 0
254 return 0
254 return len(s.splitlines()[-1])
255 return len(s.splitlines()[-1])
255
256
256
257
257 class UserNSFormatter(Formatter):
258 class UserNSFormatter(Formatter):
258 """A Formatter that falls back on a shell's user_ns and __builtins__ for name resolution"""
259 """A Formatter that falls back on a shell's user_ns and __builtins__ for name resolution"""
259 def __init__(self, shell):
260 def __init__(self, shell):
260 self.shell = shell
261 self.shell = shell
261
262
262 def get_value(self, key, args, kwargs):
263 def get_value(self, key, args, kwargs):
263 # try regular formatting first:
264 # try regular formatting first:
264 try:
265 try:
265 return Formatter.get_value(self, key, args, kwargs)
266 return Formatter.get_value(self, key, args, kwargs)
266 except Exception:
267 except Exception:
267 pass
268 pass
268 # next, look in user_ns and builtins:
269 # next, look in user_ns and builtins:
269 for container in (self.shell.user_ns, __builtins__):
270 for container in (self.shell.user_ns, __builtins__):
270 if key in container:
271 if key in container:
271 return container[key]
272 return container[key]
272 # nothing found, put error message in its place
273 # nothing found, put error message in its place
273 return "<ERROR: '%s' not found>" % key
274 return "<ERROR: '%s' not found>" % key
274
275
275
276
276 class PromptManager(Configurable):
277 class PromptManager(Configurable):
277 """This is the primary interface for producing IPython's prompts."""
278 """This is the primary interface for producing IPython's prompts."""
278 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
279 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
279
280
280 color_scheme_table = Instance(coloransi.ColorSchemeTable)
281 color_scheme_table = Instance(coloransi.ColorSchemeTable)
281 color_scheme = Unicode('Linux', config=True)
282 color_scheme = Unicode('Linux', config=True)
282 def _color_scheme_changed(self, name, new_value):
283 def _color_scheme_changed(self, name, new_value):
283 self.color_scheme_table.set_active_scheme(new_value)
284 self.color_scheme_table.set_active_scheme(new_value)
284 for pname in ['in', 'in2', 'out', 'rewrite']:
285 for pname in ['in', 'in2', 'out', 'rewrite']:
285 # We need to recalculate the number of invisible characters
286 # We need to recalculate the number of invisible characters
286 self.update_prompt(pname)
287 self.update_prompt(pname)
287
288
288 lazy_evaluate_fields = Dict(help="""
289 lazy_evaluate_fields = Dict(help="""
289 This maps field names used in the prompt templates to functions which
290 This maps field names used in the prompt templates to functions which
290 will be called when the prompt is rendered. This allows us to include
291 will be called when the prompt is rendered. This allows us to include
291 things like the current time in the prompts. Functions are only called
292 things like the current time in the prompts. Functions are only called
292 if they are used in the prompt.
293 if they are used in the prompt.
293 """)
294 """)
294 def _lazy_evaluate_fields_default(self): return lazily_evaluate.copy()
295 def _lazy_evaluate_fields_default(self): return lazily_evaluate.copy()
295
296
296 in_template = Unicode('In [\\#]: ', config=True,
297 in_template = Unicode('In [\\#]: ', config=True,
297 help="Input prompt. '\\#' will be transformed to the prompt number")
298 help="Input prompt. '\\#' will be transformed to the prompt number")
298 in2_template = Unicode(' .\\D.: ', config=True,
299 in2_template = Unicode(' .\\D.: ', config=True,
299 help="Continuation prompt.")
300 help="Continuation prompt.")
300 out_template = Unicode('Out[\\#]: ', config=True,
301 out_template = Unicode('Out[\\#]: ', config=True,
301 help="Output prompt. '\\#' will be transformed to the prompt number")
302 help="Output prompt. '\\#' will be transformed to the prompt number")
302
303
303 justify = Bool(True, config=True, help="""
304 justify = Bool(True, config=True, help="""
304 If True (default), each prompt will be right-aligned with the
305 If True (default), each prompt will be right-aligned with the
305 preceding one.
306 preceding one.
306 """)
307 """)
307
308
308 # We actually store the expanded templates here:
309 # We actually store the expanded templates here:
309 templates = Dict()
310 templates = Dict()
310
311
311 # The number of characters in the last prompt rendered, not including
312 # The number of characters in the last prompt rendered, not including
312 # colour characters.
313 # colour characters.
313 width = Int()
314 width = Int()
314 txtwidth = Int() # Not including right-justification
315 txtwidth = Int() # Not including right-justification
315
316
316 # The number of characters in each prompt which don't contribute to width
317 # The number of characters in each prompt which don't contribute to width
317 invisible_chars = Dict()
318 invisible_chars = Dict()
318 def _invisible_chars_default(self):
319 def _invisible_chars_default(self):
319 return {'in': 0, 'in2': 0, 'out': 0, 'rewrite':0}
320 return {'in': 0, 'in2': 0, 'out': 0, 'rewrite':0}
320
321
321 def __init__(self, shell, **kwargs):
322 def __init__(self, shell, **kwargs):
322 super(PromptManager, self).__init__(shell=shell, **kwargs)
323 super(PromptManager, self).__init__(shell=shell, **kwargs)
323
324
324 # Prepare colour scheme table
325 # Prepare colour scheme table
325 self.color_scheme_table = coloransi.ColorSchemeTable([PColNoColors,
326 self.color_scheme_table = coloransi.ColorSchemeTable([PColNoColors,
326 PColLinux, PColLightBG], self.color_scheme)
327 PColLinux, PColLightBG], self.color_scheme)
327
328
328 self._formatter = UserNSFormatter(shell)
329 self._formatter = UserNSFormatter(shell)
329 # Prepare templates & numbers of invisible characters
330 # Prepare templates & numbers of invisible characters
330 self.update_prompt('in', self.in_template)
331 self.update_prompt('in', self.in_template)
331 self.update_prompt('in2', self.in2_template)
332 self.update_prompt('in2', self.in2_template)
332 self.update_prompt('out', self.out_template)
333 self.update_prompt('out', self.out_template)
333 self.update_prompt('rewrite')
334 self.update_prompt('rewrite')
334 self.on_trait_change(self._update_prompt_trait, ['in_template',
335 self.on_trait_change(self._update_prompt_trait, ['in_template',
335 'in2_template', 'out_template'])
336 'in2_template', 'out_template'])
336
337
337 def update_prompt(self, name, new_template=None):
338 def update_prompt(self, name, new_template=None):
338 """This is called when a prompt template is updated. It processes
339 """This is called when a prompt template is updated. It processes
339 abbreviations used in the prompt template (like \#) and calculates how
340 abbreviations used in the prompt template (like \#) and calculates how
340 many invisible characters (ANSI colour escapes) the resulting prompt
341 many invisible characters (ANSI colour escapes) the resulting prompt
341 contains.
342 contains.
342
343
343 It is also called for each prompt on changing the colour scheme. In both
344 It is also called for each prompt on changing the colour scheme. In both
344 cases, traitlets should take care of calling this automatically.
345 cases, traitlets should take care of calling this automatically.
345 """
346 """
346 if new_template is not None:
347 if new_template is not None:
347 self.templates[name] = multiple_replace(prompt_abbreviations, new_template)
348 self.templates[name] = multiple_replace(prompt_abbreviations, new_template)
348 # We count invisible characters (colour escapes) on the last line of the
349 # We count invisible characters (colour escapes) on the last line of the
349 # prompt, to calculate the width for lining up subsequent prompts.
350 # prompt, to calculate the width for lining up subsequent prompts.
350 invis_chars = _lenlastline(self._render(name, color=True)) - \
351 invis_chars = _lenlastline(self._render(name, color=True)) - \
351 _lenlastline(self._render(name, color=False))
352 _lenlastline(self._render(name, color=False))
352 self.invisible_chars[name] = invis_chars
353 self.invisible_chars[name] = invis_chars
353
354
354 def _update_prompt_trait(self, traitname, new_template):
355 def _update_prompt_trait(self, traitname, new_template):
355 name = traitname[:-9] # Cut off '_template'
356 name = traitname[:-9] # Cut off '_template'
356 self.update_prompt(name, new_template)
357 self.update_prompt(name, new_template)
357
358
358 def _render(self, name, color=True, **kwargs):
359 def _render(self, name, color=True, **kwargs):
359 """Render but don't justify, or update the width or txtwidth attributes.
360 """Render but don't justify, or update the width or txtwidth attributes.
360 """
361 """
361 if name == 'rewrite':
362 if name == 'rewrite':
362 return self._render_rewrite(color=color)
363 return self._render_rewrite(color=color)
363
364
364 if color:
365 if color:
365 scheme = self.color_scheme_table.active_colors
366 scheme = self.color_scheme_table.active_colors
366 if name=='out':
367 if name=='out':
367 colors = color_lists['normal']
368 colors = color_lists['normal']
368 colors.number, colors.prompt, colors.normal = \
369 colors.number, colors.prompt, colors.normal = \
369 scheme.out_number, scheme.out_prompt, scheme.normal
370 scheme.out_number, scheme.out_prompt, scheme.normal
370 else:
371 else:
371 colors = color_lists['inp']
372 colors = color_lists['inp']
372 colors.number, colors.prompt, colors.normal = \
373 colors.number, colors.prompt, colors.normal = \
373 scheme.in_number, scheme.in_prompt, scheme.in_normal
374 scheme.in_number, scheme.in_prompt, scheme.in_normal
374 if name=='in2':
375 if name=='in2':
375 colors.prompt = scheme.in_prompt2
376 colors.prompt = scheme.in_prompt2
376 else:
377 else:
377 # No color
378 # No color
378 colors = color_lists['nocolor']
379 colors = color_lists['nocolor']
379 colors.number, colors.prompt, colors.normal = '', '', ''
380 colors.number, colors.prompt, colors.normal = '', '', ''
380
381
381 count = self.shell.execution_count # Shorthand
382 count = self.shell.execution_count # Shorthand
382 # Build the dictionary to be passed to string formatting
383 # Build the dictionary to be passed to string formatting
383 fmtargs = dict(color=colors, count=count,
384 fmtargs = dict(color=colors, count=count,
384 dots="."*len(str(count)),
385 dots="."*len(str(count)),
385 width=self.width, txtwidth=self.txtwidth )
386 width=self.width, txtwidth=self.txtwidth )
386 fmtargs.update(self.lazy_evaluate_fields)
387 fmtargs.update(self.lazy_evaluate_fields)
387 fmtargs.update(kwargs)
388 fmtargs.update(kwargs)
388
389
389 # Prepare the prompt
390 # Prepare the prompt
390 prompt = colors.prompt + self.templates[name] + colors.normal
391 prompt = colors.prompt + self.templates[name] + colors.normal
391
392
392 # Fill in required fields
393 # Fill in required fields
393 return self._formatter.format(prompt, **fmtargs)
394 return self._formatter.format(prompt, **fmtargs)
394
395
395 def _render_rewrite(self, color=True):
396 def _render_rewrite(self, color=True):
396 """Render the ---> rewrite prompt."""
397 """Render the ---> rewrite prompt."""
397 if color:
398 if color:
398 scheme = self.color_scheme_table.active_colors
399 scheme = self.color_scheme_table.active_colors
399 # We need a non-input version of these escapes
400 # We need a non-input version of these escapes
400 color_prompt = scheme.in_prompt.replace("\001","").replace("\002","")
401 color_prompt = scheme.in_prompt.replace("\001","").replace("\002","")
401 color_normal = scheme.normal
402 color_normal = scheme.normal
402 else:
403 else:
403 color_prompt, color_normal = '', ''
404 color_prompt, color_normal = '', ''
404
405
405 return color_prompt + "-> ".rjust(self.txtwidth, "-") + color_normal
406 return color_prompt + "-> ".rjust(self.txtwidth, "-") + color_normal
406
407
407 def render(self, name, color=True, just=None, **kwargs):
408 def render(self, name, color=True, just=None, **kwargs):
408 """
409 """
409 Render the selected prompt.
410 Render the selected prompt.
410
411
411 Parameters
412 Parameters
412 ----------
413 ----------
413 name : str
414 name : str
414 Which prompt to render. One of 'in', 'in2', 'out', 'rewrite'
415 Which prompt to render. One of 'in', 'in2', 'out', 'rewrite'
415 color : bool
416 color : bool
416 If True (default), include ANSI escape sequences for a coloured prompt.
417 If True (default), include ANSI escape sequences for a coloured prompt.
417 just : bool
418 just : bool
418 If True, justify the prompt to the width of the last prompt. The
419 If True, justify the prompt to the width of the last prompt. The
419 default is stored in self.justify.
420 default is stored in self.justify.
420 **kwargs :
421 **kwargs :
421 Additional arguments will be passed to the string formatting operation,
422 Additional arguments will be passed to the string formatting operation,
422 so they can override the values that would otherwise fill in the
423 so they can override the values that would otherwise fill in the
423 template.
424 template.
424
425
425 Returns
426 Returns
426 -------
427 -------
427 A string containing the rendered prompt.
428 A string containing the rendered prompt.
428 """
429 """
429 res = self._render(name, color=color, **kwargs)
430 res = self._render(name, color=color, **kwargs)
430
431
431 # Handle justification of prompt
432 # Handle justification of prompt
432 invis_chars = self.invisible_chars[name] if color else 0
433 invis_chars = self.invisible_chars[name] if color else 0
433 self.txtwidth = _lenlastline(res) - invis_chars
434 self.txtwidth = _lenlastline(res) - invis_chars
434 just = self.justify if (just is None) else just
435 just = self.justify if (just is None) else just
435 # If the prompt spans more than one line, don't try to justify it:
436 # If the prompt spans more than one line, don't try to justify it:
436 if just and name != 'in' and ('\n' not in res) and ('\r' not in res):
437 if just and name != 'in' and ('\n' not in res) and ('\r' not in res):
437 res = res.rjust(self.width + invis_chars)
438 res = res.rjust(self.width + invis_chars)
438 self.width = _lenlastline(res) - invis_chars
439 self.width = _lenlastline(res) - invis_chars
439 return res
440 return res
@@ -1,532 +1,534 b''
1 # coding: utf-8
1 # coding: utf-8
2 """
2 """
3 Inputhook management for GUI event loop integration.
3 Inputhook management for GUI event loop integration.
4 """
4 """
5
5
6 #-----------------------------------------------------------------------------
6 #-----------------------------------------------------------------------------
7 # Copyright (C) 2008-2011 The IPython Development Team
7 # Copyright (C) 2008-2011 The IPython Development Team
8 #
8 #
9 # Distributed under the terms of the BSD License. The full license is in
9 # Distributed under the terms of the BSD License. The full license is in
10 # the file COPYING, distributed as part of this software.
10 # the file COPYING, distributed as part of this software.
11 #-----------------------------------------------------------------------------
11 #-----------------------------------------------------------------------------
12
12
13 #-----------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
14 # Imports
14 # Imports
15 #-----------------------------------------------------------------------------
15 #-----------------------------------------------------------------------------
16
16
17 try:
17 try:
18 import ctypes
18 import ctypes
19 except ImportError:
19 except ImportError:
20 ctypes = None
20 ctypes = None
21 except SystemError:
22 ctypes = None
21 import os
23 import os
22 import sys
24 import sys
23 from distutils.version import LooseVersion as V
25 from distutils.version import LooseVersion as V
24
26
25 from IPython.utils.warn import warn
27 from IPython.utils.warn import warn
26
28
27 #-----------------------------------------------------------------------------
29 #-----------------------------------------------------------------------------
28 # Constants
30 # Constants
29 #-----------------------------------------------------------------------------
31 #-----------------------------------------------------------------------------
30
32
31 # Constants for identifying the GUI toolkits.
33 # Constants for identifying the GUI toolkits.
32 GUI_WX = 'wx'
34 GUI_WX = 'wx'
33 GUI_QT = 'qt'
35 GUI_QT = 'qt'
34 GUI_QT4 = 'qt4'
36 GUI_QT4 = 'qt4'
35 GUI_GTK = 'gtk'
37 GUI_GTK = 'gtk'
36 GUI_TK = 'tk'
38 GUI_TK = 'tk'
37 GUI_OSX = 'osx'
39 GUI_OSX = 'osx'
38 GUI_GLUT = 'glut'
40 GUI_GLUT = 'glut'
39 GUI_PYGLET = 'pyglet'
41 GUI_PYGLET = 'pyglet'
40 GUI_GTK3 = 'gtk3'
42 GUI_GTK3 = 'gtk3'
41 GUI_NONE = 'none' # i.e. disable
43 GUI_NONE = 'none' # i.e. disable
42
44
43 #-----------------------------------------------------------------------------
45 #-----------------------------------------------------------------------------
44 # Utilities
46 # Utilities
45 #-----------------------------------------------------------------------------
47 #-----------------------------------------------------------------------------
46
48
47 def _stdin_ready_posix():
49 def _stdin_ready_posix():
48 """Return True if there's something to read on stdin (posix version)."""
50 """Return True if there's something to read on stdin (posix version)."""
49 infds, outfds, erfds = select.select([sys.stdin],[],[],0)
51 infds, outfds, erfds = select.select([sys.stdin],[],[],0)
50 return bool(infds)
52 return bool(infds)
51
53
52 def _stdin_ready_nt():
54 def _stdin_ready_nt():
53 """Return True if there's something to read on stdin (nt version)."""
55 """Return True if there's something to read on stdin (nt version)."""
54 return msvcrt.kbhit()
56 return msvcrt.kbhit()
55
57
56 def _stdin_ready_other():
58 def _stdin_ready_other():
57 """Return True, assuming there's something to read on stdin."""
59 """Return True, assuming there's something to read on stdin."""
58 return True #
60 return True #
59
61
60
62
61 def _ignore_CTRL_C_posix():
63 def _ignore_CTRL_C_posix():
62 """Ignore CTRL+C (SIGINT)."""
64 """Ignore CTRL+C (SIGINT)."""
63 signal.signal(signal.SIGINT, signal.SIG_IGN)
65 signal.signal(signal.SIGINT, signal.SIG_IGN)
64
66
65 def _allow_CTRL_C_posix():
67 def _allow_CTRL_C_posix():
66 """Take CTRL+C into account (SIGINT)."""
68 """Take CTRL+C into account (SIGINT)."""
67 signal.signal(signal.SIGINT, signal.default_int_handler)
69 signal.signal(signal.SIGINT, signal.default_int_handler)
68
70
69 def _ignore_CTRL_C_other():
71 def _ignore_CTRL_C_other():
70 """Ignore CTRL+C (not implemented)."""
72 """Ignore CTRL+C (not implemented)."""
71 pass
73 pass
72
74
73 def _allow_CTRL_C_other():
75 def _allow_CTRL_C_other():
74 """Take CTRL+C into account (not implemented)."""
76 """Take CTRL+C into account (not implemented)."""
75 pass
77 pass
76
78
77 if os.name == 'posix':
79 if os.name == 'posix':
78 import select
80 import select
79 import signal
81 import signal
80 stdin_ready = _stdin_ready_posix
82 stdin_ready = _stdin_ready_posix
81 ignore_CTRL_C = _ignore_CTRL_C_posix
83 ignore_CTRL_C = _ignore_CTRL_C_posix
82 allow_CTRL_C = _allow_CTRL_C_posix
84 allow_CTRL_C = _allow_CTRL_C_posix
83 elif os.name == 'nt':
85 elif os.name == 'nt':
84 import msvcrt
86 import msvcrt
85 stdin_ready = _stdin_ready_nt
87 stdin_ready = _stdin_ready_nt
86 ignore_CTRL_C = _ignore_CTRL_C_other
88 ignore_CTRL_C = _ignore_CTRL_C_other
87 allow_CTRL_C = _allow_CTRL_C_other
89 allow_CTRL_C = _allow_CTRL_C_other
88 else:
90 else:
89 stdin_ready = _stdin_ready_other
91 stdin_ready = _stdin_ready_other
90 ignore_CTRL_C = _ignore_CTRL_C_other
92 ignore_CTRL_C = _ignore_CTRL_C_other
91 allow_CTRL_C = _allow_CTRL_C_other
93 allow_CTRL_C = _allow_CTRL_C_other
92
94
93
95
94 #-----------------------------------------------------------------------------
96 #-----------------------------------------------------------------------------
95 # Main InputHookManager class
97 # Main InputHookManager class
96 #-----------------------------------------------------------------------------
98 #-----------------------------------------------------------------------------
97
99
98
100
99 class InputHookManager(object):
101 class InputHookManager(object):
100 """Manage PyOS_InputHook for different GUI toolkits.
102 """Manage PyOS_InputHook for different GUI toolkits.
101
103
102 This class installs various hooks under ``PyOSInputHook`` to handle
104 This class installs various hooks under ``PyOSInputHook`` to handle
103 GUI event loop integration.
105 GUI event loop integration.
104 """
106 """
105
107
106 def __init__(self):
108 def __init__(self):
107 if ctypes is None:
109 if ctypes is None:
108 warn("IPython GUI event loop requires ctypes, %gui will not be available")
110 warn("IPython GUI event loop requires ctypes, %gui will not be available")
109 return
111 return
110 self.PYFUNC = ctypes.PYFUNCTYPE(ctypes.c_int)
112 self.PYFUNC = ctypes.PYFUNCTYPE(ctypes.c_int)
111 self._apps = {}
113 self._apps = {}
112 self._reset()
114 self._reset()
113
115
114 def _reset(self):
116 def _reset(self):
115 self._callback_pyfunctype = None
117 self._callback_pyfunctype = None
116 self._callback = None
118 self._callback = None
117 self._installed = False
119 self._installed = False
118 self._current_gui = None
120 self._current_gui = None
119
121
120 def get_pyos_inputhook(self):
122 def get_pyos_inputhook(self):
121 """Return the current PyOS_InputHook as a ctypes.c_void_p."""
123 """Return the current PyOS_InputHook as a ctypes.c_void_p."""
122 return ctypes.c_void_p.in_dll(ctypes.pythonapi,"PyOS_InputHook")
124 return ctypes.c_void_p.in_dll(ctypes.pythonapi,"PyOS_InputHook")
123
125
124 def get_pyos_inputhook_as_func(self):
126 def get_pyos_inputhook_as_func(self):
125 """Return the current PyOS_InputHook as a ctypes.PYFUNCYPE."""
127 """Return the current PyOS_InputHook as a ctypes.PYFUNCYPE."""
126 return self.PYFUNC.in_dll(ctypes.pythonapi,"PyOS_InputHook")
128 return self.PYFUNC.in_dll(ctypes.pythonapi,"PyOS_InputHook")
127
129
128 def set_inputhook(self, callback):
130 def set_inputhook(self, callback):
129 """Set PyOS_InputHook to callback and return the previous one."""
131 """Set PyOS_InputHook to callback and return the previous one."""
130 # On platforms with 'readline' support, it's all too likely to
132 # On platforms with 'readline' support, it's all too likely to
131 # have a KeyboardInterrupt signal delivered *even before* an
133 # have a KeyboardInterrupt signal delivered *even before* an
132 # initial ``try:`` clause in the callback can be executed, so
134 # initial ``try:`` clause in the callback can be executed, so
133 # we need to disable CTRL+C in this situation.
135 # we need to disable CTRL+C in this situation.
134 ignore_CTRL_C()
136 ignore_CTRL_C()
135 self._callback = callback
137 self._callback = callback
136 self._callback_pyfunctype = self.PYFUNC(callback)
138 self._callback_pyfunctype = self.PYFUNC(callback)
137 pyos_inputhook_ptr = self.get_pyos_inputhook()
139 pyos_inputhook_ptr = self.get_pyos_inputhook()
138 original = self.get_pyos_inputhook_as_func()
140 original = self.get_pyos_inputhook_as_func()
139 pyos_inputhook_ptr.value = \
141 pyos_inputhook_ptr.value = \
140 ctypes.cast(self._callback_pyfunctype, ctypes.c_void_p).value
142 ctypes.cast(self._callback_pyfunctype, ctypes.c_void_p).value
141 self._installed = True
143 self._installed = True
142 return original
144 return original
143
145
144 def clear_inputhook(self, app=None):
146 def clear_inputhook(self, app=None):
145 """Set PyOS_InputHook to NULL and return the previous one.
147 """Set PyOS_InputHook to NULL and return the previous one.
146
148
147 Parameters
149 Parameters
148 ----------
150 ----------
149 app : optional, ignored
151 app : optional, ignored
150 This parameter is allowed only so that clear_inputhook() can be
152 This parameter is allowed only so that clear_inputhook() can be
151 called with a similar interface as all the ``enable_*`` methods. But
153 called with a similar interface as all the ``enable_*`` methods. But
152 the actual value of the parameter is ignored. This uniform interface
154 the actual value of the parameter is ignored. This uniform interface
153 makes it easier to have user-level entry points in the main IPython
155 makes it easier to have user-level entry points in the main IPython
154 app like :meth:`enable_gui`."""
156 app like :meth:`enable_gui`."""
155 pyos_inputhook_ptr = self.get_pyos_inputhook()
157 pyos_inputhook_ptr = self.get_pyos_inputhook()
156 original = self.get_pyos_inputhook_as_func()
158 original = self.get_pyos_inputhook_as_func()
157 pyos_inputhook_ptr.value = ctypes.c_void_p(None).value
159 pyos_inputhook_ptr.value = ctypes.c_void_p(None).value
158 allow_CTRL_C()
160 allow_CTRL_C()
159 self._reset()
161 self._reset()
160 return original
162 return original
161
163
162 def clear_app_refs(self, gui=None):
164 def clear_app_refs(self, gui=None):
163 """Clear IPython's internal reference to an application instance.
165 """Clear IPython's internal reference to an application instance.
164
166
165 Whenever we create an app for a user on qt4 or wx, we hold a
167 Whenever we create an app for a user on qt4 or wx, we hold a
166 reference to the app. This is needed because in some cases bad things
168 reference to the app. This is needed because in some cases bad things
167 can happen if a user doesn't hold a reference themselves. This
169 can happen if a user doesn't hold a reference themselves. This
168 method is provided to clear the references we are holding.
170 method is provided to clear the references we are holding.
169
171
170 Parameters
172 Parameters
171 ----------
173 ----------
172 gui : None or str
174 gui : None or str
173 If None, clear all app references. If ('wx', 'qt4') clear
175 If None, clear all app references. If ('wx', 'qt4') clear
174 the app for that toolkit. References are not held for gtk or tk
176 the app for that toolkit. References are not held for gtk or tk
175 as those toolkits don't have the notion of an app.
177 as those toolkits don't have the notion of an app.
176 """
178 """
177 if gui is None:
179 if gui is None:
178 self._apps = {}
180 self._apps = {}
179 elif gui in self._apps:
181 elif gui in self._apps:
180 del self._apps[gui]
182 del self._apps[gui]
181
183
182 def enable_wx(self, app=None):
184 def enable_wx(self, app=None):
183 """Enable event loop integration with wxPython.
185 """Enable event loop integration with wxPython.
184
186
185 Parameters
187 Parameters
186 ----------
188 ----------
187 app : WX Application, optional.
189 app : WX Application, optional.
188 Running application to use. If not given, we probe WX for an
190 Running application to use. If not given, we probe WX for an
189 existing application object, and create a new one if none is found.
191 existing application object, and create a new one if none is found.
190
192
191 Notes
193 Notes
192 -----
194 -----
193 This methods sets the ``PyOS_InputHook`` for wxPython, which allows
195 This methods sets the ``PyOS_InputHook`` for wxPython, which allows
194 the wxPython to integrate with terminal based applications like
196 the wxPython to integrate with terminal based applications like
195 IPython.
197 IPython.
196
198
197 If ``app`` is not given we probe for an existing one, and return it if
199 If ``app`` is not given we probe for an existing one, and return it if
198 found. If no existing app is found, we create an :class:`wx.App` as
200 found. If no existing app is found, we create an :class:`wx.App` as
199 follows::
201 follows::
200
202
201 import wx
203 import wx
202 app = wx.App(redirect=False, clearSigInt=False)
204 app = wx.App(redirect=False, clearSigInt=False)
203 """
205 """
204 import wx
206 import wx
205
207
206 wx_version = V(wx.__version__).version
208 wx_version = V(wx.__version__).version
207
209
208 if wx_version < [2, 8]:
210 if wx_version < [2, 8]:
209 raise ValueError("requires wxPython >= 2.8, but you have %s" % wx.__version__)
211 raise ValueError("requires wxPython >= 2.8, but you have %s" % wx.__version__)
210
212
211 from IPython.lib.inputhookwx import inputhook_wx
213 from IPython.lib.inputhookwx import inputhook_wx
212 self.set_inputhook(inputhook_wx)
214 self.set_inputhook(inputhook_wx)
213 self._current_gui = GUI_WX
215 self._current_gui = GUI_WX
214 import wx
216 import wx
215 if app is None:
217 if app is None:
216 app = wx.GetApp()
218 app = wx.GetApp()
217 if app is None:
219 if app is None:
218 app = wx.App(redirect=False, clearSigInt=False)
220 app = wx.App(redirect=False, clearSigInt=False)
219 app._in_event_loop = True
221 app._in_event_loop = True
220 self._apps[GUI_WX] = app
222 self._apps[GUI_WX] = app
221 return app
223 return app
222
224
223 def disable_wx(self):
225 def disable_wx(self):
224 """Disable event loop integration with wxPython.
226 """Disable event loop integration with wxPython.
225
227
226 This merely sets PyOS_InputHook to NULL.
228 This merely sets PyOS_InputHook to NULL.
227 """
229 """
228 if GUI_WX in self._apps:
230 if GUI_WX in self._apps:
229 self._apps[GUI_WX]._in_event_loop = False
231 self._apps[GUI_WX]._in_event_loop = False
230 self.clear_inputhook()
232 self.clear_inputhook()
231
233
232 def enable_qt4(self, app=None):
234 def enable_qt4(self, app=None):
233 """Enable event loop integration with PyQt4.
235 """Enable event loop integration with PyQt4.
234
236
235 Parameters
237 Parameters
236 ----------
238 ----------
237 app : Qt Application, optional.
239 app : Qt Application, optional.
238 Running application to use. If not given, we probe Qt for an
240 Running application to use. If not given, we probe Qt for an
239 existing application object, and create a new one if none is found.
241 existing application object, and create a new one if none is found.
240
242
241 Notes
243 Notes
242 -----
244 -----
243 This methods sets the PyOS_InputHook for PyQt4, which allows
245 This methods sets the PyOS_InputHook for PyQt4, which allows
244 the PyQt4 to integrate with terminal based applications like
246 the PyQt4 to integrate with terminal based applications like
245 IPython.
247 IPython.
246
248
247 If ``app`` is not given we probe for an existing one, and return it if
249 If ``app`` is not given we probe for an existing one, and return it if
248 found. If no existing app is found, we create an :class:`QApplication`
250 found. If no existing app is found, we create an :class:`QApplication`
249 as follows::
251 as follows::
250
252
251 from PyQt4 import QtCore
253 from PyQt4 import QtCore
252 app = QtGui.QApplication(sys.argv)
254 app = QtGui.QApplication(sys.argv)
253 """
255 """
254 from IPython.lib.inputhookqt4 import create_inputhook_qt4
256 from IPython.lib.inputhookqt4 import create_inputhook_qt4
255 app, inputhook_qt4 = create_inputhook_qt4(self, app)
257 app, inputhook_qt4 = create_inputhook_qt4(self, app)
256 self.set_inputhook(inputhook_qt4)
258 self.set_inputhook(inputhook_qt4)
257
259
258 self._current_gui = GUI_QT4
260 self._current_gui = GUI_QT4
259 app._in_event_loop = True
261 app._in_event_loop = True
260 self._apps[GUI_QT4] = app
262 self._apps[GUI_QT4] = app
261 return app
263 return app
262
264
263 def disable_qt4(self):
265 def disable_qt4(self):
264 """Disable event loop integration with PyQt4.
266 """Disable event loop integration with PyQt4.
265
267
266 This merely sets PyOS_InputHook to NULL.
268 This merely sets PyOS_InputHook to NULL.
267 """
269 """
268 if GUI_QT4 in self._apps:
270 if GUI_QT4 in self._apps:
269 self._apps[GUI_QT4]._in_event_loop = False
271 self._apps[GUI_QT4]._in_event_loop = False
270 self.clear_inputhook()
272 self.clear_inputhook()
271
273
272 def enable_gtk(self, app=None):
274 def enable_gtk(self, app=None):
273 """Enable event loop integration with PyGTK.
275 """Enable event loop integration with PyGTK.
274
276
275 Parameters
277 Parameters
276 ----------
278 ----------
277 app : ignored
279 app : ignored
278 Ignored, it's only a placeholder to keep the call signature of all
280 Ignored, it's only a placeholder to keep the call signature of all
279 gui activation methods consistent, which simplifies the logic of
281 gui activation methods consistent, which simplifies the logic of
280 supporting magics.
282 supporting magics.
281
283
282 Notes
284 Notes
283 -----
285 -----
284 This methods sets the PyOS_InputHook for PyGTK, which allows
286 This methods sets the PyOS_InputHook for PyGTK, which allows
285 the PyGTK to integrate with terminal based applications like
287 the PyGTK to integrate with terminal based applications like
286 IPython.
288 IPython.
287 """
289 """
288 import gtk
290 import gtk
289 try:
291 try:
290 gtk.set_interactive(True)
292 gtk.set_interactive(True)
291 self._current_gui = GUI_GTK
293 self._current_gui = GUI_GTK
292 except AttributeError:
294 except AttributeError:
293 # For older versions of gtk, use our own ctypes version
295 # For older versions of gtk, use our own ctypes version
294 from IPython.lib.inputhookgtk import inputhook_gtk
296 from IPython.lib.inputhookgtk import inputhook_gtk
295 self.set_inputhook(inputhook_gtk)
297 self.set_inputhook(inputhook_gtk)
296 self._current_gui = GUI_GTK
298 self._current_gui = GUI_GTK
297
299
298 def disable_gtk(self):
300 def disable_gtk(self):
299 """Disable event loop integration with PyGTK.
301 """Disable event loop integration with PyGTK.
300
302
301 This merely sets PyOS_InputHook to NULL.
303 This merely sets PyOS_InputHook to NULL.
302 """
304 """
303 self.clear_inputhook()
305 self.clear_inputhook()
304
306
305 def enable_tk(self, app=None):
307 def enable_tk(self, app=None):
306 """Enable event loop integration with Tk.
308 """Enable event loop integration with Tk.
307
309
308 Parameters
310 Parameters
309 ----------
311 ----------
310 app : toplevel :class:`Tkinter.Tk` widget, optional.
312 app : toplevel :class:`Tkinter.Tk` widget, optional.
311 Running toplevel widget to use. If not given, we probe Tk for an
313 Running toplevel widget to use. If not given, we probe Tk for an
312 existing one, and create a new one if none is found.
314 existing one, and create a new one if none is found.
313
315
314 Notes
316 Notes
315 -----
317 -----
316 If you have already created a :class:`Tkinter.Tk` object, the only
318 If you have already created a :class:`Tkinter.Tk` object, the only
317 thing done by this method is to register with the
319 thing done by this method is to register with the
318 :class:`InputHookManager`, since creating that object automatically
320 :class:`InputHookManager`, since creating that object automatically
319 sets ``PyOS_InputHook``.
321 sets ``PyOS_InputHook``.
320 """
322 """
321 self._current_gui = GUI_TK
323 self._current_gui = GUI_TK
322 if app is None:
324 if app is None:
323 try:
325 try:
324 from tkinter import Tk # Py 3
326 from tkinter import Tk # Py 3
325 except ImportError:
327 except ImportError:
326 from Tkinter import Tk # Py 2
328 from Tkinter import Tk # Py 2
327 app = Tk()
329 app = Tk()
328 app.withdraw()
330 app.withdraw()
329 self._apps[GUI_TK] = app
331 self._apps[GUI_TK] = app
330 return app
332 return app
331
333
332 def disable_tk(self):
334 def disable_tk(self):
333 """Disable event loop integration with Tkinter.
335 """Disable event loop integration with Tkinter.
334
336
335 This merely sets PyOS_InputHook to NULL.
337 This merely sets PyOS_InputHook to NULL.
336 """
338 """
337 self.clear_inputhook()
339 self.clear_inputhook()
338
340
339
341
340 def enable_glut(self, app=None):
342 def enable_glut(self, app=None):
341 """ Enable event loop integration with GLUT.
343 """ Enable event loop integration with GLUT.
342
344
343 Parameters
345 Parameters
344 ----------
346 ----------
345
347
346 app : ignored
348 app : ignored
347 Ignored, it's only a placeholder to keep the call signature of all
349 Ignored, it's only a placeholder to keep the call signature of all
348 gui activation methods consistent, which simplifies the logic of
350 gui activation methods consistent, which simplifies the logic of
349 supporting magics.
351 supporting magics.
350
352
351 Notes
353 Notes
352 -----
354 -----
353
355
354 This methods sets the PyOS_InputHook for GLUT, which allows the GLUT to
356 This methods sets the PyOS_InputHook for GLUT, which allows the GLUT to
355 integrate with terminal based applications like IPython. Due to GLUT
357 integrate with terminal based applications like IPython. Due to GLUT
356 limitations, it is currently not possible to start the event loop
358 limitations, it is currently not possible to start the event loop
357 without first creating a window. You should thus not create another
359 without first creating a window. You should thus not create another
358 window but use instead the created one. See 'gui-glut.py' in the
360 window but use instead the created one. See 'gui-glut.py' in the
359 docs/examples/lib directory.
361 docs/examples/lib directory.
360
362
361 The default screen mode is set to:
363 The default screen mode is set to:
362 glut.GLUT_DOUBLE | glut.GLUT_RGBA | glut.GLUT_DEPTH
364 glut.GLUT_DOUBLE | glut.GLUT_RGBA | glut.GLUT_DEPTH
363 """
365 """
364
366
365 import OpenGL.GLUT as glut
367 import OpenGL.GLUT as glut
366 from IPython.lib.inputhookglut import glut_display_mode, \
368 from IPython.lib.inputhookglut import glut_display_mode, \
367 glut_close, glut_display, \
369 glut_close, glut_display, \
368 glut_idle, inputhook_glut
370 glut_idle, inputhook_glut
369
371
370 if GUI_GLUT not in self._apps:
372 if GUI_GLUT not in self._apps:
371 glut.glutInit( sys.argv )
373 glut.glutInit( sys.argv )
372 glut.glutInitDisplayMode( glut_display_mode )
374 glut.glutInitDisplayMode( glut_display_mode )
373 # This is specific to freeglut
375 # This is specific to freeglut
374 if bool(glut.glutSetOption):
376 if bool(glut.glutSetOption):
375 glut.glutSetOption( glut.GLUT_ACTION_ON_WINDOW_CLOSE,
377 glut.glutSetOption( glut.GLUT_ACTION_ON_WINDOW_CLOSE,
376 glut.GLUT_ACTION_GLUTMAINLOOP_RETURNS )
378 glut.GLUT_ACTION_GLUTMAINLOOP_RETURNS )
377 glut.glutCreateWindow( sys.argv[0] )
379 glut.glutCreateWindow( sys.argv[0] )
378 glut.glutReshapeWindow( 1, 1 )
380 glut.glutReshapeWindow( 1, 1 )
379 glut.glutHideWindow( )
381 glut.glutHideWindow( )
380 glut.glutWMCloseFunc( glut_close )
382 glut.glutWMCloseFunc( glut_close )
381 glut.glutDisplayFunc( glut_display )
383 glut.glutDisplayFunc( glut_display )
382 glut.glutIdleFunc( glut_idle )
384 glut.glutIdleFunc( glut_idle )
383 else:
385 else:
384 glut.glutWMCloseFunc( glut_close )
386 glut.glutWMCloseFunc( glut_close )
385 glut.glutDisplayFunc( glut_display )
387 glut.glutDisplayFunc( glut_display )
386 glut.glutIdleFunc( glut_idle)
388 glut.glutIdleFunc( glut_idle)
387 self.set_inputhook( inputhook_glut )
389 self.set_inputhook( inputhook_glut )
388 self._current_gui = GUI_GLUT
390 self._current_gui = GUI_GLUT
389 self._apps[GUI_GLUT] = True
391 self._apps[GUI_GLUT] = True
390
392
391
393
392 def disable_glut(self):
394 def disable_glut(self):
393 """Disable event loop integration with glut.
395 """Disable event loop integration with glut.
394
396
395 This sets PyOS_InputHook to NULL and set the display function to a
397 This sets PyOS_InputHook to NULL and set the display function to a
396 dummy one and set the timer to a dummy timer that will be triggered
398 dummy one and set the timer to a dummy timer that will be triggered
397 very far in the future.
399 very far in the future.
398 """
400 """
399 import OpenGL.GLUT as glut
401 import OpenGL.GLUT as glut
400 from glut_support import glutMainLoopEvent
402 from glut_support import glutMainLoopEvent
401
403
402 glut.glutHideWindow() # This is an event to be processed below
404 glut.glutHideWindow() # This is an event to be processed below
403 glutMainLoopEvent()
405 glutMainLoopEvent()
404 self.clear_inputhook()
406 self.clear_inputhook()
405
407
406 def enable_pyglet(self, app=None):
408 def enable_pyglet(self, app=None):
407 """Enable event loop integration with pyglet.
409 """Enable event loop integration with pyglet.
408
410
409 Parameters
411 Parameters
410 ----------
412 ----------
411 app : ignored
413 app : ignored
412 Ignored, it's only a placeholder to keep the call signature of all
414 Ignored, it's only a placeholder to keep the call signature of all
413 gui activation methods consistent, which simplifies the logic of
415 gui activation methods consistent, which simplifies the logic of
414 supporting magics.
416 supporting magics.
415
417
416 Notes
418 Notes
417 -----
419 -----
418 This methods sets the ``PyOS_InputHook`` for pyglet, which allows
420 This methods sets the ``PyOS_InputHook`` for pyglet, which allows
419 pyglet to integrate with terminal based applications like
421 pyglet to integrate with terminal based applications like
420 IPython.
422 IPython.
421
423
422 """
424 """
423 from IPython.lib.inputhookpyglet import inputhook_pyglet
425 from IPython.lib.inputhookpyglet import inputhook_pyglet
424 self.set_inputhook(inputhook_pyglet)
426 self.set_inputhook(inputhook_pyglet)
425 self._current_gui = GUI_PYGLET
427 self._current_gui = GUI_PYGLET
426 return app
428 return app
427
429
428 def disable_pyglet(self):
430 def disable_pyglet(self):
429 """Disable event loop integration with pyglet.
431 """Disable event loop integration with pyglet.
430
432
431 This merely sets PyOS_InputHook to NULL.
433 This merely sets PyOS_InputHook to NULL.
432 """
434 """
433 self.clear_inputhook()
435 self.clear_inputhook()
434
436
435 def enable_gtk3(self, app=None):
437 def enable_gtk3(self, app=None):
436 """Enable event loop integration with Gtk3 (gir bindings).
438 """Enable event loop integration with Gtk3 (gir bindings).
437
439
438 Parameters
440 Parameters
439 ----------
441 ----------
440 app : ignored
442 app : ignored
441 Ignored, it's only a placeholder to keep the call signature of all
443 Ignored, it's only a placeholder to keep the call signature of all
442 gui activation methods consistent, which simplifies the logic of
444 gui activation methods consistent, which simplifies the logic of
443 supporting magics.
445 supporting magics.
444
446
445 Notes
447 Notes
446 -----
448 -----
447 This methods sets the PyOS_InputHook for Gtk3, which allows
449 This methods sets the PyOS_InputHook for Gtk3, which allows
448 the Gtk3 to integrate with terminal based applications like
450 the Gtk3 to integrate with terminal based applications like
449 IPython.
451 IPython.
450 """
452 """
451 from IPython.lib.inputhookgtk3 import inputhook_gtk3
453 from IPython.lib.inputhookgtk3 import inputhook_gtk3
452 self.set_inputhook(inputhook_gtk3)
454 self.set_inputhook(inputhook_gtk3)
453 self._current_gui = GUI_GTK
455 self._current_gui = GUI_GTK
454
456
455 def disable_gtk3(self):
457 def disable_gtk3(self):
456 """Disable event loop integration with PyGTK.
458 """Disable event loop integration with PyGTK.
457
459
458 This merely sets PyOS_InputHook to NULL.
460 This merely sets PyOS_InputHook to NULL.
459 """
461 """
460 self.clear_inputhook()
462 self.clear_inputhook()
461
463
462 def current_gui(self):
464 def current_gui(self):
463 """Return a string indicating the currently active GUI or None."""
465 """Return a string indicating the currently active GUI or None."""
464 return self._current_gui
466 return self._current_gui
465
467
466 inputhook_manager = InputHookManager()
468 inputhook_manager = InputHookManager()
467
469
468 enable_wx = inputhook_manager.enable_wx
470 enable_wx = inputhook_manager.enable_wx
469 disable_wx = inputhook_manager.disable_wx
471 disable_wx = inputhook_manager.disable_wx
470 enable_qt4 = inputhook_manager.enable_qt4
472 enable_qt4 = inputhook_manager.enable_qt4
471 disable_qt4 = inputhook_manager.disable_qt4
473 disable_qt4 = inputhook_manager.disable_qt4
472 enable_gtk = inputhook_manager.enable_gtk
474 enable_gtk = inputhook_manager.enable_gtk
473 disable_gtk = inputhook_manager.disable_gtk
475 disable_gtk = inputhook_manager.disable_gtk
474 enable_tk = inputhook_manager.enable_tk
476 enable_tk = inputhook_manager.enable_tk
475 disable_tk = inputhook_manager.disable_tk
477 disable_tk = inputhook_manager.disable_tk
476 enable_glut = inputhook_manager.enable_glut
478 enable_glut = inputhook_manager.enable_glut
477 disable_glut = inputhook_manager.disable_glut
479 disable_glut = inputhook_manager.disable_glut
478 enable_pyglet = inputhook_manager.enable_pyglet
480 enable_pyglet = inputhook_manager.enable_pyglet
479 disable_pyglet = inputhook_manager.disable_pyglet
481 disable_pyglet = inputhook_manager.disable_pyglet
480 enable_gtk3 = inputhook_manager.enable_gtk3
482 enable_gtk3 = inputhook_manager.enable_gtk3
481 disable_gtk3 = inputhook_manager.disable_gtk3
483 disable_gtk3 = inputhook_manager.disable_gtk3
482 clear_inputhook = inputhook_manager.clear_inputhook
484 clear_inputhook = inputhook_manager.clear_inputhook
483 set_inputhook = inputhook_manager.set_inputhook
485 set_inputhook = inputhook_manager.set_inputhook
484 current_gui = inputhook_manager.current_gui
486 current_gui = inputhook_manager.current_gui
485 clear_app_refs = inputhook_manager.clear_app_refs
487 clear_app_refs = inputhook_manager.clear_app_refs
486
488
487 guis = {None: clear_inputhook,
489 guis = {None: clear_inputhook,
488 GUI_NONE: clear_inputhook,
490 GUI_NONE: clear_inputhook,
489 GUI_OSX: lambda app=False: None,
491 GUI_OSX: lambda app=False: None,
490 GUI_TK: enable_tk,
492 GUI_TK: enable_tk,
491 GUI_GTK: enable_gtk,
493 GUI_GTK: enable_gtk,
492 GUI_WX: enable_wx,
494 GUI_WX: enable_wx,
493 GUI_QT: enable_qt4, # qt3 not supported
495 GUI_QT: enable_qt4, # qt3 not supported
494 GUI_QT4: enable_qt4,
496 GUI_QT4: enable_qt4,
495 GUI_GLUT: enable_glut,
497 GUI_GLUT: enable_glut,
496 GUI_PYGLET: enable_pyglet,
498 GUI_PYGLET: enable_pyglet,
497 GUI_GTK3: enable_gtk3,
499 GUI_GTK3: enable_gtk3,
498 }
500 }
499
501
500
502
501 # Convenience function to switch amongst them
503 # Convenience function to switch amongst them
502 def enable_gui(gui=None, app=None):
504 def enable_gui(gui=None, app=None):
503 """Switch amongst GUI input hooks by name.
505 """Switch amongst GUI input hooks by name.
504
506
505 This is just a utility wrapper around the methods of the InputHookManager
507 This is just a utility wrapper around the methods of the InputHookManager
506 object.
508 object.
507
509
508 Parameters
510 Parameters
509 ----------
511 ----------
510 gui : optional, string or None
512 gui : optional, string or None
511 If None (or 'none'), clears input hook, otherwise it must be one
513 If None (or 'none'), clears input hook, otherwise it must be one
512 of the recognized GUI names (see ``GUI_*`` constants in module).
514 of the recognized GUI names (see ``GUI_*`` constants in module).
513
515
514 app : optional, existing application object.
516 app : optional, existing application object.
515 For toolkits that have the concept of a global app, you can supply an
517 For toolkits that have the concept of a global app, you can supply an
516 existing one. If not given, the toolkit will be probed for one, and if
518 existing one. If not given, the toolkit will be probed for one, and if
517 none is found, a new one will be created. Note that GTK does not have
519 none is found, a new one will be created. Note that GTK does not have
518 this concept, and passing an app if ``gui=="GTK"`` will raise an error.
520 this concept, and passing an app if ``gui=="GTK"`` will raise an error.
519
521
520 Returns
522 Returns
521 -------
523 -------
522 The output of the underlying gui switch routine, typically the actual
524 The output of the underlying gui switch routine, typically the actual
523 PyOS_InputHook wrapper object or the GUI toolkit app created, if there was
525 PyOS_InputHook wrapper object or the GUI toolkit app created, if there was
524 one.
526 one.
525 """
527 """
526 try:
528 try:
527 gui_hook = guis[gui]
529 gui_hook = guis[gui]
528 except KeyError:
530 except KeyError:
529 e = "Invalid GUI request %r, valid ones are:%s" % (gui, guis.keys())
531 e = "Invalid GUI request %r, valid ones are:%s" % (gui, guis.keys())
530 raise ValueError(e)
532 raise ValueError(e)
531 return gui_hook(app)
533 return gui_hook(app)
532
534
@@ -1,262 +1,262 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """
2 """
3 IO related utilities.
3 IO related utilities.
4 """
4 """
5
5
6 #-----------------------------------------------------------------------------
6 #-----------------------------------------------------------------------------
7 # Copyright (C) 2008-2011 The IPython Development Team
7 # Copyright (C) 2008-2011 The IPython Development Team
8 #
8 #
9 # Distributed under the terms of the BSD License. The full license is in
9 # Distributed under the terms of the BSD License. The full license is in
10 # the file COPYING, distributed as part of this software.
10 # the file COPYING, distributed as part of this software.
11 #-----------------------------------------------------------------------------
11 #-----------------------------------------------------------------------------
12 from __future__ import print_function
12 from __future__ import print_function
13 from __future__ import absolute_import
13 from __future__ import absolute_import
14
14
15 #-----------------------------------------------------------------------------
15 #-----------------------------------------------------------------------------
16 # Imports
16 # Imports
17 #-----------------------------------------------------------------------------
17 #-----------------------------------------------------------------------------
18 import codecs
18 import codecs
19 import os
19 import os
20 import sys
20 import sys
21 import tempfile
21 import tempfile
22 from .capture import CapturedIO, capture_output
22 from .capture import CapturedIO, capture_output
23 from .py3compat import string_types, input, PY3
23 from .py3compat import string_types, input, PY3
24
24
25 #-----------------------------------------------------------------------------
25 #-----------------------------------------------------------------------------
26 # Code
26 # Code
27 #-----------------------------------------------------------------------------
27 #-----------------------------------------------------------------------------
28
28
29
29
30 class IOStream:
30 class IOStream:
31
31
32 def __init__(self,stream, fallback=None):
32 def __init__(self,stream, fallback=None):
33 if not hasattr(stream,'write') or not hasattr(stream,'flush'):
33 if not hasattr(stream,'write') or not hasattr(stream,'flush'):
34 if fallback is not None:
34 if fallback is not None:
35 stream = fallback
35 stream = fallback
36 else:
36 else:
37 raise ValueError("fallback required, but not specified")
37 raise ValueError("fallback required, but not specified")
38 self.stream = stream
38 self.stream = stream
39 self._swrite = stream.write
39 self._swrite = stream.write
40
40
41 # clone all methods not overridden:
41 # clone all methods not overridden:
42 def clone(meth):
42 def clone(meth):
43 return not hasattr(self, meth) and not meth.startswith('_')
43 return not hasattr(self, meth) and not meth.startswith('_')
44 for meth in filter(clone, dir(stream)):
44 for meth in filter(clone, dir(stream)):
45 setattr(self, meth, getattr(stream, meth))
45 setattr(self, meth, getattr(stream, meth))
46
46
47 def __repr__(self):
47 def __repr__(self):
48 cls = self.__class__
48 cls = self.__class__
49 tpl = '{mod}.{cls}({args})'
49 tpl = '{mod}.{cls}({args})'
50 return tpl.format(mod=cls.__module__, cls=cls.__name__, args=self.stream)
50 return tpl.format(mod=cls.__module__, cls=cls.__name__, args=self.stream)
51
51
52 def write(self,data):
52 def write(self,data):
53 try:
53 try:
54 self._swrite(data)
54 self._swrite(data)
55 except:
55 except:
56 try:
56 try:
57 # print handles some unicode issues which may trip a plain
57 # print handles some unicode issues which may trip a plain
58 # write() call. Emulate write() by using an empty end
58 # write() call. Emulate write() by using an empty end
59 # argument.
59 # argument.
60 print(data, end='', file=self.stream)
60 print(data, end='', file=self.stream)
61 except:
61 except:
62 # if we get here, something is seriously broken.
62 # if we get here, something is seriously broken.
63 print('ERROR - failed to write data to stream:', self.stream,
63 print('ERROR - failed to write data to stream:', self.stream,
64 file=sys.stderr)
64 file=sys.stderr)
65
65
66 def writelines(self, lines):
66 def writelines(self, lines):
67 if isinstance(lines, string_types):
67 if isinstance(lines, string_types):
68 lines = [lines]
68 lines = [lines]
69 for line in lines:
69 for line in lines:
70 self.write(line)
70 self.write(line)
71
71
72 # This class used to have a writeln method, but regular files and streams
72 # This class used to have a writeln method, but regular files and streams
73 # in Python don't have this method. We need to keep this completely
73 # in Python don't have this method. We need to keep this completely
74 # compatible so we removed it.
74 # compatible so we removed it.
75
75
76 @property
76 @property
77 def closed(self):
77 def closed(self):
78 return self.stream.closed
78 return self.stream.closed
79
79
80 def close(self):
80 def close(self):
81 pass
81 pass
82
82
83 # setup stdin/stdout/stderr to sys.stdin/sys.stdout/sys.stderr
83 # setup stdin/stdout/stderr to sys.stdin/sys.stdout/sys.stderr
84 devnull = open(os.devnull, 'a')
84 devnull = open(os.devnull, 'w')
85 stdin = IOStream(sys.stdin, fallback=devnull)
85 stdin = IOStream(sys.stdin, fallback=devnull)
86 stdout = IOStream(sys.stdout, fallback=devnull)
86 stdout = IOStream(sys.stdout, fallback=devnull)
87 stderr = IOStream(sys.stderr, fallback=devnull)
87 stderr = IOStream(sys.stderr, fallback=devnull)
88
88
89 class IOTerm:
89 class IOTerm:
90 """ Term holds the file or file-like objects for handling I/O operations.
90 """ Term holds the file or file-like objects for handling I/O operations.
91
91
92 These are normally just sys.stdin, sys.stdout and sys.stderr but for
92 These are normally just sys.stdin, sys.stdout and sys.stderr but for
93 Windows they can can replaced to allow editing the strings before they are
93 Windows they can can replaced to allow editing the strings before they are
94 displayed."""
94 displayed."""
95
95
96 # In the future, having IPython channel all its I/O operations through
96 # In the future, having IPython channel all its I/O operations through
97 # this class will make it easier to embed it into other environments which
97 # this class will make it easier to embed it into other environments which
98 # are not a normal terminal (such as a GUI-based shell)
98 # are not a normal terminal (such as a GUI-based shell)
99 def __init__(self, stdin=None, stdout=None, stderr=None):
99 def __init__(self, stdin=None, stdout=None, stderr=None):
100 mymodule = sys.modules[__name__]
100 mymodule = sys.modules[__name__]
101 self.stdin = IOStream(stdin, mymodule.stdin)
101 self.stdin = IOStream(stdin, mymodule.stdin)
102 self.stdout = IOStream(stdout, mymodule.stdout)
102 self.stdout = IOStream(stdout, mymodule.stdout)
103 self.stderr = IOStream(stderr, mymodule.stderr)
103 self.stderr = IOStream(stderr, mymodule.stderr)
104
104
105
105
106 class Tee(object):
106 class Tee(object):
107 """A class to duplicate an output stream to stdout/err.
107 """A class to duplicate an output stream to stdout/err.
108
108
109 This works in a manner very similar to the Unix 'tee' command.
109 This works in a manner very similar to the Unix 'tee' command.
110
110
111 When the object is closed or deleted, it closes the original file given to
111 When the object is closed or deleted, it closes the original file given to
112 it for duplication.
112 it for duplication.
113 """
113 """
114 # Inspired by:
114 # Inspired by:
115 # http://mail.python.org/pipermail/python-list/2007-May/442737.html
115 # http://mail.python.org/pipermail/python-list/2007-May/442737.html
116
116
117 def __init__(self, file_or_name, mode="w", channel='stdout'):
117 def __init__(self, file_or_name, mode="w", channel='stdout'):
118 """Construct a new Tee object.
118 """Construct a new Tee object.
119
119
120 Parameters
120 Parameters
121 ----------
121 ----------
122 file_or_name : filename or open filehandle (writable)
122 file_or_name : filename or open filehandle (writable)
123 File that will be duplicated
123 File that will be duplicated
124
124
125 mode : optional, valid mode for open().
125 mode : optional, valid mode for open().
126 If a filename was give, open with this mode.
126 If a filename was give, open with this mode.
127
127
128 channel : str, one of ['stdout', 'stderr']
128 channel : str, one of ['stdout', 'stderr']
129 """
129 """
130 if channel not in ['stdout', 'stderr']:
130 if channel not in ['stdout', 'stderr']:
131 raise ValueError('Invalid channel spec %s' % channel)
131 raise ValueError('Invalid channel spec %s' % channel)
132
132
133 if hasattr(file_or_name, 'write') and hasattr(file_or_name, 'seek'):
133 if hasattr(file_or_name, 'write') and hasattr(file_or_name, 'seek'):
134 self.file = file_or_name
134 self.file = file_or_name
135 else:
135 else:
136 self.file = open(file_or_name, mode)
136 self.file = open(file_or_name, mode)
137 self.channel = channel
137 self.channel = channel
138 self.ostream = getattr(sys, channel)
138 self.ostream = getattr(sys, channel)
139 setattr(sys, channel, self)
139 setattr(sys, channel, self)
140 self._closed = False
140 self._closed = False
141
141
142 def close(self):
142 def close(self):
143 """Close the file and restore the channel."""
143 """Close the file and restore the channel."""
144 self.flush()
144 self.flush()
145 setattr(sys, self.channel, self.ostream)
145 setattr(sys, self.channel, self.ostream)
146 self.file.close()
146 self.file.close()
147 self._closed = True
147 self._closed = True
148
148
149 def write(self, data):
149 def write(self, data):
150 """Write data to both channels."""
150 """Write data to both channels."""
151 self.file.write(data)
151 self.file.write(data)
152 self.ostream.write(data)
152 self.ostream.write(data)
153 self.ostream.flush()
153 self.ostream.flush()
154
154
155 def flush(self):
155 def flush(self):
156 """Flush both channels."""
156 """Flush both channels."""
157 self.file.flush()
157 self.file.flush()
158 self.ostream.flush()
158 self.ostream.flush()
159
159
160 def __del__(self):
160 def __del__(self):
161 if not self._closed:
161 if not self._closed:
162 self.close()
162 self.close()
163
163
164
164
165 def ask_yes_no(prompt, default=None, interrupt=None):
165 def ask_yes_no(prompt, default=None, interrupt=None):
166 """Asks a question and returns a boolean (y/n) answer.
166 """Asks a question and returns a boolean (y/n) answer.
167
167
168 If default is given (one of 'y','n'), it is used if the user input is
168 If default is given (one of 'y','n'), it is used if the user input is
169 empty. If interrupt is given (one of 'y','n'), it is used if the user
169 empty. If interrupt is given (one of 'y','n'), it is used if the user
170 presses Ctrl-C. Otherwise the question is repeated until an answer is
170 presses Ctrl-C. Otherwise the question is repeated until an answer is
171 given.
171 given.
172
172
173 An EOF is treated as the default answer. If there is no default, an
173 An EOF is treated as the default answer. If there is no default, an
174 exception is raised to prevent infinite loops.
174 exception is raised to prevent infinite loops.
175
175
176 Valid answers are: y/yes/n/no (match is not case sensitive)."""
176 Valid answers are: y/yes/n/no (match is not case sensitive)."""
177
177
178 answers = {'y':True,'n':False,'yes':True,'no':False}
178 answers = {'y':True,'n':False,'yes':True,'no':False}
179 ans = None
179 ans = None
180 while ans not in answers.keys():
180 while ans not in answers.keys():
181 try:
181 try:
182 ans = input(prompt+' ').lower()
182 ans = input(prompt+' ').lower()
183 if not ans: # response was an empty string
183 if not ans: # response was an empty string
184 ans = default
184 ans = default
185 except KeyboardInterrupt:
185 except KeyboardInterrupt:
186 if interrupt:
186 if interrupt:
187 ans = interrupt
187 ans = interrupt
188 except EOFError:
188 except EOFError:
189 if default in answers.keys():
189 if default in answers.keys():
190 ans = default
190 ans = default
191 print()
191 print()
192 else:
192 else:
193 raise
193 raise
194
194
195 return answers[ans]
195 return answers[ans]
196
196
197
197
198 def temp_pyfile(src, ext='.py'):
198 def temp_pyfile(src, ext='.py'):
199 """Make a temporary python file, return filename and filehandle.
199 """Make a temporary python file, return filename and filehandle.
200
200
201 Parameters
201 Parameters
202 ----------
202 ----------
203 src : string or list of strings (no need for ending newlines if list)
203 src : string or list of strings (no need for ending newlines if list)
204 Source code to be written to the file.
204 Source code to be written to the file.
205
205
206 ext : optional, string
206 ext : optional, string
207 Extension for the generated file.
207 Extension for the generated file.
208
208
209 Returns
209 Returns
210 -------
210 -------
211 (filename, open filehandle)
211 (filename, open filehandle)
212 It is the caller's responsibility to close the open file and unlink it.
212 It is the caller's responsibility to close the open file and unlink it.
213 """
213 """
214 fname = tempfile.mkstemp(ext)[1]
214 fname = tempfile.mkstemp(ext)[1]
215 f = open(fname,'w')
215 f = open(fname,'w')
216 f.write(src)
216 f.write(src)
217 f.flush()
217 f.flush()
218 return fname, f
218 return fname, f
219
219
220
220
221 def raw_print(*args, **kw):
221 def raw_print(*args, **kw):
222 """Raw print to sys.__stdout__, otherwise identical interface to print()."""
222 """Raw print to sys.__stdout__, otherwise identical interface to print()."""
223
223
224 print(*args, sep=kw.get('sep', ' '), end=kw.get('end', '\n'),
224 print(*args, sep=kw.get('sep', ' '), end=kw.get('end', '\n'),
225 file=sys.__stdout__)
225 file=sys.__stdout__)
226 sys.__stdout__.flush()
226 sys.__stdout__.flush()
227
227
228
228
229 def raw_print_err(*args, **kw):
229 def raw_print_err(*args, **kw):
230 """Raw print to sys.__stderr__, otherwise identical interface to print()."""
230 """Raw print to sys.__stderr__, otherwise identical interface to print()."""
231
231
232 print(*args, sep=kw.get('sep', ' '), end=kw.get('end', '\n'),
232 print(*args, sep=kw.get('sep', ' '), end=kw.get('end', '\n'),
233 file=sys.__stderr__)
233 file=sys.__stderr__)
234 sys.__stderr__.flush()
234 sys.__stderr__.flush()
235
235
236
236
237 # Short aliases for quick debugging, do NOT use these in production code.
237 # Short aliases for quick debugging, do NOT use these in production code.
238 rprint = raw_print
238 rprint = raw_print
239 rprinte = raw_print_err
239 rprinte = raw_print_err
240
240
241 def unicode_std_stream(stream='stdout'):
241 def unicode_std_stream(stream='stdout'):
242 u"""Get a wrapper to write unicode to stdout/stderr as UTF-8.
242 u"""Get a wrapper to write unicode to stdout/stderr as UTF-8.
243
243
244 This ignores environment variables and default encodings, to reliably write
244 This ignores environment variables and default encodings, to reliably write
245 unicode to stdout or stderr.
245 unicode to stdout or stderr.
246
246
247 ::
247 ::
248
248
249 unicode_std_stream().write(u'Ε‚@e¢ŧ←')
249 unicode_std_stream().write(u'Ε‚@e¢ŧ←')
250 """
250 """
251 assert stream in ('stdout', 'stderr')
251 assert stream in ('stdout', 'stderr')
252 stream = getattr(sys, stream)
252 stream = getattr(sys, stream)
253 if PY3:
253 if PY3:
254 try:
254 try:
255 stream_b = stream.buffer
255 stream_b = stream.buffer
256 except AttributeError:
256 except AttributeError:
257 # sys.stdout has been replaced - use it directly
257 # sys.stdout has been replaced - use it directly
258 return stream
258 return stream
259 else:
259 else:
260 stream_b = stream
260 stream_b = stream
261
261
262 return codecs.getwriter('utf-8')(stream_b)
262 return codecs.getwriter('utf-8')(stream_b)
@@ -1,123 +1,124 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """
2 """
3 Utilities for working with external processes.
3 Utilities for working with external processes.
4 """
4 """
5
5
6 #-----------------------------------------------------------------------------
6 #-----------------------------------------------------------------------------
7 # Copyright (C) 2008-2011 The IPython Development Team
7 # Copyright (C) 2008-2011 The IPython Development Team
8 #
8 #
9 # Distributed under the terms of the BSD License. The full license is in
9 # Distributed under the terms of the BSD License. The full license is in
10 # the file COPYING, distributed as part of this software.
10 # the file COPYING, distributed as part of this software.
11 #-----------------------------------------------------------------------------
11 #-----------------------------------------------------------------------------
12
12
13 #-----------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
14 # Imports
14 # Imports
15 #-----------------------------------------------------------------------------
15 #-----------------------------------------------------------------------------
16 from __future__ import print_function
16 from __future__ import print_function
17
17
18 # Stdlib
18 # Stdlib
19 import os
19 import os
20 import sys
20 import sys
21 import shlex
21 import shlex
22
22
23 # Our own
23 # Our own
24 if sys.platform == 'win32':
24 if sys.platform == 'win32':
25 from ._process_win32 import _find_cmd, system, getoutput, AvoidUNCPath, arg_split
25 from ._process_win32 import _find_cmd, system, getoutput, arg_split
26 elif sys.platform == 'cli':
27 from ._process_cli import _find_cmd, system, getoutput, arg_split
26 else:
28 else:
27 from ._process_posix import _find_cmd, system, getoutput, arg_split
29 from ._process_posix import _find_cmd, system, getoutput, arg_split
28
30
29
30 from ._process_common import getoutputerror, get_output_error_code, process_handler
31 from ._process_common import getoutputerror, get_output_error_code, process_handler
31 from . import py3compat
32 from . import py3compat
32
33
33 #-----------------------------------------------------------------------------
34 #-----------------------------------------------------------------------------
34 # Code
35 # Code
35 #-----------------------------------------------------------------------------
36 #-----------------------------------------------------------------------------
36
37
37
38
38 class FindCmdError(Exception):
39 class FindCmdError(Exception):
39 pass
40 pass
40
41
41
42
42 def find_cmd(cmd):
43 def find_cmd(cmd):
43 """Find absolute path to executable cmd in a cross platform manner.
44 """Find absolute path to executable cmd in a cross platform manner.
44
45
45 This function tries to determine the full path to a command line program
46 This function tries to determine the full path to a command line program
46 using `which` on Unix/Linux/OS X and `win32api` on Windows. Most of the
47 using `which` on Unix/Linux/OS X and `win32api` on Windows. Most of the
47 time it will use the version that is first on the users `PATH`.
48 time it will use the version that is first on the users `PATH`.
48
49
49 Warning, don't use this to find IPython command line programs as there
50 Warning, don't use this to find IPython command line programs as there
50 is a risk you will find the wrong one. Instead find those using the
51 is a risk you will find the wrong one. Instead find those using the
51 following code and looking for the application itself::
52 following code and looking for the application itself::
52
53
53 from IPython.utils.path import get_ipython_module_path
54 from IPython.utils.path import get_ipython_module_path
54 from IPython.utils.process import pycmd2argv
55 from IPython.utils.process import pycmd2argv
55 argv = pycmd2argv(get_ipython_module_path('IPython.terminal.ipapp'))
56 argv = pycmd2argv(get_ipython_module_path('IPython.terminal.ipapp'))
56
57
57 Parameters
58 Parameters
58 ----------
59 ----------
59 cmd : str
60 cmd : str
60 The command line program to look for.
61 The command line program to look for.
61 """
62 """
62 try:
63 try:
63 path = _find_cmd(cmd).rstrip()
64 path = _find_cmd(cmd).rstrip()
64 except OSError:
65 except OSError:
65 raise FindCmdError('command could not be found: %s' % cmd)
66 raise FindCmdError('command could not be found: %s' % cmd)
66 # which returns empty if not found
67 # which returns empty if not found
67 if path == '':
68 if path == '':
68 raise FindCmdError('command could not be found: %s' % cmd)
69 raise FindCmdError('command could not be found: %s' % cmd)
69 return os.path.abspath(path)
70 return os.path.abspath(path)
70
71
71
72
72 def is_cmd_found(cmd):
73 def is_cmd_found(cmd):
73 """Check whether executable `cmd` exists or not and return a bool."""
74 """Check whether executable `cmd` exists or not and return a bool."""
74 try:
75 try:
75 find_cmd(cmd)
76 find_cmd(cmd)
76 return True
77 return True
77 except FindCmdError:
78 except FindCmdError:
78 return False
79 return False
79
80
80
81
81 def pycmd2argv(cmd):
82 def pycmd2argv(cmd):
82 r"""Take the path of a python command and return a list (argv-style).
83 r"""Take the path of a python command and return a list (argv-style).
83
84
84 This only works on Python based command line programs and will find the
85 This only works on Python based command line programs and will find the
85 location of the ``python`` executable using ``sys.executable`` to make
86 location of the ``python`` executable using ``sys.executable`` to make
86 sure the right version is used.
87 sure the right version is used.
87
88
88 For a given path ``cmd``, this returns [cmd] if cmd's extension is .exe,
89 For a given path ``cmd``, this returns [cmd] if cmd's extension is .exe,
89 .com or .bat, and [, cmd] otherwise.
90 .com or .bat, and [, cmd] otherwise.
90
91
91 Parameters
92 Parameters
92 ----------
93 ----------
93 cmd : string
94 cmd : string
94 The path of the command.
95 The path of the command.
95
96
96 Returns
97 Returns
97 -------
98 -------
98 argv-style list.
99 argv-style list.
99 """
100 """
100 ext = os.path.splitext(cmd)[1]
101 ext = os.path.splitext(cmd)[1]
101 if ext in ['.exe', '.com', '.bat']:
102 if ext in ['.exe', '.com', '.bat']:
102 return [cmd]
103 return [cmd]
103 else:
104 else:
104 return [sys.executable, cmd]
105 return [sys.executable, cmd]
105
106
106
107
107 def abbrev_cwd():
108 def abbrev_cwd():
108 """ Return abbreviated version of cwd, e.g. d:mydir """
109 """ Return abbreviated version of cwd, e.g. d:mydir """
109 cwd = py3compat.getcwd().replace('\\','/')
110 cwd = py3compat.getcwd().replace('\\','/')
110 drivepart = ''
111 drivepart = ''
111 tail = cwd
112 tail = cwd
112 if sys.platform == 'win32':
113 if sys.platform == 'win32':
113 if len(cwd) < 4:
114 if len(cwd) < 4:
114 return cwd
115 return cwd
115 drivepart,tail = os.path.splitdrive(cwd)
116 drivepart,tail = os.path.splitdrive(cwd)
116
117
117
118
118 parts = tail.split('/')
119 parts = tail.split('/')
119 if len(parts) > 2:
120 if len(parts) > 2:
120 tail = '/'.join(parts[-2:])
121 tail = '/'.join(parts[-2:])
121
122
122 return (drivepart + (
123 return (drivepart + (
123 cwd == '/' and '/' or tail))
124 cwd == '/' and '/' or tail))
General Comments 0
You need to be logged in to leave comments. Login now