~abentley/bzrtools/bzrtools.dev

« back to all changes in this revision

Viewing changes to shell.py

  • Committer: Aaron Bentley
  • Date: 2005-10-30 03:51:19 UTC
  • mfrom: (257.1.3)
  • Revision ID: aaron.bentley@utoronto.ca-20051030035119-7cda4f9164ea6449
Merged latest changes

Show diffs side-by-side

added added

removed removed

Lines of Context:
20
20
import terminal
21
21
import readline
22
22
import string
 
23
from itertools import chain
23
24
from bzrlib.errors import BzrError
24
 
from bzrlib.commands import get_cmd_object
 
25
from bzrlib.commands import get_cmd_object, get_all_cmds
 
26
 
 
27
SHELL_BLACKLIST = set(['rm', 'ls'])
 
28
COMPLETION_BLACKLIST = set(['shell'])
 
29
 
 
30
class BlackListedCommand(BzrError):
 
31
    def __init__(self, command):
 
32
        BzrError.__init__(self, "The command %s is blacklisted for shell use" %
 
33
                          command)
 
34
 
 
35
class CompletionContext(object):
 
36
    def __init__(self, text, command=None, prev_opt=None, arg_pos=None):
 
37
        self.text = text
 
38
        self.command = command
 
39
        self.prev_opt = prev_opt
 
40
        self.arg_pos = None
 
41
 
 
42
    def get_completions(self):
 
43
        if not command:
 
44
            iter = (c for c in iter_command_names() if
 
45
                    c not in COMPLETION_BLACKLIST)
 
46
            try:
 
47
                if len(line) > 0:
 
48
                    arg = line.split()[-1]
 
49
                else:
 
50
                    arg = ""
 
51
                iter = list(iter_munged_completions(iter, arg, text))
 
52
            except Exception, e:
 
53
                print e, type(e)
 
54
 
 
55
 
25
56
 
26
57
class PromptCmd(cmd.Cmd):
27
58
    def __init__(self):
46
77
 
47
78
    def do_quit(self, args):
48
79
        self.write_history()
49
 
        sys.exit(0)
 
80
        raise StopIteration
50
81
 
51
82
    def do_exit(self, args):
52
83
        self.do_quit(args)
103
134
            self.tree = None
104
135
 
105
136
    def do_help(self, line):
106
 
        Help()(line)
 
137
        self.default("help "+line)
107
138
 
108
139
    def default(self, line):
109
140
        args = line.split()
110
141
        commandname = args.pop(0)
 
142
        for char in ('|', '<', '>'):
 
143
            commandname = commandname.split(char)[0]
 
144
        if commandname[-1] in ('|', '<', '>'):
 
145
            commandname = commandname[:-1]
111
146
        try:
 
147
            if commandname in SHELL_BLACKLIST:
 
148
                raise BlackListedCommand(commandname)
112
149
            cmd_obj = get_cmd_object(commandname)
113
 
        except BzrError:
 
150
        except (BlackListedCommand, BzrError):
114
151
            return os.system(line)
115
152
 
116
 
 
117
153
        try:
118
 
            return (cmd_obj.run_argv(args) or 0)
 
154
            if too_complicated(line):
 
155
                return os.system("bzr "+line)
 
156
            else:
 
157
                return (cmd_obj.run_argv(args) or 0)
119
158
        except BzrError, e:
120
159
            print e
121
160
        except KeyboardInterrupt, e:
127
166
 
128
167
    def completenames(self, text, line, begidx, endidx):
129
168
        completions = []
130
 
        iter = iter_command_names(self.fake_aba)
 
169
        iter = (c for c in iter_command_names() if
 
170
                c not in COMPLETION_BLACKLIST)
131
171
        try:
132
172
            if len(line) > 0:
133
173
                arg = line.split()[-1]
134
174
            else:
135
175
                arg = ""
136
 
            iter = cmdutil.iter_munged_completions(iter, arg, text)
 
176
            iter = list(iter_munged_completions(iter, arg, text))
137
177
        except Exception, e:
138
 
            print e
 
178
            print e, type(e)
139
179
        return list(iter)
140
180
 
141
181
    def completedefault(self, text, line, begidx, endidx):
150
190
        :param endidx: The end of the text in the line
151
191
        :type endidx: int
