Show More
@@ -1,957 +1,956 b'' | |||||
1 | # encoding: utf-8 |
|
1 | # encoding: utf-8 | |
2 | """ |
|
2 | """ | |
3 | Prefiltering components. |
|
3 | Prefiltering components. | |
4 |
|
4 | |||
5 | Prefilters transform user input before it is exec'd by Python. These |
|
5 | Prefilters transform user input before it is exec'd by Python. These | |
6 | transforms are used to implement additional syntax such as !ls and %magic. |
|
6 | transforms are used to implement additional syntax such as !ls and %magic. | |
7 |
|
7 | |||
8 | Authors: |
|
8 | Authors: | |
9 |
|
9 | |||
10 | * Brian Granger |
|
10 | * Brian Granger | |
11 | * Fernando Perez |
|
11 | * Fernando Perez | |
12 | * Dan Milstein |
|
12 | * Dan Milstein | |
13 | * Ville Vainio |
|
13 | * Ville Vainio | |
14 | """ |
|
14 | """ | |
15 |
|
15 | |||
16 | #----------------------------------------------------------------------------- |
|
16 | #----------------------------------------------------------------------------- | |
17 | # Copyright (C) 2008-2011 The IPython Development Team |
|
17 | # Copyright (C) 2008-2011 The IPython Development Team | |
18 | # |
|
18 | # | |
19 | # Distributed under the terms of the BSD License. The full license is in |
|
19 | # Distributed under the terms of the BSD License. The full license is in | |
20 | # the file COPYING, distributed as part of this software. |
|
20 | # the file COPYING, distributed as part of this software. | |
21 | #----------------------------------------------------------------------------- |
|
21 | #----------------------------------------------------------------------------- | |
22 |
|
22 | |||
23 | #----------------------------------------------------------------------------- |
|
23 | #----------------------------------------------------------------------------- | |
24 | # Imports |
|
24 | # Imports | |
25 | #----------------------------------------------------------------------------- |
|
25 | #----------------------------------------------------------------------------- | |
26 |
|
26 | |||
27 | import __builtin__ |
|
27 | import __builtin__ | |
28 | import codeop |
|
28 | import codeop | |
29 | import re |
|
29 | import re | |
30 |
|
30 | |||
31 | from IPython.core.alias import AliasManager |
|
31 | from IPython.core.alias import AliasManager | |
32 | from IPython.core.autocall import IPyAutocall |
|
32 | from IPython.core.autocall import IPyAutocall | |
33 | from IPython.config.configurable import Configurable |
|
33 | from IPython.config.configurable import Configurable | |
34 | from IPython.core.macro import Macro |
|
34 | from IPython.core.macro import Macro | |
35 | from IPython.core.splitinput import split_user_input, LineInfo |
|
35 | from IPython.core.splitinput import split_user_input, LineInfo | |
36 | from IPython.core import page |
|
36 | from IPython.core import page | |
37 |
|
37 | |||
38 | from IPython.utils.traitlets import ( |
|
38 | from IPython.utils.traitlets import ( | |
39 | List, Integer, Any, Unicode, CBool, Bool, Instance, CRegExp |
|
39 | List, Integer, Any, Unicode, CBool, Bool, Instance, CRegExp | |
40 | ) |
|
40 | ) | |
41 | from IPython.utils.autoattr import auto_attr |
|
41 | from IPython.utils.autoattr import auto_attr | |
42 |
|
42 | |||
43 | #----------------------------------------------------------------------------- |
|
43 | #----------------------------------------------------------------------------- | |
44 | # Global utilities, errors and constants |
|
44 | # Global utilities, errors and constants | |
45 | #----------------------------------------------------------------------------- |
|
45 | #----------------------------------------------------------------------------- | |
46 |
|
46 | |||
47 | # Warning, these cannot be changed unless various regular expressions |
|
47 | # Warning, these cannot be changed unless various regular expressions | |
48 | # are updated in a number of places. Not great, but at least we told you. |
|
48 | # are updated in a number of places. Not great, but at least we told you. | |
49 | ESC_SHELL = '!' |
|
49 | ESC_SHELL = '!' | |
50 | ESC_SH_CAP = '!!' |
|
50 | ESC_SH_CAP = '!!' | |
51 | ESC_HELP = '?' |
|
51 | ESC_HELP = '?' | |
52 | ESC_MAGIC = '%' |
|
52 | ESC_MAGIC = '%' | |
53 | ESC_QUOTE = ',' |
|
53 | ESC_QUOTE = ',' | |
54 | ESC_QUOTE2 = ';' |
|
54 | ESC_QUOTE2 = ';' | |
55 | ESC_PAREN = '/' |
|
55 | ESC_PAREN = '/' | |
56 |
|
56 | |||
57 |
|
57 | |||
58 | class PrefilterError(Exception): |
|
58 | class PrefilterError(Exception): | |
59 | pass |
|
59 | pass | |
60 |
|
60 | |||
61 |
|
61 | |||
62 | # RegExp to identify potential function names |
|
62 | # RegExp to identify potential function names | |
63 | re_fun_name = re.compile(r'[a-zA-Z_]([a-zA-Z0-9_.]*) *$') |
|
63 | re_fun_name = re.compile(r'[a-zA-Z_]([a-zA-Z0-9_.]*) *$') | |
64 |
|
64 | |||
65 | # RegExp to exclude strings with this start from autocalling. In |
|
65 | # RegExp to exclude strings with this start from autocalling. In | |
66 | # particular, all binary operators should be excluded, so that if foo is |
|
66 | # particular, all binary operators should be excluded, so that if foo is | |
67 | # callable, foo OP bar doesn't become foo(OP bar), which is invalid. The |
|
67 | # callable, foo OP bar doesn't become foo(OP bar), which is invalid. The | |
68 | # characters '!=()' don't need to be checked for, as the checkPythonChars |
|
68 | # characters '!=()' don't need to be checked for, as the checkPythonChars | |
69 | # routine explicitely does so, to catch direct calls and rebindings of |
|
69 | # routine explicitely does so, to catch direct calls and rebindings of | |
70 | # existing names. |
|
70 | # existing names. | |
71 |
|
71 | |||
72 | # Warning: the '-' HAS TO BE AT THE END of the first group, otherwise |
|
72 | # Warning: the '-' HAS TO BE AT THE END of the first group, otherwise | |
73 | # it affects the rest of the group in square brackets. |
|
73 | # it affects the rest of the group in square brackets. | |
74 | re_exclude_auto = re.compile(r'^[,&^\|\*/\+-]' |
|
74 | re_exclude_auto = re.compile(r'^[,&^\|\*/\+-]' | |
75 | r'|^is |^not |^in |^and |^or ') |
|
75 | r'|^is |^not |^in |^and |^or ') | |
76 |
|
76 | |||
77 | # try to catch also methods for stuff in lists/tuples/dicts: off |
|
77 | # try to catch also methods for stuff in lists/tuples/dicts: off | |
78 | # (experimental). For this to work, the line_split regexp would need |
|
78 | # (experimental). For this to work, the line_split regexp would need | |
79 | # to be modified so it wouldn't break things at '['. That line is |
|
79 | # to be modified so it wouldn't break things at '['. That line is | |
80 | # nasty enough that I shouldn't change it until I can test it _well_. |
|
80 | # nasty enough that I shouldn't change it until I can test it _well_. | |
81 | #self.re_fun_name = re.compile (r'[a-zA-Z_]([a-zA-Z0-9_.\[\]]*) ?$') |
|
81 | #self.re_fun_name = re.compile (r'[a-zA-Z_]([a-zA-Z0-9_.\[\]]*) ?$') | |
82 |
|
82 | |||
83 |
|
83 | |||
84 | # Handler Check Utilities |
|
84 | # Handler Check Utilities | |
85 | def is_shadowed(identifier, ip): |
|
85 | def is_shadowed(identifier, ip): | |
86 | """Is the given identifier defined in one of the namespaces which shadow |
|
86 | """Is the given identifier defined in one of the namespaces which shadow | |
87 | the alias and magic namespaces? Note that an identifier is different |
|
87 | the alias and magic namespaces? Note that an identifier is different | |
88 | than ifun, because it can not contain a '.' character.""" |
|
88 | than ifun, because it can not contain a '.' character.""" | |
89 | # This is much safer than calling ofind, which can change state |
|
89 | # This is much safer than calling ofind, which can change state | |
90 | return (identifier in ip.user_ns \ |
|
90 | return (identifier in ip.user_ns \ | |
91 | or identifier in ip.user_global_ns \ |
|
91 | or identifier in ip.user_global_ns \ | |
92 | or identifier in ip.ns_table['builtin']) |
|
92 | or identifier in ip.ns_table['builtin']) | |
93 |
|
93 | |||
94 |
|
94 | |||
95 | #----------------------------------------------------------------------------- |
|
95 | #----------------------------------------------------------------------------- | |
96 | # Main Prefilter manager |
|
96 | # Main Prefilter manager | |
97 | #----------------------------------------------------------------------------- |
|
97 | #----------------------------------------------------------------------------- | |
98 |
|
98 | |||
99 |
|
99 | |||
100 | class PrefilterManager(Configurable): |
|
100 | class PrefilterManager(Configurable): | |
101 | """Main prefilter component. |
|
101 | """Main prefilter component. | |
102 |
|
102 | |||
103 | The IPython prefilter is run on all user input before it is run. The |
|
103 | The IPython prefilter is run on all user input before it is run. The | |
104 | prefilter consumes lines of input and produces transformed lines of |
|
104 | prefilter consumes lines of input and produces transformed lines of | |
105 | input. |
|
105 | input. | |
106 |
|
106 | |||
107 | The iplementation consists of two phases: |
|
107 | The iplementation consists of two phases: | |
108 |
|
108 | |||
109 | 1. Transformers |
|
109 | 1. Transformers | |
110 | 2. Checkers and handlers |
|
110 | 2. Checkers and handlers | |
111 |
|
111 | |||
112 | Over time, we plan on deprecating the checkers and handlers and doing |
|
112 | Over time, we plan on deprecating the checkers and handlers and doing | |
113 | everything in the transformers. |
|
113 | everything in the transformers. | |
114 |
|
114 | |||
115 | The transformers are instances of :class:`PrefilterTransformer` and have |
|
115 | The transformers are instances of :class:`PrefilterTransformer` and have | |
116 | a single method :meth:`transform` that takes a line and returns a |
|
116 | a single method :meth:`transform` that takes a line and returns a | |
117 | transformed line. The transformation can be accomplished using any |
|
117 | transformed line. The transformation can be accomplished using any | |
118 |
tool, but our current ones use regular expressions for speed. |
|
118 | tool, but our current ones use regular expressions for speed. | |
119 | ship :mod:`pyparsing` in :mod:`IPython.external` for use in transformers. |
|
|||
120 |
|
119 | |||
121 | After all the transformers have been run, the line is fed to the checkers, |
|
120 | After all the transformers have been run, the line is fed to the checkers, | |
122 | which are instances of :class:`PrefilterChecker`. The line is passed to |
|
121 | which are instances of :class:`PrefilterChecker`. The line is passed to | |
123 | the :meth:`check` method, which either returns `None` or a |
|
122 | the :meth:`check` method, which either returns `None` or a | |
124 | :class:`PrefilterHandler` instance. If `None` is returned, the other |
|
123 | :class:`PrefilterHandler` instance. If `None` is returned, the other | |
125 | checkers are tried. If an :class:`PrefilterHandler` instance is returned, |
|
124 | checkers are tried. If an :class:`PrefilterHandler` instance is returned, | |
126 | the line is passed to the :meth:`handle` method of the returned |
|
125 | the line is passed to the :meth:`handle` method of the returned | |
127 | handler and no further checkers are tried. |
|
126 | handler and no further checkers are tried. | |
128 |
|
127 | |||
129 | Both transformers and checkers have a `priority` attribute, that determines |
|
128 | Both transformers and checkers have a `priority` attribute, that determines | |
130 | the order in which they are called. Smaller priorities are tried first. |
|
129 | the order in which they are called. Smaller priorities are tried first. | |
131 |
|
130 | |||
132 | Both transformers and checkers also have `enabled` attribute, which is |
|
131 | Both transformers and checkers also have `enabled` attribute, which is | |
133 | a boolean that determines if the instance is used. |
|
132 | a boolean that determines if the instance is used. | |
134 |
|
133 | |||
135 | Users or developers can change the priority or enabled attribute of |
|
134 | Users or developers can change the priority or enabled attribute of | |
136 | transformers or checkers, but they must call the :meth:`sort_checkers` |
|
135 | transformers or checkers, but they must call the :meth:`sort_checkers` | |
137 | or :meth:`sort_transformers` method after changing the priority. |
|
136 | or :meth:`sort_transformers` method after changing the priority. | |
138 | """ |
|
137 | """ | |
139 |
|
138 | |||
140 | multi_line_specials = CBool(True, config=True) |
|
139 | multi_line_specials = CBool(True, config=True) | |
141 | shell = Instance('IPython.core.interactiveshell.InteractiveShellABC') |
|
140 | shell = Instance('IPython.core.interactiveshell.InteractiveShellABC') | |
142 |
|
141 | |||
143 | def __init__(self, shell=None, config=None): |
|
142 | def __init__(self, shell=None, config=None): | |
144 | super(PrefilterManager, self).__init__(shell=shell, config=config) |
|
143 | super(PrefilterManager, self).__init__(shell=shell, config=config) | |
145 | self.shell = shell |
|
144 | self.shell = shell | |
146 | self.init_transformers() |
|
145 | self.init_transformers() | |
147 | self.init_handlers() |
|
146 | self.init_handlers() | |
148 | self.init_checkers() |
|
147 | self.init_checkers() | |
149 |
|
148 | |||
150 | #------------------------------------------------------------------------- |
|
149 | #------------------------------------------------------------------------- | |
151 | # API for managing transformers |
|
150 | # API for managing transformers | |
152 | #------------------------------------------------------------------------- |
|
151 | #------------------------------------------------------------------------- | |
153 |
|
152 | |||
154 | def init_transformers(self): |
|
153 | def init_transformers(self): | |
155 | """Create the default transformers.""" |
|
154 | """Create the default transformers.""" | |
156 | self._transformers = [] |
|
155 | self._transformers = [] | |
157 | for transformer_cls in _default_transformers: |
|
156 | for transformer_cls in _default_transformers: | |
158 | transformer_cls( |
|
157 | transformer_cls( | |
159 | shell=self.shell, prefilter_manager=self, config=self.config |
|
158 | shell=self.shell, prefilter_manager=self, config=self.config | |
160 | ) |
|
159 | ) | |
161 |
|
160 | |||
162 | def sort_transformers(self): |
|
161 | def sort_transformers(self): | |
163 | """Sort the transformers by priority. |
|
162 | """Sort the transformers by priority. | |
164 |
|
163 | |||
165 | This must be called after the priority of a transformer is changed. |
|
164 | This must be called after the priority of a transformer is changed. | |
166 | The :meth:`register_transformer` method calls this automatically. |
|
165 | The :meth:`register_transformer` method calls this automatically. | |
167 | """ |
|
166 | """ | |
168 | self._transformers.sort(key=lambda x: x.priority) |
|
167 | self._transformers.sort(key=lambda x: x.priority) | |
169 |
|
168 | |||
170 | @property |
|
169 | @property | |
171 | def transformers(self): |
|
170 | def transformers(self): | |
172 | """Return a list of checkers, sorted by priority.""" |
|
171 | """Return a list of checkers, sorted by priority.""" | |
173 | return self._transformers |
|
172 | return self._transformers | |
174 |
|
173 | |||
175 | def register_transformer(self, transformer): |
|
174 | def register_transformer(self, transformer): | |
176 | """Register a transformer instance.""" |
|
175 | """Register a transformer instance.""" | |
177 | if transformer not in self._transformers: |
|
176 | if transformer not in self._transformers: | |
178 | self._transformers.append(transformer) |
|
177 | self._transformers.append(transformer) | |
179 | self.sort_transformers() |
|
178 | self.sort_transformers() | |
180 |
|
179 | |||
181 | def unregister_transformer(self, transformer): |
|
180 | def unregister_transformer(self, transformer): | |
182 | """Unregister a transformer instance.""" |
|
181 | """Unregister a transformer instance.""" | |
183 | if transformer in self._transformers: |
|
182 | if transformer in self._transformers: | |
184 | self._transformers.remove(transformer) |
|
183 | self._transformers.remove(transformer) | |
185 |
|
184 | |||
186 | #------------------------------------------------------------------------- |
|
185 | #------------------------------------------------------------------------- | |
187 | # API for managing checkers |
|
186 | # API for managing checkers | |
188 | #------------------------------------------------------------------------- |
|
187 | #------------------------------------------------------------------------- | |
189 |
|
188 | |||
190 | def init_checkers(self): |
|
189 | def init_checkers(self): | |
191 | """Create the default checkers.""" |
|
190 | """Create the default checkers.""" | |
192 | self._checkers = [] |
|
191 | self._checkers = [] | |
193 | for checker in _default_checkers: |
|
192 | for checker in _default_checkers: | |
194 | checker( |
|
193 | checker( | |
195 | shell=self.shell, prefilter_manager=self, config=self.config |
|
194 | shell=self.shell, prefilter_manager=self, config=self.config | |
196 | ) |
|
195 | ) | |
197 |
|
196 | |||
198 | def sort_checkers(self): |
|
197 | def sort_checkers(self): | |
199 | """Sort the checkers by priority. |
|
198 | """Sort the checkers by priority. | |
200 |
|
199 | |||
201 | This must be called after the priority of a checker is changed. |
|
200 | This must be called after the priority of a checker is changed. | |
202 | The :meth:`register_checker` method calls this automatically. |
|
201 | The :meth:`register_checker` method calls this automatically. | |
203 | """ |
|
202 | """ | |
204 | self._checkers.sort(key=lambda x: x.priority) |
|
203 | self._checkers.sort(key=lambda x: x.priority) | |
205 |
|
204 | |||
206 | @property |
|
205 | @property | |
207 | def checkers(self): |
|
206 | def checkers(self): | |
208 | """Return a list of checkers, sorted by priority.""" |
|
207 | """Return a list of checkers, sorted by priority.""" | |
209 | return self._checkers |
|
208 | return self._checkers | |
210 |
|
209 | |||
211 | def register_checker(self, checker): |
|
210 | def register_checker(self, checker): | |
212 | """Register a checker instance.""" |
|
211 | """Register a checker instance.""" | |
213 | if checker not in self._checkers: |
|
212 | if checker not in self._checkers: | |
214 | self._checkers.append(checker) |
|
213 | self._checkers.append(checker) | |
215 | self.sort_checkers() |
|
214 | self.sort_checkers() | |
216 |
|
215 | |||
217 | def unregister_checker(self, checker): |
|
216 | def unregister_checker(self, checker): | |
218 | """Unregister a checker instance.""" |
|
217 | """Unregister a checker instance.""" | |
219 | if checker in self._checkers: |
|
218 | if checker in self._checkers: | |
220 | self._checkers.remove(checker) |
|
219 | self._checkers.remove(checker) | |
221 |
|
220 | |||
222 | #------------------------------------------------------------------------- |
|
221 | #------------------------------------------------------------------------- | |
223 | # API for managing checkers |
|
222 | # API for managing checkers | |
224 | #------------------------------------------------------------------------- |
|
223 | #------------------------------------------------------------------------- | |
225 |
|
224 | |||
226 | def init_handlers(self): |
|
225 | def init_handlers(self): | |
227 | """Create the default handlers.""" |
|
226 | """Create the default handlers.""" | |
228 | self._handlers = {} |
|
227 | self._handlers = {} | |
229 | self._esc_handlers = {} |
|
228 | self._esc_handlers = {} | |
230 | for handler in _default_handlers: |
|
229 | for handler in _default_handlers: | |
231 | handler( |
|
230 | handler( | |
232 | shell=self.shell, prefilter_manager=self, config=self.config |
|
231 | shell=self.shell, prefilter_manager=self, config=self.config | |
233 | ) |
|
232 | ) | |
234 |
|
233 | |||
235 | @property |
|
234 | @property | |
236 | def handlers(self): |
|
235 | def handlers(self): | |
237 | """Return a dict of all the handlers.""" |
|
236 | """Return a dict of all the handlers.""" | |
238 | return self._handlers |
|
237 | return self._handlers | |
239 |
|
238 | |||
240 | def register_handler(self, name, handler, esc_strings): |
|
239 | def register_handler(self, name, handler, esc_strings): | |
241 | """Register a handler instance by name with esc_strings.""" |
|
240 | """Register a handler instance by name with esc_strings.""" | |
242 | self._handlers[name] = handler |
|
241 | self._handlers[name] = handler | |
243 | for esc_str in esc_strings: |
|
242 | for esc_str in esc_strings: | |
244 | self._esc_handlers[esc_str] = handler |
|
243 | self._esc_handlers[esc_str] = handler | |
245 |
|
244 | |||
246 | def unregister_handler(self, name, handler, esc_strings): |
|
245 | def unregister_handler(self, name, handler, esc_strings): | |
247 | """Unregister a handler instance by name with esc_strings.""" |
|
246 | """Unregister a handler instance by name with esc_strings.""" | |
248 | try: |
|
247 | try: | |
249 | del self._handlers[name] |
|
248 | del self._handlers[name] | |
250 | except KeyError: |
|
249 | except KeyError: | |
251 | pass |
|
250 | pass | |
252 | for esc_str in esc_strings: |
|
251 | for esc_str in esc_strings: | |
253 | h = self._esc_handlers.get(esc_str) |
|
252 | h = self._esc_handlers.get(esc_str) | |
254 | if h is handler: |
|
253 | if h is handler: | |
255 | del self._esc_handlers[esc_str] |
|
254 | del self._esc_handlers[esc_str] | |
256 |
|
255 | |||
257 | def get_handler_by_name(self, name): |
|
256 | def get_handler_by_name(self, name): | |
258 | """Get a handler by its name.""" |
|
257 | """Get a handler by its name.""" | |
259 | return self._handlers.get(name) |
|
258 | return self._handlers.get(name) | |
260 |
|
259 | |||
261 | def get_handler_by_esc(self, esc_str): |
|
260 | def get_handler_by_esc(self, esc_str): | |
262 | """Get a handler by its escape string.""" |
|
261 | """Get a handler by its escape string.""" | |
263 | return self._esc_handlers.get(esc_str) |
|
262 | return self._esc_handlers.get(esc_str) | |
264 |
|
263 | |||
265 | #------------------------------------------------------------------------- |
|
264 | #------------------------------------------------------------------------- | |
266 | # Main prefiltering API |
|
265 | # Main prefiltering API | |
267 | #------------------------------------------------------------------------- |
|
266 | #------------------------------------------------------------------------- | |
268 |
|
267 | |||
269 | def prefilter_line_info(self, line_info): |
|
268 | def prefilter_line_info(self, line_info): | |
270 | """Prefilter a line that has been converted to a LineInfo object. |
|
269 | """Prefilter a line that has been converted to a LineInfo object. | |
271 |
|
270 | |||
272 | This implements the checker/handler part of the prefilter pipe. |
|
271 | This implements the checker/handler part of the prefilter pipe. | |
273 | """ |
|
272 | """ | |
274 | # print "prefilter_line_info: ", line_info |
|
273 | # print "prefilter_line_info: ", line_info | |
275 | handler = self.find_handler(line_info) |
|
274 | handler = self.find_handler(line_info) | |
276 | return handler.handle(line_info) |
|
275 | return handler.handle(line_info) | |
277 |
|
276 | |||
278 | def find_handler(self, line_info): |
|
277 | def find_handler(self, line_info): | |
279 | """Find a handler for the line_info by trying checkers.""" |
|
278 | """Find a handler for the line_info by trying checkers.""" | |
280 | for checker in self.checkers: |
|
279 | for checker in self.checkers: | |
281 | if checker.enabled: |
|
280 | if checker.enabled: | |
282 | handler = checker.check(line_info) |
|
281 | handler = checker.check(line_info) | |
283 | if handler: |
|
282 | if handler: | |
284 | return handler |
|
283 | return handler | |
285 | return self.get_handler_by_name('normal') |
|
284 | return self.get_handler_by_name('normal') | |
286 |
|
285 | |||
287 | def transform_line(self, line, continue_prompt): |
|
286 | def transform_line(self, line, continue_prompt): | |
288 | """Calls the enabled transformers in order of increasing priority.""" |
|
287 | """Calls the enabled transformers in order of increasing priority.""" | |
289 | for transformer in self.transformers: |
|
288 | for transformer in self.transformers: | |
290 | if transformer.enabled: |
|
289 | if transformer.enabled: | |
291 | line = transformer.transform(line, continue_prompt) |
|
290 | line = transformer.transform(line, continue_prompt) | |
292 | return line |
|
291 | return line | |
293 |
|
292 | |||
294 | def prefilter_line(self, line, continue_prompt=False): |
|
293 | def prefilter_line(self, line, continue_prompt=False): | |
295 | """Prefilter a single input line as text. |
|
294 | """Prefilter a single input line as text. | |
296 |
|
295 | |||
297 | This method prefilters a single line of text by calling the |
|
296 | This method prefilters a single line of text by calling the | |
298 | transformers and then the checkers/handlers. |
|
297 | transformers and then the checkers/handlers. | |
299 | """ |
|
298 | """ | |
300 |
|
299 | |||
301 | # print "prefilter_line: ", line, continue_prompt |
|
300 | # print "prefilter_line: ", line, continue_prompt | |
302 | # All handlers *must* return a value, even if it's blank (''). |
|
301 | # All handlers *must* return a value, even if it's blank (''). | |
303 |
|
302 | |||
304 | # save the line away in case we crash, so the post-mortem handler can |
|
303 | # save the line away in case we crash, so the post-mortem handler can | |
305 | # record it |
|
304 | # record it | |
306 | self.shell._last_input_line = line |
|
305 | self.shell._last_input_line = line | |
307 |
|
306 | |||
308 | if not line: |
|
307 | if not line: | |
309 | # Return immediately on purely empty lines, so that if the user |
|
308 | # Return immediately on purely empty lines, so that if the user | |
310 | # previously typed some whitespace that started a continuation |
|
309 | # previously typed some whitespace that started a continuation | |
311 | # prompt, he can break out of that loop with just an empty line. |
|
310 | # prompt, he can break out of that loop with just an empty line. | |
312 | # This is how the default python prompt works. |
|
311 | # This is how the default python prompt works. | |
313 | return '' |
|
312 | return '' | |
314 |
|
313 | |||
315 | # At this point, we invoke our transformers. |
|
314 | # At this point, we invoke our transformers. | |
316 | if not continue_prompt or (continue_prompt and self.multi_line_specials): |
|
315 | if not continue_prompt or (continue_prompt and self.multi_line_specials): | |
317 | line = self.transform_line(line, continue_prompt) |
|
316 | line = self.transform_line(line, continue_prompt) | |
318 |
|
317 | |||
319 | # Now we compute line_info for the checkers and handlers |
|
318 | # Now we compute line_info for the checkers and handlers | |
320 | line_info = LineInfo(line, continue_prompt) |
|
319 | line_info = LineInfo(line, continue_prompt) | |
321 |
|
320 | |||
322 | # the input history needs to track even empty lines |
|
321 | # the input history needs to track even empty lines | |
323 | stripped = line.strip() |
|
322 | stripped = line.strip() | |
324 |
|
323 | |||
325 | normal_handler = self.get_handler_by_name('normal') |
|
324 | normal_handler = self.get_handler_by_name('normal') | |
326 | if not stripped: |
|
325 | if not stripped: | |
327 | if not continue_prompt: |
|
326 | if not continue_prompt: | |
328 | self.shell.displayhook.prompt_count -= 1 |
|
327 | self.shell.displayhook.prompt_count -= 1 | |
329 |
|
328 | |||
330 | return normal_handler.handle(line_info) |
|
329 | return normal_handler.handle(line_info) | |
331 |
|
330 | |||
332 | # special handlers are only allowed for single line statements |
|
331 | # special handlers are only allowed for single line statements | |
333 | if continue_prompt and not self.multi_line_specials: |
|
332 | if continue_prompt and not self.multi_line_specials: | |
334 | return normal_handler.handle(line_info) |
|
333 | return normal_handler.handle(line_info) | |
335 |
|
334 | |||
336 | prefiltered = self.prefilter_line_info(line_info) |
|
335 | prefiltered = self.prefilter_line_info(line_info) | |
337 | # print "prefiltered line: %r" % prefiltered |
|
336 | # print "prefiltered line: %r" % prefiltered | |
338 | return prefiltered |
|
337 | return prefiltered | |
339 |
|
338 | |||
340 | def prefilter_lines(self, lines, continue_prompt=False): |
|
339 | def prefilter_lines(self, lines, continue_prompt=False): | |
341 | """Prefilter multiple input lines of text. |
|
340 | """Prefilter multiple input lines of text. | |
342 |
|
341 | |||
343 | This is the main entry point for prefiltering multiple lines of |
|
342 | This is the main entry point for prefiltering multiple lines of | |
344 | input. This simply calls :meth:`prefilter_line` for each line of |
|
343 | input. This simply calls :meth:`prefilter_line` for each line of | |
345 | input. |
|
344 | input. | |
346 |
|
345 | |||
347 | This covers cases where there are multiple lines in the user entry, |
|
346 | This covers cases where there are multiple lines in the user entry, | |
348 | which is the case when the user goes back to a multiline history |
|
347 | which is the case when the user goes back to a multiline history | |
349 | entry and presses enter. |
|
348 | entry and presses enter. | |
350 | """ |
|
349 | """ | |
351 | llines = lines.rstrip('\n').split('\n') |
|
350 | llines = lines.rstrip('\n').split('\n') | |
352 | # We can get multiple lines in one shot, where multiline input 'blends' |
|
351 | # We can get multiple lines in one shot, where multiline input 'blends' | |
353 | # into one line, in cases like recalling from the readline history |
|
352 | # into one line, in cases like recalling from the readline history | |
354 | # buffer. We need to make sure that in such cases, we correctly |
|
353 | # buffer. We need to make sure that in such cases, we correctly | |
355 | # communicate downstream which line is first and which are continuation |
|
354 | # communicate downstream which line is first and which are continuation | |
356 | # ones. |
|
355 | # ones. | |
357 | if len(llines) > 1: |
|
356 | if len(llines) > 1: | |
358 | out = '\n'.join([self.prefilter_line(line, lnum>0) |
|
357 | out = '\n'.join([self.prefilter_line(line, lnum>0) | |
359 | for lnum, line in enumerate(llines) ]) |
|
358 | for lnum, line in enumerate(llines) ]) | |
360 | else: |
|
359 | else: | |
361 | out = self.prefilter_line(llines[0], continue_prompt) |
|
360 | out = self.prefilter_line(llines[0], continue_prompt) | |
362 |
|
361 | |||
363 | return out |
|
362 | return out | |
364 |
|
363 | |||
365 | #----------------------------------------------------------------------------- |
|
364 | #----------------------------------------------------------------------------- | |
366 | # Prefilter transformers |
|
365 | # Prefilter transformers | |
367 | #----------------------------------------------------------------------------- |
|
366 | #----------------------------------------------------------------------------- | |
368 |
|
367 | |||
369 |
|
368 | |||
370 | class PrefilterTransformer(Configurable): |
|
369 | class PrefilterTransformer(Configurable): | |
371 | """Transform a line of user input.""" |
|
370 | """Transform a line of user input.""" | |
372 |
|
371 | |||
373 | priority = Integer(100, config=True) |
|
372 | priority = Integer(100, config=True) | |
374 | # Transformers don't currently use shell or prefilter_manager, but as we |
|
373 | # Transformers don't currently use shell or prefilter_manager, but as we | |
375 | # move away from checkers and handlers, they will need them. |
|
374 | # move away from checkers and handlers, they will need them. | |
376 | shell = Instance('IPython.core.interactiveshell.InteractiveShellABC') |
|
375 | shell = Instance('IPython.core.interactiveshell.InteractiveShellABC') | |
377 | prefilter_manager = Instance('IPython.core.prefilter.PrefilterManager') |
|
376 | prefilter_manager = Instance('IPython.core.prefilter.PrefilterManager') | |
378 | enabled = Bool(True, config=True) |
|
377 | enabled = Bool(True, config=True) | |
379 |
|
378 | |||
380 | def __init__(self, shell=None, prefilter_manager=None, config=None): |
|
379 | def __init__(self, shell=None, prefilter_manager=None, config=None): | |
381 | super(PrefilterTransformer, self).__init__( |
|
380 | super(PrefilterTransformer, self).__init__( | |
382 | shell=shell, prefilter_manager=prefilter_manager, config=config |
|
381 | shell=shell, prefilter_manager=prefilter_manager, config=config | |
383 | ) |
|
382 | ) | |
384 | self.prefilter_manager.register_transformer(self) |
|
383 | self.prefilter_manager.register_transformer(self) | |
385 |
|
384 | |||
386 | def transform(self, line, continue_prompt): |
|
385 | def transform(self, line, continue_prompt): | |
387 | """Transform a line, returning the new one.""" |
|
386 | """Transform a line, returning the new one.""" | |
388 | return None |
|
387 | return None | |
389 |
|
388 | |||
390 | def __repr__(self): |
|
389 | def __repr__(self): | |
391 | return "<%s(priority=%r, enabled=%r)>" % ( |
|
390 | return "<%s(priority=%r, enabled=%r)>" % ( | |
392 | self.__class__.__name__, self.priority, self.enabled) |
|
391 | self.__class__.__name__, self.priority, self.enabled) | |
393 |
|
392 | |||
394 |
|
393 | |||
395 | _assign_system_re = re.compile(r'(?P<lhs>(\s*)([\w\.]+)((\s*,\s*[\w\.]+)*))' |
|
394 | _assign_system_re = re.compile(r'(?P<lhs>(\s*)([\w\.]+)((\s*,\s*[\w\.]+)*))' | |
396 | r'\s*=\s*!(?P<cmd>.*)') |
|
395 | r'\s*=\s*!(?P<cmd>.*)') | |
397 |
|
396 | |||
398 |
|
397 | |||
399 | class AssignSystemTransformer(PrefilterTransformer): |
|
398 | class AssignSystemTransformer(PrefilterTransformer): | |
400 | """Handle the `files = !ls` syntax.""" |
|
399 | """Handle the `files = !ls` syntax.""" | |
401 |
|
400 | |||
402 | priority = Integer(100, config=True) |
|
401 | priority = Integer(100, config=True) | |
403 |
|
402 | |||
404 | def transform(self, line, continue_prompt): |
|
403 | def transform(self, line, continue_prompt): | |
405 | m = _assign_system_re.match(line) |
|
404 | m = _assign_system_re.match(line) | |
406 | if m is not None: |
|
405 | if m is not None: | |
407 | cmd = m.group('cmd') |
|
406 | cmd = m.group('cmd') | |
408 | lhs = m.group('lhs') |
|
407 | lhs = m.group('lhs') | |
409 | expr = "sc =%s" % cmd |
|
408 | expr = "sc =%s" % cmd | |
410 | new_line = '%s = get_ipython().magic(%r)' % (lhs, expr) |
|
409 | new_line = '%s = get_ipython().magic(%r)' % (lhs, expr) | |
411 | return new_line |
|
410 | return new_line | |
412 | return line |
|
411 | return line | |
413 |
|
412 | |||
414 |
|
413 | |||
415 | _assign_magic_re = re.compile(r'(?P<lhs>(\s*)([\w\.]+)((\s*,\s*[\w\.]+)*))' |
|
414 | _assign_magic_re = re.compile(r'(?P<lhs>(\s*)([\w\.]+)((\s*,\s*[\w\.]+)*))' | |
416 | r'\s*=\s*%(?P<cmd>.*)') |
|
415 | r'\s*=\s*%(?P<cmd>.*)') | |
417 |
|
416 | |||
418 | class AssignMagicTransformer(PrefilterTransformer): |
|
417 | class AssignMagicTransformer(PrefilterTransformer): | |
419 | """Handle the `a = %who` syntax.""" |
|
418 | """Handle the `a = %who` syntax.""" | |
420 |
|
419 | |||
421 | priority = Integer(200, config=True) |
|
420 | priority = Integer(200, config=True) | |
422 |
|
421 | |||
423 | def transform(self, line, continue_prompt): |
|
422 | def transform(self, line, continue_prompt): | |
424 | m = _assign_magic_re.match(line) |
|
423 | m = _assign_magic_re.match(line) | |
425 | if m is not None: |
|
424 | if m is not None: | |
426 | cmd = m.group('cmd') |
|
425 | cmd = m.group('cmd') | |
427 | lhs = m.group('lhs') |
|
426 | lhs = m.group('lhs') | |
428 | new_line = '%s = get_ipython().magic(%r)' % (lhs, cmd) |
|
427 | new_line = '%s = get_ipython().magic(%r)' % (lhs, cmd) | |
429 | return new_line |
|
428 | return new_line | |
430 | return line |
|
429 | return line | |
431 |
|
430 | |||
432 |
|
431 | |||
433 | _classic_prompt_re = re.compile(r'(^[ \t]*>>> |^[ \t]*\.\.\. )') |
|
432 | _classic_prompt_re = re.compile(r'(^[ \t]*>>> |^[ \t]*\.\.\. )') | |
434 |
|
433 | |||
435 | class PyPromptTransformer(PrefilterTransformer): |
|
434 | class PyPromptTransformer(PrefilterTransformer): | |
436 | """Handle inputs that start with '>>> ' syntax.""" |
|
435 | """Handle inputs that start with '>>> ' syntax.""" | |
437 |
|
436 | |||
438 | priority = Integer(50, config=True) |
|
437 | priority = Integer(50, config=True) | |
439 |
|
438 | |||
440 | def transform(self, line, continue_prompt): |
|
439 | def transform(self, line, continue_prompt): | |
441 |
|
440 | |||
442 | if not line or line.isspace() or line.strip() == '...': |
|
441 | if not line or line.isspace() or line.strip() == '...': | |
443 | # This allows us to recognize multiple input prompts separated by |
|
442 | # This allows us to recognize multiple input prompts separated by | |
444 | # blank lines and pasted in a single chunk, very common when |
|
443 | # blank lines and pasted in a single chunk, very common when | |
445 | # pasting doctests or long tutorial passages. |
|
444 | # pasting doctests or long tutorial passages. | |
446 | return '' |
|
445 | return '' | |
447 | m = _classic_prompt_re.match(line) |
|
446 | m = _classic_prompt_re.match(line) | |
448 | if m: |
|
447 | if m: | |
449 | return line[len(m.group(0)):] |
|
448 | return line[len(m.group(0)):] | |
450 | else: |
|
449 | else: | |
451 | return line |
|
450 | return line | |
452 |
|
451 | |||
453 |
|
452 | |||
454 | _ipy_prompt_re = re.compile(r'(^[ \t]*In \[\d+\]: |^[ \t]*\ \ \ \.\.\.+: )') |
|
453 | _ipy_prompt_re = re.compile(r'(^[ \t]*In \[\d+\]: |^[ \t]*\ \ \ \.\.\.+: )') | |
455 |
|
454 | |||
456 | class IPyPromptTransformer(PrefilterTransformer): |
|
455 | class IPyPromptTransformer(PrefilterTransformer): | |
457 | """Handle inputs that start classic IPython prompt syntax.""" |
|
456 | """Handle inputs that start classic IPython prompt syntax.""" | |
458 |
|
457 | |||
459 | priority = Integer(50, config=True) |
|
458 | priority = Integer(50, config=True) | |
460 |
|
459 | |||
461 | def transform(self, line, continue_prompt): |
|
460 | def transform(self, line, continue_prompt): | |
462 |
|
461 | |||
463 | if not line or line.isspace() or line.strip() == '...': |
|
462 | if not line or line.isspace() or line.strip() == '...': | |
464 | # This allows us to recognize multiple input prompts separated by |
|
463 | # This allows us to recognize multiple input prompts separated by | |
465 | # blank lines and pasted in a single chunk, very common when |
|
464 | # blank lines and pasted in a single chunk, very common when | |
466 | # pasting doctests or long tutorial passages. |
|
465 | # pasting doctests or long tutorial passages. | |
467 | return '' |
|
466 | return '' | |
468 | m = _ipy_prompt_re.match(line) |
|
467 | m = _ipy_prompt_re.match(line) | |
469 | if m: |
|
468 | if m: | |
470 | return line[len(m.group(0)):] |
|
469 | return line[len(m.group(0)):] | |
471 | else: |
|
470 | else: | |
472 | return line |
|
471 | return line | |
473 |
|
472 | |||
474 | #----------------------------------------------------------------------------- |
|
473 | #----------------------------------------------------------------------------- | |
475 | # Prefilter checkers |
|
474 | # Prefilter checkers | |
476 | #----------------------------------------------------------------------------- |
|
475 | #----------------------------------------------------------------------------- | |
477 |
|
476 | |||
478 |
|
477 | |||
479 | class PrefilterChecker(Configurable): |
|
478 | class PrefilterChecker(Configurable): | |
480 | """Inspect an input line and return a handler for that line.""" |
|
479 | """Inspect an input line and return a handler for that line.""" | |
481 |
|
480 | |||
482 | priority = Integer(100, config=True) |
|
481 | priority = Integer(100, config=True) | |
483 | shell = Instance('IPython.core.interactiveshell.InteractiveShellABC') |
|
482 | shell = Instance('IPython.core.interactiveshell.InteractiveShellABC') | |
484 | prefilter_manager = Instance('IPython.core.prefilter.PrefilterManager') |
|
483 | prefilter_manager = Instance('IPython.core.prefilter.PrefilterManager') | |
485 | enabled = Bool(True, config=True) |
|
484 | enabled = Bool(True, config=True) | |
486 |
|
485 | |||
487 | def __init__(self, shell=None, prefilter_manager=None, config=None): |
|
486 | def __init__(self, shell=None, prefilter_manager=None, config=None): | |
488 | super(PrefilterChecker, self).__init__( |
|
487 | super(PrefilterChecker, self).__init__( | |
489 | shell=shell, prefilter_manager=prefilter_manager, config=config |
|
488 | shell=shell, prefilter_manager=prefilter_manager, config=config | |
490 | ) |
|
489 | ) | |
491 | self.prefilter_manager.register_checker(self) |
|
490 | self.prefilter_manager.register_checker(self) | |
492 |
|
491 | |||
493 | def check(self, line_info): |
|
492 | def check(self, line_info): | |
494 | """Inspect line_info and return a handler instance or None.""" |
|
493 | """Inspect line_info and return a handler instance or None.""" | |
495 | return None |
|
494 | return None | |
496 |
|
495 | |||
497 | def __repr__(self): |
|
496 | def __repr__(self): | |
498 | return "<%s(priority=%r, enabled=%r)>" % ( |
|
497 | return "<%s(priority=%r, enabled=%r)>" % ( | |
499 | self.__class__.__name__, self.priority, self.enabled) |
|
498 | self.__class__.__name__, self.priority, self.enabled) | |
500 |
|
499 | |||
501 |
|
500 | |||
502 | class EmacsChecker(PrefilterChecker): |
|
501 | class EmacsChecker(PrefilterChecker): | |
503 |
|
502 | |||
504 | priority = Integer(100, config=True) |
|
503 | priority = Integer(100, config=True) | |
505 | enabled = Bool(False, config=True) |
|
504 | enabled = Bool(False, config=True) | |
506 |
|
505 | |||
507 | def check(self, line_info): |
|
506 | def check(self, line_info): | |
508 | "Emacs ipython-mode tags certain input lines." |
|
507 | "Emacs ipython-mode tags certain input lines." | |
509 | if line_info.line.endswith('# PYTHON-MODE'): |
|
508 | if line_info.line.endswith('# PYTHON-MODE'): | |
510 | return self.prefilter_manager.get_handler_by_name('emacs') |
|
509 | return self.prefilter_manager.get_handler_by_name('emacs') | |
511 | else: |
|
510 | else: | |
512 | return None |
|
511 | return None | |
513 |
|
512 | |||
514 |
|
513 | |||
515 | class ShellEscapeChecker(PrefilterChecker): |
|
514 | class ShellEscapeChecker(PrefilterChecker): | |
516 |
|
515 | |||
517 | priority = Integer(200, config=True) |
|
516 | priority = Integer(200, config=True) | |
518 |
|
517 | |||
519 | def check(self, line_info): |
|
518 | def check(self, line_info): | |
520 | if line_info.line.lstrip().startswith(ESC_SHELL): |
|
519 | if line_info.line.lstrip().startswith(ESC_SHELL): | |
521 | return self.prefilter_manager.get_handler_by_name('shell') |
|
520 | return self.prefilter_manager.get_handler_by_name('shell') | |
522 |
|
521 | |||
523 |
|
522 | |||
524 | class MacroChecker(PrefilterChecker): |
|
523 | class MacroChecker(PrefilterChecker): | |
525 |
|
524 | |||
526 | priority = Integer(250, config=True) |
|
525 | priority = Integer(250, config=True) | |
527 |
|
526 | |||
528 | def check(self, line_info): |
|
527 | def check(self, line_info): | |
529 | obj = self.shell.user_ns.get(line_info.ifun) |
|
528 | obj = self.shell.user_ns.get(line_info.ifun) | |
530 | if isinstance(obj, Macro): |
|
529 | if isinstance(obj, Macro): | |
531 | return self.prefilter_manager.get_handler_by_name('macro') |
|
530 | return self.prefilter_manager.get_handler_by_name('macro') | |
532 | else: |
|
531 | else: | |
533 | return None |
|
532 | return None | |
534 |
|
533 | |||
535 |
|
534 | |||
536 | class IPyAutocallChecker(PrefilterChecker): |
|
535 | class IPyAutocallChecker(PrefilterChecker): | |
537 |
|
536 | |||
538 | priority = Integer(300, config=True) |
|
537 | priority = Integer(300, config=True) | |
539 |
|
538 | |||
540 | def check(self, line_info): |
|
539 | def check(self, line_info): | |
541 | "Instances of IPyAutocall in user_ns get autocalled immediately" |
|
540 | "Instances of IPyAutocall in user_ns get autocalled immediately" | |
542 | obj = self.shell.user_ns.get(line_info.ifun, None) |
|
541 | obj = self.shell.user_ns.get(line_info.ifun, None) | |
543 | if isinstance(obj, IPyAutocall): |
|
542 | if isinstance(obj, IPyAutocall): | |
544 | obj.set_ip(self.shell) |
|
543 | obj.set_ip(self.shell) | |
545 | return self.prefilter_manager.get_handler_by_name('auto') |
|
544 | return self.prefilter_manager.get_handler_by_name('auto') | |
546 | else: |
|
545 | else: | |
547 | return None |
|
546 | return None | |
548 |
|
547 | |||
549 |
|
548 | |||
550 | class MultiLineMagicChecker(PrefilterChecker): |
|
549 | class MultiLineMagicChecker(PrefilterChecker): | |
551 |
|
550 | |||
552 | priority = Integer(400, config=True) |
|
551 | priority = Integer(400, config=True) | |
553 |
|
552 | |||
554 | def check(self, line_info): |
|
553 | def check(self, line_info): | |
555 | "Allow ! and !! in multi-line statements if multi_line_specials is on" |
|
554 | "Allow ! and !! in multi-line statements if multi_line_specials is on" | |
556 | # Note that this one of the only places we check the first character of |
|
555 | # Note that this one of the only places we check the first character of | |
557 | # ifun and *not* the pre_char. Also note that the below test matches |
|
556 | # ifun and *not* the pre_char. Also note that the below test matches | |
558 | # both ! and !!. |
|
557 | # both ! and !!. | |
559 | if line_info.continue_prompt \ |
|
558 | if line_info.continue_prompt \ | |
560 | and self.prefilter_manager.multi_line_specials: |
|
559 | and self.prefilter_manager.multi_line_specials: | |
561 | if line_info.esc == ESC_MAGIC: |
|
560 | if line_info.esc == ESC_MAGIC: | |
562 | return self.prefilter_manager.get_handler_by_name('magic') |
|
561 | return self.prefilter_manager.get_handler_by_name('magic') | |
563 | else: |
|
562 | else: | |
564 | return None |
|
563 | return None | |
565 |
|
564 | |||
566 |
|
565 | |||
567 | class EscCharsChecker(PrefilterChecker): |
|
566 | class EscCharsChecker(PrefilterChecker): | |
568 |
|
567 | |||
569 | priority = Integer(500, config=True) |
|
568 | priority = Integer(500, config=True) | |
570 |
|
569 | |||
571 | def check(self, line_info): |
|
570 | def check(self, line_info): | |
572 | """Check for escape character and return either a handler to handle it, |
|
571 | """Check for escape character and return either a handler to handle it, | |
573 | or None if there is no escape char.""" |
|
572 | or None if there is no escape char.""" | |
574 | if line_info.line[-1] == ESC_HELP \ |
|
573 | if line_info.line[-1] == ESC_HELP \ | |
575 | and line_info.esc != ESC_SHELL \ |
|
574 | and line_info.esc != ESC_SHELL \ | |
576 | and line_info.esc != ESC_SH_CAP: |
|
575 | and line_info.esc != ESC_SH_CAP: | |
577 | # the ? can be at the end, but *not* for either kind of shell escape, |
|
576 | # the ? can be at the end, but *not* for either kind of shell escape, | |
578 | # because a ? can be a vaild final char in a shell cmd |
|
577 | # because a ? can be a vaild final char in a shell cmd | |
579 | return self.prefilter_manager.get_handler_by_name('help') |
|
578 | return self.prefilter_manager.get_handler_by_name('help') | |
580 | else: |
|
579 | else: | |
581 | if line_info.pre: |
|
580 | if line_info.pre: | |
582 | return None |
|
581 | return None | |
583 | # This returns None like it should if no handler exists |
|
582 | # This returns None like it should if no handler exists | |
584 | return self.prefilter_manager.get_handler_by_esc(line_info.esc) |
|
583 | return self.prefilter_manager.get_handler_by_esc(line_info.esc) | |
585 |
|
584 | |||
586 |
|
585 | |||
587 | class AssignmentChecker(PrefilterChecker): |
|
586 | class AssignmentChecker(PrefilterChecker): | |
588 |
|
587 | |||
589 | priority = Integer(600, config=True) |
|
588 | priority = Integer(600, config=True) | |
590 |
|
589 | |||
591 | def check(self, line_info): |
|
590 | def check(self, line_info): | |
592 | """Check to see if user is assigning to a var for the first time, in |
|
591 | """Check to see if user is assigning to a var for the first time, in | |
593 | which case we want to avoid any sort of automagic / autocall games. |
|
592 | which case we want to avoid any sort of automagic / autocall games. | |
594 |
|
593 | |||
595 | This allows users to assign to either alias or magic names true python |
|
594 | This allows users to assign to either alias or magic names true python | |
596 | variables (the magic/alias systems always take second seat to true |
|
595 | variables (the magic/alias systems always take second seat to true | |
597 | python code). E.g. ls='hi', or ls,that=1,2""" |
|
596 | python code). E.g. ls='hi', or ls,that=1,2""" | |
598 | if line_info.the_rest: |
|
597 | if line_info.the_rest: | |
599 | if line_info.the_rest[0] in '=,': |
|
598 | if line_info.the_rest[0] in '=,': | |
600 | return self.prefilter_manager.get_handler_by_name('normal') |
|
599 | return self.prefilter_manager.get_handler_by_name('normal') | |
601 | else: |
|
600 | else: | |
602 | return None |
|
601 | return None | |
603 |
|
602 | |||
604 |
|
603 | |||
605 | class AutoMagicChecker(PrefilterChecker): |
|
604 | class AutoMagicChecker(PrefilterChecker): | |
606 |
|
605 | |||
607 | priority = Integer(700, config=True) |
|
606 | priority = Integer(700, config=True) | |
608 |
|
607 | |||
609 | def check(self, line_info): |
|
608 | def check(self, line_info): | |
610 | """If the ifun is magic, and automagic is on, run it. Note: normal, |
|
609 | """If the ifun is magic, and automagic is on, run it. Note: normal, | |
611 | non-auto magic would already have been triggered via '%' in |
|
610 | non-auto magic would already have been triggered via '%' in | |
612 | check_esc_chars. This just checks for automagic. Also, before |
|
611 | check_esc_chars. This just checks for automagic. Also, before | |
613 | triggering the magic handler, make sure that there is nothing in the |
|
612 | triggering the magic handler, make sure that there is nothing in the | |
614 | user namespace which could shadow it.""" |
|
613 | user namespace which could shadow it.""" | |
615 | if not self.shell.automagic or not self.shell.find_magic(line_info.ifun): |
|
614 | if not self.shell.automagic or not self.shell.find_magic(line_info.ifun): | |
616 | return None |
|
615 | return None | |
617 |
|
616 | |||
618 | # We have a likely magic method. Make sure we should actually call it. |
|
617 | # We have a likely magic method. Make sure we should actually call it. | |
619 | if line_info.continue_prompt and not self.prefilter_manager.multi_line_specials: |
|
618 | if line_info.continue_prompt and not self.prefilter_manager.multi_line_specials: | |
620 | return None |
|
619 | return None | |
621 |
|
620 | |||
622 | head = line_info.ifun.split('.',1)[0] |
|
621 | head = line_info.ifun.split('.',1)[0] | |
623 | if is_shadowed(head, self.shell): |
|
622 | if is_shadowed(head, self.shell): | |
624 | return None |
|
623 | return None | |
625 |
|
624 | |||
626 | return self.prefilter_manager.get_handler_by_name('magic') |
|
625 | return self.prefilter_manager.get_handler_by_name('magic') | |
627 |
|
626 | |||
628 |
|
627 | |||
629 | class AliasChecker(PrefilterChecker): |
|
628 | class AliasChecker(PrefilterChecker): | |
630 |
|
629 | |||
631 | priority = Integer(800, config=True) |
|
630 | priority = Integer(800, config=True) | |
632 |
|
631 | |||
633 | def check(self, line_info): |
|
632 | def check(self, line_info): | |
634 | "Check if the initital identifier on the line is an alias." |
|
633 | "Check if the initital identifier on the line is an alias." | |
635 | # Note: aliases can not contain '.' |
|
634 | # Note: aliases can not contain '.' | |
636 | head = line_info.ifun.split('.',1)[0] |
|
635 | head = line_info.ifun.split('.',1)[0] | |
637 | if line_info.ifun not in self.shell.alias_manager \ |
|
636 | if line_info.ifun not in self.shell.alias_manager \ | |
638 | or head not in self.shell.alias_manager \ |
|
637 | or head not in self.shell.alias_manager \ | |
639 | or is_shadowed(head, self.shell): |
|
638 | or is_shadowed(head, self.shell): | |
640 | return None |
|
639 | return None | |
641 |
|
640 | |||
642 | return self.prefilter_manager.get_handler_by_name('alias') |
|
641 | return self.prefilter_manager.get_handler_by_name('alias') | |
643 |
|
642 | |||
644 |
|
643 | |||
645 | class PythonOpsChecker(PrefilterChecker): |
|
644 | class PythonOpsChecker(PrefilterChecker): | |
646 |
|
645 | |||
647 | priority = Integer(900, config=True) |
|
646 | priority = Integer(900, config=True) | |
648 |
|
647 | |||
649 | def check(self, line_info): |
|
648 | def check(self, line_info): | |
650 | """If the 'rest' of the line begins with a function call or pretty much |
|
649 | """If the 'rest' of the line begins with a function call or pretty much | |
651 | any python operator, we should simply execute the line (regardless of |
|
650 | any python operator, we should simply execute the line (regardless of | |
652 | whether or not there's a possible autocall expansion). This avoids |
|
651 | whether or not there's a possible autocall expansion). This avoids | |
653 | spurious (and very confusing) geattr() accesses.""" |
|
652 | spurious (and very confusing) geattr() accesses.""" | |
654 | if line_info.the_rest and line_info.the_rest[0] in '!=()<>,+*/%^&|': |
|
653 | if line_info.the_rest and line_info.the_rest[0] in '!=()<>,+*/%^&|': | |
655 | return self.prefilter_manager.get_handler_by_name('normal') |
|
654 | return self.prefilter_manager.get_handler_by_name('normal') | |
656 | else: |
|
655 | else: | |
657 | return None |
|
656 | return None | |
658 |
|
657 | |||
659 |
|
658 | |||
660 | class AutocallChecker(PrefilterChecker): |
|
659 | class AutocallChecker(PrefilterChecker): | |
661 |
|
660 | |||
662 | priority = Integer(1000, config=True) |
|
661 | priority = Integer(1000, config=True) | |
663 |
|
662 | |||
664 | function_name_regexp = CRegExp(re_fun_name, config=True, |
|
663 | function_name_regexp = CRegExp(re_fun_name, config=True, | |
665 | help="RegExp to identify potential function names.") |
|
664 | help="RegExp to identify potential function names.") | |
666 | exclude_regexp = CRegExp(re_exclude_auto, config=True, |
|
665 | exclude_regexp = CRegExp(re_exclude_auto, config=True, | |
667 | help="RegExp to exclude strings with this start from autocalling.") |
|
666 | help="RegExp to exclude strings with this start from autocalling.") | |
668 |
|
667 | |||
669 | def check(self, line_info): |
|
668 | def check(self, line_info): | |
670 | "Check if the initial word/function is callable and autocall is on." |
|
669 | "Check if the initial word/function is callable and autocall is on." | |
671 | if not self.shell.autocall: |
|
670 | if not self.shell.autocall: | |
672 | return None |
|
671 | return None | |
673 |
|
672 | |||
674 | oinfo = line_info.ofind(self.shell) # This can mutate state via getattr |
|
673 | oinfo = line_info.ofind(self.shell) # This can mutate state via getattr | |
675 | if not oinfo['found']: |
|
674 | if not oinfo['found']: | |
676 | return None |
|
675 | return None | |
677 |
|
676 | |||
678 | if callable(oinfo['obj']) \ |
|
677 | if callable(oinfo['obj']) \ | |
679 | and (not self.exclude_regexp.match(line_info.the_rest)) \ |
|
678 | and (not self.exclude_regexp.match(line_info.the_rest)) \ | |
680 | and self.function_name_regexp.match(line_info.ifun): |
|
679 | and self.function_name_regexp.match(line_info.ifun): | |
681 | return self.prefilter_manager.get_handler_by_name('auto') |
|
680 | return self.prefilter_manager.get_handler_by_name('auto') | |
682 | else: |
|
681 | else: | |
683 | return None |
|
682 | return None | |
684 |
|
683 | |||
685 |
|
684 | |||
686 | #----------------------------------------------------------------------------- |
|
685 | #----------------------------------------------------------------------------- | |
687 | # Prefilter handlers |
|
686 | # Prefilter handlers | |
688 | #----------------------------------------------------------------------------- |
|
687 | #----------------------------------------------------------------------------- | |
689 |
|
688 | |||
690 |
|
689 | |||
691 | class PrefilterHandler(Configurable): |
|
690 | class PrefilterHandler(Configurable): | |
692 |
|
691 | |||
693 | handler_name = Unicode('normal') |
|
692 | handler_name = Unicode('normal') | |
694 | esc_strings = List([]) |
|
693 | esc_strings = List([]) | |
695 | shell = Instance('IPython.core.interactiveshell.InteractiveShellABC') |
|
694 | shell = Instance('IPython.core.interactiveshell.InteractiveShellABC') | |
696 | prefilter_manager = Instance('IPython.core.prefilter.PrefilterManager') |
|
695 | prefilter_manager = Instance('IPython.core.prefilter.PrefilterManager') | |
697 |
|
696 | |||
698 | def __init__(self, shell=None, prefilter_manager=None, config=None): |
|
697 | def __init__(self, shell=None, prefilter_manager=None, config=None): | |
699 | super(PrefilterHandler, self).__init__( |
|
698 | super(PrefilterHandler, self).__init__( | |
700 | shell=shell, prefilter_manager=prefilter_manager, config=config |
|
699 | shell=shell, prefilter_manager=prefilter_manager, config=config | |
701 | ) |
|
700 | ) | |
702 | self.prefilter_manager.register_handler( |
|
701 | self.prefilter_manager.register_handler( | |
703 | self.handler_name, |
|
702 | self.handler_name, | |
704 | self, |
|
703 | self, | |
705 | self.esc_strings |
|
704 | self.esc_strings | |
706 | ) |
|
705 | ) | |
707 |
|
706 | |||
708 | def handle(self, line_info): |
|
707 | def handle(self, line_info): | |
709 | # print "normal: ", line_info |
|
708 | # print "normal: ", line_info | |
710 | """Handle normal input lines. Use as a template for handlers.""" |
|
709 | """Handle normal input lines. Use as a template for handlers.""" | |
711 |
|
710 | |||
712 | # With autoindent on, we need some way to exit the input loop, and I |
|
711 | # With autoindent on, we need some way to exit the input loop, and I | |
713 | # don't want to force the user to have to backspace all the way to |
|
712 | # don't want to force the user to have to backspace all the way to | |
714 | # clear the line. The rule will be in this case, that either two |
|
713 | # clear the line. The rule will be in this case, that either two | |
715 | # lines of pure whitespace in a row, or a line of pure whitespace but |
|
714 | # lines of pure whitespace in a row, or a line of pure whitespace but | |
716 | # of a size different to the indent level, will exit the input loop. |
|
715 | # of a size different to the indent level, will exit the input loop. | |
717 | line = line_info.line |
|
716 | line = line_info.line | |
718 | continue_prompt = line_info.continue_prompt |
|
717 | continue_prompt = line_info.continue_prompt | |
719 |
|
718 | |||
720 | if (continue_prompt and |
|
719 | if (continue_prompt and | |
721 | self.shell.autoindent and |
|
720 | self.shell.autoindent and | |
722 | line.isspace() and |
|
721 | line.isspace() and | |
723 | 0 < abs(len(line) - self.shell.indent_current_nsp) <= 2): |
|
722 | 0 < abs(len(line) - self.shell.indent_current_nsp) <= 2): | |
724 | line = '' |
|
723 | line = '' | |
725 |
|
724 | |||
726 | return line |
|
725 | return line | |
727 |
|
726 | |||
728 | def __str__(self): |
|
727 | def __str__(self): | |
729 | return "<%s(name=%s)>" % (self.__class__.__name__, self.handler_name) |
|
728 | return "<%s(name=%s)>" % (self.__class__.__name__, self.handler_name) | |
730 |
|
729 | |||
731 |
|
730 | |||
732 | class AliasHandler(PrefilterHandler): |
|
731 | class AliasHandler(PrefilterHandler): | |
733 |
|
732 | |||
734 | handler_name = Unicode('alias') |
|
733 | handler_name = Unicode('alias') | |
735 |
|
734 | |||
736 | def handle(self, line_info): |
|
735 | def handle(self, line_info): | |
737 | """Handle alias input lines. """ |
|
736 | """Handle alias input lines. """ | |
738 | transformed = self.shell.alias_manager.expand_aliases(line_info.ifun,line_info.the_rest) |
|
737 | transformed = self.shell.alias_manager.expand_aliases(line_info.ifun,line_info.the_rest) | |
739 | # pre is needed, because it carries the leading whitespace. Otherwise |
|
738 | # pre is needed, because it carries the leading whitespace. Otherwise | |
740 | # aliases won't work in indented sections. |
|
739 | # aliases won't work in indented sections. | |
741 | line_out = '%sget_ipython().system(%r)' % (line_info.pre_whitespace, transformed) |
|
740 | line_out = '%sget_ipython().system(%r)' % (line_info.pre_whitespace, transformed) | |
742 |
|
741 | |||
743 | return line_out |
|
742 | return line_out | |
744 |
|
743 | |||
745 |
|
744 | |||
746 | class ShellEscapeHandler(PrefilterHandler): |
|
745 | class ShellEscapeHandler(PrefilterHandler): | |
747 |
|
746 | |||
748 | handler_name = Unicode('shell') |
|
747 | handler_name = Unicode('shell') | |
749 | esc_strings = List([ESC_SHELL, ESC_SH_CAP]) |
|
748 | esc_strings = List([ESC_SHELL, ESC_SH_CAP]) | |
750 |
|
749 | |||
751 | def handle(self, line_info): |
|
750 | def handle(self, line_info): | |
752 | """Execute the line in a shell, empty return value""" |
|
751 | """Execute the line in a shell, empty return value""" | |
753 | magic_handler = self.prefilter_manager.get_handler_by_name('magic') |
|
752 | magic_handler = self.prefilter_manager.get_handler_by_name('magic') | |
754 |
|
753 | |||
755 | line = line_info.line |
|
754 | line = line_info.line | |
756 | if line.lstrip().startswith(ESC_SH_CAP): |
|
755 | if line.lstrip().startswith(ESC_SH_CAP): | |
757 | # rewrite LineInfo's line, ifun and the_rest to properly hold the |
|
756 | # rewrite LineInfo's line, ifun and the_rest to properly hold the | |
758 | # call to %sx and the actual command to be executed, so |
|
757 | # call to %sx and the actual command to be executed, so | |
759 | # handle_magic can work correctly. Note that this works even if |
|
758 | # handle_magic can work correctly. Note that this works even if | |
760 | # the line is indented, so it handles multi_line_specials |
|
759 | # the line is indented, so it handles multi_line_specials | |
761 | # properly. |
|
760 | # properly. | |
762 | new_rest = line.lstrip()[2:] |
|
761 | new_rest = line.lstrip()[2:] | |
763 | line_info.line = '%ssx %s' % (ESC_MAGIC, new_rest) |
|
762 | line_info.line = '%ssx %s' % (ESC_MAGIC, new_rest) | |
764 | line_info.ifun = 'sx' |
|
763 | line_info.ifun = 'sx' | |
765 | line_info.the_rest = new_rest |
|
764 | line_info.the_rest = new_rest | |
766 | return magic_handler.handle(line_info) |
|
765 | return magic_handler.handle(line_info) | |
767 | else: |
|
766 | else: | |
768 | cmd = line.lstrip().lstrip(ESC_SHELL) |
|
767 | cmd = line.lstrip().lstrip(ESC_SHELL) | |
769 | line_out = '%sget_ipython().system(%r)' % (line_info.pre_whitespace, cmd) |
|
768 | line_out = '%sget_ipython().system(%r)' % (line_info.pre_whitespace, cmd) | |
770 | return line_out |
|
769 | return line_out | |
771 |
|
770 | |||
772 |
|
771 | |||
773 | class MacroHandler(PrefilterHandler): |
|
772 | class MacroHandler(PrefilterHandler): | |
774 | handler_name = Unicode("macro") |
|
773 | handler_name = Unicode("macro") | |
775 |
|
774 | |||
776 | def handle(self, line_info): |
|
775 | def handle(self, line_info): | |
777 | obj = self.shell.user_ns.get(line_info.ifun) |
|
776 | obj = self.shell.user_ns.get(line_info.ifun) | |
778 | pre_space = line_info.pre_whitespace |
|
777 | pre_space = line_info.pre_whitespace | |
779 | line_sep = "\n" + pre_space |
|
778 | line_sep = "\n" + pre_space | |
780 | return pre_space + line_sep.join(obj.value.splitlines()) |
|
779 | return pre_space + line_sep.join(obj.value.splitlines()) | |
781 |
|
780 | |||
782 |
|
781 | |||
783 | class MagicHandler(PrefilterHandler): |
|
782 | class MagicHandler(PrefilterHandler): | |
784 |
|
783 | |||
785 | handler_name = Unicode('magic') |
|
784 | handler_name = Unicode('magic') | |
786 | esc_strings = List([ESC_MAGIC]) |
|
785 | esc_strings = List([ESC_MAGIC]) | |
787 |
|
786 | |||
788 | def handle(self, line_info): |
|
787 | def handle(self, line_info): | |
789 | """Execute magic functions.""" |
|
788 | """Execute magic functions.""" | |
790 | ifun = line_info.ifun |
|
789 | ifun = line_info.ifun | |
791 | the_rest = line_info.the_rest |
|
790 | the_rest = line_info.the_rest | |
792 | cmd = '%sget_ipython().magic(%r)' % (line_info.pre_whitespace, |
|
791 | cmd = '%sget_ipython().magic(%r)' % (line_info.pre_whitespace, | |
793 | (ifun + " " + the_rest)) |
|
792 | (ifun + " " + the_rest)) | |
794 | return cmd |
|
793 | return cmd | |
795 |
|
794 | |||
796 |
|
795 | |||
797 | class AutoHandler(PrefilterHandler): |
|
796 | class AutoHandler(PrefilterHandler): | |
798 |
|
797 | |||
799 | handler_name = Unicode('auto') |
|
798 | handler_name = Unicode('auto') | |
800 | esc_strings = List([ESC_PAREN, ESC_QUOTE, ESC_QUOTE2]) |
|
799 | esc_strings = List([ESC_PAREN, ESC_QUOTE, ESC_QUOTE2]) | |
801 |
|
800 | |||
802 | def handle(self, line_info): |
|
801 | def handle(self, line_info): | |
803 | """Handle lines which can be auto-executed, quoting if requested.""" |
|
802 | """Handle lines which can be auto-executed, quoting if requested.""" | |
804 | line = line_info.line |
|
803 | line = line_info.line | |
805 | ifun = line_info.ifun |
|
804 | ifun = line_info.ifun | |
806 | the_rest = line_info.the_rest |
|
805 | the_rest = line_info.the_rest | |
807 | pre = line_info.pre |
|
806 | pre = line_info.pre | |
808 | esc = line_info.esc |
|
807 | esc = line_info.esc | |
809 | continue_prompt = line_info.continue_prompt |
|
808 | continue_prompt = line_info.continue_prompt | |
810 | obj = line_info.ofind(self.shell)['obj'] |
|
809 | obj = line_info.ofind(self.shell)['obj'] | |
811 | #print 'pre <%s> ifun <%s> rest <%s>' % (pre,ifun,the_rest) # dbg |
|
810 | #print 'pre <%s> ifun <%s> rest <%s>' % (pre,ifun,the_rest) # dbg | |
812 |
|
811 | |||
813 | # This should only be active for single-line input! |
|
812 | # This should only be active for single-line input! | |
814 | if continue_prompt: |
|
813 | if continue_prompt: | |
815 | return line |
|
814 | return line | |
816 |
|
815 | |||
817 | force_auto = isinstance(obj, IPyAutocall) |
|
816 | force_auto = isinstance(obj, IPyAutocall) | |
818 |
|
817 | |||
819 | # User objects sometimes raise exceptions on attribute access other |
|
818 | # User objects sometimes raise exceptions on attribute access other | |
820 | # than AttributeError (we've seen it in the past), so it's safest to be |
|
819 | # than AttributeError (we've seen it in the past), so it's safest to be | |
821 | # ultra-conservative here and catch all. |
|
820 | # ultra-conservative here and catch all. | |
822 | try: |
|
821 | try: | |
823 | auto_rewrite = obj.rewrite |
|
822 | auto_rewrite = obj.rewrite | |
824 | except Exception: |
|
823 | except Exception: | |
825 | auto_rewrite = True |
|
824 | auto_rewrite = True | |
826 |
|
825 | |||
827 | if esc == ESC_QUOTE: |
|
826 | if esc == ESC_QUOTE: | |
828 | # Auto-quote splitting on whitespace |
|
827 | # Auto-quote splitting on whitespace | |
829 | newcmd = '%s("%s")' % (ifun,'", "'.join(the_rest.split()) ) |
|
828 | newcmd = '%s("%s")' % (ifun,'", "'.join(the_rest.split()) ) | |
830 | elif esc == ESC_QUOTE2: |
|
829 | elif esc == ESC_QUOTE2: | |
831 | # Auto-quote whole string |
|
830 | # Auto-quote whole string | |
832 | newcmd = '%s("%s")' % (ifun,the_rest) |
|
831 | newcmd = '%s("%s")' % (ifun,the_rest) | |
833 | elif esc == ESC_PAREN: |
|
832 | elif esc == ESC_PAREN: | |
834 | newcmd = '%s(%s)' % (ifun,",".join(the_rest.split())) |
|
833 | newcmd = '%s(%s)' % (ifun,",".join(the_rest.split())) | |
835 | else: |
|
834 | else: | |
836 | # Auto-paren. |
|
835 | # Auto-paren. | |
837 | if force_auto: |
|
836 | if force_auto: | |
838 | # Don't rewrite if it is already a call. |
|
837 | # Don't rewrite if it is already a call. | |
839 | do_rewrite = not the_rest.startswith('(') |
|
838 | do_rewrite = not the_rest.startswith('(') | |
840 | else: |
|
839 | else: | |
841 | if not the_rest: |
|
840 | if not the_rest: | |
842 | # We only apply it to argument-less calls if the autocall |
|
841 | # We only apply it to argument-less calls if the autocall | |
843 | # parameter is set to 2. |
|
842 | # parameter is set to 2. | |
844 | do_rewrite = (self.shell.autocall >= 2) |
|
843 | do_rewrite = (self.shell.autocall >= 2) | |
845 | elif the_rest.startswith('[') and hasattr(obj, '__getitem__'): |
|
844 | elif the_rest.startswith('[') and hasattr(obj, '__getitem__'): | |
846 | # Don't autocall in this case: item access for an object |
|
845 | # Don't autocall in this case: item access for an object | |
847 | # which is BOTH callable and implements __getitem__. |
|
846 | # which is BOTH callable and implements __getitem__. | |
848 | do_rewrite = False |
|
847 | do_rewrite = False | |
849 | else: |
|
848 | else: | |
850 | do_rewrite = True |
|
849 | do_rewrite = True | |
851 |
|
850 | |||
852 | # Figure out the rewritten command |
|
851 | # Figure out the rewritten command | |
853 | if do_rewrite: |
|
852 | if do_rewrite: | |
854 | if the_rest.endswith(';'): |
|
853 | if the_rest.endswith(';'): | |
855 | newcmd = '%s(%s);' % (ifun.rstrip(),the_rest[:-1]) |
|
854 | newcmd = '%s(%s);' % (ifun.rstrip(),the_rest[:-1]) | |
856 | else: |
|
855 | else: | |
857 | newcmd = '%s(%s)' % (ifun.rstrip(), the_rest) |
|
856 | newcmd = '%s(%s)' % (ifun.rstrip(), the_rest) | |
858 | else: |
|
857 | else: | |
859 | normal_handler = self.prefilter_manager.get_handler_by_name('normal') |
|
858 | normal_handler = self.prefilter_manager.get_handler_by_name('normal') | |
860 | return normal_handler.handle(line_info) |
|
859 | return normal_handler.handle(line_info) | |
861 |
|
860 | |||
862 | # Display the rewritten call |
|
861 | # Display the rewritten call | |
863 | if auto_rewrite: |
|
862 | if auto_rewrite: | |
864 | self.shell.auto_rewrite_input(newcmd) |
|
863 | self.shell.auto_rewrite_input(newcmd) | |
865 |
|
864 | |||
866 | return newcmd |
|
865 | return newcmd | |
867 |
|
866 | |||
868 |
|
867 | |||
869 | class HelpHandler(PrefilterHandler): |
|
868 | class HelpHandler(PrefilterHandler): | |
870 |
|
869 | |||
871 | handler_name = Unicode('help') |
|
870 | handler_name = Unicode('help') | |
872 | esc_strings = List([ESC_HELP]) |
|
871 | esc_strings = List([ESC_HELP]) | |
873 |
|
872 | |||
874 | def handle(self, line_info): |
|
873 | def handle(self, line_info): | |
875 | """Try to get some help for the object. |
|
874 | """Try to get some help for the object. | |
876 |
|
875 | |||
877 | obj? or ?obj -> basic information. |
|
876 | obj? or ?obj -> basic information. | |
878 | obj?? or ??obj -> more details. |
|
877 | obj?? or ??obj -> more details. | |
879 | """ |
|
878 | """ | |
880 | normal_handler = self.prefilter_manager.get_handler_by_name('normal') |
|
879 | normal_handler = self.prefilter_manager.get_handler_by_name('normal') | |
881 | line = line_info.line |
|
880 | line = line_info.line | |
882 | # We need to make sure that we don't process lines which would be |
|
881 | # We need to make sure that we don't process lines which would be | |
883 | # otherwise valid python, such as "x=1 # what?" |
|
882 | # otherwise valid python, such as "x=1 # what?" | |
884 | try: |
|
883 | try: | |
885 | codeop.compile_command(line) |
|
884 | codeop.compile_command(line) | |
886 | except SyntaxError: |
|
885 | except SyntaxError: | |
887 | # We should only handle as help stuff which is NOT valid syntax |
|
886 | # We should only handle as help stuff which is NOT valid syntax | |
888 | if line[0]==ESC_HELP: |
|
887 | if line[0]==ESC_HELP: | |
889 | line = line[1:] |
|
888 | line = line[1:] | |
890 | elif line[-1]==ESC_HELP: |
|
889 | elif line[-1]==ESC_HELP: | |
891 | line = line[:-1] |
|
890 | line = line[:-1] | |
892 | if line: |
|
891 | if line: | |
893 | #print 'line:<%r>' % line # dbg |
|
892 | #print 'line:<%r>' % line # dbg | |
894 | self.shell.magic('pinfo %s' % line_info.ifun) |
|
893 | self.shell.magic('pinfo %s' % line_info.ifun) | |
895 | else: |
|
894 | else: | |
896 | self.shell.show_usage() |
|
895 | self.shell.show_usage() | |
897 | return '' # Empty string is needed here! |
|
896 | return '' # Empty string is needed here! | |
898 | except: |
|
897 | except: | |
899 | raise |
|
898 | raise | |
900 | # Pass any other exceptions through to the normal handler |
|
899 | # Pass any other exceptions through to the normal handler | |
901 | return normal_handler.handle(line_info) |
|
900 | return normal_handler.handle(line_info) | |
902 | else: |
|
901 | else: | |
903 | # If the code compiles ok, we should handle it normally |
|
902 | # If the code compiles ok, we should handle it normally | |
904 | return normal_handler.handle(line_info) |
|
903 | return normal_handler.handle(line_info) | |
905 |
|
904 | |||
906 |
|
905 | |||
907 | class EmacsHandler(PrefilterHandler): |
|
906 | class EmacsHandler(PrefilterHandler): | |
908 |
|
907 | |||
909 | handler_name = Unicode('emacs') |
|
908 | handler_name = Unicode('emacs') | |
910 | esc_strings = List([]) |
|
909 | esc_strings = List([]) | |
911 |
|
910 | |||
912 | def handle(self, line_info): |
|
911 | def handle(self, line_info): | |
913 | """Handle input lines marked by python-mode.""" |
|
912 | """Handle input lines marked by python-mode.""" | |
914 |
|
913 | |||
915 | # Currently, nothing is done. Later more functionality can be added |
|
914 | # Currently, nothing is done. Later more functionality can be added | |
916 | # here if needed. |
|
915 | # here if needed. | |
917 |
|
916 | |||
918 | # The input cache shouldn't be updated |
|
917 | # The input cache shouldn't be updated | |
919 | return line_info.line |
|
918 | return line_info.line | |
920 |
|
919 | |||
921 |
|
920 | |||
922 | #----------------------------------------------------------------------------- |
|
921 | #----------------------------------------------------------------------------- | |
923 | # Defaults |
|
922 | # Defaults | |
924 | #----------------------------------------------------------------------------- |
|
923 | #----------------------------------------------------------------------------- | |
925 |
|
924 | |||
926 |
|
925 | |||
927 | _default_transformers = [ |
|
926 | _default_transformers = [ | |
928 | AssignSystemTransformer, |
|
927 | AssignSystemTransformer, | |
929 | AssignMagicTransformer, |
|
928 | AssignMagicTransformer, | |
930 | PyPromptTransformer, |
|
929 | PyPromptTransformer, | |
931 | IPyPromptTransformer, |
|
930 | IPyPromptTransformer, | |
932 | ] |
|
931 | ] | |
933 |
|
932 | |||
934 | _default_checkers = [ |
|
933 | _default_checkers = [ | |
935 | EmacsChecker, |
|
934 | EmacsChecker, | |
936 | ShellEscapeChecker, |
|
935 | ShellEscapeChecker, | |
937 | MacroChecker, |
|
936 | MacroChecker, | |
938 | IPyAutocallChecker, |
|
937 | IPyAutocallChecker, | |
939 | MultiLineMagicChecker, |
|
938 | MultiLineMagicChecker, | |
940 | EscCharsChecker, |
|
939 | EscCharsChecker, | |
941 | AssignmentChecker, |
|
940 | AssignmentChecker, | |
942 | AutoMagicChecker, |
|
941 | AutoMagicChecker, | |
943 | AliasChecker, |
|
942 | AliasChecker, | |
944 | PythonOpsChecker, |
|
943 | PythonOpsChecker, | |
945 | AutocallChecker |
|
944 | AutocallChecker | |
946 | ] |
|
945 | ] | |
947 |
|
946 | |||
948 | _default_handlers = [ |
|
947 | _default_handlers = [ | |
949 | PrefilterHandler, |
|
948 | PrefilterHandler, | |
950 | AliasHandler, |
|
949 | AliasHandler, | |
951 | ShellEscapeHandler, |
|
950 | ShellEscapeHandler, | |
952 | MacroHandler, |
|
951 | MacroHandler, | |
953 | MagicHandler, |
|
952 | MagicHandler, | |
954 | AutoHandler, |
|
953 | AutoHandler, | |
955 | HelpHandler, |
|
954 | HelpHandler, | |
956 | EmacsHandler |
|
955 | EmacsHandler | |
957 | ] |
|
956 | ] |
@@ -1,271 +1,268 b'' | |||||
1 | """Shell mode for IPython. |
|
1 | """Shell mode for IPython. | |
2 |
|
2 | |||
3 | Start ipython in shell mode by invoking "ipython -p sh" |
|
3 | Start ipython in shell mode by invoking "ipython -p sh" | |
4 |
|
4 | |||
5 | (the old version, "ipython -p pysh" still works but this is the more "modern" |
|
5 | (the old version, "ipython -p pysh" still works but this is the more "modern" | |
6 | shell mode and is recommended for users who don't care about pysh-mode |
|
6 | shell mode and is recommended for users who don't care about pysh-mode | |
7 | compatibility) |
|
7 | compatibility) | |
8 | """ |
|
8 | """ | |
9 |
|
9 | |||
10 | from IPython.core import ipapi |
|
10 | from IPython.core import ipapi | |
11 | from IPython.core.error import TryNext |
|
11 | from IPython.core.error import TryNext | |
12 | import os,re,textwrap |
|
12 | import os,re,textwrap | |
13 |
|
13 | |||
14 | # The import below effectively obsoletes your old-style ipythonrc[.ini], |
|
14 | # The import below effectively obsoletes your old-style ipythonrc[.ini], | |
15 | # so consider yourself warned! |
|
15 | # so consider yourself warned! | |
16 |
|
16 | |||
17 | import ipy_defaults |
|
17 | import ipy_defaults | |
18 |
|
18 | |||
19 | def main(): |
|
19 | def main(): | |
20 | ip = ipapi.get() |
|
20 | ip = ipapi.get() | |
21 | o = ip.options |
|
21 | o = ip.options | |
22 | # autocall to "full" mode (smart mode is default, I like full mode) |
|
22 | # autocall to "full" mode (smart mode is default, I like full mode) | |
23 |
|
23 | |||
24 | o.autocall = 2 |
|
24 | o.autocall = 2 | |
25 |
|
25 | |||
26 | # Jason Orendorff's path class is handy to have in user namespace |
|
26 | # Jason Orendorff's path class is handy to have in user namespace | |
27 | # if you are doing shell-like stuff |
|
27 | # if you are doing shell-like stuff | |
28 | try: |
|
28 | try: | |
29 | ip.ex("from IPython.external.path import path" ) |
|
29 | ip.ex("from IPython.external.path import path" ) | |
30 | except ImportError: |
|
30 | except ImportError: | |
31 | pass |
|
31 | pass | |
32 |
|
32 | |||
33 | # beefed up %env is handy in shell mode |
|
33 | # beefed up %env is handy in shell mode | |
34 | import envpersist |
|
34 | import envpersist | |
35 |
|
35 | |||
36 | # To see where mycmd resides (in path/aliases), do %which mycmd |
|
36 | # To see where mycmd resides (in path/aliases), do %which mycmd | |
37 | import ipy_which |
|
37 | import ipy_which | |
38 |
|
38 | |||
39 | # tab completers for hg, svn, ... |
|
39 | # tab completers for hg, svn, ... | |
40 | import ipy_app_completers |
|
40 | import ipy_app_completers | |
41 |
|
41 | |||
42 | # To make executables foo and bar in mybin usable without PATH change, do: |
|
42 | # To make executables foo and bar in mybin usable without PATH change, do: | |
43 | # %rehashdir c:/mybin |
|
43 | # %rehashdir c:/mybin | |
44 | # %store foo |
|
44 | # %store foo | |
45 | # %store bar |
|
45 | # %store bar | |
46 | import ipy_rehashdir |
|
46 | import ipy_rehashdir | |
47 |
|
47 | |||
48 | # does not work without subprocess module! |
|
48 | # does not work without subprocess module! | |
49 | #import ipy_signals |
|
49 | #import ipy_signals | |
50 |
|
50 | |||
51 | ip.ex('import os') |
|
51 | ip.ex('import os') | |
52 | ip.ex("def up(): os.chdir('..')") |
|
52 | ip.ex("def up(): os.chdir('..')") | |
53 | ip.user_ns['LA'] = LastArgFinder() |
|
53 | ip.user_ns['LA'] = LastArgFinder() | |
54 |
|
54 | |||
55 | # You can assign to _prompt_title variable |
|
55 | # You can assign to _prompt_title variable | |
56 | # to provide some extra information for prompt |
|
56 | # to provide some extra information for prompt | |
57 | # (e.g. the current mode, host/username...) |
|
57 | # (e.g. the current mode, host/username...) | |
58 |
|
58 | |||
59 | ip.user_ns['_prompt_title'] = '' |
|
59 | ip.user_ns['_prompt_title'] = '' | |
60 |
|
60 | |||
61 | # Nice prompt |
|
61 | # Nice prompt | |
62 | o.prompt_in1= r'\C_Green${_prompt_title}\C_LightBlue[\C_LightCyan\Y2\C_LightBlue]\C_Green|\#> ' |
|
62 | o.prompt_in1= r'\C_Green${_prompt_title}\C_LightBlue[\C_LightCyan\Y2\C_LightBlue]\C_Green|\#> ' | |
63 | o.prompt_in2= r'\C_Green|\C_LightGreen\D\C_Green> ' |
|
63 | o.prompt_in2= r'\C_Green|\C_LightGreen\D\C_Green> ' | |
64 | o.prompt_out= '<\#> ' |
|
64 | o.prompt_out= '<\#> ' | |
65 |
|
65 | |||
66 | from IPython.core import release |
|
66 | from IPython.core import release | |
67 |
|
67 | |||
68 | import sys |
|
68 | import sys | |
69 | # Non-chatty banner |
|
69 | # Non-chatty banner | |
70 | o.banner = "IPython %s [on Py %s]\n" % (release.version,sys.version.split(None,1)[0]) |
|
70 | o.banner = "IPython %s [on Py %s]\n" % (release.version,sys.version.split(None,1)[0]) | |
71 |
|
71 | |||
72 |
|
72 | |||
73 | ip.default_option('cd','-q') |
|
73 | ip.default_option('cd','-q') | |
74 | ip.default_option('macro', '-r') |
|
74 | ip.default_option('macro', '-r') | |
75 | # If you only rarely want to execute the things you %edit... |
|
75 | # If you only rarely want to execute the things you %edit... | |
76 | #ip.default_option('edit','-x') |
|
76 | #ip.default_option('edit','-x') | |
77 |
|
77 | |||
78 |
|
78 | |||
79 | o.prompts_pad_left="1" |
|
79 | o.prompts_pad_left="1" | |
80 | # Remove all blank lines in between prompts, like a normal shell. |
|
80 | # Remove all blank lines in between prompts, like a normal shell. | |
81 | o.separate_in="0" |
|
81 | o.separate_in="0" | |
82 | o.separate_out="0" |
|
82 | o.separate_out="0" | |
83 | o.separate_out2="0" |
|
83 | o.separate_out2="0" | |
84 |
|
84 | |||
85 | # now alias all syscommands |
|
85 | # now alias all syscommands | |
86 |
|
86 | |||
87 | db = ip.db |
|
87 | db = ip.db | |
88 |
|
88 | |||
89 | syscmds = db.get("syscmdlist",[] ) |
|
89 | syscmds = db.get("syscmdlist",[] ) | |
90 | if not syscmds: |
|
90 | if not syscmds: | |
91 | print textwrap.dedent(""" |
|
91 | print textwrap.dedent(""" | |
92 | System command list not initialized, probably the first run... |
|
92 | System command list not initialized, probably the first run... | |
93 | running %rehashx to refresh the command list. Run %rehashx |
|
93 | running %rehashx to refresh the command list. Run %rehashx | |
94 | again to refresh command list (after installing new software etc.) |
|
94 | again to refresh command list (after installing new software etc.) | |
95 | """) |
|
95 | """) | |
96 | ip.magic('rehashx') |
|
96 | ip.magic('rehashx') | |
97 | syscmds = db.get("syscmdlist") |
|
97 | syscmds = db.get("syscmdlist") | |
98 |
|
98 | |||
99 | # lowcase aliases on win32 only |
|
99 | # lowcase aliases on win32 only | |
100 | if os.name == 'posix': |
|
100 | if os.name == 'posix': | |
101 | mapper = lambda s:s |
|
101 | mapper = lambda s:s | |
102 | else: |
|
102 | else: | |
103 | def mapper(s): return s.lower() |
|
103 | def mapper(s): return s.lower() | |
104 |
|
104 | |||
105 | for cmd in syscmds: |
|
105 | for cmd in syscmds: | |
106 | # print "sys",cmd #dbg |
|
106 | # print "sys",cmd #dbg | |
107 | noext, ext = os.path.splitext(cmd) |
|
107 | noext, ext = os.path.splitext(cmd) | |
108 | if ext.lower() == '.exe': |
|
108 | if ext.lower() == '.exe': | |
109 | cmd = noext |
|
109 | cmd = noext | |
110 |
|
110 | |||
111 | key = mapper(cmd) |
|
111 | key = mapper(cmd) | |
112 | if key not in ip.alias_manager.alias_table: |
|
112 | if key not in ip.alias_manager.alias_table: | |
113 | # Dots will be removed from alias names, since ipython |
|
113 | # Dots will be removed from alias names, since ipython | |
114 | # assumes names with dots to be python code |
|
114 | # assumes names with dots to be python code | |
115 |
|
115 | |||
116 | ip.define_alias(key.replace('.',''), cmd) |
|
116 | ip.define_alias(key.replace('.',''), cmd) | |
117 |
|
117 | |||
118 | # mglob combines 'find', recursion, exclusion... '%mglob?' to learn more |
|
|||
119 | ip.load("IPython.external.mglob") |
|
|||
120 |
|
||||
121 | # win32 is crippled w/o cygwin, try to help it a little bit |
|
118 | # win32 is crippled w/o cygwin, try to help it a little bit | |
122 | if sys.platform == 'win32': |
|
119 | if sys.platform == 'win32': | |
123 | if 'cygwin' in os.environ['PATH'].lower(): |
|
120 | if 'cygwin' in os.environ['PATH'].lower(): | |
124 | # use the colors of cygwin ls (recommended) |
|
121 | # use the colors of cygwin ls (recommended) | |
125 | ip.define_alias('d', 'ls -F --color=auto') |
|
122 | ip.define_alias('d', 'ls -F --color=auto') | |
126 | else: |
|
123 | else: | |
127 | # get icp, imv, imkdir, igrep, irm,... |
|
124 | # get icp, imv, imkdir, igrep, irm,... | |
128 | ip.load('ipy_fsops') |
|
125 | ip.load('ipy_fsops') | |
129 |
|
126 | |||
130 | # and the next best thing to real 'ls -F' |
|
127 | # and the next best thing to real 'ls -F' | |
131 | ip.define_alias('d','dir /w /og /on') |
|
128 | ip.define_alias('d','dir /w /og /on') | |
132 |
|
129 | |||
133 | ip.set_hook('input_prefilter', slash_prefilter_f) |
|
130 | ip.set_hook('input_prefilter', slash_prefilter_f) | |
134 | extend_shell_behavior(ip) |
|
131 | extend_shell_behavior(ip) | |
135 |
|
132 | |||
136 | class LastArgFinder: |
|
133 | class LastArgFinder: | |
137 | """ Allow $LA to work as "last argument of previous command", like $! in bash |
|
134 | """ Allow $LA to work as "last argument of previous command", like $! in bash | |
138 |
|
135 | |||
139 | To call this in normal IPython code, do LA() |
|
136 | To call this in normal IPython code, do LA() | |
140 | """ |
|
137 | """ | |
141 | def __call__(self, hist_idx = None): |
|
138 | def __call__(self, hist_idx = None): | |
142 | ip = ipapi.get() |
|
139 | ip = ipapi.get() | |
143 | if hist_idx is None: |
|
140 | if hist_idx is None: | |
144 | return str(self) |
|
141 | return str(self) | |
145 | return ip.input_hist_raw[hist_idx].strip().split()[-1] |
|
142 | return ip.input_hist_raw[hist_idx].strip().split()[-1] | |
146 | def __str__(self): |
|
143 | def __str__(self): | |
147 | ip = ipapi.get() |
|
144 | ip = ipapi.get() | |
148 | for cmd in reversed(ip.input_hist_raw): |
|
145 | for cmd in reversed(ip.input_hist_raw): | |
149 | parts = cmd.strip().split() |
|
146 | parts = cmd.strip().split() | |
150 | if len(parts) < 2 or parts[-1] in ['$LA', 'LA()']: |
|
147 | if len(parts) < 2 or parts[-1] in ['$LA', 'LA()']: | |
151 | continue |
|
148 | continue | |
152 | return parts[-1] |
|
149 | return parts[-1] | |
153 | return "" |
|
150 | return "" | |
154 |
|
151 | |||
155 | def slash_prefilter_f(self,line): |
|
152 | def slash_prefilter_f(self,line): | |
156 | """ ./foo, ~/foo and /bin/foo now run foo as system command |
|
153 | """ ./foo, ~/foo and /bin/foo now run foo as system command | |
157 |
|
154 | |||
158 | Removes the need for doing !./foo, !~/foo or !/bin/foo |
|
155 | Removes the need for doing !./foo, !~/foo or !/bin/foo | |
159 | """ |
|
156 | """ | |
160 | from IPython.utils import genutils |
|
157 | from IPython.utils import genutils | |
161 | if re.match('(?:[.~]|/[a-zA-Z_0-9]+)/', line): |
|
158 | if re.match('(?:[.~]|/[a-zA-Z_0-9]+)/', line): | |
162 | return "get_ipython().system(" + genutils.make_quoted_expr(line)+")" |
|
159 | return "get_ipython().system(" + genutils.make_quoted_expr(line)+")" | |
163 | raise TryNext |
|
160 | raise TryNext | |
164 |
|
161 | |||
165 | # XXX You do not need to understand the next function! |
|
162 | # XXX You do not need to understand the next function! | |
166 | # This should probably be moved out of profile |
|
163 | # This should probably be moved out of profile | |
167 |
|
164 | |||
168 | def extend_shell_behavior(ip): |
|
165 | def extend_shell_behavior(ip): | |
169 |
|
166 | |||
170 | # Instead of making signature a global variable tie it to IPSHELL. |
|
167 | # Instead of making signature a global variable tie it to IPSHELL. | |
171 | # In future if it is required to distinguish between different |
|
168 | # In future if it is required to distinguish between different | |
172 | # shells we can assign a signature per shell basis |
|
169 | # shells we can assign a signature per shell basis | |
173 | ip.__sig__ = 0xa005 |
|
170 | ip.__sig__ = 0xa005 | |
174 | # mark the IPSHELL with this signature |
|
171 | # mark the IPSHELL with this signature | |
175 | ip.user_ns['__builtins__'].__dict__['__sig__'] = ip.__sig__ |
|
172 | ip.user_ns['__builtins__'].__dict__['__sig__'] = ip.__sig__ | |
176 |
|
173 | |||
177 | from IPython.external.Itpl import ItplNS |
|
174 | from IPython.external.Itpl import ItplNS | |
178 | from IPython.utils.genutils import shell |
|
175 | from IPython.utils.genutils import shell | |
179 | # utility to expand user variables via Itpl |
|
176 | # utility to expand user variables via Itpl | |
180 | # xxx do something sensible with depth? |
|
177 | # xxx do something sensible with depth? | |
181 | ip.var_expand = lambda cmd, lvars=None, depth=2: \ |
|
178 | ip.var_expand = lambda cmd, lvars=None, depth=2: \ | |
182 | str(ItplNS(cmd, ip.user_ns, get_locals())) |
|
179 | str(ItplNS(cmd, ip.user_ns, get_locals())) | |
183 |
|
180 | |||
184 | def get_locals(): |
|
181 | def get_locals(): | |
185 | """ Substituting a variable through Itpl deep inside the IPSHELL stack |
|
182 | """ Substituting a variable through Itpl deep inside the IPSHELL stack | |
186 | requires the knowledge of all the variables in scope upto the last |
|
183 | requires the knowledge of all the variables in scope upto the last | |
187 | IPSHELL frame. This routine simply merges all the local variables |
|
184 | IPSHELL frame. This routine simply merges all the local variables | |
188 | on the IPSHELL stack without worrying about their scope rules |
|
185 | on the IPSHELL stack without worrying about their scope rules | |
189 | """ |
|
186 | """ | |
190 | import sys |
|
187 | import sys | |
191 | # note lambda expression constitues a function call |
|
188 | # note lambda expression constitues a function call | |
192 | # hence fno should be incremented by one |
|
189 | # hence fno should be incremented by one | |
193 | getsig = lambda fno: sys._getframe(fno+1).f_globals \ |
|
190 | getsig = lambda fno: sys._getframe(fno+1).f_globals \ | |
194 | ['__builtins__'].__dict__['__sig__'] |
|
191 | ['__builtins__'].__dict__['__sig__'] | |
195 | getlvars = lambda fno: sys._getframe(fno+1).f_locals |
|
192 | getlvars = lambda fno: sys._getframe(fno+1).f_locals | |
196 | # trackback until we enter the IPSHELL |
|
193 | # trackback until we enter the IPSHELL | |
197 | frame_no = 1 |
|
194 | frame_no = 1 | |
198 | sig = ip.__sig__ |
|
195 | sig = ip.__sig__ | |
199 | fsig = ~sig |
|
196 | fsig = ~sig | |
200 | while fsig != sig : |
|
197 | while fsig != sig : | |
201 | try: |
|
198 | try: | |
202 | fsig = getsig(frame_no) |
|
199 | fsig = getsig(frame_no) | |
203 | except (AttributeError, KeyError): |
|
200 | except (AttributeError, KeyError): | |
204 | frame_no += 1 |
|
201 | frame_no += 1 | |
205 | except ValueError: |
|
202 | except ValueError: | |
206 | # stack is depleted |
|
203 | # stack is depleted | |
207 | # call did not originate from IPSHELL |
|
204 | # call did not originate from IPSHELL | |
208 | return {} |
|
205 | return {} | |
209 | first_frame = frame_no |
|
206 | first_frame = frame_no | |
210 | # walk further back until we exit from IPSHELL or deplete stack |
|
207 | # walk further back until we exit from IPSHELL or deplete stack | |
211 | try: |
|
208 | try: | |
212 | while(sig == getsig(frame_no+1)): |
|
209 | while(sig == getsig(frame_no+1)): | |
213 | frame_no += 1 |
|
210 | frame_no += 1 | |
214 | except (AttributeError, KeyError, ValueError): |
|
211 | except (AttributeError, KeyError, ValueError): | |
215 | pass |
|
212 | pass | |
216 | # merge the locals from top down hence overriding |
|
213 | # merge the locals from top down hence overriding | |
217 | # any re-definitions of variables, functions etc. |
|
214 | # any re-definitions of variables, functions etc. | |
218 | lvars = {} |
|
215 | lvars = {} | |
219 | for fno in range(frame_no, first_frame-1, -1): |
|
216 | for fno in range(frame_no, first_frame-1, -1): | |
220 | lvars.update(getlvars(fno)) |
|
217 | lvars.update(getlvars(fno)) | |
221 | #print '\n'*5, first_frame, frame_no, '\n', lvars, '\n'*5 #dbg |
|
218 | #print '\n'*5, first_frame, frame_no, '\n', lvars, '\n'*5 #dbg | |
222 | return lvars |
|
219 | return lvars | |
223 |
|
220 | |||
224 | def _runlines(lines): |
|
221 | def _runlines(lines): | |
225 | """Run a string of one or more lines of source. |
|
222 | """Run a string of one or more lines of source. | |
226 |
|
223 | |||
227 | This method is capable of running a string containing multiple source |
|
224 | This method is capable of running a string containing multiple source | |
228 | lines, as if they had been entered at the IPython prompt. Since it |
|
225 | lines, as if they had been entered at the IPython prompt. Since it | |
229 | exposes IPython's processing machinery, the given strings can contain |
|
226 | exposes IPython's processing machinery, the given strings can contain | |
230 | magic calls (%magic), special shell access (!cmd), etc.""" |
|
227 | magic calls (%magic), special shell access (!cmd), etc.""" | |
231 |
|
228 | |||
232 | # We must start with a clean buffer, in case this is run from an |
|
229 | # We must start with a clean buffer, in case this is run from an | |
233 | # interactive IPython session (via a magic, for example). |
|
230 | # interactive IPython session (via a magic, for example). | |
234 | ip.resetbuffer() |
|
231 | ip.resetbuffer() | |
235 | lines = lines.split('\n') |
|
232 | lines = lines.split('\n') | |
236 | more = 0 |
|
233 | more = 0 | |
237 | command = '' |
|
234 | command = '' | |
238 | for line in lines: |
|
235 | for line in lines: | |
239 | # skip blank lines so we don't mess up the prompt counter, but do |
|
236 | # skip blank lines so we don't mess up the prompt counter, but do | |
240 | # NOT skip even a blank line if we are in a code block (more is |
|
237 | # NOT skip even a blank line if we are in a code block (more is | |
241 | # true) |
|
238 | # true) | |
242 | # if command is not empty trim the line |
|
239 | # if command is not empty trim the line | |
243 | if command != '' : |
|
240 | if command != '' : | |
244 | line = line.strip() |
|
241 | line = line.strip() | |
245 | # add the broken line to the command |
|
242 | # add the broken line to the command | |
246 | if line and line[-1] == '\\' : |
|
243 | if line and line[-1] == '\\' : | |
247 | command += line[0:-1] + ' ' |
|
244 | command += line[0:-1] + ' ' | |
248 | more = True |
|
245 | more = True | |
249 | continue |
|
246 | continue | |
250 | else : |
|
247 | else : | |
251 | # add the last (current) line to the command |
|
248 | # add the last (current) line to the command | |
252 | command += line |
|
249 | command += line | |
253 | if command or more: |
|
250 | if command or more: | |
254 | # push to raw history, so hist line numbers stay in sync |
|
251 | # push to raw history, so hist line numbers stay in sync | |
255 | ip.input_hist_raw.append("# " + command + "\n") |
|
252 | ip.input_hist_raw.append("# " + command + "\n") | |
256 |
|
253 | |||
257 | more = ip.push_line(ip.prefilter(command,more)) |
|
254 | more = ip.push_line(ip.prefilter(command,more)) | |
258 | command = '' |
|
255 | command = '' | |
259 | # IPython's runsource returns None if there was an error |
|
256 | # IPython's runsource returns None if there was an error | |
260 | # compiling the code. This allows us to stop processing right |
|
257 | # compiling the code. This allows us to stop processing right | |
261 | # away, so the user gets the error message at the right place. |
|
258 | # away, so the user gets the error message at the right place. | |
262 | if more is None: |
|
259 | if more is None: | |
263 | break |
|
260 | break | |
264 | # final newline in case the input didn't have it, so that the code |
|
261 | # final newline in case the input didn't have it, so that the code | |
265 | # actually does get executed |
|
262 | # actually does get executed | |
266 | if more: |
|
263 | if more: | |
267 | ip.push_line('\n') |
|
264 | ip.push_line('\n') | |
268 |
|
265 | |||
269 | ip.runlines = _runlines |
|
266 | ip.runlines = _runlines | |
270 |
|
267 | |||
271 | main() |
|
268 | main() |
@@ -1,246 +1,254 b'' | |||||
1 | """ File system operations |
|
1 | """ File system operations | |
2 |
|
2 | |||
3 | Contains: Simple variants of normal unix shell commands (icp, imv, irm, |
|
3 | Contains: Simple variants of normal unix shell commands (icp, imv, irm, | |
4 | imkdir, igrep). |
|
4 | imkdir, igrep). | |
5 |
|
5 | |||
6 | Some "otherwise handy" utils ('collect' for gathering files to |
|
6 | Some "otherwise handy" utils ('collect' for gathering files to | |
7 | ~/_ipython/collect, 'inote' for collecting single note lines to |
|
7 | ~/_ipython/collect, 'inote' for collecting single note lines to | |
8 | ~/_ipython/note.txt) |
|
8 | ~/_ipython/note.txt) | |
9 |
|
9 | |||
10 | Mostly of use for bare windows installations where cygwin/equivalent is not |
|
10 | Mostly of use for bare windows installations where cygwin/equivalent is not | |
11 | installed and you would otherwise need to deal with dos versions of the |
|
11 | installed and you would otherwise need to deal with dos versions of the | |
12 | commands (that e.g. don't understand / as path separator). These can |
|
12 | commands (that e.g. don't understand / as path separator). These can | |
13 | do some useful tricks on their own, though (like use 'mglob' patterns). |
|
13 | do some useful tricks on their own, though (like use 'mglob' patterns). | |
14 |
|
14 | |||
15 | Not to be confused with ipipe commands (ils etc.) that also start with i. |
|
15 | Not to be confused with ipipe commands (ils etc.) that also start with i. | |
|
16 | ||||
|
17 | QUARANTINE, NEEDS UPDATING TO THE NEW IPYTHON API TO WORK | |||
|
18 | ||||
|
19 | this depends on mglob that used to be in externals, | |||
|
20 | if this code is updated to run again with current IPython, you may need to | |||
|
21 | reintroduce that file back. In doing so, look for the possibility of achieving | |||
|
22 | the same effect only with the standard library (which may have improved by now, | |||
|
23 | since we currently depend on Python 2.6). | |||
16 | """ |
|
24 | """ | |
17 |
|
25 | |||
18 | from IPython.core import ipapi |
|
26 | from IPython.core import ipapi | |
19 | from IPython.core.error import TryNext |
|
27 | from IPython.core.error import TryNext | |
20 | ip = ipapi.get() |
|
28 | ip = ipapi.get() | |
21 |
|
29 | |||
22 | import shutil,os,shlex |
|
30 | import shutil,os,shlex | |
23 | from IPython.external import mglob |
|
31 | from IPython.external import mglob | |
24 | from IPython.external.path import path |
|
32 | from IPython.external.path import path | |
25 | from IPython.core.error import UsageError |
|
33 | from IPython.core.error import UsageError | |
26 | import IPython.utils.generics |
|
34 | import IPython.utils.generics | |
27 |
|
35 | |||
28 | def parse_args(args): |
|
36 | def parse_args(args): | |
29 | """ Given arg string 'CMD files... target', return ([files], target) """ |
|
37 | """ Given arg string 'CMD files... target', return ([files], target) """ | |
30 |
|
38 | |||
31 | tup = args.split(None, 1) |
|
39 | tup = args.split(None, 1) | |
32 | if len(tup) == 1: |
|
40 | if len(tup) == 1: | |
33 | raise UsageError("Expected arguments for " + tup[0]) |
|
41 | raise UsageError("Expected arguments for " + tup[0]) | |
34 |
|
42 | |||
35 | tup2 = shlex.split(tup[1]) |
|
43 | tup2 = shlex.split(tup[1]) | |
36 |
|
44 | |||
37 | flist, trg = mglob.expand(tup2[0:-1]), tup2[-1] |
|
45 | flist, trg = mglob.expand(tup2[0:-1]), tup2[-1] | |
38 | if not flist: |
|
46 | if not flist: | |
39 | raise UsageError("No files found:" + str(tup2[0:-1])) |
|
47 | raise UsageError("No files found:" + str(tup2[0:-1])) | |
40 | return flist, trg |
|
48 | return flist, trg | |
41 |
|
49 | |||
42 | def icp(ip,arg): |
|
50 | def icp(ip,arg): | |
43 | """ icp files... targetdir |
|
51 | """ icp files... targetdir | |
44 |
|
52 | |||
45 | Copy all files to target, creating dirs for target if necessary |
|
53 | Copy all files to target, creating dirs for target if necessary | |
46 |
|
54 | |||
47 | icp srcdir dstdir |
|
55 | icp srcdir dstdir | |
48 |
|
56 | |||
49 | Copy srcdir to distdir |
|
57 | Copy srcdir to distdir | |
50 |
|
58 | |||
51 | """ |
|
59 | """ | |
52 | import distutils.dir_util |
|
60 | import distutils.dir_util | |
53 |
|
61 | |||
54 | fs, targetdir = parse_args(arg) |
|
62 | fs, targetdir = parse_args(arg) | |
55 | if not os.path.isdir(targetdir) and len(fs) > 1: |
|
63 | if not os.path.isdir(targetdir) and len(fs) > 1: | |
56 | distutils.dir_util.mkpath(targetdir,verbose =1) |
|
64 | distutils.dir_util.mkpath(targetdir,verbose =1) | |
57 | for f in fs: |
|
65 | for f in fs: | |
58 | if os.path.isdir(f): |
|
66 | if os.path.isdir(f): | |
59 | shutil.copytree(f, targetdir) |
|
67 | shutil.copytree(f, targetdir) | |
60 | else: |
|
68 | else: | |
61 | shutil.copy2(f,targetdir) |
|
69 | shutil.copy2(f,targetdir) | |
62 | return fs |
|
70 | return fs | |
63 | ip.define_alias("icp",icp) |
|
71 | ip.define_alias("icp",icp) | |
64 |
|
72 | |||
65 | def imv(ip,arg): |
|
73 | def imv(ip,arg): | |
66 | """ imv src tgt |
|
74 | """ imv src tgt | |
67 |
|
75 | |||
68 | Move source to target. |
|
76 | Move source to target. | |
69 | """ |
|
77 | """ | |
70 |
|
78 | |||
71 | fs, target = parse_args(arg) |
|
79 | fs, target = parse_args(arg) | |
72 | if len(fs) > 1: |
|
80 | if len(fs) > 1: | |
73 | assert os.path.isdir(target) |
|
81 | assert os.path.isdir(target) | |
74 | for f in fs: |
|
82 | for f in fs: | |
75 | shutil.move(f, target) |
|
83 | shutil.move(f, target) | |
76 | return fs |
|
84 | return fs | |
77 | ip.define_alias("imv",imv) |
|
85 | ip.define_alias("imv",imv) | |
78 |
|
86 | |||
79 | def irm(ip,arg): |
|
87 | def irm(ip,arg): | |
80 | """ irm path[s]... |
|
88 | """ irm path[s]... | |
81 |
|
89 | |||
82 | Remove file[s] or dir[s] path. Dirs are deleted recursively. |
|
90 | Remove file[s] or dir[s] path. Dirs are deleted recursively. | |
83 | """ |
|
91 | """ | |
84 | try: |
|
92 | try: | |
85 | paths = mglob.expand(arg.split(None,1)[1]) |
|
93 | paths = mglob.expand(arg.split(None,1)[1]) | |
86 | except IndexError: |
|
94 | except IndexError: | |
87 | raise UsageError("%irm paths...") |
|
95 | raise UsageError("%irm paths...") | |
88 | import distutils.dir_util |
|
96 | import distutils.dir_util | |
89 | for p in paths: |
|
97 | for p in paths: | |
90 | print "rm",p |
|
98 | print "rm",p | |
91 | if os.path.isdir(p): |
|
99 | if os.path.isdir(p): | |
92 | distutils.dir_util.remove_tree(p, verbose = 1) |
|
100 | distutils.dir_util.remove_tree(p, verbose = 1) | |
93 | else: |
|
101 | else: | |
94 | os.remove(p) |
|
102 | os.remove(p) | |
95 |
|
103 | |||
96 | ip.define_alias("irm",irm) |
|
104 | ip.define_alias("irm",irm) | |
97 |
|
105 | |||
98 | def imkdir(ip,arg): |
|
106 | def imkdir(ip,arg): | |
99 | """ imkdir path |
|
107 | """ imkdir path | |
100 |
|
108 | |||
101 | Creates dir path, and all dirs on the road |
|
109 | Creates dir path, and all dirs on the road | |
102 | """ |
|
110 | """ | |
103 | import distutils.dir_util |
|
111 | import distutils.dir_util | |
104 | targetdir = arg.split(None,1)[1] |
|
112 | targetdir = arg.split(None,1)[1] | |
105 | distutils.dir_util.mkpath(targetdir,verbose =1) |
|
113 | distutils.dir_util.mkpath(targetdir,verbose =1) | |
106 |
|
114 | |||
107 | ip.define_alias("imkdir",imkdir) |
|
115 | ip.define_alias("imkdir",imkdir) | |
108 |
|
116 | |||
109 | def igrep(ip,arg): |
|
117 | def igrep(ip,arg): | |
110 | """ igrep PAT files... |
|
118 | """ igrep PAT files... | |
111 |
|
119 | |||
112 | Very dumb file scan, case-insensitive. |
|
120 | Very dumb file scan, case-insensitive. | |
113 |
|
121 | |||
114 | e.g. |
|
122 | e.g. | |
115 |
|
123 | |||
116 | igrep "test this" rec:*.py |
|
124 | igrep "test this" rec:*.py | |
117 |
|
125 | |||
118 | """ |
|
126 | """ | |
119 | elems = shlex.split(arg) |
|
127 | elems = shlex.split(arg) | |
120 | dummy, pat, fs = elems[0], elems[1], mglob.expand(elems[2:]) |
|
128 | dummy, pat, fs = elems[0], elems[1], mglob.expand(elems[2:]) | |
121 | res = [] |
|
129 | res = [] | |
122 | for f in fs: |
|
130 | for f in fs: | |
123 | found = False |
|
131 | found = False | |
124 | for l in open(f): |
|
132 | for l in open(f): | |
125 | if pat.lower() in l.lower(): |
|
133 | if pat.lower() in l.lower(): | |
126 | if not found: |
|
134 | if not found: | |
127 | print "[[",f,"]]" |
|
135 | print "[[",f,"]]" | |
128 | found = True |
|
136 | found = True | |
129 | res.append(f) |
|
137 | res.append(f) | |
130 | print l.rstrip() |
|
138 | print l.rstrip() | |
131 | return res |
|
139 | return res | |
132 |
|
140 | |||
133 | ip.define_alias("igrep",igrep) |
|
141 | ip.define_alias("igrep",igrep) | |
134 |
|
142 | |||
135 | def collect(ip,arg): |
|
143 | def collect(ip,arg): | |
136 | """ collect foo/a.txt rec:bar=*.py |
|
144 | """ collect foo/a.txt rec:bar=*.py | |
137 |
|
145 | |||
138 | Copies foo/a.txt to ~/_ipython/collect/foo/a.txt and *.py from bar, |
|
146 | Copies foo/a.txt to ~/_ipython/collect/foo/a.txt and *.py from bar, | |
139 | likewise |
|
147 | likewise | |
140 |
|
148 | |||
141 | Without args, try to open ~/_ipython/collect dir (in win32 at least). |
|
149 | Without args, try to open ~/_ipython/collect dir (in win32 at least). | |
142 | """ |
|
150 | """ | |
143 | from IPython.external.path import path |
|
151 | from IPython.external.path import path | |
144 | basedir = path(ip.ipython_dir + '/collect') |
|
152 | basedir = path(ip.ipython_dir + '/collect') | |
145 | try: |
|
153 | try: | |
146 | fs = mglob.expand(arg.split(None,1)[1]) |
|
154 | fs = mglob.expand(arg.split(None,1)[1]) | |
147 | except IndexError: |
|
155 | except IndexError: | |
148 | os.startfile(basedir) |
|
156 | os.startfile(basedir) | |
149 | return |
|
157 | return | |
150 | for f in fs: |
|
158 | for f in fs: | |
151 | f = path(f) |
|
159 | f = path(f) | |
152 | trg = basedir / f.splitdrive()[1].lstrip('/\\') |
|
160 | trg = basedir / f.splitdrive()[1].lstrip('/\\') | |
153 | if f.isdir(): |
|
161 | if f.isdir(): | |
154 | print "mkdir",trg |
|
162 | print "mkdir",trg | |
155 | trg.makedirs() |
|
163 | trg.makedirs() | |
156 | continue |
|
164 | continue | |
157 | dname = trg.dirname() |
|
165 | dname = trg.dirname() | |
158 | if not dname.isdir(): |
|
166 | if not dname.isdir(): | |
159 | dname.makedirs() |
|
167 | dname.makedirs() | |
160 | print f,"=>",trg |
|
168 | print f,"=>",trg | |
161 | shutil.copy2(f,trg) |
|
169 | shutil.copy2(f,trg) | |
162 |
|
170 | |||
163 | ip.define_alias("collect",collect) |
|
171 | ip.define_alias("collect",collect) | |
164 |
|
172 | |||
165 | def inote(ip,arg): |
|
173 | def inote(ip,arg): | |
166 | """ inote Hello world |
|
174 | """ inote Hello world | |
167 |
|
175 | |||
168 | Adds timestamp and Hello world to ~/_ipython/notes.txt |
|
176 | Adds timestamp and Hello world to ~/_ipython/notes.txt | |
169 |
|
177 | |||
170 | Without args, opens notes.txt for editing. |
|
178 | Without args, opens notes.txt for editing. | |
171 | """ |
|
179 | """ | |
172 | import time |
|
180 | import time | |
173 | fname = ip.ipython_dir + '/notes.txt' |
|
181 | fname = ip.ipython_dir + '/notes.txt' | |
174 |
|
182 | |||
175 | try: |
|
183 | try: | |
176 | entry = " === " + time.asctime() + ': ===\n' + arg.split(None,1)[1] + '\n' |
|
184 | entry = " === " + time.asctime() + ': ===\n' + arg.split(None,1)[1] + '\n' | |
177 | f= open(fname, 'a').write(entry) |
|
185 | f= open(fname, 'a').write(entry) | |
178 | except IndexError: |
|
186 | except IndexError: | |
179 | ip.hooks.editor(fname) |
|
187 | ip.hooks.editor(fname) | |
180 |
|
188 | |||
181 | ip.define_alias("inote",inote) |
|
189 | ip.define_alias("inote",inote) | |
182 |
|
190 | |||
183 | def pathobj_mangle(p): |
|
191 | def pathobj_mangle(p): | |
184 | return p.replace(' ', '__').replace('.','DOT') |
|
192 | return p.replace(' ', '__').replace('.','DOT') | |
185 | def pathobj_unmangle(s): |
|
193 | def pathobj_unmangle(s): | |
186 | return s.replace('__',' ').replace('DOT','.') |
|
194 | return s.replace('__',' ').replace('DOT','.') | |
187 |
|
195 | |||
188 |
|
196 | |||
189 |
|
197 | |||
190 | class PathObj(path): |
|
198 | class PathObj(path): | |
191 | def __init__(self,p): |
|
199 | def __init__(self,p): | |
192 | self.path = p |
|
200 | self.path = p | |
193 | if p != '.': |
|
201 | if p != '.': | |
194 | self.ents = [pathobj_mangle(ent) for ent in os.listdir(p)] |
|
202 | self.ents = [pathobj_mangle(ent) for ent in os.listdir(p)] | |
195 | else: |
|
203 | else: | |
196 | self.ents = None |
|
204 | self.ents = None | |
197 | def __complete__(self): |
|
205 | def __complete__(self): | |
198 | if self.path != '.': |
|
206 | if self.path != '.': | |
199 | return self.ents |
|
207 | return self.ents | |
200 | self.ents = [pathobj_mangle(ent) for ent in os.listdir('.')] |
|
208 | self.ents = [pathobj_mangle(ent) for ent in os.listdir('.')] | |
201 | return self.ents |
|
209 | return self.ents | |
202 | def __getattr__(self,name): |
|
210 | def __getattr__(self,name): | |
203 | if name in self.ents: |
|
211 | if name in self.ents: | |
204 | if self.path.endswith('/'): |
|
212 | if self.path.endswith('/'): | |
205 | sep = '' |
|
213 | sep = '' | |
206 | else: |
|
214 | else: | |
207 | sep = '/' |
|
215 | sep = '/' | |
208 |
|
216 | |||
209 | tgt = self.path + sep + pathobj_unmangle(name) |
|
217 | tgt = self.path + sep + pathobj_unmangle(name) | |
210 | #print "tgt",tgt |
|
218 | #print "tgt",tgt | |
211 | if os.path.isdir(tgt): |
|
219 | if os.path.isdir(tgt): | |
212 | return PathObj(tgt) |
|
220 | return PathObj(tgt) | |
213 | if os.path.isfile(tgt): |
|
221 | if os.path.isfile(tgt): | |
214 | return path(tgt) |
|
222 | return path(tgt) | |
215 |
|
223 | |||
216 | raise AttributeError, name # <<< DON'T FORGET THIS LINE !! |
|
224 | raise AttributeError, name # <<< DON'T FORGET THIS LINE !! | |
217 | def __str__(self): |
|
225 | def __str__(self): | |
218 | return self.path |
|
226 | return self.path | |
219 |
|
227 | |||
220 | def __repr__(self): |
|
228 | def __repr__(self): | |
221 | return "<PathObj to %s>" % self.path |
|
229 | return "<PathObj to %s>" % self.path | |
222 |
|
230 | |||
223 | def __call__(self): |
|
231 | def __call__(self): | |
224 | print "cd:",self.path |
|
232 | print "cd:",self.path | |
225 | os.chdir(self.path) |
|
233 | os.chdir(self.path) | |
226 |
|
234 | |||
227 | def complete_pathobj(obj, prev_completions): |
|
235 | def complete_pathobj(obj, prev_completions): | |
228 | if hasattr(obj,'__complete__'): |
|
236 | if hasattr(obj,'__complete__'): | |
229 | res = obj.__complete__() |
|
237 | res = obj.__complete__() | |
230 | if res: |
|
238 | if res: | |
231 | return res |
|
239 | return res | |
232 | # just return normal attributes of 'path' object if the dir is empty |
|
240 | # just return normal attributes of 'path' object if the dir is empty | |
233 | raise TryNext |
|
241 | raise TryNext | |
234 |
|
242 | |||
235 | complete_pathobj = IPython.utils.generics.complete_object.when_type(PathObj)(complete_pathobj) |
|
243 | complete_pathobj = IPython.utils.generics.complete_object.when_type(PathObj)(complete_pathobj) | |
236 |
|
244 | |||
237 | def test_pathobj(): |
|
245 | def test_pathobj(): | |
238 | #p = PathObj('c:/prj') |
|
246 | #p = PathObj('c:/prj') | |
239 | #p2 = p.cgi |
|
247 | #p2 = p.cgi | |
240 | #print p,p2 |
|
248 | #print p,p2 | |
241 | rootdir = PathObj("/") |
|
249 | rootdir = PathObj("/") | |
242 | startmenu = PathObj("d:/Documents and Settings/All Users/Start Menu/Programs") |
|
250 | startmenu = PathObj("d:/Documents and Settings/All Users/Start Menu/Programs") | |
243 | cwd = PathObj('.') |
|
251 | cwd = PathObj('.') | |
244 | ip.push("rootdir startmenu cwd") |
|
252 | ip.push("rootdir startmenu cwd") | |
245 |
|
253 | |||
246 | #test_pathobj() No newline at end of file |
|
254 | #test_pathobj() |
@@ -1,294 +1,283 b'' | |||||
1 | .. _ipython_as_shell: |
|
1 | .. _ipython_as_shell: | |
2 |
|
2 | |||
3 | ========================= |
|
3 | ========================= | |
4 | IPython as a system shell |
|
4 | IPython as a system shell | |
5 | ========================= |
|
5 | ========================= | |
6 |
|
6 | |||
7 | .. warning:: |
|
7 | .. warning:: | |
8 |
|
8 | |||
9 | As of the 0.11 version of IPython, most of the APIs used by the shell |
|
9 | As of the 0.11 version of IPython, most of the APIs used by the shell | |
10 | profile have been changed, so the profile currently does very little |
|
10 | profile have been changed, so the profile currently does very little | |
11 | beyond changing the IPython prompt. To help restore the shell |
|
11 | beyond changing the IPython prompt. To help restore the shell | |
12 | profile to past functionality described here, the old code is found in |
|
12 | profile to past functionality described here, the old code is found in | |
13 | :file:`IPython/deathrow`, which needs to be updated to use the |
|
13 | :file:`IPython/deathrow`, which needs to be updated to use the | |
14 | APIs in 0.11. |
|
14 | APIs in 0.11. | |
15 |
|
15 | |||
16 | Overview |
|
16 | Overview | |
17 | ======== |
|
17 | ======== | |
18 |
|
18 | |||
19 | The 'sh' profile optimizes IPython for system shell usage. Apart from |
|
19 | The 'sh' profile optimizes IPython for system shell usage. Apart from | |
20 | certain job control functionality that is present in unix (ctrl+z does |
|
20 | certain job control functionality that is present in unix (ctrl+z does | |
21 | "suspend"), the sh profile should provide you with most of the |
|
21 | "suspend"), the sh profile should provide you with most of the | |
22 | functionality you use daily in system shell, and more. Invoke IPython |
|
22 | functionality you use daily in system shell, and more. Invoke IPython | |
23 | in 'sh' profile by doing 'ipython -p sh', or (in win32) by launching |
|
23 | in 'sh' profile by doing 'ipython -p sh', or (in win32) by launching | |
24 | the "pysh" shortcut in start menu. |
|
24 | the "pysh" shortcut in start menu. | |
25 |
|
25 | |||
26 | If you want to use the features of sh profile as your defaults (which |
|
26 | If you want to use the features of sh profile as your defaults (which | |
27 | might be a good idea if you use other profiles a lot of the time but |
|
27 | might be a good idea if you use other profiles a lot of the time but | |
28 | still want the convenience of sh profile), add ``import ipy_profile_sh`` |
|
28 | still want the convenience of sh profile), add ``import ipy_profile_sh`` | |
29 | to your $IPYTHONDIR/ipy_user_conf.py. |
|
29 | to your $IPYTHONDIR/ipy_user_conf.py. | |
30 |
|
30 | |||
31 | The 'sh' profile is different from the default profile in that: |
|
31 | The 'sh' profile is different from the default profile in that: | |
32 |
|
32 | |||
33 | * Prompt shows the current directory |
|
33 | * Prompt shows the current directory | |
34 | * Spacing between prompts and input is more compact (no padding with |
|
34 | * Spacing between prompts and input is more compact (no padding with | |
35 | empty lines). The startup banner is more compact as well. |
|
35 | empty lines). The startup banner is more compact as well. | |
36 | * System commands are directly available (in alias table) without |
|
36 | * System commands are directly available (in alias table) without | |
37 | requesting %rehashx - however, if you install new programs along |
|
37 | requesting %rehashx - however, if you install new programs along | |
38 | your PATH, you might want to run %rehashx to update the persistent |
|
38 | your PATH, you might want to run %rehashx to update the persistent | |
39 | alias table |
|
39 | alias table | |
40 | * Macros are stored in raw format by default. That is, instead of |
|
40 | * Macros are stored in raw format by default. That is, instead of | |
41 | '_ip.system("cat foo"), the macro will contain text 'cat foo') |
|
41 | '_ip.system("cat foo"), the macro will contain text 'cat foo') | |
42 | * Autocall is in full mode |
|
42 | * Autocall is in full mode | |
43 | * Calling "up" does "cd .." |
|
43 | * Calling "up" does "cd .." | |
44 |
|
44 | |||
45 | The 'sh' profile is different from the now-obsolete (and unavailable) |
|
45 | The 'sh' profile is different from the now-obsolete (and unavailable) | |
46 | 'pysh' profile in that the ``$$var = command`` and ``$var = command`` syntax is |
|
46 | 'pysh' profile in that the ``$$var = command`` and ``$var = command`` syntax is | |
47 | not supported anymore. Use ``var = !command`` instead (which is available in all |
|
47 | not supported anymore. Use ``var = !command`` instead (which is available in all | |
48 | IPython profiles). |
|
48 | IPython profiles). | |
49 |
|
49 | |||
50 | Aliases |
|
50 | Aliases | |
51 | ======= |
|
51 | ======= | |
52 |
|
52 | |||
53 | All of your $PATH has been loaded as IPython aliases, so you should be |
|
53 | All of your $PATH has been loaded as IPython aliases, so you should be | |
54 | able to type any normal system command and have it executed. See |
|
54 | able to type any normal system command and have it executed. See | |
55 | %alias? and %unalias? for details on the alias facilities. See also |
|
55 | %alias? and %unalias? for details on the alias facilities. See also | |
56 | %rehashx? for details on the mechanism used to load $PATH. |
|
56 | %rehashx? for details on the mechanism used to load $PATH. | |
57 |
|
57 | |||
58 |
|
58 | |||
59 | Directory management |
|
59 | Directory management | |
60 | ==================== |
|
60 | ==================== | |
61 |
|
61 | |||
62 | Since each command passed by ipython to the underlying system is executed |
|
62 | Since each command passed by ipython to the underlying system is executed | |
63 | in a subshell which exits immediately, you can NOT use !cd to navigate |
|
63 | in a subshell which exits immediately, you can NOT use !cd to navigate | |
64 | the filesystem. |
|
64 | the filesystem. | |
65 |
|
65 | |||
66 | IPython provides its own builtin '%cd' magic command to move in the |
|
66 | IPython provides its own builtin '%cd' magic command to move in the | |
67 | filesystem (the % is not required with automagic on). It also maintains |
|
67 | filesystem (the % is not required with automagic on). It also maintains | |
68 | a list of visited directories (use %dhist to see it) and allows direct |
|
68 | a list of visited directories (use %dhist to see it) and allows direct | |
69 | switching to any of them. Type 'cd?' for more details. |
|
69 | switching to any of them. Type 'cd?' for more details. | |
70 |
|
70 | |||
71 | %pushd, %popd and %dirs are provided for directory stack handling. |
|
71 | %pushd, %popd and %dirs are provided for directory stack handling. | |
72 |
|
72 | |||
73 |
|
73 | |||
74 | Enabled extensions |
|
74 | Enabled extensions | |
75 | ================== |
|
75 | ================== | |
76 |
|
76 | |||
77 | Some extensions, listed below, are enabled as default in this profile. |
|
77 | Some extensions, listed below, are enabled as default in this profile. | |
78 |
|
78 | |||
79 | envpersist |
|
79 | envpersist | |
80 | ---------- |
|
80 | ---------- | |
81 |
|
81 | |||
82 | %env can be used to "remember" environment variable manipulations. Examples:: |
|
82 | %env can be used to "remember" environment variable manipulations. Examples:: | |
83 |
|
83 | |||
84 | %env - Show all environment variables |
|
84 | %env - Show all environment variables | |
85 | %env VISUAL=jed - set VISUAL to jed |
|
85 | %env VISUAL=jed - set VISUAL to jed | |
86 | %env PATH+=;/foo - append ;foo to PATH |
|
86 | %env PATH+=;/foo - append ;foo to PATH | |
87 | %env PATH+=;/bar - also append ;bar to PATH |
|
87 | %env PATH+=;/bar - also append ;bar to PATH | |
88 | %env PATH-=/wbin; - prepend /wbin; to PATH |
|
88 | %env PATH-=/wbin; - prepend /wbin; to PATH | |
89 | %env -d VISUAL - forget VISUAL persistent val |
|
89 | %env -d VISUAL - forget VISUAL persistent val | |
90 | %env -p - print all persistent env modifications |
|
90 | %env -p - print all persistent env modifications | |
91 |
|
91 | |||
92 | ipy_which |
|
92 | ipy_which | |
93 | --------- |
|
93 | --------- | |
94 |
|
94 | |||
95 | %which magic command. Like 'which' in unix, but knows about ipython aliases. |
|
95 | %which magic command. Like 'which' in unix, but knows about ipython aliases. | |
96 |
|
96 | |||
97 | Example:: |
|
97 | Example:: | |
98 |
|
98 | |||
99 | [C:/ipython]|14> %which st |
|
99 | [C:/ipython]|14> %which st | |
100 | st -> start . |
|
100 | st -> start . | |
101 | [C:/ipython]|15> %which d |
|
101 | [C:/ipython]|15> %which d | |
102 | d -> dir /w /og /on |
|
102 | d -> dir /w /og /on | |
103 | [C:/ipython]|16> %which cp |
|
103 | [C:/ipython]|16> %which cp | |
104 | cp -> cp |
|
104 | cp -> cp | |
105 | == c:\bin\cp.exe |
|
105 | == c:\bin\cp.exe | |
106 | c:\bin\cp.exe |
|
106 | c:\bin\cp.exe | |
107 |
|
107 | |||
108 | ipy_app_completers |
|
108 | ipy_app_completers | |
109 | ------------------ |
|
109 | ------------------ | |
110 |
|
110 | |||
111 | Custom tab completers for some apps like svn, hg, bzr, apt-get. Try 'apt-get install <TAB>' in debian/ubuntu. |
|
111 | Custom tab completers for some apps like svn, hg, bzr, apt-get. Try 'apt-get install <TAB>' in debian/ubuntu. | |
112 |
|
112 | |||
113 | ipy_rehashdir |
|
113 | ipy_rehashdir | |
114 | ------------- |
|
114 | ------------- | |
115 |
|
115 | |||
116 | Allows you to add system command aliases for commands that are not along your path. Let's say that you just installed Putty and want to be able to invoke it without adding it to path, you can create the alias for it with rehashdir:: |
|
116 | Allows you to add system command aliases for commands that are not along your path. Let's say that you just installed Putty and want to be able to invoke it without adding it to path, you can create the alias for it with rehashdir:: | |
117 |
|
117 | |||
118 | [~]|22> cd c:/opt/PuTTY/ |
|
118 | [~]|22> cd c:/opt/PuTTY/ | |
119 | [c:opt/PuTTY]|23> rehashdir . |
|
119 | [c:opt/PuTTY]|23> rehashdir . | |
120 | <23> ['pageant', 'plink', 'pscp', 'psftp', 'putty', 'puttygen', 'unins000'] |
|
120 | <23> ['pageant', 'plink', 'pscp', 'psftp', 'putty', 'puttygen', 'unins000'] | |
121 |
|
121 | |||
122 | Now, you can execute any of those commams directly:: |
|
122 | Now, you can execute any of those commams directly:: | |
123 |
|
123 | |||
124 | [c:opt/PuTTY]|24> cd |
|
124 | [c:opt/PuTTY]|24> cd | |
125 | [~]|25> putty |
|
125 | [~]|25> putty | |
126 |
|
126 | |||
127 | (the putty window opens). |
|
127 | (the putty window opens). | |
128 |
|
128 | |||
129 | If you want to store the alias so that it will always be available, do '%store putty'. If you want to %store all these aliases persistently, just do it in a for loop:: |
|
129 | If you want to store the alias so that it will always be available, do '%store putty'. If you want to %store all these aliases persistently, just do it in a for loop:: | |
130 |
|
130 | |||
131 | [~]|27> for a in _23: |
|
131 | [~]|27> for a in _23: | |
132 | |..> %store $a |
|
132 | |..> %store $a | |
133 | |..> |
|
133 | |..> | |
134 | |..> |
|
134 | |..> | |
135 | Alias stored: pageant (0, 'c:\\opt\\PuTTY\\pageant.exe') |
|
135 | Alias stored: pageant (0, 'c:\\opt\\PuTTY\\pageant.exe') | |
136 | Alias stored: plink (0, 'c:\\opt\\PuTTY\\plink.exe') |
|
136 | Alias stored: plink (0, 'c:\\opt\\PuTTY\\plink.exe') | |
137 | Alias stored: pscp (0, 'c:\\opt\\PuTTY\\pscp.exe') |
|
137 | Alias stored: pscp (0, 'c:\\opt\\PuTTY\\pscp.exe') | |
138 | Alias stored: psftp (0, 'c:\\opt\\PuTTY\\psftp.exe') |
|
138 | Alias stored: psftp (0, 'c:\\opt\\PuTTY\\psftp.exe') | |
139 | ... |
|
139 | ... | |
140 |
|
140 | |||
141 | mglob |
|
|||
142 | ----- |
|
|||
143 |
|
||||
144 | Provide the magic function %mglob, which makes it easier (than the 'find' command) to collect (possibly recursive) file lists. Examples:: |
|
|||
145 |
|
||||
146 | [c:/ipython]|9> mglob *.py |
|
|||
147 | [c:/ipython]|10> mglob *.py rec:*.txt |
|
|||
148 | [c:/ipython]|19> workfiles = %mglob !.svn/ !.hg/ !*_Data/ !*.bak rec:. |
|
|||
149 |
|
||||
150 | Note that the first 2 calls will put the file list in result history (_, _9, _10), and the last one will assign it to 'workfiles'. |
|
|||
151 |
|
||||
152 |
|
141 | |||
153 | Prompt customization |
|
142 | Prompt customization | |
154 | ==================== |
|
143 | ==================== | |
155 |
|
144 | |||
156 | The sh profile uses the following prompt configurations:: |
|
145 | The sh profile uses the following prompt configurations:: | |
157 |
|
146 | |||
158 | c.PromptManager.in_template = r'{color.LightGreen}\u@\h{color.LightBlue}[{color.LightCyan}\Y1{color.LightBlue}]{color.Green}|\#> ' |
|
147 | c.PromptManager.in_template = r'{color.LightGreen}\u@\h{color.LightBlue}[{color.LightCyan}\Y1{color.LightBlue}]{color.Green}|\#> ' | |
159 | c.PromptManager.in2_template = r'{color.Green}|{color.LightGreen}\D{color.Green}> ' |
|
148 | c.PromptManager.in2_template = r'{color.Green}|{color.LightGreen}\D{color.Green}> ' | |
160 | c.PromptManager.out_template = r'<\#> ' |
|
149 | c.PromptManager.out_template = r'<\#> ' | |
161 |
|
150 | |||
162 | You can change the prompt configuration to your liking by editing |
|
151 | You can change the prompt configuration to your liking by editing | |
163 | ipython_config.py. |
|
152 | ipython_config.py. | |
164 |
|
153 | |||
165 | .. _string_lists: |
|
154 | .. _string_lists: | |
166 |
|
155 | |||
167 | String lists |
|
156 | String lists | |
168 | ============ |
|
157 | ============ | |
169 |
|
158 | |||
170 | String lists (IPython.utils.text.SList) are handy way to process output |
|
159 | String lists (IPython.utils.text.SList) are handy way to process output | |
171 | from system commands. They are produced by ``var = !cmd`` syntax. |
|
160 | from system commands. They are produced by ``var = !cmd`` syntax. | |
172 |
|
161 | |||
173 | First, we acquire the output of 'ls -l':: |
|
162 | First, we acquire the output of 'ls -l':: | |
174 |
|
163 | |||
175 | [Q:doc/examples]|2> lines = !ls -l |
|
164 | [Q:doc/examples]|2> lines = !ls -l | |
176 | == |
|
165 | == | |
177 | ['total 23', |
|
166 | ['total 23', | |
178 | '-rw-rw-rw- 1 ville None 1163 Sep 30 2006 example-demo.py', |
|
167 | '-rw-rw-rw- 1 ville None 1163 Sep 30 2006 example-demo.py', | |
179 | '-rw-rw-rw- 1 ville None 1927 Sep 30 2006 example-embed-short.py', |
|
168 | '-rw-rw-rw- 1 ville None 1927 Sep 30 2006 example-embed-short.py', | |
180 | '-rwxrwxrwx 1 ville None 4606 Sep 1 17:15 example-embed.py', |
|
169 | '-rwxrwxrwx 1 ville None 4606 Sep 1 17:15 example-embed.py', | |
181 | '-rwxrwxrwx 1 ville None 1017 Sep 30 2006 example-gnuplot.py', |
|
170 | '-rwxrwxrwx 1 ville None 1017 Sep 30 2006 example-gnuplot.py', | |
182 | '-rwxrwxrwx 1 ville None 339 Jun 11 18:01 extension.py', |
|
171 | '-rwxrwxrwx 1 ville None 339 Jun 11 18:01 extension.py', | |
183 | '-rwxrwxrwx 1 ville None 113 Dec 20 2006 seteditor.py', |
|
172 | '-rwxrwxrwx 1 ville None 113 Dec 20 2006 seteditor.py', | |
184 | '-rwxrwxrwx 1 ville None 245 Dec 12 2006 seteditor.pyc'] |
|
173 | '-rwxrwxrwx 1 ville None 245 Dec 12 2006 seteditor.pyc'] | |
185 |
|
174 | |||
186 | Now, let's take a look at the contents of 'lines' (the first number is |
|
175 | Now, let's take a look at the contents of 'lines' (the first number is | |
187 | the list element number):: |
|
176 | the list element number):: | |
188 |
|
177 | |||
189 | [Q:doc/examples]|3> lines |
|
178 | [Q:doc/examples]|3> lines | |
190 | <3> SList (.p, .n, .l, .s, .grep(), .fields() available). Value: |
|
179 | <3> SList (.p, .n, .l, .s, .grep(), .fields() available). Value: | |
191 |
|
180 | |||
192 | 0: total 23 |
|
181 | 0: total 23 | |
193 | 1: -rw-rw-rw- 1 ville None 1163 Sep 30 2006 example-demo.py |
|
182 | 1: -rw-rw-rw- 1 ville None 1163 Sep 30 2006 example-demo.py | |
194 | 2: -rw-rw-rw- 1 ville None 1927 Sep 30 2006 example-embed-short.py |
|
183 | 2: -rw-rw-rw- 1 ville None 1927 Sep 30 2006 example-embed-short.py | |
195 | 3: -rwxrwxrwx 1 ville None 4606 Sep 1 17:15 example-embed.py |
|
184 | 3: -rwxrwxrwx 1 ville None 4606 Sep 1 17:15 example-embed.py | |
196 | 4: -rwxrwxrwx 1 ville None 1017 Sep 30 2006 example-gnuplot.py |
|
185 | 4: -rwxrwxrwx 1 ville None 1017 Sep 30 2006 example-gnuplot.py | |
197 | 5: -rwxrwxrwx 1 ville None 339 Jun 11 18:01 extension.py |
|
186 | 5: -rwxrwxrwx 1 ville None 339 Jun 11 18:01 extension.py | |
198 | 6: -rwxrwxrwx 1 ville None 113 Dec 20 2006 seteditor.py |
|
187 | 6: -rwxrwxrwx 1 ville None 113 Dec 20 2006 seteditor.py | |
199 | 7: -rwxrwxrwx 1 ville None 245 Dec 12 2006 seteditor.pyc |
|
188 | 7: -rwxrwxrwx 1 ville None 245 Dec 12 2006 seteditor.pyc | |
200 |
|
189 | |||
201 | Now, let's filter out the 'embed' lines:: |
|
190 | Now, let's filter out the 'embed' lines:: | |
202 |
|
191 | |||
203 | [Q:doc/examples]|4> l2 = lines.grep('embed',prune=1) |
|
192 | [Q:doc/examples]|4> l2 = lines.grep('embed',prune=1) | |
204 | [Q:doc/examples]|5> l2 |
|
193 | [Q:doc/examples]|5> l2 | |
205 | <5> SList (.p, .n, .l, .s, .grep(), .fields() available). Value: |
|
194 | <5> SList (.p, .n, .l, .s, .grep(), .fields() available). Value: | |
206 |
|
195 | |||
207 | 0: total 23 |
|
196 | 0: total 23 | |
208 | 1: -rw-rw-rw- 1 ville None 1163 Sep 30 2006 example-demo.py |
|
197 | 1: -rw-rw-rw- 1 ville None 1163 Sep 30 2006 example-demo.py | |
209 | 2: -rwxrwxrwx 1 ville None 1017 Sep 30 2006 example-gnuplot.py |
|
198 | 2: -rwxrwxrwx 1 ville None 1017 Sep 30 2006 example-gnuplot.py | |
210 | 3: -rwxrwxrwx 1 ville None 339 Jun 11 18:01 extension.py |
|
199 | 3: -rwxrwxrwx 1 ville None 339 Jun 11 18:01 extension.py | |
211 | 4: -rwxrwxrwx 1 ville None 113 Dec 20 2006 seteditor.py |
|
200 | 4: -rwxrwxrwx 1 ville None 113 Dec 20 2006 seteditor.py | |
212 | 5: -rwxrwxrwx 1 ville None 245 Dec 12 2006 seteditor.pyc |
|
201 | 5: -rwxrwxrwx 1 ville None 245 Dec 12 2006 seteditor.pyc | |
213 |
|
202 | |||
214 | Now, we want strings having just file names and permissions:: |
|
203 | Now, we want strings having just file names and permissions:: | |
215 |
|
204 | |||
216 | [Q:doc/examples]|6> l2.fields(8,0) |
|
205 | [Q:doc/examples]|6> l2.fields(8,0) | |
217 | <6> SList (.p, .n, .l, .s, .grep(), .fields() available). Value: |
|
206 | <6> SList (.p, .n, .l, .s, .grep(), .fields() available). Value: | |
218 |
|
207 | |||
219 | 0: total |
|
208 | 0: total | |
220 | 1: example-demo.py -rw-rw-rw- |
|
209 | 1: example-demo.py -rw-rw-rw- | |
221 | 2: example-gnuplot.py -rwxrwxrwx |
|
210 | 2: example-gnuplot.py -rwxrwxrwx | |
222 | 3: extension.py -rwxrwxrwx |
|
211 | 3: extension.py -rwxrwxrwx | |
223 | 4: seteditor.py -rwxrwxrwx |
|
212 | 4: seteditor.py -rwxrwxrwx | |
224 | 5: seteditor.pyc -rwxrwxrwx |
|
213 | 5: seteditor.pyc -rwxrwxrwx | |
225 |
|
214 | |||
226 | Note how the line with 'total' does not raise IndexError. |
|
215 | Note how the line with 'total' does not raise IndexError. | |
227 |
|
216 | |||
228 | If you want to split these (yielding lists), call fields() without |
|
217 | If you want to split these (yielding lists), call fields() without | |
229 | arguments:: |
|
218 | arguments:: | |
230 |
|
219 | |||
231 | [Q:doc/examples]|7> _.fields() |
|
220 | [Q:doc/examples]|7> _.fields() | |
232 | <7> |
|
221 | <7> | |
233 | [['total'], |
|
222 | [['total'], | |
234 | ['example-demo.py', '-rw-rw-rw-'], |
|
223 | ['example-demo.py', '-rw-rw-rw-'], | |
235 | ['example-gnuplot.py', '-rwxrwxrwx'], |
|
224 | ['example-gnuplot.py', '-rwxrwxrwx'], | |
236 | ['extension.py', '-rwxrwxrwx'], |
|
225 | ['extension.py', '-rwxrwxrwx'], | |
237 | ['seteditor.py', '-rwxrwxrwx'], |
|
226 | ['seteditor.py', '-rwxrwxrwx'], | |
238 | ['seteditor.pyc', '-rwxrwxrwx']] |
|
227 | ['seteditor.pyc', '-rwxrwxrwx']] | |
239 |
|
228 | |||
240 | If you want to pass these separated with spaces to a command (typical |
|
229 | If you want to pass these separated with spaces to a command (typical | |
241 | for lists if files), use the .s property:: |
|
230 | for lists if files), use the .s property:: | |
242 |
|
231 | |||
243 |
|
232 | |||
244 | [Q:doc/examples]|13> files = l2.fields(8).s |
|
233 | [Q:doc/examples]|13> files = l2.fields(8).s | |
245 | [Q:doc/examples]|14> files |
|
234 | [Q:doc/examples]|14> files | |
246 | <14> 'example-demo.py example-gnuplot.py extension.py seteditor.py seteditor.pyc' |
|
235 | <14> 'example-demo.py example-gnuplot.py extension.py seteditor.py seteditor.pyc' | |
247 | [Q:doc/examples]|15> ls $files |
|
236 | [Q:doc/examples]|15> ls $files | |
248 | example-demo.py example-gnuplot.py extension.py seteditor.py seteditor.pyc |
|
237 | example-demo.py example-gnuplot.py extension.py seteditor.py seteditor.pyc | |
249 |
|
238 | |||
250 | SLists are inherited from normal python lists, so every list method is |
|
239 | SLists are inherited from normal python lists, so every list method is | |
251 | available:: |
|
240 | available:: | |
252 |
|
241 | |||
253 | [Q:doc/examples]|21> lines.append('hey') |
|
242 | [Q:doc/examples]|21> lines.append('hey') | |
254 |
|
243 | |||
255 |
|
244 | |||
256 | Real world example: remove all files outside version control |
|
245 | Real world example: remove all files outside version control | |
257 | ------------------------------------------------------------ |
|
246 | ------------------------------------------------------------ | |
258 |
|
247 | |||
259 | First, capture output of "hg status":: |
|
248 | First, capture output of "hg status":: | |
260 |
|
249 | |||
261 | [Q:/ipython]|28> out = !hg status |
|
250 | [Q:/ipython]|28> out = !hg status | |
262 | == |
|
251 | == | |
263 | ['M IPython\\extensions\\ipy_kitcfg.py', |
|
252 | ['M IPython\\extensions\\ipy_kitcfg.py', | |
264 | 'M IPython\\extensions\\ipy_rehashdir.py', |
|
253 | 'M IPython\\extensions\\ipy_rehashdir.py', | |
265 | ... |
|
254 | ... | |
266 | '? build\\lib\\IPython\\Debugger.py', |
|
255 | '? build\\lib\\IPython\\Debugger.py', | |
267 | '? build\\lib\\IPython\\extensions\\InterpreterExec.py', |
|
256 | '? build\\lib\\IPython\\extensions\\InterpreterExec.py', | |
268 | '? build\\lib\\IPython\\extensions\\InterpreterPasteInput.py', |
|
257 | '? build\\lib\\IPython\\extensions\\InterpreterPasteInput.py', | |
269 | ... |
|
258 | ... | |
270 |
|
259 | |||
271 | (lines starting with ? are not under version control). |
|
260 | (lines starting with ? are not under version control). | |
272 |
|
261 | |||
273 | :: |
|
262 | :: | |
274 |
|
263 | |||
275 | [Q:/ipython]|35> junk = out.grep(r'^\?').fields(1) |
|
264 | [Q:/ipython]|35> junk = out.grep(r'^\?').fields(1) | |
276 | [Q:/ipython]|36> junk |
|
265 | [Q:/ipython]|36> junk | |
277 | <36> SList (.p, .n, .l, .s, .grep(), .fields() availab |
|
266 | <36> SList (.p, .n, .l, .s, .grep(), .fields() availab | |
278 | ... |
|
267 | ... | |
279 | 10: build\bdist.win32\winexe\temp\_ctypes.py |
|
268 | 10: build\bdist.win32\winexe\temp\_ctypes.py | |
280 | 11: build\bdist.win32\winexe\temp\_hashlib.py |
|
269 | 11: build\bdist.win32\winexe\temp\_hashlib.py | |
281 | 12: build\bdist.win32\winexe\temp\_socket.py |
|
270 | 12: build\bdist.win32\winexe\temp\_socket.py | |
282 |
|
271 | |||
283 | Now we can just remove these files by doing 'rm $junk.s'. |
|
272 | Now we can just remove these files by doing 'rm $junk.s'. | |
284 |
|
273 | |||
285 | The .s, .n, .p properties |
|
274 | The .s, .n, .p properties | |
286 | ------------------------- |
|
275 | ------------------------- | |
287 |
|
276 | |||
288 | The ``.s`` property returns one string where lines are separated by |
|
277 | The ``.s`` property returns one string where lines are separated by | |
289 | single space (for convenient passing to system commands). The ``.n`` |
|
278 | single space (for convenient passing to system commands). The ``.n`` | |
290 | property return one string where the lines are separated by a newline |
|
279 | property return one string where the lines are separated by a newline | |
291 | (i.e. the original output of the function). If the items in string |
|
280 | (i.e. the original output of the function). If the items in string | |
292 | list are file names, ``.p`` can be used to get a list of "path" objects |
|
281 | list are file names, ``.p`` can be used to get a list of "path" objects | |
293 | for convenient file manipulation. |
|
282 | for convenient file manipulation. | |
294 |
|
283 |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
General Comments 0
You need to be logged in to leave comments.
Login now