##// END OF EJS Templates
Document globbing in `%history -g <pattern>`....
Bradley M. Froehle -
Show More
@@ -1,287 +1,289 b''
1 """Implementation of magic functions related to History.
1 """Implementation of magic functions related to History.
2 """
2 """
3 #-----------------------------------------------------------------------------
3 #-----------------------------------------------------------------------------
4 # Copyright (c) 2012, IPython Development Team.
4 # Copyright (c) 2012, IPython Development Team.
5 #
5 #
6 # Distributed under the terms of the Modified BSD License.
6 # Distributed under the terms of the Modified BSD License.
7 #
7 #
8 # The full license is in the file COPYING.txt, distributed with this software.
8 # The full license is in the file COPYING.txt, distributed with this software.
9 #-----------------------------------------------------------------------------
9 #-----------------------------------------------------------------------------
10
10
11 #-----------------------------------------------------------------------------
11 #-----------------------------------------------------------------------------
12 # Imports
12 # Imports
13 #-----------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
14 from __future__ import print_function
14 from __future__ import print_function
15
15
16 # Stdlib
16 # Stdlib
17 import os
17 import os
18 from io import open as io_open
18 from io import open as io_open
19
19
20 # Our own packages
20 # Our own packages
21 from IPython.core.error import StdinNotImplementedError
21 from IPython.core.error import StdinNotImplementedError
22 from IPython.core.magic import Magics, magics_class, line_magic
22 from IPython.core.magic import Magics, magics_class, line_magic
23 from IPython.testing.skipdoctest import skip_doctest
23 from IPython.testing.skipdoctest import skip_doctest
24 from IPython.utils import io
24 from IPython.utils import io
25
25
26 #-----------------------------------------------------------------------------
26 #-----------------------------------------------------------------------------
27 # Magics class implementation
27 # Magics class implementation
28 #-----------------------------------------------------------------------------
28 #-----------------------------------------------------------------------------
29
29
30 @magics_class
30 @magics_class
31 class HistoryMagics(Magics):
31 class HistoryMagics(Magics):
32
32
33 @skip_doctest
33 @skip_doctest
34 @line_magic
34 @line_magic
35 def history(self, parameter_s = ''):
35 def history(self, parameter_s = ''):
36 """Print input history (_i<n> variables), with most recent last.
36 """Print input history (_i<n> variables), with most recent last.
37
37
38 %history [-o -p -t -n] [-f filename] [range | -g pattern | -l number]
38 %history [-o -p -t -n] [-f filename] [range | -g pattern | -l number]
39
39
40 By default, input history is printed without line numbers so it can be
40 By default, input history is printed without line numbers so it can be
41 directly pasted into an editor. Use -n to show them.
41 directly pasted into an editor. Use -n to show them.
42
42
43 By default, all input history from the current session is displayed.
43 By default, all input history from the current session is displayed.
44 Ranges of history can be indicated using the syntax:
44 Ranges of history can be indicated using the syntax:
45 4 : Line 4, current session
45 4 : Line 4, current session
46 4-6 : Lines 4-6, current session
46 4-6 : Lines 4-6, current session
47 243/1-5: Lines 1-5, session 243
47 243/1-5: Lines 1-5, session 243
48 ~2/7 : Line 7, session 2 before current
48 ~2/7 : Line 7, session 2 before current
49 ~8/1-~6/5 : From the first line of 8 sessions ago, to the fifth line
49 ~8/1-~6/5 : From the first line of 8 sessions ago, to the fifth line
50 of 6 sessions ago.
50 of 6 sessions ago.
51 Multiple ranges can be entered, separated by spaces
51 Multiple ranges can be entered, separated by spaces
52
52
53 The same syntax is used by %macro, %save, %edit, %rerun
53 The same syntax is used by %macro, %save, %edit, %rerun
54
54
55 Options:
55 Options:
56
56
57 -n: print line numbers for each input.
57 -n: print line numbers for each input.
58 This feature is only available if numbered prompts are in use.
58 This feature is only available if numbered prompts are in use.
59
59
60 -o: also print outputs for each input.
60 -o: also print outputs for each input.
61
61
62 -p: print classic '>>>' python prompts before each input. This is
62 -p: print classic '>>>' python prompts before each input. This is
63 useful for making documentation, and in conjunction with -o, for
63 useful for making documentation, and in conjunction with -o, for
64 producing doctest-ready output.
64 producing doctest-ready output.
65
65
66 -r: (default) print the 'raw' history, i.e. the actual commands you
66 -r: (default) print the 'raw' history, i.e. the actual commands you
67 typed.
67 typed.
68
68
69 -t: print the 'translated' history, as IPython understands it.
69 -t: print the 'translated' history, as IPython understands it.
70 IPython filters your input and converts it all into valid Python
70 IPython filters your input and converts it all into valid Python
71 source before executing it (things like magics or aliases are turned
71 source before executing it (things like magics or aliases are turned
72 into function calls, for example). With this option, you'll see the
72 into function calls, for example). With this option, you'll see the
73 native history instead of the user-entered version: '%cd /' will be
73 native history instead of the user-entered version: '%cd /' will be
74 seen as 'get_ipython().magic("%cd /")' instead of '%cd /'.
74 seen as 'get_ipython().magic("%cd /")' instead of '%cd /'.
75
75
76 -g: treat the arg as a pattern to grep for in (full) history.
76 -g: treat the arg as a pattern to grep for in (full) history.
77 This includes the saved history (almost all commands ever written).
77 This includes the saved history (almost all commands ever written).
78 Use '%hist -g' to show full saved history (may be very long).
78 The pattern may contain '?' to match one unknown character and '*'
79 to match any number of unknown characters. Use '%hist -g' to show
80 full saved history (may be very long).
79
81
80 -l: get the last n lines from all sessions. Specify n as a single
82 -l: get the last n lines from all sessions. Specify n as a single
81 arg, or the default is the last 10 lines.
83 arg, or the default is the last 10 lines.
82
84
83 -f FILENAME: instead of printing the output to the screen, redirect
85 -f FILENAME: instead of printing the output to the screen, redirect
84 it to the given file. The file is always overwritten, though *when
86 it to the given file. The file is always overwritten, though *when
85 it can*, IPython asks for confirmation first. In particular, running
87 it can*, IPython asks for confirmation first. In particular, running
86 the command 'history -f FILENAME' from the IPython Notebook
88 the command 'history -f FILENAME' from the IPython Notebook
87 interface will replace FILENAME even if it already exists *without*
89 interface will replace FILENAME even if it already exists *without*
88 confirmation.
90 confirmation.
89
91
90 Examples
92 Examples
91 --------
93 --------
92 ::
94 ::
93
95
94 In [6]: %history -n 4-6
96 In [6]: %history -n 4-6
95 4:a = 12
97 4:a = 12
96 5:print a**2
98 5:print a**2
97 6:%history -n 4-6
99 6:%history -n 4-6
98
100
99 """
101 """
100
102
101 if not self.shell.displayhook.do_full_cache:
103 if not self.shell.displayhook.do_full_cache:
102 print('This feature is only available if numbered prompts '
104 print('This feature is only available if numbered prompts '
103 'are in use.')
105 'are in use.')
104 return
106 return
105 opts,args = self.parse_options(parameter_s,'noprtglf:',mode='string')
107 opts,args = self.parse_options(parameter_s,'noprtglf:',mode='string')
106
108
107 # For brevity
109 # For brevity
108 history_manager = self.shell.history_manager
110 history_manager = self.shell.history_manager
109
111
110 def _format_lineno(session, line):
112 def _format_lineno(session, line):
111 """Helper function to format line numbers properly."""
113 """Helper function to format line numbers properly."""
112 if session in (0, history_manager.session_number):
114 if session in (0, history_manager.session_number):
113 return str(line)
115 return str(line)
114 return "%s/%s" % (session, line)
116 return "%s/%s" % (session, line)
115
117
116 # Check if output to specific file was requested.
118 # Check if output to specific file was requested.
117 try:
119 try:
118 outfname = opts['f']
120 outfname = opts['f']
119 except KeyError:
121 except KeyError:
120 outfile = io.stdout # default
122 outfile = io.stdout # default
121 # We don't want to close stdout at the end!
123 # We don't want to close stdout at the end!
122 close_at_end = False
124 close_at_end = False
123 else:
125 else:
124 if os.path.exists(outfname):
126 if os.path.exists(outfname):
125 try:
127 try:
126 ans = io.ask_yes_no("File %r exists. Overwrite?" % outfname)
128 ans = io.ask_yes_no("File %r exists. Overwrite?" % outfname)
127 except StdinNotImplementedError:
129 except StdinNotImplementedError:
128 ans = True
130 ans = True
129 if not ans:
131 if not ans:
130 print('Aborting.')
132 print('Aborting.')
131 return
133 return
132 print("Overwriting file.")
134 print("Overwriting file.")
133 outfile = io_open(outfname, 'w', encoding='utf-8')
135 outfile = io_open(outfname, 'w', encoding='utf-8')
134 close_at_end = True
136 close_at_end = True
135
137
136 print_nums = 'n' in opts
138 print_nums = 'n' in opts
137 get_output = 'o' in opts
139 get_output = 'o' in opts
138 pyprompts = 'p' in opts
140 pyprompts = 'p' in opts
139 # Raw history is the default
141 # Raw history is the default
140 raw = not('t' in opts)
142 raw = not('t' in opts)
141
143
142 pattern = None
144 pattern = None
143
145
144 if 'g' in opts: # Glob search
146 if 'g' in opts: # Glob search
145 pattern = "*" + args + "*" if args else "*"
147 pattern = "*" + args + "*" if args else "*"
146 hist = history_manager.search(pattern, raw=raw, output=get_output)
148 hist = history_manager.search(pattern, raw=raw, output=get_output)
147 print_nums = True
149 print_nums = True
148 elif 'l' in opts: # Get 'tail'
150 elif 'l' in opts: # Get 'tail'
149 try:
151 try:
150 n = int(args)
152 n = int(args)
151 except (ValueError, IndexError):
153 except (ValueError, IndexError):
152 n = 10
154 n = 10
153 hist = history_manager.get_tail(n, raw=raw, output=get_output)
155 hist = history_manager.get_tail(n, raw=raw, output=get_output)
154 else:
156 else:
155 if args: # Get history by ranges
157 if args: # Get history by ranges
156 hist = history_manager.get_range_by_str(args, raw, get_output)
158 hist = history_manager.get_range_by_str(args, raw, get_output)
157 else: # Just get history for the current session
159 else: # Just get history for the current session
158 hist = history_manager.get_range(raw=raw, output=get_output)
160 hist = history_manager.get_range(raw=raw, output=get_output)
159
161
160 # We could be displaying the entire history, so let's not try to pull
162 # We could be displaying the entire history, so let's not try to pull
161 # it into a list in memory. Anything that needs more space will just
163 # it into a list in memory. Anything that needs more space will just
162 # misalign.
164 # misalign.
163 width = 4
165 width = 4
164
166
165 for session, lineno, inline in hist:
167 for session, lineno, inline in hist:
166 # Print user history with tabs expanded to 4 spaces. The GUI
168 # Print user history with tabs expanded to 4 spaces. The GUI
167 # clients use hard tabs for easier usability in auto-indented code,
169 # clients use hard tabs for easier usability in auto-indented code,
168 # but we want to produce PEP-8 compliant history for safe pasting
170 # but we want to produce PEP-8 compliant history for safe pasting
169 # into an editor.
171 # into an editor.
170 if get_output:
172 if get_output:
171 inline, output = inline
173 inline, output = inline
172 inline = inline.expandtabs(4).rstrip()
174 inline = inline.expandtabs(4).rstrip()
173
175
174 multiline = "\n" in inline
176 multiline = "\n" in inline
175 line_sep = '\n' if multiline else ' '
177 line_sep = '\n' if multiline else ' '
176 if print_nums:
178 if print_nums:
177 print(u'%s:%s' % (_format_lineno(session, lineno).rjust(width),
179 print(u'%s:%s' % (_format_lineno(session, lineno).rjust(width),
178 line_sep), file=outfile, end=u'')
180 line_sep), file=outfile, end=u'')
179 if pyprompts:
181 if pyprompts:
180 print(u">>> ", end=u"", file=outfile)
182 print(u">>> ", end=u"", file=outfile)
181 if multiline:
183 if multiline:
182 inline = "\n... ".join(inline.splitlines()) + "\n..."
184 inline = "\n... ".join(inline.splitlines()) + "\n..."
183 print(inline, file=outfile)
185 print(inline, file=outfile)
184 if get_output and output:
186 if get_output and output:
185 print(output, file=outfile)
187 print(output, file=outfile)
186
188
187 if close_at_end:
189 if close_at_end:
188 outfile.close()
190 outfile.close()
189
191
190 @line_magic
192 @line_magic
191 def recall(self, arg):
193 def recall(self, arg):
192 r"""Repeat a command, or get command to input line for editing.
194 r"""Repeat a command, or get command to input line for editing.
193
195
194 %recall and %rep are equivalent.
196 %recall and %rep are equivalent.
195
197
196 - %recall (no arguments):
198 - %recall (no arguments):
197
199
198 Place a string version of last computation result (stored in the
200 Place a string version of last computation result (stored in the
199 special '_' variable) to the next input prompt. Allows you to create
201 special '_' variable) to the next input prompt. Allows you to create
200 elaborate command lines without using copy-paste::
202 elaborate command lines without using copy-paste::
201
203
202 In[1]: l = ["hei", "vaan"]
204 In[1]: l = ["hei", "vaan"]
203 In[2]: "".join(l)
205 In[2]: "".join(l)
204 Out[2]: heivaan
206 Out[2]: heivaan
205 In[3]: %recall
207 In[3]: %recall
206 In[4]: heivaan_ <== cursor blinking
208 In[4]: heivaan_ <== cursor blinking
207
209
208 %recall 45
210 %recall 45
209
211
210 Place history line 45 on the next input prompt. Use %hist to find
212 Place history line 45 on the next input prompt. Use %hist to find
211 out the number.
213 out the number.
212
214
213 %recall 1-4
215 %recall 1-4
214
216
215 Combine the specified lines into one cell, and place it on the next
217 Combine the specified lines into one cell, and place it on the next
216 input prompt. See %history for the slice syntax.
218 input prompt. See %history for the slice syntax.
217
219
218 %recall foo+bar
220 %recall foo+bar
219
221
220 If foo+bar can be evaluated in the user namespace, the result is
222 If foo+bar can be evaluated in the user namespace, the result is
221 placed at the next input prompt. Otherwise, the history is searched
223 placed at the next input prompt. Otherwise, the history is searched
222 for lines which contain that substring, and the most recent one is
224 for lines which contain that substring, and the most recent one is
223 placed at the next input prompt.
225 placed at the next input prompt.
224 """
226 """
225 if not arg: # Last output
227 if not arg: # Last output
226 self.shell.set_next_input(str(self.shell.user_ns["_"]))
228 self.shell.set_next_input(str(self.shell.user_ns["_"]))
227 return
229 return
228 # Get history range
230 # Get history range
229 histlines = self.shell.history_manager.get_range_by_str(arg)
231 histlines = self.shell.history_manager.get_range_by_str(arg)
230 cmd = "\n".join(x[2] for x in histlines)
232 cmd = "\n".join(x[2] for x in histlines)
231 if cmd:
233 if cmd:
232 self.shell.set_next_input(cmd.rstrip())
234 self.shell.set_next_input(cmd.rstrip())
233 return
235 return
234
236
235 try: # Variable in user namespace
237 try: # Variable in user namespace
236 cmd = str(eval(arg, self.shell.user_ns))
238 cmd = str(eval(arg, self.shell.user_ns))
237 except Exception: # Search for term in history
239 except Exception: # Search for term in history
238 histlines = self.shell.history_manager.search("*"+arg+"*")
240 histlines = self.shell.history_manager.search("*"+arg+"*")
239 for h in reversed([x[2] for x in histlines]):
241 for h in reversed([x[2] for x in histlines]):
240 if 'recall' in h or 'rep' in h:
242 if 'recall' in h or 'rep' in h:
241 continue
243 continue
242 self.shell.set_next_input(h.rstrip())
244 self.shell.set_next_input(h.rstrip())
243 return
245 return
244 else:
246 else:
245 self.shell.set_next_input(cmd.rstrip())
247 self.shell.set_next_input(cmd.rstrip())
246 print("Couldn't evaluate or find in history:", arg)
248 print("Couldn't evaluate or find in history:", arg)
247
249
248 @line_magic
250 @line_magic
249 def rerun(self, parameter_s=''):
251 def rerun(self, parameter_s=''):
250 """Re-run previous input
252 """Re-run previous input
251
253
252 By default, you can specify ranges of input history to be repeated
254 By default, you can specify ranges of input history to be repeated
253 (as with %history). With no arguments, it will repeat the last line.
255 (as with %history). With no arguments, it will repeat the last line.
254
256
255 Options:
257 Options:
256
258
257 -l <n> : Repeat the last n lines of input, not including the
259 -l <n> : Repeat the last n lines of input, not including the
258 current command.
260 current command.
259
261
260 -g foo : Repeat the most recent line which contains foo
262 -g foo : Repeat the most recent line which contains foo
261 """
263 """
262 opts, args = self.parse_options(parameter_s, 'l:g:', mode='string')
264 opts, args = self.parse_options(parameter_s, 'l:g:', mode='string')
263 if "l" in opts: # Last n lines
265 if "l" in opts: # Last n lines
264 n = int(opts['l'])
266 n = int(opts['l'])
265 hist = self.shell.history_manager.get_tail(n)
267 hist = self.shell.history_manager.get_tail(n)
266 elif "g" in opts: # Search
268 elif "g" in opts: # Search
267 p = "*"+opts['g']+"*"
269 p = "*"+opts['g']+"*"
268 hist = list(self.shell.history_manager.search(p))
270 hist = list(self.shell.history_manager.search(p))
269 for l in reversed(hist):
271 for l in reversed(hist):
270 if "rerun" not in l[2]:
272 if "rerun" not in l[2]:
271 hist = [l] # The last match which isn't a %rerun
273 hist = [l] # The last match which isn't a %rerun
272 break
274 break
273 else:
275 else:
274 hist = [] # No matches except %rerun
276 hist = [] # No matches except %rerun
275 elif args: # Specify history ranges
277 elif args: # Specify history ranges
276 hist = self.shell.history_manager.get_range_by_str(args)
278 hist = self.shell.history_manager.get_range_by_str(args)
277 else: # Last line
279 else: # Last line
278 hist = self.shell.history_manager.get_tail(1)
280 hist = self.shell.history_manager.get_tail(1)
279 hist = [x[2] for x in hist]
281 hist = [x[2] for x in hist]
280 if not hist:
282 if not hist:
281 print("No lines in history match specification")
283 print("No lines in history match specification")
282 return
284 return
283 histlines = "\n".join(hist)
285 histlines = "\n".join(hist)
284 print("=== Executing: ===")
286 print("=== Executing: ===")
285 print(histlines)
287 print(histlines)
286 print("=== Output: ===")
288 print("=== Output: ===")
287 self.shell.run_cell("\n".join(hist), store_history=False)
289 self.shell.run_cell("\n".join(hist), store_history=False)
General Comments 0
You need to be logged in to leave comments. Login now