~abentley/bzrtools/bzrtools.dev

« back to all changes in this revision

Viewing changes to shell.py

  • Committer: Aaron Bentley
  • Date: 2013-08-20 03:02:43 UTC
  • Revision ID: aaron@aaronbentley.com-20130820030243-r8v1xfbcnd8f10p4
Fix zap command for 2.6/7

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
# Copyright (C) 2004, 2005 Aaron Bentley
2
 
# <aaron.bentley@utoronto.ca>
 
2
# <aaron@aaronbentley.com>
3
3
#
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
18
18
import cmd
19
19
from itertools import chain
20
20
import os
21
 
import readline
 
21
try:
 
22
    import readline
 
23
except ImportError:
 
24
    _has_readline = False
 
25
else:
 
26
    _has_readline = True
22
27
import shlex
 
28
import stat
23
29
import string
24
30
import sys
25
31
 
 
32
from bzrlib import osutils, trace
26
33
from bzrlib.branch import Branch
27
 
from bzrlib.commands import get_cmd_object, get_all_cmds, get_alias
 
34
from bzrlib.config import config_dir, ensure_config_dir_exists
 
35
from bzrlib.commands import get_cmd_object, all_command_names, get_alias
28
36
from bzrlib.errors import BzrError
 
37
from bzrlib.workingtree import WorkingTree
29
38
 
30
39
import terminal
31
40
 
64
73
 
65
74
    def get_completions_or_raise(self):
66
75
        if self.command is None:
67
 
            iter = (c+" " for c in iter_command_names() if
68
 
                    c not in COMPLETION_BLACKLIST)
 
76
            if '/' in self.text:
 
77
                iter = iter_executables(self.text)
 
78
            else:
 
79
                iter = (c+" " for c in iter_command_names() if
 
80
                        c not in COMPLETION_BLACKLIST)
69
81
            return list(filter_completions(iter, self.text))
70
82
        if self.prev_opt is None:
71
83
            completions = self.get_option_completions()
74
86
                completions.extend(list(filter_completions(iter, self.text)))
75
87
            else:
76
88
                iter = iter_file_completions(self.text)
77
 
                completions.extend([f+" " for f in 
78
 
                                    filter_completions(iter, self.text)])
79
 
            return completions 
 
89
                completions.extend(filter_completions(iter, self.text))
 
90
            return completions
80
91
 
81
92
 
82
93
class PromptCmd(cmd.Cmd):
 
94
 
83
95
    def __init__(self):
84
96
        cmd.Cmd.__init__(self)
85
97
        self.prompt = "bzr> "
90
102
        self.set_title()
91
103
        self.set_prompt()
92
104
        self.identchars += '-'
93
 
        self.history_file = os.path.expanduser("~/.bazaar/shell-history")
94
 
        readline.set_completer_delims(string.whitespace)
95
 
        if os.access(self.history_file, os.R_OK) and \
96
 
            os.path.isfile(self.history_file):
97
 
            readline.read_history_file(self.history_file)
 
105
        ensure_config_dir_exists()
 
106
        self.history_file = osutils.pathjoin(config_dir(), 'shell-history')
 
107
        whitespace = ''.join(c for c in string.whitespace if c < chr(127))
 
108
        if _has_readline:
 
109
            readline.set_completer_delims(whitespace)
 
110
            if os.access(self.history_file, os.R_OK) and \
 
111
                os.path.isfile(self.history_file):
 
112
                readline.read_history_file(self.history_file)
98
113
        self.cwd = os.getcwd()
99
114
 
100
115
    def write_history(self):
101
 
        readline.write_history_file(self.history_file)
 
116
        if _has_readline:
 
117
            readline.write_history_file(self.history_file)
102
118
 
103
119
    def do_quit(self, args):
104
120
        self.write_history()
118
134
    def set_prompt(self):
119
135
        if self.tree is not None:
120
136
            try:
121
 
                prompt_data = (self.tree.branch.nick, self.tree.branch.revno(), 
122
 
                               self.tree.branch.relpath('.'))
 
137
                prompt_data = (self.tree.branch.nick, self.tree.branch.revno(),
 
138
                               self.tree.relpath('.'))
