diff options
Diffstat (limited to '')
-rwxr-xr-x | src/auto-auto-complete.py | 281 |
1 files changed, 160 insertions, 121 deletions
diff --git a/src/auto-auto-complete.py b/src/auto-auto-complete.py index 35d8ab4..1f77fd8 100755 --- a/src/auto-auto-complete.py +++ b/src/auto-auto-complete.py @@ -21,51 +21,51 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. import sys -''' -Hack to enforce UTF-8 in output (in the future, if you see anypony not using utf-8 in -programs by default, report them to Princess Celestia so she can banish them to the moon) - -@param text:str The text to print (empty string is default) -@param end:str The appendix to the text to print (line breaking is default) -''' def print(text = '', end = '\n'): + ''' + Hack to enforce UTF-8 in output (in the future, if you see anypony not using utf-8 in + programs by default, report them to Princess Celestia so she can banish them to the moon) + + @param text:str The text to print (empty string is default) + @param end:str The appendix to the text to print (line breaking is default) + ''' sys.stdout.buffer.write((str(text) + end).encode('utf-8')) -''' -stderr equivalent to print() - -@param text:str The text to print (empty string is default) -@param end:str The appendix to the text to print (line breaking is default) -''' def printerr(text = '', end = '\n'): + ''' + stderr equivalent to print() + + @param text:str The text to print (empty string is default) + @param end:str The appendix to the text to print (line breaking is default) + ''' sys.stderr.buffer.write((str(text) + end).encode('utf-8')) -''' -Abort the program - -@param text:str Error message -@return returncode:int The programs return code -''' def abort(text, returncode = 1): + ''' + Abort the program + + @param text:str Error message + @return returncode:int The programs return code + ''' printerr('\033[01;31m%s\033[00m' % text) sys.exit(returncode) -''' -Bracket tree parser -''' class Parser: ''' - Parse a code and return a tree - - @param code:str The code to parse - @return :list<↑|str> The root node in the tree + Bracket tree parser ''' @staticmethod def parse(code): + ''' + Parse a code and return a tree + + @param code:str The code to parse + @return :list<↑|str> The root node in the tree + ''' stack = [] stackptr = -1 @@ -146,13 +146,13 @@ class Parser: abort('premature end of file') - ''' - Simplifies a tree - - @param tree:list<↑|str> The tree - ''' @staticmethod def simplify(tree): + ''' + Simplifies a tree + + @param tree:list<↑|str> The tree + ''' global variables program = tree[0] stack = [tree] @@ -196,21 +196,21 @@ class Parser: -''' -Completion script generator for GNU Bash -''' class GeneratorBASH: ''' - 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 - @param default:dict<str, list<str>>? Specification for optionless arguments + Completion script generator for GNU Bash ''' def __init__(self, program, unargumented, argumented, variadic, suggestion, default): + ''' + 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 + @param default:dict<str, list<str>>? Specification for optionless arguments + ''' self.program = program self.unargumented = unargumented self.argumented = argumented @@ -219,12 +219,12 @@ class GeneratorBASH: self.default = default - ''' - Gets the argument suggesters for each option - - @return :dist<str, str> Map from option to suggester - ''' def __getSuggesters(self): + ''' + Gets the argument suggesters for each option + + @return :dist<str, str> Map from option to suggester + ''' suggesters = {} for group in (self.unargumented, self.argumented, self.variadic): @@ -246,12 +246,12 @@ class GeneratorBASH: return suggesters - ''' - Returns the generated code - - @return :str The generated code - ''' def get(self): + ''' + Returns the generated code + + @return :str The generated code + ''' buf = '# bash completion for %s -*- shell-script -*-\n\n' % self.program buf += '_%s()\n{\n' % self.program buf += ' local cur prev words cword\n' @@ -353,24 +353,29 @@ class GeneratorBASH: buf += '}\n\ncomplete -o default -F _%s %s\n\n' % (self.program, self.program) return buf + + + @staticmethod + def where(command): + return '/share/bash-completion/completions/%s' % command -''' -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 - @param default:dict<str, list<str>>? Specification for optionless arguments + Completion script generator for fish ''' def __init__(self, program, unargumented, argumented, variadic, suggestion, default): + ''' + 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 + @param default:dict<str, list<str>>? Specification for optionless arguments + ''' self.program = program self.unargumented = unargumented self.argumented = argumented @@ -379,12 +384,12 @@ class GeneratorFISH: self.default = default - ''' - Gets the argument suggesters for each option - - @return :dist<str, str> Map from option to suggester - ''' def __getSuggesters(self): + ''' + Gets the argument suggesters for each option + + @return :dist<str, str> Map from option to suggester + ''' suggesters = {} for group in (self.unargumented, self.argumented, self.variadic): @@ -406,12 +411,12 @@ class GeneratorFISH: return suggesters - ''' - Gets the file pattern for each option - - @return :dist<str, list<str>> Map from option to file pattern - ''' def __getFiles(self): + ''' + Gets the file pattern for each option + + @return :dist<str, list<str>> Map from option to file pattern + ''' files = {} for group in (self.unargumented, self.argumented, self.variadic): @@ -433,12 +438,12 @@ class GeneratorFISH: return files - ''' - Returns the generated code - - @return :str The generated code - ''' def get(self): + ''' + Returns the generated code + + @return :str The generated code + ''' buf = '# fish completion for %s -*- shell-script -*-\n\n' % self.program files = self.__getFiles() @@ -542,24 +547,29 @@ class GeneratorFISH: buf += '\n' return buf + + + @staticmethod + def where(command): + return '/share/fish/completions/%s.fish' % command -''' -Completion script generator for zsh -''' class GeneratorZSH: ''' - 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 - @param default:dict<str, list<str>>? Specification for optionless arguments + Completion script generator for zsh ''' def __init__(self, program, unargumented, argumented, variadic, suggestion, default): + ''' + 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 + @param default:dict<str, list<str>>? Specification for optionless arguments + ''' self.program = program self.unargumented = unargumented self.argumented = argumented @@ -568,12 +578,12 @@ class GeneratorZSH: self.default = default - ''' - Gets the argument suggesters for each option - - @return :dist<str, str> Map from option to suggester - ''' def __getSuggesters(self): + ''' + Gets the argument suggesters for each option + + @return :dist<str, str> Map from option to suggester + ''' suggesters = {} for group in (self.unargumented, self.argumented, self.variadic): @@ -595,12 +605,12 @@ class GeneratorZSH: return suggesters - ''' - Gets the file pattern for each option - - @return :dist<str, list<str>> Map from option to file pattern - ''' def __getFiles(self): + ''' + Gets the file pattern for each option + + @return :dist<str, list<str>> Map from option to file pattern + ''' files = {} for group in (self.unargumented, self.argumented, self.variadic): @@ -622,12 +632,12 @@ class GeneratorZSH: return files - ''' - Returns the generated code - - @return :str The generated code - ''' def get(self): + ''' + Returns the generated code + + @return :str The generated code + ''' buf = '# zsh completion for %s -*- shell-script -*-\n\n' % self.program files = self.__getFiles() @@ -720,17 +730,22 @@ class GeneratorZSH: buf += ' )\n\n_arguments "$_opts[@]"\n\n' return buf + + + @staticmethod + def where(command): + return '/share/zsh/site-functions/_%s' % command -''' -mane! - -@param shell:str Shell to generato completion for -@param output:str Output file -@param source:str Source file -''' def main(shell, output, source): + ''' + mane! + + @param shell:str Shell for which to generate completion + @param output:str Output file + @param source:str Source file + ''' with open(source, 'rb') as file: source = file.read().decode('utf8', 'replace') source = Parser.parse(source) @@ -776,7 +791,9 @@ def main(shell, output, source): map[elem[0]] = elem[1:] default = map - generator = 'Generator' + shell.upper() + generator = 'Generator' + shell.upper() + if generator not in globals(): + abort('%s is not a supported shell' % shell) generator = globals()[generator] generator = generator(program, unargumented, argumented, variadic, suggestion, default) code = generator.get() @@ -786,31 +803,49 @@ def main(shell, output, source): -''' -mane! -''' +def where_main(shell, command): + ''' + --where mane! + + @param shell:str Shell for which the completion should be installed + @param command:str The commmad name + ''' + generator = 'Generator' + shell.upper() + if generator not in globals(): + abort('%s is not a supported shell' % shell) + generator = globals()[generator] + print(generator.where(command)) + + + +# supermane! if __name__ == '__main__': - if len(sys.argv) < 4: + if (len(sys.argv) == 1) or ((len(sys.argv) == 2) and (sys.argv[1] in ('-h', '--help'))): print("USAGE: auto-auto-complete SHELL --output OUTPUT_FILE --source SOURCE_FILE [VARIABLE=VALUE...]") + print(" or: auto-auto-complete SHELL --where COMMAND") exit(2) shell = None output = None source = None + where = None variables = {} option = None aliases = {'-o' : '--output', '-f' : '--source', '--file' : '--source', - '-s' : '--source'} + '-s' : '--source', + '-w' : '--where'} def useopt(option, arg): global source global output + global where global variables old = None if option == '--output': old = output; output = arg elif option == '--source': old = source; source = arg + elif option == '--where': old = where; where = arg elif not option.startswith('-'): if option not in variables: variables[option] = [] @@ -834,8 +869,12 @@ if __name__ == '__main__': else: option = arg - if output is None: abort('Unused option: --output') - if source is None: abort('Unused option: --source') - - main(shell= shell, output= output, source= source) + if shell is None: + abort('No shell has been specified') + if where is None: + if output is None: abort('Unused option: --output') + if source is None: abort('Unused option: --source') + main(shell= shell, output= output, source= source) + else: + where_main(shell= shell, command= where) |