aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xauto-auto-complete.py178
-rw-r--r--example2
2 files changed, 176 insertions, 4 deletions
diff --git a/auto-auto-complete.py b/auto-auto-complete.py
index e4cfadc..db4576f 100755
--- a/auto-auto-complete.py
+++ b/auto-auto-complete.py
@@ -184,7 +184,7 @@ class GeneratorBASH:
'''
Gets the argument suggesters for each option
- @param :dist<str, str> Map from option to suggester
+ @return :dist<str, str> Map from option to suggester
'''
def __getSuggesters(self):
suggesters = {}
@@ -227,7 +227,7 @@ class GeneratorBASH:
buf += ' options="%s"\n' % (' '.join(options))
buf += ' COMPREPLY=( $( compgen -W "$options" -- "$cur" ) )\n\n'
- suggesters = self.__getSuggesters();
+ suggesters = self.__getSuggesters()
suggestFunctions = {}
for function in self.suggestion:
suggestFunctions[function[0]] = function[1:]
@@ -297,7 +297,7 @@ class GeneratorBASH:
expression.append(verb(item))
suggestion += '" $(( %s ))"' % (' '.join(expression))
if len(suggestion) > 0:
- buf += ' suggestions=%s\n' % str(suggestion)
+ buf += ' suggestions=%s\n' % suggestion
buf += ' COMPREPLY=( $( compgen -W "$suggestions" -- "$cur" ) )\n'
index += 1
@@ -310,6 +310,178 @@ class GeneratorBASH:
'''
+Completion script generator for FISH
+'''
+class GeneratorFISH:
+ '''
+ Constructor
+
+ @param program:str The command to generate completion for
+ @param unargumented:list<dict<str, list<str>>> Specification of unargumented options
+ @param argumented:list<dict<str, list<str>>> Specification of argumented options
+ @param variadic:list<dict<str, list<str>>> Specification of variadic options
+ @param suggestion:list<list<↑|str>> Specification of argument suggestions
+ '''
+ def __init__(self, program, unargumented, argumented, variadic, suggestion):
+ self.program = program
+ self.unargumented = unargumented
+ self.argumented = argumented
+ self.variadic = variadic
+ self.suggestion = suggestion
+
+
+ '''
+ Gets the argument suggesters for each option
+
+ @return :dist<str, str> Map from option to suggester
+ '''
+ def __getSuggesters(self):
+ suggesters = {}
+
+ for group in (self.unargumented, self.argumented, self.variadic):
+ for item in group:
+ if 'suggest' in item:
+ suggester = item['suggest']
+ for option in item['options']:
+ suggesters[option] = suggester[0]
+
+ for group in (self.unargumented, self.argumented, self.variadic):
+ for item in group:
+ if ('suggest' not in item) and ('bind' in item):
+ bind = item['bind'][0]
+ if bind in suggesters:
+ suggester = suggesters[bind]
+ for option in item['options']:
+ suggesters[option] = suggester
+
+ return suggesters
+
+
+ '''
+ Gets the file pattern for each option
+
+ @return :dist<str, list<str>> Map from option to file pattern
+ '''
+ def __getFiles(self):
+ files = {}
+
+ for group in (self.unargumented, self.argumented, self.variadic):
+ for item in group:
+ if 'files' in item:
+ _files = item['files']
+ for option in item['options']:
+ files[option] = _files
+
+ for group in (self.unargumented, self.argumented, self.variadic):
+ for item in group:
+ if ('files' not in item) and ('bind' in item):
+ bind = item['bind'][0]
+ if bind in files:
+ _files = files[bind]
+ for option in item['options']:
+ files[option] = _files
+
+ return files
+
+
+ '''
+ Returns the generated code
+
+ @return :str The generated code
+ '''
+ def get(self):
+ buf = '# fish completion for %s -*- shell-script -*-\n\n' % self.program
+
+ files = self.__getFiles()
+
+ suggesters = self.__getSuggesters()
+ suggestFunctions = {}
+ for function in self.suggestion:
+ suggestFunctions[function[0]] = function[1:]
+
+ def verb(text):
+ temp = text
+ for char in 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-+=/@:\'':
+ temp = temp.replace(char, '')
+ if len(temp) == 0:
+ return text
+ return '\'' + text.replace('\'', '\'\\\'\'') + '\''
+
+ def makeexec(functionType, function):
+ if functionType in ('exec', 'pipe', 'fullpipe', 'cat', 'and', 'or'):
+ elems = [(' %s ' % makeexec(item[0], item[1:]) if isinstance(item, list) else verb(item)) for item in function]
+ if functionType == 'exec':
+ return ' "$( %s )" ' % (' '.join(elems))
+ if functionType == 'pipe':
+ return ' ( %s ) ' % (' | '.join(elems))
+ if functionType == 'fullpipe':
+ return ' ( %s ) ' % (' |% '.join(elems))
+ if functionType == 'cat':
+ return ' ( %s ) ' % (' ; '.join(elems))
+ if functionType == 'and':
+ return ' ( %s ) ' % (' && '.join(elems))
+ if functionType == 'or':
+ return ' ( %s ) ' % (' || '.join(elems))
+ if functionType in ('params', 'verbatim'):
+ return ' '.join([verb(item) for item in function])
+ return ' '.join([verb(functionType)] + [verb(item) for item in function])
+
+ index = 0
+ for name in suggestFunctions:
+ suggestion = '';
+ for function in suggestFunctions[name]:
+ functionType = function[0]
+ function = function[1:]
+ if functionType == 'verbatim':
+ suggestion += '" %s"' % (' '.join([verb(item) for item in function]))
+ elif functionType == 'ls':
+ filter = ''
+ if len(function) > 1:
+ filter = ' | grep -v \\/%s\\$ | grep %s\\$' % (function[1], function[1])
+ suggestion += '" $(ls -1 --color=no %s%s)"' % (function[0], filter)
+ elif functionType in ('exec', 'pipe', 'fullpipe', 'cat', 'and', 'or'):
+ suggestion += ('" %s"' if functionType == 'exec' else '" $(%s)"') % makeexec(functionType, function)
+ elif functionType == 'calc':
+ expression = []
+ for item in function:
+ if isinstance(item, list):
+ expression.append(('%s' if item[0] == 'exec' else '$(%s)') % makeexec(item[0], item[1:]))
+ else:
+ expression.append(verb(item))
+ suggestion += '" $(( %s ))"' % (' '.join(expression))
+ if len(suggestion) > 0:
+ suggestFunctions[name] = suggestion
+
+ for group in (self.unargumented, self.argumented, self.variadic):
+ for item in group:
+ options = item['options']
+ shortopt = []
+ longopt = []
+ for opt in options:
+ if opt.startswith('--'):
+ longopt.append(opt)
+ elif opt.startswith('-') and (len(opt) == 2):
+ shortopt.append(opt)
+ options = shortopt + longopt
+ if len(options) == 0:
+ continue
+ buf += 'complete --command %s' % self.program
+ if 'desc' in item:
+ buf += ' --description %s' % verb(' '.join(item['desc']))
+ if options[0] in files:
+ if (files[options[0]] == 1) and ('-0' in files[options[0]][0]):
+ buf += ' --no-files'
+ if options[0] in suggesters:
+ buf += ' --arguments %s' % suggestFunctions[suggesters[options[0]]]
+ if len(shortopt) > 0: buf += ' --short-option %s' % shortopt[0]
+ if len( longopt) > 0: buf += ' --long-option %s' % longopt[0]
+ buf += '\n'
+
+ return buf
+
+
+
+'''
mane!
@param shell:str Shell to generato completion for
diff --git a/example b/example
index 7feb8e4..4316d50 100644
--- a/example
+++ b/example
@@ -23,7 +23,7 @@
((options -f --file --pony) (complete --file --pony) (arg PONY) (suggest pony-f) (files -f *.pony) (desc 'Specify the pony that should printed'))
((options +f ++file ++pony) (complete ++file ++pony) (arg PONY) (suggest pony+f) (files -f *.pony) (desc 'Specify the extrapony that should printed'))
((options -q --quote) (complete --quote) (arg PONY) (suggest pony-q) (files -f *.pony) (desc 'Specify the pony that should quote herself'))
- ((options -b --bubble --balloon) (complete --balloon) (arg STYLE) (suggest balloon) (files -f (case (ponysay *.say) (ponyhink *.think)) (desc 'Specify message balloon style'))
+ ((options -b --bubble --balloon) (complete --balloon) (arg STYLE) (suggest balloon) (files -f (case (ponysay *.say) (ponyhink *.think))) (desc 'Specify message balloon style'))
((options -W --wrap) (complete --wrap) (arg COLUMN) (suggest wrap) (files -0) (desc 'Specify wrapping column'))
((options +c --colour) (complete --colour) (arg ANSI-COLOUR) (files -0) (desc 'Specify colour of the balloon, balloon link and message'))
((options --colour-bubble --colour-balloon) (arg ANSI-COLOUR) (files -0) (desc 'Specify colour of the balloon'))