~abentley/bzrtools/bzrtools.dev

« back to all changes in this revision

Viewing changes to shell.py

  • Committer: Aaron Bentley
  • Date: 2005-10-27 04:45:06 UTC
  • Revision ID: aaron.bentley@utoronto.ca-20051027044506-45f616c07537a1da
Got the shell basics working properly

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Copyright (C) 2004, 2005 Aaron Bentley
 
2
# <aaron.bentley@utoronto.ca>
 
3
#
 
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.
 
8
#
 
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.
 
13
#
 
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
 
17
import cmd
 
18
import sys
 
19
import os
 
20
import terminal
 
21
import readline
 
22
import string
 
23
from bzrlib.errors import BzrError
 
24
from bzrlib.commands import get_cmd_object
 
25
 
 
26
class PromptCmd(cmd.Cmd):
 
27
    def __init__(self):
 
28
        cmd.Cmd.__init__(self)
 
29
        self.prompt = "bzr> "
 
30
        try:
 
31
            self.tree = arch.tree_root(".")
 
32
        except:
 
33
            self.tree = None
 
34
        self.set_title()
 
35
        self.set_prompt()
 
36
        self.identchars += '-'
 
37
        self.history_file = os.path.expanduser("~/.bazaar/shell-history")
 
38
        readline.set_completer_delims(string.whitespace)
 
39
        if os.access(self.history_file, os.R_OK) and \
 
40
            os.path.isfile(self.history_file):
 
41
            readline.read_history_file(self.history_file)
 
42
        self.cwd = os.getcwd()
 
43
 
 
44
    def write_history(self):
 
45
        readline.write_history_file(self.history_file)
 
46
 
 
47
    def do_quit(self, args):
 
48
        self.write_history()
 
49
        sys.exit(0)
 
50
 
 
51
    def do_exit(self, args):
 
52
        self.do_quit(args)
 
53
 
 
54
    def do_EOF(self, args):
 
55
        print
 
56
        self.do_quit(args)
 
57
 
 
58
    def postcmd(self, line, bar):
 
59
        self.set_title()
 
60
        self.set_prompt()
 
61
 
 
62
    def set_prompt(self):
 
63
        if self.tree is not None:
 
64
            try:
 
65
                prompt = pylon.alias_or_version(self.tree.tree_version, 
 
66
                                                self.tree, 
 
67
                                                full=False)
 
68
                if prompt is not None:
 
69
                    prompt = " " + prompt +":"+ pylon.tree_cwd(self.tree)
 
70
            except:
 
71
                prompt = ""
 
72
        else:
 
73
            prompt = ""
 
74
        self.prompt = "bzr%s> " % prompt
 
75
 
 
76
    def set_title(self, command=None):
 
77
        try:
 
78
            version = pylon.alias_or_version(self.tree.tree_version, self.tree, 
 
79
                                             full=False)
 
80
        except:
 
81
            version = "[no version]"
 
82
        if command is None:
 
83
            command = ""
 
84
        sys.stdout.write(terminal.term_title("bzr %s %s" % (command, version)))
 
85
 
 
86
    def do_cd(self, line):
 
87
        if line == "":
 
88
            line = "~"
 
89
        line = os.path.expanduser(line)
 
90
        if os.path.isabs(line):
 
91
            newcwd = line
 
92
        else:
 
93
            newcwd = self.cwd+'/'+line
 
94
        newcwd = os.path.normpath(newcwd)
 
95
        try:
 
96
            os.chdir(newcwd)
 
97
            self.cwd = newcwd
 
98
        except Exception, e:
 
99
            print e
 
100
        try:
 
101
            self.tree = arch.tree_root(".")
 
102
        except:
 
103
            self.tree = None
 
104
 
 
105
    def do_help(self, line):
 
106
        Help()(line)
 
107
 
 
108
    def default(self, line):
 
109
        args = line.split()
 
110
        commandname = args.pop(0)
 
111
        try:
 
112
            cmd_obj = get_cmd_object(commandname)
 
