Skip to content

Commit 99175be

Browse files
committed
Initial, functioning code
0 parents  commit 99175be

File tree

5 files changed

+139
-0
lines changed

5 files changed

+139
-0
lines changed

Diff for: .gitignore

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
/MANIFEST
2+
/build
3+
/dist
4+
*.pyc

Diff for: README

+69
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
selfcompletion
2+
==============
3+
4+
selfcompletion is a layer on top of argparse to take the fine-grained model
5+
argparse builds of the arguments your program accepts and automatically
6+
generate an extra '--_completion' argument that generates all possible
7+
completions given a partial command line as a string.
8+
9+
The '--_completion' argument in turn is used by a generic bash programmable
10+
completion script that tries '--_completion' on any program that doesn't have
11+
its own completion already available, renders the output of the program's
12+
built-in completion if available, and otherwise silently falls back to the
13+
shell default.
14+
15+
About
16+
-----
17+
18+
* Author: David Barnett <[email protected]>
19+
* Home: http://github.com/dbarnett/cyberpyg
20+
* License: BSD
21+
22+
How to Use
23+
----------
24+
prog.py:
25+
#!/usr/bin/env python
26+
try:
27+
from selfcompletion import SelfCompletingArgumentParser as ArgumentParser
28+
except ImportError, e:
29+
from argparse import ArgumentParser
30+
31+
parser = ArgumentParser(description='Process some integers.')
32+
parser.add_argument('integers', metavar='N', type=int, nargs='+',
33+
help='an integer for the accumulator')
34+
parser.add_argument('--sum', dest='accumulate', action='store_const',
35+
const=sum, default=max,
36+
help='sum the integers (default: find the max)')
37+
38+
args = parser.parse_args()
39+
print(args.accumulate(args.integers))
40+
41+
$ chmod +x prog.py
42+
$ ./prog.py <TAB><TAB>
43+
0 2 4 6 8 -h --sum
44+
1 3 5 7 9 --help
45+
$ ./prog.py -<TAB><TAB>
46+
-h --help --sum
47+
$ ./prog.py 1<TAB><TAB>
48+
0 1 2 3 4 5 6 7 8 9
49+
50+
Why?
51+
----
52+
Command-line completion is very, very cool, and along with good built-in help,
53+
can make even the most complex program usable. Unfortunately, it's a pain to
54+
implement. It requires an entirely separate shell script *per shell syntax*
55+
to support (e.g., bash, zsh, fish), it's a challenge for maintainers to
56+
distribute, and it must be kept in sync with changes in the program itself or
57+
else it becomes less useful or even gets in the way.
58+
59+
selfcompletion is an attempt to create a standard, and reduce a matrix of
60+
supported shell/application combinations to a list of supported shells and a
61+
list of compliant programs. Now all python software using argparse can add
62+
fine-grained command-line completion essentially for free!
63+
64+
Installing
65+
----------
66+
selfcompletion uses distutils2. To install, run
67+
pysetup install
68+
or
69+
python -m distutils2.run install

Diff for: bash_completion.d/_selfcompletion

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# -*- mode: shell-script; sh-basic-offset: 8; indent-tabs-mode: t -*-
2+
# ex: ts=8 sw=8 noet filetype=sh
3+
#
4+
5+
_foo()
6+
{
7+
prog="$1"
8+
which "$prog" >/dev/null
9+
if test $? -eq 0; then
10+
COMP_STR="${COMP_WORDS[*]}"
11+
_ORIG_IFS="$IFS"
12+
IFS="
13+
"
14+
COMPREPLY=( $( $prog --_completion $COMP_STR 2>/dev/null) )
15+
IFS="$_ORIG_IFS"
16+
fi
17+
}
18+
19+
complete -o default -o nospace -D -F _foo

Diff for: selfcompletion/__init__.py

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import argparse
2+
import re
3+
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)
9+
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
23+
24+
self.exit(0)
25+
else:
26+
return argparse.ArgumentParser.parse_args(self, *args, **kw)

Diff for: setup.cfg

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
[metadata]
2+
name = selfcompletion
3+
version = 0.0.1
4+
author = David Barnett
5+
author_email = [email protected]
6+
summary = Automatically-generated command completion built on argparse
7+
description-file = README
8+
home_page = http://github.com/dbarnett/python-selfcompletion
9+
10+
classifier = License :: OSI Approved :: BSD License
11+
Development Status :: 2 - Pre-Alpha
12+
13+
requires-dist = argparse; python_version < '2.7'
14+
15+
[files]
16+
17+
packages = selfcompletion
18+
extra_files =
19+
20+
resources =
21+

0 commit comments

Comments
 (0)