1#!/usr/bin/env python 2# -*- coding: utf-8 -*- 3 4from __future__ import unicode_literals 5from __future__ import print_function 6import subprocess 7import io 8import re 9import sys 10import os.path 11 12class Option: 13 def __init__(self, long_opt, short_opt): 14 self.long_opt = long_opt 15 self.short_opt = short_opt 16 17def get_all_options(cmd): 18 opt_pattern = re.compile(r' (?:(-.), )?(--[^\s\[=]+)(\[)?') 19 proc = subprocess.Popen([cmd, "--help"], stdout=subprocess.PIPE) 20 stdoutdata, _ = proc.communicate() 21 cur_option = None 22 opts = {} 23 for line in io.StringIO(stdoutdata.decode('utf-8')): 24 match = opt_pattern.match(line) 25 if not match: 26 continue 27 long_opt = match.group(2) 28 short_opt = match.group(1) 29 opts[long_opt] = Option(long_opt, short_opt) 30 31 return opts 32 33def output_case(out, name, opts): 34 out.write('''\ 35_{name}() 36{{ 37 local cur prev split=false 38 COMPREPLY=() 39 COMP_WORDBREAKS=${{COMP_WORDBREAKS//=}} 40 41 cmd=${{COMP_WORDS[0]}} 42 _get_comp_words_by_ref cur prev 43'''.format(name=name)) 44 45 # Complete option name. 46 out.write('''\ 47 case $cur in 48 -*) 49 COMPREPLY=( $( compgen -W '\ 50''') 51 for opt in opts.values(): 52 out.write(opt.long_opt) 53 out.write(' ') 54 55 out.write('''\ 56' -- "$cur" ) ) 57 ;; 58''') 59 # If no option found for completion then complete with files. 60 out.write('''\ 61 *) 62 _filedir 63 return 0 64 esac 65 return 0 66}} 67complete -F _{name} {name} 68'''.format(name=name)) 69 70if __name__ == '__main__': 71 if len(sys.argv) < 2: 72 print("Generates bash_completion using `/path/to/cmd --help'") 73 print("Usage: make_bash_completion.py /path/to/cmd") 74 exit(1) 75 name = os.path.basename(sys.argv[1]) 76 opts = get_all_options(sys.argv[1]) 77 output_case(sys.stdout, name, opts) 78