123
139
                prompt = " %s:%d/%s" % prompt_data
124
140
            except:
125
141
                prompt = ""
160
176
        self.default("help "+line)
161
177
 
162
178
    def default(self, line):
163
 
        args = shlex.split(line)
 
179
        try:
 
180
            args = shlex.split(line)
 
181
        except ValueError, e:
 
182
            print 'Parse error:', e
 
183
            return
 
184
 
164
185
        alias_args = get_alias(args[0])
165
186
        if alias_args is not None:
166
187
            args[0] = alias_args.pop(0)
167
 
            
 
188
 
168
189
        commandname = args.pop(0)
169
190
        for char in ('|', '<', '>'):
170
191
            commandname = commandname.split(char)[0]
178
199
            return os.system(line)
179
200
 
180
201
        try:
181
 
            if too_complicated(line):
 
202
            is_qbzr = cmd_obj.__module__.startswith('bzrlib.plugins.qbzr.')
 
203
            if too_complicated(line) or is_qbzr:
182
204
                return os.system("bzr "+line)
183
205
            else:
184
206
                return (cmd_obj.run_argv_aliases(args, alias_args) or 0)
185
207
        except BzrError, e:
 
208
            trace.log_exception_quietly()
186
209
            print e
187
210
        except KeyboardInterrupt, e:
188
211
            print "Interrupted"
189
212
        except Exception, e:
190
 
#            print "Unhandled error:\n%s" % errors.exception_str(e)
 
213
            trace.log_exception_quietly()
191
214
            print "Unhandled error:\n%s" % (e)
192
215
 
193
216
 
196
219
 
197
220
    def completedefault(self, text, line, begidx, endidx):
198
221
        """Perform completion for native commands.
199
 
        
 
222
 
200
223
        :param text: The text to complete
201
224
        :type text: str
202
225
        :param line: The entire line to complete
212
235
        return CompletionContext(text, command=cmd).get_completions()
213
236
 
214
237
 
215
 
def run_shell():
 
238
def run_shell(directory=None):
216
239
    try:
 
240
        if not directory is None:
 
241
            os.chdir(directory)
217
242
        prompt = PromptCmd()
218
 
        try:
219
 
            prompt.cmdloop()
220
 
        finally:
221
 
            prompt.write_history()
 
243
        while True:
 
244
            try:
 
245
                try:
 
246
                    prompt.cmdloop()
 
247
                except KeyboardInterrupt:
 
248
                    print
 
249
            finally:
 
250
                prompt.write_history()
222
251
    except StopIteration:
223
252
        pass
224
253
 
259
288
                userfile+='/'
260
289
                yield userfile
261
290
            elif not only_dirs:
262
 
                yield userfile
 
291
                yield userfile + ' '
263
292
 
264
293
 
265
294
def iter_dir_completions(arg):
272
301
 
273
302
 
274
303
def iter_command_names(hidden=False):
275
 
    for real_cmd_name, cmd_class in get_all_cmds():
276
 
        if not hidden and cmd_class.hidden:
 
304
    for real_cmd_name in all_command_names():
 
305
        cmd_obj = get_cmd_object(real_cmd_name)
 
306
        if not hidden and cmd_obj.hidden:
277
307
            continue
278
 
        for name in [real_cmd_name] + cmd_class.aliases:
 
308
        for name in [real_cmd_name] + cmd_obj.aliases:
279
309
            # Don't complete on aliases that are prefixes of the canonical name
280
310
            if name == real_cmd_name or not real_cmd_name.startswith(name):
281
311
                yield name
282
312
 
283
313
 
 
314
def iter_executables(path):
 
315
    dirname, partial = os.path.split(path)
 
316
    for filename in os.listdir(dirname):
 
317
        if not filename.startswith(partial):
 
318
            continue
 
319
        fullpath = os.path.join(dirname, filename)
 
320
        mode=os.lstat(fullpath)[stat.ST_MODE]
 
321
        if stat.S_ISREG(mode) and 0111 & mode:
 
322
            yield fullpath + ' '
 
323
 
 
324
 
284
325
def filter_completions(iter, arg):
285
326
    return (c for c in iter if c.startswith(arg))
286
327