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