diff options
author | Lucas Hoffmann <l-m-h@web.de> | 2016-12-29 16:03:35 +0100 |
---|---|---|
committer | Lucas Hoffmann <l-m-h@web.de> | 2017-01-10 08:56:26 +0100 |
commit | 2d7d048f3e2eb33b20944d307a998abe09f2329b (patch) | |
tree | dd4863ee0797cd582d03ea336f5cbf5172e4a921 /alot/__main__.py | |
parent | 658f83d7e5c78894bb427e088af51b092c1fb256 (diff) |
Replace twisted command line parsing with argparse
The command line interface is copied as directly as possible. But at least
the help output is formatted differently.
Diffstat (limited to 'alot/__main__.py')
-rw-r--r-- | alot/__main__.py | 190 |
1 files changed, 69 insertions, 121 deletions
diff --git a/alot/__main__.py b/alot/__main__.py index 00b34c4e..de46a727 100644 --- a/alot/__main__.py +++ b/alot/__main__.py @@ -1,9 +1,10 @@ # Copyright (C) 2011-2012 Patrick Totzke <patricktotzke@gmail.com> # This file is released under the GNU GPL, version 3 or a later revision. # For further details see the COPYING file -import sys +import argparse import logging import os +import sys import alot from alot.settings import settings @@ -13,115 +14,65 @@ from alot.ui import UI from alot.commands import * from alot.commands import CommandParseError -from twisted.python import usage - - -class SubcommandOptions(usage.Options): - optFlags = [] - - def parseArgs(self, *args): - self.args = args - - def as_argparse_opts(self): - optstr = '' - for k, v in self.iteritems(): - # flags translate int value 0 or 1.. - if k in [a[0] for a in self.optFlags]: # if flag - optstr += ('--%s ' % k) * v - else: - if v is not None: - optstr += '--%s \'%s\' ' % (k, v) - return optstr - - def opt_version(self): - print alot.__version__ - sys.exit(0) - - -class ComposeOptions(SubcommandOptions): - optParameters = [ - ['sender', '', None, 'From line'], - ['subject', '', None, 'subject line'], - ['to', [], None, 'recipients'], - ['cc', '', None, 'copy to'], - ['bcc', '', None, 'blind copy to'], - ['template', '', None, 'path to template file'], - ['attach', '', None, 'files to attach'], - ] - optFlags = [ - ['omit_signature', '', 'do not add signature'], - ] - - def parseArgs(self, *args): - SubcommandOptions.parseArgs(self, *args) - self.rest = ' '.join(args) or None - - -class SearchOptions(SubcommandOptions): - accepted = ['oldest_first', 'newest_first', 'message_id', 'unsorted'] - - def colourint(val): - if val not in accepted: - raise ValueError("Unknown sort order") - return val - colourint.coerceDoc = "Must be one of " + str(accepted) - optParameters = [ - ['sort', 'newest_first', None, 'Sort order'], - ] - - -class Options(usage.Options): - optFlags = [["read-only", "r", 'open db in read only mode'], ] - - def colourint(val): - val = int(val) - if val not in [1, 16, 256]: - raise ValueError("Not in range") - return val - colourint.coerceDoc = "Must be 1, 16 or 256" - - def debuglogstring(val): - if val not in ['error', 'debug', 'info', 'warning']: - raise ValueError("Not in range") - return val - debuglogstring.coerceDoc = "Must be one of debug,info,warning or error" - - optParameters = [ - ['config', 'c', None, 'config file'], - ['notmuch-config', 'n', None, 'notmuch config'], - ['colour-mode', 'C', None, 'terminal colour mode', colourint], - ['mailindex-path', 'p', None, 'path to notmuch index'], - ['debug-level', 'd', 'info', 'debug log', debuglogstring], - ['logfile', 'l', '/dev/null', 'logfile'], - ] - search_help = "start in a search buffer using the querystring provided "\ - "as parameter. See the SEARCH SYNTAX section of notmuch(1)." - - subCommands = [['search', None, SearchOptions, search_help], - ['compose', None, ComposeOptions, "compose a new message"]] - - def opt_version(self): - print alot.__version__ - sys.exit(0) - def main(): - # interpret cml arguments - args = Options() - try: - args.parseOptions() # When given no argument, parses sys.argv[1:] - except usage.UsageError as errortext: - print '%s' % errortext - print 'Try --help for usage details.' - sys.exit(1) + # set up the parser to parse the command line options. + parser = argparse.ArgumentParser() + parser.add_argument('-v', '--version', action='version', + version=alot.__version__) + parser.add_argument('-r', '--read-only', action='store_true', + help='open db in read only mode') + parser.add_argument('-c', '--config', type=argparse.FileType('r'), + help='config file') + parser.add_argument('-n', '--notmuch-config', type=argparse.FileType('r'), + help='notmuch config') + parser.add_argument('-C', '--colour-mode', + choices=(1, 16, 256), type=int, default=256, + help='terminal colour mode [default: %(default)s].') + parser.add_argument('-p', '--mailindex-path', #type=directory, + help='path to notmuch index') + parser.add_argument('-d', '--debug-level', default='info', + choices=('debug', 'info', 'warning', 'error'), + help='debug log [default: %(default)s]') + parser.add_argument('-l', '--logfile', default='/dev/null', + type=lambda x: argparse.FileType('w')(x).name, + help='logfile [default: %(default)s]') + parser.add_argument('command', nargs=argparse.REMAINDER) + options = parser.parse_args() + if options.command: + # We have a command after the initial options so we also parse that. + parser = argparse.ArgumentParser() + subparsers = parser.add_subparsers(dest='subcommand') + search = subparsers.add_parser('search') + search.add_argument('--sort', default='newest_first', + help='sort order', + choices=('oldest_first', 'newest_first', + 'message_id', 'unsorted')) + search.add_argument('terms', nargs='+') + compose = subparsers.add_parser('compose') + compose.add_argument('--omit_signature', action='store_true', + help='do not add signature') + compose.add_argument('--sender', help='From line') + compose.add_argument('--subject', help='subject line') + compose.add_argument('--to', help='recipients') + compose.add_argument('--cc', help='copy to') + compose.add_argument('--bcc', help='blind copy to') + compose.add_argument('--template', type=argparse.FileType('r'), + help='path to template file') + compose.add_argument('--attach', type=argparse.FileType('r'), + help='files to attach') + + command = parser.parse_args(options.command) + else: + command = None # logging root_logger = logging.getLogger() for log_handler in root_logger.handlers: root_logger.removeHandler(log_handler) root_logger = None - numeric_loglevel = getattr(logging, args['debug-level'].upper(), None) - logfilename = os.path.expanduser(args['logfile']) + numeric_loglevel = getattr(logging, options.debug_level.upper(), None) + logfilename = os.path.expanduser(options.logfile) logformat = '%(levelname)s:%(module)s:%(message)s' logging.basicConfig(level=numeric_loglevel, filename=logfilename, filemode='w', format=logformat) @@ -132,8 +83,8 @@ def main(): os.path.expanduser('~/.config')), 'alot', 'config'), ] - if args['config']: - expanded_path = os.path.expanduser(args['config']) + if options.config: + expanded_path = os.path.expanduser(options.config) if not os.path.exists(expanded_path): msg = 'Config file "%s" does not exist. Goodbye for now.' sys.exit(msg % expanded_path) @@ -141,8 +92,8 @@ def main(): # locate notmuch config notmuchpath = os.environ.get('NOTMUCH_CONFIG', '~/.notmuch-config') - if args['notmuch-config']: - notmuchpath = args['notmuch-config'] + if options.notmuch_config: + notmuchpath = options.notmuch_config notmuchconfig = os.path.expanduser(notmuchpath) alotconfig = None @@ -159,28 +110,25 @@ def main(): sys.exit(e) # store options given by config swiches to the settingsManager: - if args['colour-mode']: - settings.set('colourmode', args['colour-mode']) + if options.colour_mode: + settings.set('colourmode', options.colour_mode) # get ourselves a database manager indexpath = settings.get_notmuch_setting('database', 'path') - indexpath = args['mailindex-path'] or indexpath - dbman = DBManager(path=indexpath, ro=args['read-only']) + indexpath = options.mailindex_path or indexpath + dbman = DBManager(path=indexpath, ro=options.read_only) # determine what to do try: - if args.subCommand == 'search': - query = ' '.join(args.subOptions.args) - cmdstring = 'search %s %s' % (args.subOptions.as_argparse_opts(), - query) - elif args.subCommand == 'compose': - cmdstring = 'compose %s' % args.subOptions.as_argparse_opts() - if args.subOptions.rest is not None: - cmdstring += ' ' + args.subOptions.rest - else: + if command is None: cmdstring = settings.get('initial_command') - except CommandParseError as e: - sys.exit(e) + elif command.subcommand == 'search': + query = ' '.join(command.terms) + cmdstring = 'search --sort {} {}'.format(command.sort, query) + elif command.subcommand == 'compose': + cmdstring = ' '.join(options.command) + except CommandParseError as err: + sys.exit(err) # set up and start interface UI(dbman, cmdstring) |