113
        except BzrError:
 
114
            return os.system(line)
 
115
 
 
116
 
 
117
        try:
 
118
            return (cmd_obj.run_argv(args) or 0)
 
119
        except BzrError, e:
 
120
            print e
 
121
        except KeyboardInterrupt, e:
 
122
            print "Interrupted"
 
123
        except Exception, e:
 
124
#            print "Unhandled error:\n%s" % errors.exception_str(e)
 
125
            print "Unhandled error:\n%s" % (e)
 
126
 
 
127
 
 
128
    def completenames(self, text, line, begidx, endidx):
 
129
        completions = []
 
130
        iter = iter_command_names(self.fake_aba)
 
131
        try:
 
132
            if len(line) > 0:
 
133
                arg = line.split()[-1]
 
134
            else:
 
135
                arg = ""
 
136
            iter = cmdutil.iter_munged_completions(iter, arg, text)
 
137
        except Exception, e:
 
138
            print e
 
139
        return list(iter)
 
140
 
 
141
    def completedefault(self, text, line, begidx, endidx):
 
142
        """Perform completion for native commands.
 
143
        
 
144
        :param text: The text to complete
 
145
        :type text: str
 
146
        :param line: The entire line to complete
 
147
        :type line: str
 
148
        :param begidx: The start of the text in the line
 
149
        :type begidx: int
 
150
        :param endidx: The end of the text in the line
 
151
        :type endidx: int
 
152
        """
 
153
        try:
 
154
            (cmd, args, foo) = self.parseline(line)
 
155
            command_obj=find_command(cmd)
 
156
            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
 
 
173
            elif cmd == "cd":
 
174
                if len(args) > 0:
 
175
                    arg = args.split()[-1]
 
176
                else:
 
177
                    arg = ""
 
178
                iter = cmdutil.iter_dir_completions(arg)
 
179
                iter = cmdutil.iter_munged_completions(iter, arg, text)
 
180
                return list(iter)
 
181
            elif len(args)>0:
 
182
                arg = args.split()[-1]
 
183
                iter = cmdutil.iter_file_completions(arg)
 
184
                return list(cmdutil.iter_munged_completions(iter, arg, text))
 
185
            else:
 
186
                return self.completenames(text, line, begidx, endidx)
 
187
        except Exception, e:
 
188
            print e
 
189
 
 
190
def run_shell():
 
191
    prompt = PromptCmd()
 
192
    try:
 
193
        prompt.cmdloop()
 
194
    finally:
 
195
        prompt.write_history()
 
196
 
 
197
def iter_file_completions(arg, only_dirs = False):
 
198
    """Generate an iterator that iterates through filename completions.
 
199
 
 
200
    :param arg: The filename fragment to match
 
201
    :type arg: str
 
202
    :param only_dirs: If true, match only directories
 
203
    :type only_dirs: bool
 
204
    """
 
205
    cwd = os.getcwd()
 
206
    if cwd != "/":
 
207
        extras = [".", ".."]
 
208
    else:
 
209
        extras = []
 
210
    (dir, file) = os.path.split(arg)
 
211
    if dir != "":
 
212
        listingdir = os.path.expanduser(dir)
 
213
    else:
 
214
        listingdir = cwd
 
215
    for file in iter_combine([os.listdir(listingdir), extras]):
 
216
        if dir != "":
 
217
            userfile = dir+'/'+file
 
218
        else:
 
219
            userfile = file
 
220
        if userfile.startswith(arg):
 
221
            if os.path.isdir(listingdir+'/'+file):
 
222
                userfile+='/'
 
223
                yield userfile
 
224
            elif not only_dirs:
 
225
                yield userfile
 
226
 
 
227
 
 
228
def iter_dir_completions(arg):
 
229
    """Generate an iterator that iterates through directory name completions.
 
230
 
 
231
    :param arg: The directory name fragment to match
 
232
    :type arg: str
 
233
    """
 
234
    return iter_file_completions(arg, True)