##// END OF EJS Templates
doc, changelog
vivainio -
Show More

The requested changes are too big and content was truncated. Show full diff

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