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