~ipython-contrib/+junk/ipython-zmq

« back to all changes in this revision

Viewing changes to IPython/history.py

  • Committer: ville
  • Date: 2008-02-16 09:50:47 UTC
  • mto: (0.12.1 ipython_main)
  • mto: This revision was merged to the branch mainline in revision 990.
  • Revision ID: ville@ville-pc-20080216095047-500x6dluki1iz40o
initialization (no svn history)

Show diffs side-by-side

added added

removed removed

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