Skip to content

Commit

Permalink
Auto complete feature for CLI. Now logic moved from bash to python.
Browse files Browse the repository at this point in the history
Not bind to bash yet. Use as 'ceph --comp osd ls'.
Able to fulfill commands as well as print command line help, when matching is complete.
Signed-off-by: Adam Kupczyk(a.kupczyk@mirantis.com)
  • Loading branch information
Adam Kupczyk committed Feb 18, 2016
1 parent 037852e commit 7b7a44e
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 41 deletions.
75 changes: 34 additions & 41 deletions src/ceph.in
Expand Up @@ -486,46 +486,40 @@ def complete(sigdict, args, target):
args = args[2:]
# look for best match, accumulate possibles in bestcmds
# (so we can maybe give a more-useful error message)
best_match_cnt = 0
bestcmds = []

match_count = 0
comps = []
for cmdtag, cmd in sigdict.iteritems():
sig = cmd['sig']
matched = matchnum(args, sig, partial=True)
if (matched > best_match_cnt):
if complete_verbose:
print >> sys.stderr, \
"better match: {0} > {1}: {2}:{3} ".format(matched,
best_match_cnt, cmdtag, concise_sig(sig))
best_match_cnt = matched
bestcmds = [{cmdtag:cmd}]
elif matched == best_match_cnt:
if complete_verbose:
print >> sys.stderr, \
"equal match: {0} > {1}: {2}:{3} ".format(matched,
best_match_cnt, cmdtag, concise_sig(sig))
bestcmds.append({cmdtag:cmd})

# look through all matching sigs
comps = []
for cmddict in bestcmds:
for cmd in cmddict.itervalues():
sig = cmd['sig']
# either:
# we match everything fully, so we want the next desc, or
# we match more partially, so we want the partial match
fullindex = matchnum(args, sig, partial=False) - 1
partindex = matchnum(args, sig, partial=True) - 1
if complete_verbose:
print >> sys.stderr, '{}: f {} p {} len {}'.format(sig, fullindex, partindex, len(sig))
if fullindex == partindex and fullindex + 1 < len(sig):
d = sig[fullindex + 1]
else:
d = sig[partindex]
comps.append(str(d))
if complete_verbose:
print >> sys.stderr, '\n'.join(comps)
print '\n'.join(comps)
i = 0
j = 0
matches = True
for i in range(0,len(args)-1):
if j > len(sig)-1:
#ran out of argument definitions
matches = False
break
r = [t for t in sig[j].complete(args[i]) if t == args[i]]
if len(r) == 0 and sig[j].req:
#no elements that match
matches = False
break
if not sig[j].N:
j = j + 1

if not matches:
continue

if j < len(sig) and len(args)>0:
comps = comps + sig[j].complete(args[-1])

match_count = match_count + 1
match_cmd = cmd

if match_count == 1 and len(comps) == 0:
#only one command matched and no hints yet => add help
comps = comps + [" ","#"+match_cmd['help']]
print '\n'.join( sorted( set(comps) ))
return 0

###
Expand Down Expand Up @@ -709,9 +703,6 @@ def main():
print >> sys.stderr, '"{0} tell" is deprecated; try "tell {0}.<id> <command> [options...]" instead (id can be "*") '.format(childargs[0])
return 1

if childargs in [['mon'], ['osd']]:
parsed_args.help = True

if parsed_args.help:
# short default timeout for -h
if not timeout:
Expand All @@ -724,7 +715,9 @@ def main():
if len(childargs) < 2:
print >> sys.stderr, '"ping" requires a monitor name as argument: "ping mon.<id>"'
return 1

if parsed_args.completion:
#for completion let timeout be really small
timeout = 3
try:
if childargs and childargs[0] == 'ping':
return ping_monitor(cluster_handle, childargs[1], timeout)
Expand Down
22 changes: 22 additions & 0 deletions src/pybind/ceph_argparse.py
Expand Up @@ -120,6 +120,9 @@ def __str__(self):
"""
return '<{0}>'.format(self.__class__.__name__)

def complete(self, s):
return []


class CephInt(CephArgtype):
"""
Expand Down Expand Up @@ -219,6 +222,12 @@ def __str__(self):
b += '(goodchars {0})'.format(self.goodchars)
return '<string{0}>'.format(b)

def complete(self, s):
if s=='':
return []
else:
return [s]


class CephSocketpath(CephArgtype):
"""
Expand Down Expand Up @@ -450,6 +459,10 @@ def __str__(self):
else:
return '{0}'.format('|'.join(self.strings))

def complete(self, s):
all_elems = [token for token in self.strings if token.startswith(s)]
return all_elems


class CephFilepath(CephArgtype):
"""
Expand Down Expand Up @@ -536,6 +549,12 @@ def valid(self, s, partial=False):
def __str__(self):
return self.prefix

def complete(self, s):
if self.prefix.startswith(s):
return [self.prefix.rstrip(' ')]
else:
return []


class argdesc(object):
"""
Expand Down Expand Up @@ -618,6 +637,9 @@ def helpstr(self):
s = '{' + s + '}'
return s

def complete(self, s):
return self.instance.complete(s)


def concise_sig(sig):
"""
Expand Down

0 comments on commit 7b7a44e

Please sign in to comment.