aboutsummaryrefslogtreecommitdiffstats
path: root/libbe/ui/command_line.py
diff options
context:
space:
mode:
Diffstat (limited to 'libbe/ui/command_line.py')
-rwxr-xr-xlibbe/ui/command_line.py270
1 files changed, 270 insertions, 0 deletions
diff --git a/libbe/ui/command_line.py b/libbe/ui/command_line.py
new file mode 100755
index 0000000..e84d32a
--- /dev/null
+++ b/libbe/ui/command_line.py
@@ -0,0 +1,270 @@
+# Copyright (C) 2005-2009 Aaron Bentley and Panometrics, Inc.
+# Chris Ball <cjb@laptop.org>
+# Gianluca Montecchi <gian@grys.it>
+# Oleg Romanyshyn <oromanyshyn@panoramicfeedback.com>
+# W. Trevor King <wking@drexel.edu>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+"""
+A command line interface to Bugs Everywhere.
+"""
+
+import optparse
+import os
+import sys
+
+import libbe
+import libbe.command
+import libbe.command.util
+import libbe.version
+import libbe.ui.util.pager
+
+if libbe.TESTING == True:
+ import doctest
+
+class CallbackExit (Exception):
+ pass
+
+class CmdOptionParser(optparse.OptionParser):
+ def __init__(self, command):
+ self.command = command
+ optparse.OptionParser.__init__(self)
+ self.disable_interspersed_args()
+ self.remove_option('-h')
+ self._option_by_name = {}
+ for option in self.command.options:
+ self._add_option(option)
+
+ def _add_option(self, option):
+ option.validate()
+ self._option_by_name[option.name] = option
+ opt_strings = ['--'+option.name]
+ if option.short_name != None:
+ opt_strings.append('-'+option.short_name)
+ if option.arg == None: # a callback option
+ opt = optparse.Option(
+ *opt_strings, action='callback',
+ callback=self.callback, help=option.help)
+ else:
+ kwargs = {}
+ if option.arg.type == 'bool':
+ action = 'store_true'
+ else:
+ kwargs['type'] = option.arg.type
+ action = 'store'
+ opt = optparse.Option(
+ *opt_strings, metavar=option.arg.metavar,
+ default=option.arg.default, action=action,
+ help=option.help, **kwargs)
+ opt._option = option
+ self.add_option(opt)
+
+ def parse_args(self, args=None, values=None):
+ args = self._get_args(args)
+ options,parsed_args = optparse.OptionParser.parse_args(
+ self, args=args, values=values)
+ for name,value in options.__dict__.items():
+ if value == '--complete':
+ argument = None
+ option = self._option_by_name[name]
+ if option.arg != None:
+ argument = option.arg
+ fragment = None
+ indices = [i for i,arg in enumerate(args)
+ if arg == '--complete']
+ for i in indices:
+ assert i > 0 # this --complete is an option value
+ if args[i-1] in ['--%s' % o.name
+ for o in self.command.options]:
+ name = args[i-1][2:]
+ if name == option.name:
+ break
+ elif option.short_name != None \
+ and args[i-1].startswith('-') \
+ and args[i-1].endswith(option.short_name):
+ break
+ if i+1 < len(args):
+ fragment = args[i+1]
+ self.complete(argument, fragment)
+ for i,arg in enumerate(parsed_args):
+ if arg == '--complete':
+ if i < len(self.command.args):
+ argument = self.command.args[i]
+ else:
+ argument = self.command.args[-1]
+ if argument.repeatable == False:
+ raise libbe.command.UserError('Too many arguments')
+ fragment = None
+ if i < len(args) - 1:
+ fragment = args[i+1]
+ self.complete(argument, fragment)
+ if len(parsed_args) > len(self.command.args) \
+ and self.command.args[-1] == False:
+ raise libbe.command.UserError('Too many arguments')
+ for arg in self.command.args[len(parsed_args):]:
+ if arg.optional == False:
+ raise libbe.command.UserError(
+ 'Missing required argument %s' % arg.metavar)
+ return (options, parsed_args)
+
+ def callback(self, option, opt, value, parser):
+ command_option = option._option
+ if command_option.name == 'complete':
+ argument = None
+ fragment = None
+ if len(parser.rargs) > 0:
+ fragment = parser.rargs[0]
+ self.complete(argument, fragment)
+ else:
+ print command_option.callback(
+ self.command, command_option, value)
+ raise CallbackExit
+
+ def complete(self, argument=None, fragment=None):
+ print argument, fragment
+ comps = self.command.complete(argument, fragment)
+ if fragment != None:
+ comps = [c for c in comps if c.startswith(fragment)]
+ print '\n'.join(comps)
+ raise CallbackExit
+
+
+class BE (libbe.command.Command):
+ """Class for parsing the command line arguments for `be`.
+ This class does not contain a useful _run() method. Call this
+ module's main() function instead.
+
+ >>> be = BE()
+ >>> p = CmdOptionParser(be)
+ >>> p.exit_after_callback = False
+ >>> try:
+ ... options,args = p.parse_args(['--help']) # doctest: +ELLIPSIS
+ ... except CallbackExit:
+ ... pass
+ usage: be [options] [COMMAND [command-options] [COMMAND-ARGS ...]]
+ <BLANKLINE>
+ Options:
+ -h HELP, --help=HELP Print a help message.
+ <BLANKLINE>
+ --complete=STRING Print a list of possible completions.
+ <BLANKLINE>
+ --version=VERSION Print version string.
+ ...
+ >>> options,args = p.parse_args(['--complete']) # doctest: +ELLIPSIS
+ """
+ name = 'be'
+
+ def __init__(self, *args, **kwargs):
+ libbe.command.Command.__init__(self, *args, **kwargs)
+ self.options.extend([
+ libbe.command.Option(name='version',
+ help='Print version string.',
+ callback=self.version),
+ libbe.command.Option(name='full-version',
+ help='Print full version information.',
+ callback=self.full_version),
+ libbe.command.Option(name='repo', short_name='r',
+ help='Select BE repository (see `be help repo`) rather '
+ 'than the current directory.',
+ arg=libbe.command.Argument(
+ name='repo', metavar='REPO', default='.',
+ completion_callback=libbe.command.util.complete_path)),
+ libbe.command.Option(name='paginate',
+ help='Pipe all output into less (or if set, $PAGER).'),
+ libbe.command.Option(name='no-pager',
+ help='Do not pipe git output into a pager.'),
+ ])
+ self.args.extend([
+ libbe.command.Argument(
+ name='command', optional=False,
+ completion_callback=libbe.command.util.complete_command),
+ libbe.command.Argument(
+ name='args', optional=True, repeatable=True)
+ ])
+
+ def _usage(self):
+ return 'usage: be [options] [COMMAND [command-options] [COMMAND-ARGS ...]]'
+
+ def _long_help(self):
+ cmdlist = []
+ for name in libbe.command.commands():
+ module = libbe.command.get_command(name)
+ Class = getattr(module, name.capitalize())
+ cmdlist.append((name, Class.__doc__.splitlines()[0]))
+ cmdlist.sort()
+ longest_cmd_len = max([len(name) for name,desc in cmdlist])
+ ret = ['Bugs Everywhere - Distributed bug tracking',
+ '', 'Supported commands']
+ for name, desc in cmdlist:
+ numExtraSpaces = longest_cmd_len-len(name)
+ ret.append('be %s%*s %s' % (name, numExtraSpaces, '', desc))
+ ret.extend(['', 'Run', ' be help [command]', 'for more information.'])
+ return '\n'.join(ret)
+
+ def version(self, *args):
+ return libbe.version.version(verbose=False)
+
+ def full_version(self, *args):
+ return libbe.version.version(verbose=True)
+
+def main():
+ parser = CmdOptionParser(BE())
+ try:
+ options,args = parser.parse_args()
+ except CallbackExit:
+ return 0
+ except libbe.command.UserError, e:
+ print 'ERROR:\n', e
+ return 1
+
+ paginate = 'auto'
+ if options.paginate == True:
+ paginate = 'always'
+ if options.no_pager== True:
+ paginate = 'never'
+ libbe.ui.util.pager.run_pager(paginate)
+
+ command_name = args[0]
+ try:
+ module = libbe.command.get_command(command_name)
+ except libbe.command.UnknownCommand, e:
+ print e
+ return 1
+ Class = getattr(module, command_name.capitalize())
+ command = Class()
+ parser = CmdOptionParser(command)
+ if command.requires_bugdir == True:
+ storage = libbe.storage.get_storage(options['repo'])
+ storage.connect()
+ bugdir = BugDir(storage)
+ else:
+ storage = None
+ bugdir = None
+ try:
+ options,args = parser.parse_args(args[1:])
+ command.run(bugdir, options, args)
+ except CallbackExit:
+ if storage != None: storage.disconnect()
+ return 0
+ except libbe.command.UserError, e:
+ if storage != None: storage.disconnect()
+ print 'ERROR:\n', e
+ return 1
+ if storage != None: storage.disconnect()
+ return 0
+
+if __name__ == '__main__':
+ sys.exit(main())