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