From 8f39257fd53a068ce6c4e6c2efeffea0bd27fb90 Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Fri, 3 Dec 2010 23:03:59 +0900 Subject: Added aria2c bash_completion. make_bash_completion.py generates aria2c bash_completion using `aria2c --help=#all'. --- doc/bash_completion/make_bash_completion.py | 162 ++++++++++++++++++++++++++++ 1 file changed, 162 insertions(+) create mode 100755 doc/bash_completion/make_bash_completion.py (limited to 'doc/bash_completion/make_bash_completion.py') diff --git a/doc/bash_completion/make_bash_completion.py b/doc/bash_completion/make_bash_completion.py new file mode 100755 index 00000000..2fb12eaa --- /dev/null +++ b/doc/bash_completion/make_bash_completion.py @@ -0,0 +1,162 @@ +#!/usr/bin/env python + +import subprocess +from StringIO import StringIO +import re +import sys + +class Option: + def __init__(self, long_opt, short_opt, optional): + self.long_opt = long_opt + self.short_opt = short_opt + self.optional = optional + self.values = [] + +def get_all_options(cmd): + opt_pattern = re.compile(r' (?:(-.), )?(--[^\s\[=]+)(\[)?') + values_pattern = re.compile(r'\s+Possible Values: (.+)') + proc = subprocess.Popen([cmd, "--help=#all"], stdout=subprocess.PIPE) + stdoutdata, stderrdata = proc.communicate() + cur_option = None + opts = {} + for line in StringIO(stdoutdata): + match = opt_pattern.match(line) + if match: + long_opt = match.group(2) + short_opt = match.group(1) + optional = match.group(3) == '[' + if cur_option: + opts[cur_option.long_opt] = cur_option + cur_option = Option(long_opt, short_opt, optional) + else: + match = values_pattern.match(line) + if match: + cur_option.values = match.group(1).split(', ') + if cur_option: + opts[cur_option.long_opt] = cur_option + + # for opt in opts.itervalues(): + # print opt.short_opt, opt.long_opt, opt.optional, opt.values + + return opts + +def output_value_case(out, key, values): + out.write("""\ + {0}) + COMPREPLY=( $( compgen -W '{1}' -- "$cur" ) ) + return 0 + ;; +""".format(key, " ".join(values))) + +def output_value_case_file_comp(out, key, exts): + out.write("""\ + {0}) + _filedir '@({1})' + return 0 + ;; +""".format(key, '|'.join(exts))) + +def output_value_case_dir_comp(out, key): + out.write("""\ + {0}) + _filedir -d + return 0 + ;; +""".format(key)) + +def output_case(out, opts): + out.write("""\ +_aria2c() +{ + local cur prev split=false + COMPREPLY=() + COMP_WORDBREAKS=${COMP_WORDBREAKS//=} + + cmd=${COMP_WORDS[0]} + _get_comp_words_by_ref cur prev +""") + bool_opts = [] + nonbool_opts = [] + for opt in opts.itervalues(): + if opt.values == ['true', 'false']: + bool_opts.append(opt) + else: + nonbool_opts.append(opt) + + out.write("""\ + case $prev in +""") + # Complete pre-defined option arguments + for long_opt in ['--ftp-type', + '--proxy-method', + '--metalink-preferred-protocol', + '--bt-min-crypto-level', + '--follow-metalink', + '--file-allocation', + '--log-level', + '--uri-selector', + '--event-poll', + '--follow-torrent']: + opt = opts[long_opt] + output_value_case(out, opt.long_opt, opt.values) + # Complete directory + dir_opts = [] + for opt in opts.itervalues(): + if opt.values and opt.values[0] == '/path/to/directory': + dir_opts.append(opt) + # Complete file + output_value_case_dir_comp(out,'|'.join([opt.long_opt for opt in dir_opts])) + # Complete specific file type + output_value_case_file_comp(out, '--torrent-file', ['torrent']) + output_value_case_file_comp(out, '--metalink-file', ['meta4', 'metalink']) + out.write("""\ + esac +""") + # Complete option name. + out.write("""\ + case $cur in + -*) + COMPREPLY=( $( compgen -W '\ +""") + bool_values = [ 'true', 'false' ] + for opt in opts.itervalues(): + out.write(opt.long_opt) + out.write(' ') + # Options which takes optional argument needs "=" between + # option name and value, so we complete them including "=" and + # value here. + if opt.optional: + if bool_values == opt.values: + # Because boolean option takes true when argument is + # omitted, we just complete additional 'false' option + # only. + out.write('='.join([opt.long_opt, 'false'])) + out.write(' ') + else: + for value in opt.values: + out.write('='.join([opt.long_opt, value])) + out.write(' ') + + out.write("""\ +' -- "$cur" ) ) + ;; +""") + # If no option found for completion then complete with files. + out.write("""\ + *) + _filedir '@(torrent|meta4|metalink|text|txt|list|lst)' + [ ${#COMPREPLY[@]} -eq 0 ] && _filedir + return 0 + esac + return 0 +} +complete -F _aria2c aria2c +""") + +if __name__ == '__main__': + if len(sys.argv) < 2: + print "Generates aria2c(1) bash_completion using `aria2c --help=#all'" + print "Usage: make_bash_completion.py /path/to/aria2c" + exit(1) + opts = get_all_options(sys.argv[1]) + output_case(sys.stdout, opts) -- cgit