summaryrefslogtreecommitdiff
path: root/alot/__main__.py
diff options
context:
space:
mode:
authorPatrick Totzke <patricktotzke@gmail.com>2017-01-10 18:31:10 +0000
committerGitHub <noreply@github.com>2017-01-10 18:31:10 +0000
commit4645c4b2eb2b3aa93305f0c10fd3567cfeeb41c7 (patch)
tree56a5b4f124924a5740dd6b46ce5633ca109e5008 /alot/__main__.py
parent20bffed730e54c9e3a6e69c5c854dcce6d6eeb59 (diff)
parent6a164565e66207cf59f5b183ef7a947a0b4c87da (diff)
Merge pull request #944 from lucc/argparse
Replace twisted command line parsing with argparse
Diffstat (limited to 'alot/__main__.py')
-rw-r--r--alot/__main__.py213
1 files changed, 68 insertions, 145 deletions
diff --git a/alot/__main__.py b/alot/__main__.py
index 00b34c4e..d68b5b87 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
@@ -11,176 +12,97 @@ from alot.settings.errors import ConfigError
from alot.db.manager import DBManager
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)
+from alot.commands import CommandParseError, COMMANDS
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', help='config file',
+ type=lambda x: argparse.FileType('r')(x).name)
+ parser.add_argument('-n', '--notmuch-config', default=os.environ.get(
+ 'NOTMUCH_CONFIG',
+ os.path.expanduser('~/.notmuch-config')),
+ type=lambda x: argparse.FileType('r')(x).name,
+ 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]')
+ # We will handle the subcommands in a seperate run of argparse as argparse
+ # does not support optional subcommands until now.
+ subcommands = ('search', 'compose', 'bufferlist', 'taglist', 'pyshell')
+ parser.add_argument('command', nargs=argparse.REMAINDER,
+ help='possible subcommands are {}'.format(
+ ', '.join(subcommands)))
+ options = parser.parse_args()
+ if options.command:
+ # We have a command after the initial options so we also parse that.
+ # But we just use the parser that is already defined for the internal
+ # command that will back this subcommand.
+ parser = argparse.ArgumentParser()
+ subparsers = parser.add_subparsers(dest='subcommand')
+ for subcommand in subcommands:
+ subparsers.add_parser(subcommand,
+ parents=[COMMANDS['global'][subcommand][1]])
+ 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)
logformat = '%(levelname)s:%(module)s:%(message)s'
- logging.basicConfig(level=numeric_loglevel, filename=logfilename,
+ logging.basicConfig(level=numeric_loglevel, filename=options.logfile,
filemode='w', format=logformat)
# locate alot config files
- configfiles = [
- os.path.join(os.environ.get('XDG_CONFIG_HOME',
- os.path.expanduser('~/.config')),
- 'alot', 'config'),
- ]
- if args['config']:
- expanded_path = os.path.expanduser(args['config'])
- if not os.path.exists(expanded_path):
- msg = 'Config file "%s" does not exist. Goodbye for now.'
- sys.exit(msg % expanded_path)
- configfiles.insert(0, expanded_path)
-
- # locate notmuch config
- notmuchpath = os.environ.get('NOTMUCH_CONFIG', '~/.notmuch-config')
- if args['notmuch-config']:
- notmuchpath = args['notmuch-config']
- notmuchconfig = os.path.expanduser(notmuchpath)
-
- alotconfig = None
- # read the first alot config file we find
- for configfilename in configfiles:
- if os.path.exists(configfilename):
- alotconfig = configfilename
- break # use only the first
+ if options.config is None:
+ alotconfig = os.path.join(
+ os.environ.get('XDG_CONFIG_HOME', os.path.expanduser('~/.config')),
+ 'alot', 'config')
+ if not os.path.exists(alotconfig):
+ alotconfig = None
+ else:
+ alotconfig = options.config
try:
settings.read_config(alotconfig)
- settings.read_notmuch_config(notmuchconfig)
+ settings.read_notmuch_config(options.notmuch_config)
except (ConfigError, OSError, IOError) as e:
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:
+ try:
cmdstring = settings.get('initial_command')
- except CommandParseError as e:
- sys.exit(e)
+ except CommandParseError as err:
+ sys.exit(err)
+ elif command.subcommand in subcommands:
+ cmdstring = ' '.join(options.command)
# set up and start interface
UI(dbman, cmdstring)
@@ -190,5 +112,6 @@ def main():
if exit_hook is not None:
exit_hook()
+
if __name__ == "__main__":
main()