comparison cmd2.py @ 21:8b55aaa52ce9

working on load, and preserving stdin/out
author devlinjs@FA7CZA6N1254998.wrightpatterson.afmc.ds.af.mil
date Wed, 19 Dec 2007 13:40:39 -0500
parents d6d64c2e3b98
children 221095f3a4af
comparison
equal deleted inserted replaced
20:d6d64c2e3b98 21:8b55aaa52ce9
2 2
3 Searchable command history 3 Searchable command history
4 Multi-line commands 4 Multi-line commands
5 Case-insensitive commands 5 Case-insensitive commands
6 Special-character shortcut commands 6 Special-character shortcut commands
7
8 still to do:
9 environment (maxrows, etc.)
10 edit
11
7 """ 12 """
8 import cmd, re, os 13 import cmd, re, os
9 14
10 class Cmd(cmd.Cmd): 15 class Cmd(cmd.Cmd):
11 excludeFromHistory = '''run r list l history hi ed li'''.split()
12 caseInsensitive = True 16 caseInsensitive = True
13 multilineCommands = [] 17 multilineCommands = []
14 continuationPrompt = '> ' 18 continuationPrompt = '> '
15 shortcuts = {'?': 'help', '!': 'shell'} 19 shortcuts = {'?': 'help', '!': 'shell', '@': 'load'}
20 excludeFromHistory = '''run r list l history hi ed li'''.split()
21 defaultExtension = 'txt'
16 def __init__(self, *args, **kwargs): 22 def __init__(self, *args, **kwargs):
17 cmd.Cmd.__init__(self, *args, **kwargs) 23 cmd.Cmd.__init__(self, *args, **kwargs)
18 self.history = History() 24 self.history = History()
19 25
20 def precmd(self, line): 26 def precmd(self, line):
44 return stop 50 return stop
45 51
46 def finishStatement(self, firstline): 52 def finishStatement(self, firstline):
47 statement = firstline 53 statement = firstline
48 while not self.statementHasEnded(statement): 54 while not self.statementHasEnded(statement):
49 statement = '%s\n%s' % (statement, raw_input(self.continuationPrompt)) 55 statement = '%s\n%s' % (statement, self.pseudo_raw_input(self.continuationPrompt))
50 return statement 56 return statement
51 # assembling a list of lines and joining them at the end would be faster, 57 # assembling a list of lines and joining them at the end would be faster,
52 # but statementHasEnded needs a string arg; anyway, we're getting 58 # but statementHasEnded needs a string arg; anyway, we're getting
53 # user input and users are slow. 59 # user input and users are slow.
54 60
61 def pseudo_raw_input(self, prompt):
62 """copied from cmd's cmdloop; like raw_input, but accounts for changed stdin, stdout"""
63
64 if self.use_rawinput:
65 try:
66 line = raw_input(prompt)
67 except EOFError:
68 line = 'EOF'
69 else:
70 self.stdout.write(prompt)
71 self.stdout.flush()
72 line = self.stdin.readline()
73 if not len(line):
74 line = 'EOF'
75 else:
76 line = line[:-1] # chop \n
77 return line
78
55 statementEndPattern = re.compile(r'[\n;]\s*$') 79 statementEndPattern = re.compile(r'[\n;]\s*$')
56 def statementHasEnded(self, lines): 80 def statementHasEnded(self, lines):
57 """This version lets statements end with ; or with a blank line. 81 """This version lets statements end with ; or with a blank line.
58 Override for your own needs.""" 82 Override for your own needs."""
59 return bool(self.statementEndPattern.search(lines)) 83 return bool(self.statementEndPattern.search(lines))
89 if arg: 113 if arg:
90 history = self.history.get(arg) 114 history = self.history.get(arg)
91 else: 115 else:
92 history = self.history 116 history = self.history
93 for hi in history: 117 for hi in history:
94 hi.pr() 118 self.stdout.write(hi.pr())
95 def last_matching(self, arg): 119 def last_matching(self, arg):
96 try: 120 try:
97 if arg: 121 if arg:
98 return self.history.get(arg)[-1] 122 return self.history.get(arg)[-1]
99 else: 123 else:
108 - arg, arg - (integer) -> list up to or after #arg 132 - arg, arg - (integer) -> list up to or after #arg
109 arg is string -> list last command matching string search 133 arg is string -> list last command matching string search
110 arg is /enclosed in forward-slashes/ -> regular expression search 134 arg is /enclosed in forward-slashes/ -> regular expression search
111 """ 135 """
112 try: 136 try:
113 self.last_matching(arg).pr() 137 self.stdout.write(self.last_matching(arg).pr())
114 except: 138 except:
115 pass 139 pass
116 do_hi = do_history 140 do_hi = do_history
117 do_l = do_list 141 do_l = do_list
118 do_li = do_list 142 do_li = do_list
143
144 def breakupStatements(self, txt):
145 """takes text that may include multiple statements and
146 breaks it into a list of individual statements."""
147 result = ['']
148 for line in txt.splitlines():
149 result[-1] += line
150 if self.statementHasEnded(result[-1]):
151 result.append('')
152
153 def do_load(self, fname):
154 """Runs command(s) from a file."""
155 stdin = self.stdin
156 try:
157 self.stdin = open(fname, 'r')
158 except IOError, e:
159 try:
160 self.stdin = open('%s.%s' % (fname, self.defaultExtension), 'r')
161 except:
162 print 'Problem opening file %s: \n%s' % (fname, e)
163 self.stdin = stdin
164 return
165 use_rawinput = self.use_rawinput
166 self.use_rawinput = False
167 print 'stdin = ' + str(self.stdin)
168 self.cmdloop()
169 self.stdin.close()
170 self.stdin = stdin
171 self.use_rawinput = use_rawinput
119 172
120 class HistoryItem(str): 173 class HistoryItem(str):
121 def __init__(self, instr): 174 def __init__(self, instr):
122 str.__init__(self, instr) 175 str.__init__(self, instr)
123 self.lowercase = self.lower() 176 self.lowercase = self.lower()
124 self.idx = None 177 self.idx = None
125 def pr(self): 178 def pr(self):
126 print '-------------------------[%d]' % (self.idx) 179 return '-------------------------[%d]\n%s\n' % (self.idx, str(self))
127 print self
128 180
129 class History(list): 181 class History(list):
130 rangeFrom = re.compile(r'^([\d])+\s*\-$') 182 rangeFrom = re.compile(r'^([\d])+\s*\-$')
131 def append(self, new): 183 def append(self, new):
132 new = HistoryItem(new) 184 new = HistoryItem(new)