~abentley/bzrtools/bzrtools.dev

« back to all changes in this revision

Viewing changes to shell.py

  • Committer: Aaron Bentley
  • Date: 2007-05-18 09:20:47 UTC
  • Revision ID: aaron.bentley@utoronto.ca-20070518092047-c25wfogkpw1c8yj1
Tags: release-0.17.0
Update version number to 0.17.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
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
 
17
 
17
18
import cmd
18
 
import sys
 
19
from itertools import chain
19
20
import os
20
 
import terminal
21
21
import readline
 
22
import shlex
 
23
import stat
22
24
import string
23
 
from itertools import chain
 
25
import sys
 
26
 
 
27
from bzrlib.branch import Branch
 
28
from bzrlib.commands import get_cmd_object, get_all_cmds, get_alias
24
29
from bzrlib.errors import BzrError
25
 
from bzrlib.commands import get_cmd_object, get_all_cmds
26
 
from bzrlib.branch import Branch
 
30
from bzrlib.workingtree import WorkingTree
 
31
 
 
32
import terminal
 
33
 
27
34
 
28
35
SHELL_BLACKLIST = set(['rm', 'ls'])
29
36
COMPLETION_BLACKLIST = set(['shell'])
30
37
 
 
38
 
31
39
class BlackListedCommand(BzrError):
32
40
    def __init__(self, command):
33
41
        BzrError.__init__(self, "The command %s is blacklisted for shell use" %
34
42
                          command)
35
43
 
 
44
 
36
45
class CompletionContext(object):
37
46
    def __init__(self, text, command=None, prev_opt=None, arg_pos=None):
38
47
        self.text = text
57
66
 
58
67
    def get_completions_or_raise(self):
59
68
        if self.command is None:
60
 
            iter = (c+" " for c in iter_command_names() if
61
 
                    c not in COMPLETION_BLACKLIST)
 
69
            if '/' in self.text:
 
70
                iter = iter_executables(self.text)
 
71
            else:
 
72
                iter = (c+" " for c in iter_command_names() if
 
73
                        c not in COMPLETION_BLACKLIST)
62
74
            return list(filter_completions(iter, self.text))
63
75
        if self.prev_opt is None:
64
76
            completions = self.get_option_completions()
67
79
                completions.extend(list(filter_completions(iter, self.text)))
68
80
            else:
69
81
                iter = iter_file_completions(self.text)
70
 
                completions.extend([f+" " for f in 
71
 
                                    filter_completions(iter, self.text)])
 
82
                completions.extend(filter_completions(iter, self.text))
72
83
            return completions 
73
84
 
74
85
 
77
88
        cmd.Cmd.__init__(self)
78
89
        self.prompt = "bzr> "
79
90
        try:
80
 
            self.branch = Branch.open_containing('.')[0]
 
91
            self.tree = WorkingTree.open_containing('.')[0]
81
92
        except:
82
 
            self.branch = None
 
93
            self.tree = None
83
94
        self.set_title()
84
95
        self.set_prompt()
85
96
        self.identchars += '-'
109
120
        self.set_prompt()
110
121
 
111
122
    def set_prompt(self):
112
 
        if self.branch is not None:
 
123
        if self.tree is not None:
113
124
            try:
114
 
                prompt_data = (self.branch.nick, self.branch.revno(), 
115
 
                               self.branch.working_tree().relpath('.'))
 
125
                prompt_data = (self.tree.branch.nick, self.tree.branch.revno(), 
 
126
                               self.tree.relpath('.'))
116
127
                prompt = " %s:%d/%s" % prompt_data
117
128
            except:
118
129
                prompt = ""
145
156
        except Exception, e:
146
157
            print e
147
158
        try:
148
 
            self.branch = Branch.open_containing(".")[0]
 
159
            self.tree = WorkingTree.open_containing(".")[0]
149
160
        except:
150
 
            self.branch = None
 
161
            self.tree = None
151
162
 
152
163
    def do_help(self, line):
153
164
        self.default("help "+line)
154
165
 
155
166
    def default(self, line):
156
 
        args = line.split()
 
167
        args = shlex.split(line)
 
168
        alias_args = get_alias(args[0])
 
169
        if alias_args is not None:
 
170
            args[0] = alias_args.pop(0)
 
171
            
157
172
        commandname = args.pop(0)
158
173
        for char in ('|', '<', '>'):
159
174
            commandname = commandname.split(char)[0]
170
185
            if too_complicated(line):
171
186
                return os.system("bzr "+line)
172
187
            else:
173
 
                return (cmd_obj.run_argv(args) or 0)
 
188
                return (cmd_obj.run_argv_aliases(args, alias_args) or 0)
174
189
        except BzrError, e:
175
190
            print e
176
191
        except KeyboardInterrupt, e:
200
215
            cmd = None
201
216
        return CompletionContext(text, command=cmd).get_completions()
202
217
 
 
218
 
203
219
def run_shell():
204
220
    try:
205
221
        prompt = PromptCmd()
210
226
    except StopIteration:
211
227
        pass
212
228
 
 
229
 
213
230
def iter_opt_completions(command_obj):
214
231
    for option_name, option in command_obj.options().items():
215
232
        yield "--" + option_name
217
234
        if short_name:
218
235
            yield "-" + short_name
219
236
 
 
237
 
220
238
def iter_file_completions(arg, only_dirs = False):
221
239
    """Generate an iterator that iterates through filename completions.
222
240
 
245
263
                userfile+='/'
246
264
                yield userfile
247
265
            elif not only_dirs:
248
 
                yield userfile
 
266
                yield userfile + ' '
249
267
 
250
268
 
251
269
def iter_dir_completions(arg):
256
274
    """
257
275
    return iter_file_completions(arg, True)
258
276
 
 
277
 
259
278
def iter_command_names(hidden=False):
260
279
    for real_cmd_name, cmd_class in get_all_cmds():
261
280
        if not hidden and cmd_class.hidden:
265
284
            if name == real_cmd_name or not real_cmd_name.startswith(name):
266
285
                yield name
267
286
 
 
287
 
 
288
def iter_executables(path):
 
289
    dirname, partial = os.path.split(path)
 
290
    for filename in os.listdir(dirname):
 
291
        if not filename.startswith(partial):
 
292
            continue
 
293
        fullpath = os.path.join(dirname, filename)
 
294
        mode=os.lstat(fullpath)[stat.ST_MODE]
 
295
        if stat.S_ISREG(mode) and 0111 & mode:
 
296
            yield fullpath + ' '
 
297
 
 
298
 
268
299
def filter_completions(iter, arg):
269
300
    return (c for c in iter if c.startswith(arg))
270
301
 
 
302
 
271
303
def iter_munged_completions(iter, arg, text):
272
304
    for completion in iter:
273
305
        completion = str(completion)
274
306
        if completion.startswith(arg):
275
307
            yield completion[len(arg)-len(text):]+" "
276
308
 
 
309
 
277
310
def too_complicated(line):
278
 
    for char in '|<>"\"*?':
 
311
    for char in '|<>*?':
279
312
        if char in line:
280
313
            return True
281
314
    return False