1
# Copyright (C) 2004, 2005 Aaron Bentley
2
# <aaron.bentley@utoronto.ca>
4
# This program is free software; you can redistribute it and/or modify
5
# it under the terms of the GNU General Public License as published by
6
# the Free Software Foundation; either version 2 of the License, or
7
# (at your option) any later version.
9
# This program is distributed in the hope that it will be useful,
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
# GNU General Public License for more details.
14
# You should have received a copy of the GNU General Public License
15
# along with this program; if not, write to the Free Software
16
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23
from itertools import chain
24
from bzrlib.errors import BzrError
25
from bzrlib.commands import get_cmd_object, get_all_cmds, get_alias
26
from bzrlib.branch import Branch
28
SHELL_BLACKLIST = set(['rm', 'ls'])
29
COMPLETION_BLACKLIST = set(['shell'])
31
class BlackListedCommand(BzrError):
32
def __init__(self, command):
33
BzrError.__init__(self, "The command %s is blacklisted for shell use" %
36
class CompletionContext(object):
37
def __init__(self, text, command=None, prev_opt=None, arg_pos=None):
39
self.command = command
40
self.prev_opt = prev_opt
43
def get_completions(self):
45
return self.get_completions_or_raise()
50
def get_option_completions(self):
52
command_obj = get_cmd_object(self.command)
55
opts = [o+" " for o in iter_opt_completions(command_obj)]
56
return list(filter_completions(opts, self.text))
58
def get_completions_or_raise(self):
59
if self.command is None:
60
iter = (c+" " for c in iter_command_names() if
61
c not in COMPLETION_BLACKLIST)
62
return list(filter_completions(iter, self.text))
63
if self.prev_opt is None:
64
completions = self.get_option_completions()
65
if self.command == "cd":
66
iter = iter_dir_completions(self.text)
67
completions.extend(list(filter_completions(iter, self.text)))
69
iter = iter_file_completions(self.text)
70
completions.extend([f+" " for f in
71
filter_completions(iter, self.text)])
75
1
class PromptCmd(cmd.Cmd):
77
3
cmd.Cmd.__init__(self)
80
self.tree = WorkingTree.open_containing('.')[0]
6
self.tree = arch.tree_root(".")
11
self.fake_aba = abacmds.AbaCmds()
85
12
self.identchars += '-'
86
self.history_file = os.path.expanduser("~/.bazaar/shell-history")
13
self.history_file = os.path.expanduser("~/.fai-history")
87
14
readline.set_completer_delims(string.whitespace)
88
15
if os.access(self.history_file, os.R_OK) and \
89
16
os.path.isfile(self.history_file):
111
38
def set_prompt(self):
112
39
if self.tree is not None:
114
prompt_data = (self.tree.branch.nick, self.tree.branch.revno(),
115
self.tree.branch.relpath('.'))
116
prompt = " %s:%d/%s" % prompt_data
41
prompt = pylon.alias_or_version(self.tree.tree_version,
44
if prompt is not None:
45
prompt = " " + prompt +":"+ pylon.tree_cwd(self.tree)
121
self.prompt = "bzr%s> " % prompt
50
self.prompt = "Fai%s> " % prompt
123
52
def set_title(self, command=None):
125
b = Branch.open_containing('.')[0]
126
version = "%s:%d" % (b.nick, b.revno())
54
version = pylon.alias_or_version(self.tree.tree_version, self.tree,
128
57
version = "[no version]"
129
58
if command is None:
131
sys.stdout.write(terminal.term_title("bzr %s %s" % (command, version)))
60
sys.stdout.write(terminal.term_title("Fai %s %s" % (command, version)))
133
62
def do_cd(self, line):
145
74
except Exception, e:
148
self.tree = WorkingTree.open_containing(".")[0]
77
self.tree = arch.tree_root(".")
152
81
def do_help(self, line):
153
self.default("help "+line)
155
84
def default(self, line):
156
85
args = line.split()
157
alias_args = get_alias(args[0])
158
if alias_args is not None:
159
args[0] = alias_args.pop(0)
161
commandname = args.pop(0)
162
for char in ('|', '<', '>'):
163
commandname = commandname.split(char)[0]
164
if commandname[-1] in ('|', '<', '>'):
165
commandname = commandname[:-1]
167
if commandname in SHELL_BLACKLIST:
168
raise BlackListedCommand(commandname)
169
cmd_obj = get_cmd_object(commandname)
170
except (BlackListedCommand, BzrError):
171
return os.system(line)
174
if too_complicated(line):
175
return os.system("bzr "+line)
177
return (cmd_obj.run_argv_aliases(args, alias_args) or 0)
180
except KeyboardInterrupt, e:
183
# print "Unhandled error:\n%s" % errors.exception_str(e)
184
print "Unhandled error:\n%s" % (e)
86
if find_command(args[0]):
88
find_command(args[0]).do_command(args[1:])
89
except cmdutil.BadCommandOption, e:
91
except cmdutil.GetHelp, e:
92
find_command(args[0]).help()
93
except CommandFailed, e:
95
except arch.errors.ArchiveNotRegistered, e:
97
except KeyboardInterrupt, e:
99
except arch.util.ExecProblem, e:
100
print e.proc.error.rstrip('\n')
101
except cmdutil.CantDetermineVersion, e:
103
except cmdutil.CantDetermineRevision, e:
106
print "Unhandled error:\n%s" % errors.exception_str(e)
108
elif suggestions.has_key(args[0]):
109
print suggestions[args[0]]
111
elif self.fake_aba.is_command(args[0]):
114
tree = arch.tree_root(".")
115
except arch.errors.TreeRootError:
117
cmd = self.fake_aba.is_command(args[0])
119
args = cmdutil.expand_prefix_alias(args[1:], tree)
125
except KeyboardInterrupt, e:
128
elif options.tla_fallthrough and args[0] != "rm" and \
129
cmdutil.is_tla_command(args[0]):
133
tree = arch.tree_root(".")
134
except arch.errors.TreeRootError:
137
args = cmdutil.expand_prefix_alias(args, tree)
141
arch.util.exec_safe('tla', args, stderr=sys.stderr,
142
stdout=sys.stdout, expected=(0, 1))
143
except arch.util.ExecProblem, e:
145
except KeyboardInterrupt, e:
150
tree = arch.tree_root(".")
151
except arch.errors.TreeRootError:
155
args = cmdutil.expand_prefix_alias(args, tree)
159
os.system(" ".join(args))
160
except KeyboardInterrupt, e:
187
163
def completenames(self, text, line, begidx, endidx):
188
return CompletionContext(text).get_completions()
165
iter = iter_command_names(self.fake_aba)
168
arg = line.split()[-1]
171
iter = cmdutil.iter_munged_completions(iter, arg, text)
190
176
def completedefault(self, text, line, begidx, endidx):
191
177
"""Perform completion for native commands.
199
185
:param endidx: The end of the text in the line
200
186
:type endidx: int
202
(cmd, args, foo) = self.parseline(line)
205
return CompletionContext(text, command=cmd).get_completions()
189
(cmd, args, foo) = self.parseline(line)
190
command_obj=find_command(cmd)
191
if command_obj is not None:
192
return command_obj.complete(args.split(), text)
193
elif not self.fake_aba.is_command(cmd) and \
194
cmdutil.is_tla_command(cmd):
195
iter = cmdutil.iter_supported_switches(cmd)
197
arg = args.split()[-1]
200
if arg.startswith("-"):
201
return list(cmdutil.iter_munged_completions(iter, arg,
204
return list(cmdutil.iter_munged_completions(
205
cmdutil.iter_file_completions(arg), arg, text))
210
arg = args.split()[-1]
213
iter = cmdutil.iter_dir_completions(arg)
214
iter = cmdutil.iter_munged_completions(iter, arg, text)
217
arg = args.split()[-1]
218
iter = cmdutil.iter_file_completions(arg)
219
return list(cmdutil.iter_munged_completions(iter, arg, text))
221
return self.completenames(text, line, begidx, endidx)
227
raise cmdutil.GetHelp
213
prompt.write_history()
214
except StopIteration:
217
def iter_opt_completions(command_obj):
218
for option_name, option in command_obj.options().items():
219
yield "--" + option_name
220
short_name = option.short_name()
222
yield "-" + short_name
232
prompt.write_history()
224
234
def iter_file_completions(arg, only_dirs = False):
225
235
"""Generate an iterator that iterates through filename completions.
261
271
return iter_file_completions(arg, True)
263
def iter_command_names(hidden=False):
264
for real_cmd_name, cmd_class in get_all_cmds():
265
if not hidden and cmd_class.hidden:
267
for name in [real_cmd_name] + cmd_class.aliases:
268
# Don't complete on aliases that are prefixes of the canonical name
269
if name == real_cmd_name or not real_cmd_name.startswith(name):
272
def filter_completions(iter, arg):
273
return (c for c in iter if c.startswith(arg))
275
def iter_munged_completions(iter, arg, text):
276
for completion in iter:
277
completion = str(completion)
278
if completion.startswith(arg):
279
yield completion[len(arg)-len(text):]+" "
281
def too_complicated(line):
282
for char in '|<>"\"*?':