Skip to content

Commit 77ea690

Browse files
committed
Create _CompletingAction and add to parser explicitly so the --_completion option shows up in help and command completion
1 parent 99175be commit 77ea690

2 files changed

Lines changed: 37 additions & 24 deletions

File tree

README

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,12 @@ prog.py:
4040

4141
$ chmod +x prog.py
4242
$ ./prog.py <TAB><TAB>
43-
0 2 4 6 8 -h --sum
44-
1 3 5 7 9 --help
43+
0 4 8 --help
44+
1 5 9 --sum
45+
2 6 --_completion
46+
3 7 -h
4547
$ ./prog.py -<TAB><TAB>
46-
-h --help --sum
48+
--_completion -h --help --sum
4749
$ ./prog.py 1<TAB><TAB>
4850
0 1 2 3 4 5 6 7 8 9
4951

selfcompletion/__init__.py

Lines changed: 32 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,37 @@
11
import argparse
22
import re
33

4-
class SelfCompletingArgumentParser(argparse.ArgumentParser):
5-
def __init__(self, *args, **kw):
6-
argparse.ArgumentParser.__init__(self, *args, **kw)
7-
self._completion_parser = argparse.ArgumentParser()
8-
self._completion_parser.add_argument('--_completion', type=str)
4+
class _CompletionAction(argparse.Action):
5+
def __init__(self,
6+
option_strings,
7+
dest='_completion',
8+
metavar='CMD_LINE',
9+
default=argparse.SUPPRESS,
10+
help="Built-in command completion"):
11+
super(_CompletionAction, self).__init__(
12+
option_strings=option_strings,
13+
dest=dest,
14+
metavar=metavar,
15+
default=default,
16+
nargs=1,
17+
type=str,
18+
help=help)
919

10-
def parse_args(self, *args, **kw):
11-
comp_args = self._completion_parser.parse_args(*args, **kw)
12-
if comp_args._completion is not None:
13-
comp_words = re.split(r'\s+', comp_args._completion)
14-
comp_word = comp_words[-1]
15-
all_options = sum((a.option_strings for a in self._actions), [])
16-
types = [a.type for a in self._actions if a.nargs != 0 and a.type is not None]
17-
for opt in all_options:
18-
if opt.startswith(comp_word):
19-
print opt+' '
20-
if int in types and re.match(r'^\d*$', comp_word):
21-
for i in xrange(10):
22-
print i
20+
def __call__(self, parser, namespace, values, option_string=None):
21+
comp_words = re.split(r'\s+', values[0])
22+
comp_word = comp_words[-1]
23+
all_options = sum((a.option_strings for a in parser._actions), [])
24+
types = [a.type for a in parser._actions if a.nargs != 0 and a.type is not None]
25+
for opt in all_options:
26+
if opt.startswith(comp_word):
27+
print opt+' '
28+
if int in types and re.match(r'^\d*$', comp_word):
29+
for i in xrange(10):
30+
print i
31+
parser.exit()
2332

24-
self.exit(0)
25-
else:
26-
return argparse.ArgumentParser.parse_args(self, *args, **kw)
33+
class SelfCompletingArgumentParser(argparse.ArgumentParser):
34+
def __init__(self, *args, **kw):
35+
super(SelfCompletingArgumentParser, self).__init__(*args, **kw)
36+
completion_action = _CompletionAction(['--_completion'])
37+
self._add_action(completion_action)

0 commit comments

Comments
 (0)