Changing aur-shell.py name to pyshell.py
[AurShell.git] / pyshell.py
blobba87ac6a06ab939df12702a70e3c8a20689c714b
1 #!/usr/bin/python
2 # -*- coding: utf-8-*-
4 """
5 Aur Shell is simple shell framework.
7 To use it, write some plugins that Aur Shell would use.
8 """
10 import cmd
11 import string
12 import sys
13 import os
14 import os.path
15 import types
16 import readline
18 import conf
19 import plugload
20 from showinfo import Put
22 __version__ = "0.1"
25 class AurShell(cmd.Cmd):
26 """Interactive shell framework.
27 To use it, write some modules, becouse by default it's very poor shell.
28 """
29 def __init__(self, init_message=""):
30 cmd.Cmd.__init__(self)
31 self.put = Put()
32 self.prompt = conf.shell_prompt
33 if init_message:
34 self.intro = init_message
35 else:
36 self.intro = "\n\tWelcome to aurShell v%(__version__)s\n" % globals()
37 self.commands = plugload.load(conf.modules_path)
38 # load history, create empty file if history doesn't exist
39 if not os.path.isfile(conf.history_file):
40 open(conf.history_file, "w").close()
41 readline.read_history_file(conf.history_file)
42 readline.set_history_length(conf.history_length)
45 def default(self, cmd=None):
46 """Run commands.
48 cmd = (<class>, [method], [arg1], [arg2], ...)
49 """
50 # cmd[0] should be class name
51 # cmd[1] should be method name (or arugmet if class is callable)
52 # cmd[1] can be empty
53 # cmd[2:] should be method argumments, can be empty
54 cmd = cmd.split()
55 # check if alias exists and if so, replace command
56 if cmd[0] in conf.alias.keys():
57 cmd[0] = conf.alias[cmd[0]]
58 self.onecmd(" ".join(cmd))
59 # operations for single command with no arguments
60 elif len(cmd) == 1:
61 # if there's no such command (or plugin class)
62 if not cmd[0] in self.commands.keys():
63 self.put("%s : command not found." % cmd[0])
64 # for only one argument, try to run __call__() method with
65 # no arguments
66 elif "__call__" in dir(self.commands[cmd[0]]):
67 a = self.put(getattr(self.commands[cmd[0]], "__call__")())
68 if a:
69 self.put(a)
70 else:
71 self.put("%s : bad usege. Try to run help." % cmd[0])
72 # if command was called with arguments
73 elif len(cmd) > 1:
74 if not cmd[0] in self.commands.keys():
75 self.put("%s : command not found." % cmd[0])
76 # if method named arg[1] exist in class arg[0],
77 # then try to run in
78 elif cmd[1] in dir(self.commands[cmd[0]]):
79 a = self.put(getattr(self.commands[cmd[0]], cmd[1])(cmd[2:]))
80 if a:
81 self.put(a)
82 # if there's no such method arg[1] in class arg[0],
83 # try to run class.__call__(args..)
84 else:
85 try:
86 a = self.commands[cmd[0]](*cmd[1:])
87 if a:
88 self.put(a)
89 except TypeError:
90 # object is not callable
91 self.put("%s : bad usage" % cmd[0])
94 def completenames(self, text, *ignored):
95 """Complete commands"""
96 dotext = 'do_'+text
97 # local methods
98 local_cmd_list = [a[3:] + " " for a in self.get_names() if a.startswith(dotext)]
99 # + all metrods from modules
100 module_cmd_list = [a + " " for a in self.commands.keys() if a.startswith(text)]
101 return local_cmd_list + module_cmd_list
104 def completedefault(self, text, line, begidx, endidx):
105 """Complete commands argument"""
106 line = line.split()
107 # if only commands was given
108 if len(line) == 1:
109 cmds = [a + " " for a in dir(self.commands[line[0]]) if not
110 a.startswith("__")]
111 return cmds
112 # if command and argument begin was given
113 elif len(line) == 2:
114 return [a + " " for a in dir(self.commands[line[0]]) if
115 a.startswith(line[1])]
116 # else don't complete (or should I?)
117 else:
118 return []
121 def do_help(self, arg):
122 """Show help for commands"""
123 arg = arg.split()
124 if not arg:
125 self.put("Usage: help <command>")
126 else:
127 try:
128 # try to run help() method
129 self.put(getattr(self.commands[arg[0]], "help")())
130 except AttributeError:
131 # try to show __doc__
132 if self.commands[arg[0]].__doc__:
133 self.put(self.commands[arg[0]].__doc__)
134 else:
135 self.put("No help found.")
136 except KeyError:
137 self.put("No help found.")
140 def do_clear(self, *ignored):
141 """Clear the screen"""
142 # TODO 2008-02-09 20:44:50
143 self.put("Todo, sorry")
146 def do_history(self, hnumb=None, *ignored):
147 """Show the history"""
148 # TODO better history listing
149 # 2008-01-27 18:51:22
150 # print whole history
151 if not hnumb:
152 for number in range(1, conf.history_length):
153 cmd = readline.get_history_item(number)
154 if not cmd:
155 break
156 self.put("%6d %s" % (number, cmd))
157 # for history range 12-22 or -22 or 22-
158 else:
159 try:
160 if "-" in hnumb:
161 if hnumb[-1] == "-" or hnumb[0] == "-":
162 start = int(hnumb.replace("-", " "))
163 end = conf.history_length
164 else:
165 start, end = hnumb.split("-")
166 start = int(start)
167 end = int(end) + 1
168 for number in range(start, end):
169 cmd = readline.get_history_item(number)
170 if not cmd:
171 break
172 self.put("%6d %s" % (number, cmd))
173 else:
174 hnumb = int(hnumb)
175 self.put(readline.get_history_item(hnumb))
176 except ValueError:
177 self.put("""Bad value.
178 Usage: history <number or range>
179 history 11-20 -> from 11 to 20
180 history 22- -> from 22 fo the end of history file
181 history -22 -> same as 22-""")
184 def do_quit(self, *ignored):
185 """Quit from shell"""
186 if conf.history_length:
187 readline.write_history_file(conf.history_file)
188 print ""
189 sys.exit(1)
191 # function aliases
192 do_EOF = do_quit
193 do_exit = do_quit
197 if __name__ == "__main__":
198 shell = AurShell()
199 try:
200 shell.cmdloop()
201 except KeyboardInterrupt:
202 # TODO 2008-01-27 16:56:31
203 sys.exit(shell.do_quit())