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