""" Simple automated generation of a bash_completion file for yunohost command from the actionsmap. Generates a bash completion file assuming the structure `yunohost category action` adds `--help` at the end if one presses [tab] again. author: Christophe Vuillot """ import os import yaml THIS_SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) ACTIONSMAP_FILE = THIS_SCRIPT_DIR + '/yunohost.yml' BASH_COMPLETION_FILE = THIS_SCRIPT_DIR + '/../bash-completion.d/yunohost' def get_dict_actions(OPTION_SUBTREE, category): ACTIONS = [action for action in OPTION_SUBTREE[category]["actions"].keys() if not action.startswith('_')] ACTIONS_STR = '{}'.format(' '.join(ACTIONS)) DICT = {"actions_str": ACTIONS_STR} return DICT with open(ACTIONSMAP_FILE, 'r') as stream: # Getting the dictionary containning what actions are possible per category OPTION_TREE = yaml.load(stream) CATEGORY = [category for category in OPTION_TREE.keys() if not category.startswith('_')] CATEGORY_STR = '{}'.format(' '.join(CATEGORY)) ACTIONS_DICT = {} for category in CATEGORY: ACTIONS_DICT[category] = get_dict_actions(OPTION_TREE, category) ACTIONS_DICT[category]["subcategories"] = {} ACTIONS_DICT[category]["subcategories_str"] = "" if "subcategories" in OPTION_TREE[category].keys(): SUBCATEGORIES = [subcategory for subcategory in OPTION_TREE[category]["subcategories"].keys()] SUBCATEGORIES_STR = '{}'.format(' '.join(SUBCATEGORIES)) ACTIONS_DICT[category]["subcategories_str"] = SUBCATEGORIES_STR for subcategory in SUBCATEGORIES: ACTIONS_DICT[category]["subcategories"][subcategory] = get_dict_actions(OPTION_TREE[category]["subcategories"], subcategory) with open(BASH_COMPLETION_FILE, 'w') as generated_file: # header of the file generated_file.write('#\n') generated_file.write('# completion for yunohost\n') generated_file.write('# automatically generated from the actionsmap\n') generated_file.write('#\n\n') # Start of the completion function generated_file.write('_yunohost()\n') generated_file.write('{\n') # Defining local variable for previously and currently typed words generated_file.write('\tlocal cur prev opts narg\n') generated_file.write('\tCOMPREPLY=()\n\n') generated_file.write('\t# the number of words already typed\n') generated_file.write('\tnarg=${#COMP_WORDS[@]}\n\n') generated_file.write('\t# the current word being typed\n') generated_file.write('\tcur="${COMP_WORDS[COMP_CWORD]}"\n\n') # If one is currently typing a category then match with the category list generated_file.write('\t# If one is currently typing a category,\n') generated_file.write('\t# match with categorys\n') generated_file.write('\tif [[ $narg == 2 ]]; then\n') generated_file.write('\t\topts="{}"\n'.format(CATEGORY_STR)) generated_file.write('\tfi\n\n') # If one is currently typing an action then match with the action list # of the previously typed category generated_file.write('\t# If one already typed a category,\n') generated_file.write('\t# match the actions or the subcategories of that category\n') generated_file.write('\tif [[ $narg == 3 ]]; then\n') generated_file.write('\t\t# the category typed\n') generated_file.write('\t\tcategory="${COMP_WORDS[1]}"\n\n') for category in CATEGORY: generated_file.write('\t\tif [[ $category == "{}" ]]; then\n'.format(category)) generated_file.write('\t\t\topts="{} {}"\n'.format(ACTIONS_DICT[category]["actions_str"], ACTIONS_DICT[category]["subcategories_str"])) generated_file.write('\t\tfi\n') generated_file.write('\tfi\n\n') generated_file.write('\t# If one already typed an action or a subcategory,\n') generated_file.write('\t# match the actions of that subcategory\n') generated_file.write('\tif [[ $narg == 4 ]]; then\n') generated_file.write('\t\t# the category typed\n') generated_file.write('\t\tcategory="${COMP_WORDS[1]}"\n\n') generated_file.write('\t\t# the action or the subcategory typed\n') generated_file.write('\t\taction_or_subcategory="${COMP_WORDS[2]}"\n\n') for category in CATEGORY: if len(ACTIONS_DICT[category]["subcategories"]): generated_file.write('\t\tif [[ $category == "{}" ]]; then\n'.format(category)) for subcategory in ACTIONS_DICT[category]["subcategories"]: generated_file.write('\t\t\tif [[ $action_or_subcategory == "{}" ]]; then\n'.format(subcategory)) generated_file.write('\t\t\t\topts="{}"\n'.format(ACTIONS_DICT[category]["subcategories"][subcategory]["actions_str"])) generated_file.write('\t\t\tfi\n') generated_file.write('\t\tfi\n') generated_file.write('\tfi\n\n') # If both category and action have been typed or the category # was not recognized propose --help (only once) generated_file.write('\t# If no options were found propose --help\n') generated_file.write('\tif [ -z "$opts" ]; then\n') generated_file.write('\t\tprev="${COMP_WORDS[COMP_CWORD-1]}"\n\n') generated_file.write('\t\tif [[ $prev != "--help" ]]; then\n') generated_file.write('\t\t\topts=( --help )\n') generated_file.write('\t\tfi\n') generated_file.write('\tfi\n') # generate the completion list from the possible options generated_file.write('\tCOMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )\n') generated_file.write('\treturn 0\n') generated_file.write('}\n\n') # Add the function to bash completion generated_file.write('complete -F _yunohost yunohost')