1
1
# Copyright (C) 2004, 2005 Aaron Bentley
2
# <aaron.bentley@utoronto.ca>
2
# <aaron@aaronbentley.com>
4
4
# This program is free software; you can redistribute it and/or modify
5
5
# it under the terms of the GNU General Public License as published by
14
14
# You should have received a copy of the GNU General Public License
15
15
# along with this program; if not, write to the Free Software
16
16
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19
from itertools import chain
23
from itertools import chain
27
from bzrlib import osutils
28
from bzrlib.branch import Branch
29
from bzrlib.config import config_dir, ensure_config_dir_exists
30
from bzrlib.commands import get_cmd_object, get_all_cmds, get_alias
24
31
from bzrlib.errors import BzrError
25
from bzrlib.commands import get_cmd_object, get_all_cmds, get_alias
26
from bzrlib.branch import Branch
32
from bzrlib.workingtree import WorkingTree
28
37
SHELL_BLACKLIST = set(['rm', 'ls'])
29
38
COMPLETION_BLACKLIST = set(['shell'])
31
41
class BlackListedCommand(BzrError):
32
42
def __init__(self, command):
33
43
BzrError.__init__(self, "The command %s is blacklisted for shell use" %
36
47
class CompletionContext(object):
37
48
def __init__(self, text, command=None, prev_opt=None, arg_pos=None):
58
69
def get_completions_or_raise(self):
59
70
if self.command is None:
60
iter = (c+" " for c in iter_command_names() if
61
c not in COMPLETION_BLACKLIST)
72
iter = iter_executables(self.text)
74
iter = (c+" " for c in iter_command_names() if
75
c not in COMPLETION_BLACKLIST)
62
76
return list(filter_completions(iter, self.text))
63
77
if self.prev_opt is None:
64
78
completions = self.get_option_completions()
67
81
completions.extend(list(filter_completions(iter, self.text)))
69
83
iter = iter_file_completions(self.text)
70
completions.extend([f+" " for f in
71
filter_completions(iter, self.text)])
84
completions.extend(filter_completions(iter, self.text))
75
88
class PromptCmd(cmd.Cmd):
76
90
def __init__(self):
77
91
cmd.Cmd.__init__(self)
78
92
self.prompt = "bzr> "
85
99
self.identchars += '-'
86
self.history_file = os.path.expanduser("~/.bazaar/shell-history")
100
ensure_config_dir_exists()
101
self.history_file = osutils.pathjoin(config_dir(), 'shell-history')
87
102
readline.set_completer_delims(string.whitespace)
88
103
if os.access(self.history_file, os.R_OK) and \
89
104
os.path.isfile(self.history_file):
111
126
def set_prompt(self):
112
127
if self.tree is not None:
114
prompt_data = (self.tree.branch.nick, self.tree.branch.revno(),
115
self.tree.branch.relpath('.'))
129
prompt_data = (self.tree.branch.nick, self.tree.branch.revno(),
130
self.tree.relpath('.'))
116
131
prompt = " %s:%d/%s" % prompt_data
153
168
self.default("help "+line)
155
170
def default(self, line):
171
args = shlex.split(line)
157
172
alias_args = get_alias(args[0])
158
173
if alias_args is not None:
159
174
args[0] = alias_args.pop(0)
161
176
commandname = args.pop(0)
162
177
for char in ('|', '<', '>'):
163
178
commandname = commandname.split(char)[0]
190
205
def completedefault(self, text, line, begidx, endidx):
191
206
"""Perform completion for native commands.
193
208
:param text: The text to complete
195
210
:param line: The entire line to complete
261
279
return iter_file_completions(arg, True)
263
282
def iter_command_names(hidden=False):
264
283
for real_cmd_name, cmd_class in get_all_cmds():
265
284
if not hidden and cmd_class.hidden:
269
288
if name == real_cmd_name or not real_cmd_name.startswith(name):
292
def iter_executables(path):
293
dirname, partial = os.path.split(path)
294
for filename in os.listdir(dirname):
295
if not filename.startswith(partial):
297
fullpath = os.path.join(dirname, filename)
298
mode=os.lstat(fullpath)[stat.ST_MODE]
299
if stat.S_ISREG(mode) and 0111 & mode:
272
303
def filter_completions(iter, arg):
273
304
return (c for c in iter if c.startswith(arg))
275
307
def iter_munged_completions(iter, arg, text):
276
308
for completion in iter:
277
309
completion = str(completion)
278
310
if completion.startswith(arg):
279
311
yield completion[len(arg)-len(text):]+" "
281
314
def too_complicated(line):
282
for char in '|<>"\"*?':