##// END OF EJS Templates
nicer crash on %rep if not in history'
vivainio -
Show More
@@ -1,235 +1,239
1 1 # -*- coding: utf-8 -*-
2 2
3 3 """ History related magics and functionality """
4 4
5 5 import fnmatch
6 6
7 7 def magic_history(self, parameter_s = ''):
8 8 """Print input history (_i<n> variables), with most recent last.
9 9
10 10 %history -> print at most 40 inputs (some may be multi-line)\\
11 11 %history n -> print at most n inputs\\
12 12 %history n1 n2 -> print inputs between n1 and n2 (n2 not included)\\
13 13
14 14 Each input's number <n> is shown, and is accessible as the
15 15 automatically generated variable _i<n>. Multi-line statements are
16 16 printed starting at a new line for easy copy/paste.
17 17
18 18
19 19 Options:
20 20
21 21 -n: do NOT print line numbers. This is useful if you want to get a
22 22 printout of many lines which can be directly pasted into a text
23 23 editor.
24 24
25 25 This feature is only available if numbered prompts are in use.
26 26
27 27 -t: (default) print the 'translated' history, as IPython understands it.
28 28 IPython filters your input and converts it all into valid Python source
29 29 before executing it (things like magics or aliases are turned into
30 30 function calls, for example). With this option, you'll see the native
31 31 history instead of the user-entered version: '%cd /' will be seen as
32 32 '_ip.magic("%cd /")' instead of '%cd /'.
33 33
34 34 -r: print the 'raw' history, i.e. the actual commands you typed.
35 35
36 36 -g: treat the arg as a pattern to grep for in (full) history.
37 37 This includes the "shadow history" (almost all commands ever written).
38 38 Use '%hist -g' to show full shadow history (may be very long).
39 39 In shadow history, every index nuwber starts with 0.
40 40
41 41
42 42 """
43 43
44 44 ip = self.api
45 45 shell = self.shell
46 46 if not shell.outputcache.do_full_cache:
47 47 print 'This feature is only available if numbered prompts are in use.'
48 48 return
49 49 opts,args = self.parse_options(parameter_s,'gntsr',mode='list')
50 50
51 51 if opts.has_key('t'):
52 52 input_hist = shell.input_hist
53 53 elif opts.has_key('r'):
54 54 input_hist = shell.input_hist_raw
55 55 else:
56 56 input_hist = shell.input_hist
57 57
58 58
59 59 default_length = 40
60 60 pattern = None
61 61 if opts.has_key('g'):
62 62 init = 1
63 63 final = len(input_hist)
64 64 parts = parameter_s.split(None,1)
65 65 if len(parts) == 1:
66 66 parts += '*'
67 67 head, pattern = parts
68 68 pattern = "*" + pattern + "*"
69 69 elif len(args) == 0:
70 70 final = len(input_hist)
71 71 init = max(1,final-default_length)
72 72 elif len(args) == 1:
73 73 final = len(input_hist)
74 74 init = max(1,final-int(args[0]))
75 75 elif len(args) == 2:
76 76 init,final = map(int,args)
77 77 else:
78 78 warn('%hist takes 0, 1 or 2 arguments separated by spaces.')
79 79 print self.magic_hist.__doc__
80 80 return
81 81 width = len(str(final))
82 82 line_sep = ['','\n']
83 83 print_nums = not opts.has_key('n')
84 84
85 85 found = False
86 86 if pattern is not None:
87 87 sh = ip.IP.shadowhist.all()
88 88 for idx, s in sh:
89 89 if fnmatch.fnmatch(s, pattern):
90 90 print "0%d: %s" %(idx, s)
91 91 found = True
92 92
93 93 if found:
94 94 print "==="
95 95 print "^shadow history ends, fetch by %rep <number> (must start with 0)"
96 96 print "=== start of normal history ==="
97 97
98 98 for in_num in range(init,final):
99 99 inline = input_hist[in_num]
100 100 if pattern is not None and not fnmatch.fnmatch(inline, pattern):
101 101 continue
102 102
103 103 multiline = int(inline.count('\n') > 1)
104 104 if print_nums:
105 105 print '%s:%s' % (str(in_num).ljust(width),line_sep[multiline]),
106 106 print inline,
107 107
108 108
109 109
110 110 def magic_hist(self, parameter_s=''):
111 111 """Alternate name for %history."""
112 112 return self.magic_history(parameter_s)
113 113
114 114
115 115
116 116 def rep_f(self, arg):
117 117 r""" Repeat a command, or get command to input line for editing
118 118
119 119 - %rep (no arguments):
120 120
121 121 Place a string version of last input to the next input prompt. Allows you
122 122 to create elaborate command lines without using copy-paste::
123 123
124 124 $ l = ["hei", "vaan"]
125 125 $ "".join(l)
126 126 ==> heivaan
127 127 $ %rep
128 128 $ heivaan_ <== cursor blinking
129 129
130 130 %rep 45
131 131
132 132 Place history line 45 to next input prompt. Use %hist to find out the number.
133 133
134 134 %rep 1-4 6-7 3
135 135
136 136 Repeat the specified lines immediately. Input slice syntax is the same as
137 137 in %macro and %save.
138 138
139 139 %rep foo
140 140
141 141 Place the most recent line that has the substring "foo" to next input.
142 142 (e.g. 'svn ci -m foobar').
143 143
144 144 """
145 145
146 146
147 147 opts,args = self.parse_options(arg,'',mode='list')
148 148 ip = self.api
149 149 if not args:
150 150 ip.set_next_input(str(ip.user_ns["_"]))
151 151 return
152 152
153 153 if len(args) == 1 and not '-' in args[0]:
154 154 arg = args[0]
155 155 if len(arg) > 1 and arg.startswith('0'):
156 156 # get from shadow hist
157 157 num = int(arg[1:])
158 158 line = self.shadowhist.get(num)
159 159 ip.set_next_input(str(line))
160 160 return
161 161 try:
162 162 num = int(args[0])
163 163 ip.set_next_input(str(ip.IP.input_hist_raw[num]).rstrip())
164 164 return
165 165 except ValueError:
166 166 pass
167 167
168 168 for h in reversed(self.shell.input_hist_raw):
169 169 if 'rep' in h:
170 170 continue
171 171 if fnmatch.fnmatch(h,'*' + arg + '*'):
172 172 ip.set_next_input(str(h).rstrip())
173 173 return
174 174
175 175
176 lines = self.extract_input_slices(args, True)
177 print "lines",lines
178 ip.runlines(lines)
176 try:
177 lines = self.extract_input_slices(args, True)
178 print "lines",lines
179 ip.runlines(lines)
180 except ValueError:
181 print "Not found in recent history:", args
182
179 183
180 184
181 185 _sentinel = object()
182 186
183 187 class ShadowHist:
184 188 def __init__(self,db):
185 189 # cmd => idx mapping
186 190 self.curidx = 0
187 191 self.db = db
188 192
189 193 def inc_idx(self):
190 194 idx = self.db.get('shadowhist_idx', 1)
191 195 self.db['shadowhist_idx'] = idx + 1
192 196 return idx
193 197
194 198 def add(self, ent):
195 199 old = self.db.hget('shadowhist', ent, _sentinel)
196 200 if old is not _sentinel:
197 201 return
198 202 newidx = self.inc_idx()
199 203 #print "new",newidx # dbg
200 204 self.db.hset('shadowhist',ent, newidx)
201 205
202 206 def all(self):
203 207 d = self.db.hdict('shadowhist')
204 208 items = [(i,s) for (s,i) in d.items()]
205 209 items.sort()
206 210 return items
207 211
208 212 def get(self, idx):
209 213 all = self.all()
210 214
211 215 for k, v in all:
212 216 #print k,v
213 217 if k == idx:
214 218 return v
215 219
216 220 def test_shist():
217 221 from IPython.Extensions import pickleshare
218 222 db = pickleshare.PickleShareDB('~/shist')
219 223 s = ShadowHist(db)
220 224 s.add('hello')
221 225 s.add('world')
222 226 s.add('hello')
223 227 s.add('hello')
224 228 s.add('karhu')
225 229 print "all",s.all()
226 230 print s.get(2)
227 231
228 232 def init_ipython(ip):
229 233 ip.expose_magic("rep",rep_f)
230 234 ip.expose_magic("hist",magic_hist)
231 235 ip.expose_magic("history",magic_history)
232 236
233 237 import ipy_completers
234 238 ipy_completers.quick_completer('%hist' ,'-g -t -r -n')
235 239 #test_shist()
General Comments 0
You need to be logged in to leave comments. Login now