152
192
        """
153
 
        try:
154
 
            (cmd, args, foo) = self.parseline(line)
155
 
            command_obj=find_command(cmd)
 
193
        (cmd, args, foo) = self.parseline(line)
 
194
        if cmd == "bzr":
 
195
            try:
 
196
                return self.completenames(text, line, begidx, endidx)
 
197
            except Exception, e:
 
198
                print e
 
199
        try:
 
200
            command_obj = get_cmd_object(cmd)
 
201
        except BzrError:
 
202
            command_obj = None
 
203
        try:
156
204
            if command_obj is not None:
157
 
                return command_obj.complete(args.split(), text)
158
 
            elif not self.fake_aba.is_command(cmd) and \
159
 
                cmdutil.is_tla_command(cmd):
160
 
                iter = cmdutil.iter_supported_switches(cmd)
161
 
                if len(args) > 0:
162
 
                    arg = args.split()[-1]
163
 
                else:
164
 
                    arg = ""
165
 
                if arg.startswith("-"):
166
 
                    return list(cmdutil.iter_munged_completions(iter, arg, 
167
 
                                                                text))
168
 
                else:
169
 
                    return list(cmdutil.iter_munged_completions(
170
 
                        cmdutil.iter_file_completions(arg), arg, text))
171
 
 
172
 
 
 
205
                opts = []
 
206
                for option_name, option in command_obj.options().items():
 
207
                    opts.append("--" + option_name)
 
208
                    short_name = option.short_name()
 
209
                    if short_name:
 
210
                        opts.append("-" + short_name)
 
211
                q = list(iter_munged_completions(opts, args, text))
 
212
                return list(iter_munged_completions(opts, args, text))
173
213
            elif cmd == "cd":
174
214
                if len(args) > 0:
175
215
                    arg = args.split()[-1]
176
216
                else:
177
217
                    arg = ""
178
 
                iter = cmdutil.iter_dir_completions(arg)
179
 
                iter = cmdutil.iter_munged_completions(iter, arg, text)
 
218
                iter = iter_dir_completions(arg)
 
219
                iter = iter_munged_completions(iter, arg, text)
180
220
                return list(iter)
181
221
            elif len(args)>0:
182
222
                arg = args.split()[-1]
183
 
                iter = cmdutil.iter_file_completions(arg)
184
 
                return list(cmdutil.iter_munged_completions(iter, arg, text))
 
223
                iter = iter_file_completions(arg)
 
224
                return list(iter_munged_completions(iter, arg, text))
185
225
            else:
186
226
                return self.completenames(text, line, begidx, endidx)
187
227
        except Exception, e:
188
228
            print e
189
229
 
190
230
def run_shell():
191
 
    prompt = PromptCmd()
192
231
    try:
193
 
        prompt.cmdloop()
194
 
    finally:
195
 
        prompt.write_history()
 
232
        prompt = PromptCmd()
 
233
        try:
 
234
            prompt.cmdloop()
 
235
        finally:
 
236
            prompt.write_history()
 
237
    except StopIteration:
 
238
        pass
196
239
 
197
240
def iter_file_completions(arg, only_dirs = False):
198
241
    """Generate an iterator that iterates through filename completions.
212
255
        listingdir = os.path.expanduser(dir)
213
256
    else:
214
257
        listingdir = cwd
215
 
    for file in iter_combine([os.listdir(listingdir), extras]):
 
258
    for file in chain(os.listdir(listingdir), extras):
216
259
        if dir != "":
217
260
            userfile = dir+'/'+file
218
261
        else:
232
275
    :type arg: str
233
276
    """
234
277
    return iter_file_completions(arg, True)
 
278
 
 
279
def iter_command_names(hidden=False):
 
280
    for real_cmd_name, cmd_class in get_all_cmds():
 
281
        if not hidden and cmd_class.hidden:
 
282
            continue
 
283
        for name in [real_cmd_name] + cmd_class.aliases:
 
284
            # Don't complete on aliases that are prefixes of the canonical name
 
285
            if name == real_cmd_name or not real_cmd_name.startswith(name):
 
286
                yield name
 
287
 
 
288
def iter_munged_completions(iter, arg, text):
 
289
    for completion in iter:
 
290
        completion = str(completion)
 
291
        if completion.startswith(arg):
 
292
            yield completion[len(arg)-len(text):]+" "
 
293
 
 
294
def too_complicated(line):
 
295
    for char in '|<>"\"*?':
 
296
        if char in line:
 
297
            return True
 
298
    return False