1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 """Helper functions to support command line tools providing more than
19 one command.
20
21 e.g called as "tool command [options] args..." where <options> and <args> are
22 command'specific
23
24
25
26
27 """
28 __docformat__ = "restructuredtext en"
29
30
31 import sys
32 from os.path import basename
33
34 from logilab.common.configuration import Configuration
35
36
37 DEFAULT_COPYRIGHT = '''\
38 Copyright (c) 2004-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
39 http://www.logilab.fr/ -- mailto:contact@logilab.fr'''
40
41
42 DEFAULT_DOC = '''\
43 Type "%prog <command> --help" for more information about a specific
44 command. Available commands are :\n'''
45
47 """Raised when an unknown command is used or when a command is not
48 correctly used.
49 """
50
51
53 """Base class for command line commands."""
54 arguments = ''
55 name = ''
56
57 hidden = False
58
59 min_args = None
60 max_args = None
61 - def __init__(self, __doc__=None, version=None):
68
75
76 - def run(self, args):
77 """run the command with its specific arguments"""
78 raise NotImplementedError()
79
80
81 -def pop_arg(args_list, expected_size_after=0, msg="Missing argument"):
82 """helper function to get and check command line arguments"""
83 try:
84 value = args_list.pop(0)
85 except IndexError:
86 raise BadCommandUsage(msg)
87 if expected_size_after is not None and len(args_list) > expected_size_after:
88 raise BadCommandUsage('too many arguments')
89 return value
90
91
92 _COMMANDS = {}
93
95 """register existing commands"""
96 for command_klass in commands:
97 _COMMANDS[command_klass.name] = command_klass
98
99
101 """display usage for the main program (i.e. when no command supplied)
102 and exit
103 """
104 commands = _COMMANDS.keys()
105 commands.sort()
106 if doc != DEFAULT_DOC:
107 try:
108 doc = doc % ('<command>', '<command arguments>',
109 '''\
110 Type "%prog <command> --help" for more information about a specific
111 command. Available commands are :\n''')
112 except TypeError:
113 print 'could not find the "command", "arguments" and "default" slots'
114 doc = doc.replace('%prog', basename(sys.argv[0]))
115 print 'usage:', doc
116 max_len = max([len(cmd) for cmd in commands])
117 padding = ' '*max_len
118 for command in commands:
119 cmd = _COMMANDS[command]
120 if not cmd.hidden:
121 title = cmd.__doc__.split('.')[0]
122 print ' ', (command+padding)[:max_len], title
123 if copyright:
124 print '\n', copyright
125 sys.exit(status)
126
127
142
143
145 """command line tool"""
146 try:
147 arg = args.pop(0)
148 except IndexError:
149 main_usage(status=1, doc=doc, copyright=copyright)
150 if arg in ('-h', '--help'):
151 main_usage(doc=doc, copyright=copyright)
152 try:
153 cmd_run(arg, *args)
154 except BadCommandUsage, err:
155 print 'ERROR: ', err
156 main_usage(1, doc=doc, copyright=copyright)
157
158
160 """list available commands, useful for bash completion."""
161 name = 'listcommands'
162 arguments = '[command]'
163 hidden = True
164
165 - def run(self, args):
166 """run the command with its specific arguments"""
167 if args:
168 command = pop_arg(args)
169 cmd = _COMMANDS[command]
170 for optname, optdict in cmd.options:
171 print '--help'
172 print '--' + optname
173 else:
174 commands = _COMMANDS.keys()
175 commands.sort()
176 for command in commands:
177 cmd = _COMMANDS[command]
178 if not cmd.hidden:
179 print command
180
181 register_commands([ListCommandsCommand])
182