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