1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
|
import os
import sys
import re
import glob
import shlex
import logging
import argparse
import cStringIO
import alot.settings
class Command(object):
"""base class for commands"""
def __init__(self, prehook=None, posthook=None):
self.prehook = prehook
self.posthook = posthook
self.undoable = False
self.help = self.__doc__
def apply(self, caller):
pass
@classmethod
def get_helpstring(cls):
return cls.__doc__
COMMANDS = {
'search': {},
'envelope': {},
'bufferlist': {},
'taglist': {},
'thread': {},
'global': {},
}
def lookup_command(cmdname, mode):
"""returns commandclass, argparser and forcedparams
for `cmdname` in `mode`"""
if cmdname in COMMANDS[mode]:
return COMMANDS[mode][cmdname]
elif cmdname in COMMANDS['global']:
return COMMANDS['global'][cmdname]
else:
return None, None, None
def lookup_parser(cmdname, mode):
return lookup_command(cmdname, mode)[1]
class CommandParseError(Exception):
pass
class CommandArgumentParser(argparse.ArgumentParser):
"""ArgumentParser that raises `CommandParseError`
instead of printing to sys.stderr"""
def exit(self, message):
raise CommandParseError(message)
def error(self, message):
raise CommandParseError(message)
class registerCommand(object):
def __init__(self, mode, name, help=None, usage=None,
forced={}, arguments=[]):
self.mode = mode
self.name = name
self.help = help
self.usage = usage
self.forced = forced
self.arguments = arguments
def __call__(self, klass):
argparser = CommandArgumentParser(description=self.help,
usage=self.usage,
prog=self.name, add_help=False)
for args, kwargs in self.arguments:
argparser.add_argument(*args, **kwargs)
COMMANDS[self.mode][self.name] = (klass, argparser, self.forced)
return klass
def commandfactory(cmdline, mode='global'):
# split commandname and parameters
if not cmdline:
return None
logging.debug('mode:%s got commandline "%s"' % (mode, cmdline))
# allow to shellescape without a space after '!'
if cmdline.startswith('!'):
cmdline = 'shellescape \'%s\'' % cmdline[1:]
cmdline = re.sub(r'"(.*)"', r'"\\"\1\\""', cmdline)
try:
args = shlex.split(cmdline.encode('utf-8'))
except ValueError, e:
raise CommandParseError(e.message)
args = map(lambda x: x.decode('utf-8'), args) # get unicode strings
logging.debug('ARGS: %s' % args)
cmdname = args[0]
args = args[1:]
# unfold aliases
if alot.settings.config.has_option('command-aliases', cmdname):
cmdname = alot.settings.config.get('command-aliases', cmdname)
# get class, argparser and forced parameter
(cmdclass, parser, forcedparms) = lookup_command(cmdname, mode)
if cmdclass is None:
msg = 'unknown command: %s' % cmdname
logging.debug(msg)
raise CommandParseError(msg)
parms = vars(parser.parse_args(args))
parms.update(forcedparms)
logging.debug('PARMS: %s' % parms)
parms['prehook'] = alot.settings.hooks.get('pre_' + cmdname)
parms['posthook'] = alot.settings.hooks.get('post_' + cmdname)
logging.debug('cmd parms %s' % parms)
return cmdclass(**parms)
#def interpret_commandline(cmdline, mode):
__all__ = list(filename[:-3] for filename in glob.glob1(os.path.dirname(__file__), '*.py'))
|