aboutsummaryrefslogtreecommitdiffstats
path: root/src/auto-auto-complete.py
diff options
context:
space:
mode:
Diffstat (limited to '')
-rwxr-xr-xsrc/auto-auto-complete.py281
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)