modular_cli/modular_cli_autocomplete/modular_cli_complete.py (126 lines of code) (raw):
import json
import os
import sys
import re
from pathlib import Path
NO_DESCRIPTION = 'No description'
HELP = 'help'
BASH_INTERPRETER = 'bash'
ZSH_INTERPRETER = 'zsh'
MODULAR_CLI_DIR = '.modular_cli'
ROOT_META_FILE = 'root_commands.json'
CMD_META = 'commands_meta.json'
HELP_FILE = 'modular_cli_help.txt'
def load_meta_file():
root_commands = os.path.join(Path(__file__).parent.parent, ROOT_META_FILE)
with open(root_commands) as file:
root_file = json.load(file)
meta_file = os.path.join(str(Path.home()), MODULAR_CLI_DIR, CMD_META)
if not os.path.exists(meta_file):
return root_file
with open(meta_file) as meta_file:
meta_file = json.loads(meta_file.read())
meta_file.update(root_file)
return meta_file
def process_start_suggestion(token, meta):
suggestions = {}
for key, value in meta.items():
if key.startswith(token):
command_description = value.get('description', None)
suggestions[key] = command_description \
if command_description else NO_DESCRIPTION
format_response(suggestions)
def process_suggestions(request, meta):
suggestions = {}
completed_request = False
is_group = False
for token in request:
if meta.get(token):
meta = meta.get(token).get('body')
completed_request = True
is_group = True
elif token == request[-1] and not token.startswith('--'):
completed_request = False
is_group = False
elif token.startswith('--') and 'parameters' in meta:
completed_request = True
is_group = False
break
if 'parameters' in meta:
is_group = False
if is_group:
for item in meta:
suggestions[item] = None
format_response(suggestions)
if completed_request:
if meta.get('parameters', None):
parameters_list = meta.get('parameters')
index_of_first_param = 0
for index, token in enumerate(request):
if '--' in token:
index_of_first_param = index
break
no_params_request = request[:index_of_first_param]
params_request = [param for param in
list(set(request) - set(no_params_request))
if re.match(r'^--[a-z]', param)]
for parameter in parameters_list:
param = parameter.get('name')
param_description = parameter.get('description', None)
suggestions[
f'--{param}'] = param_description if param_description \
else NO_DESCRIPTION
updated_suggestions = {}
for specified_param in params_request:
if specified_param not in suggestions.keys():
for suggested_param in suggestions.keys():
if suggested_param.startswith(specified_param) \
and not specified_param == suggested_param:
updated_suggestions[
suggested_param] = suggestions.get(
suggested_param)
else:
del suggestions[specified_param]
if updated_suggestions:
suggestions = updated_suggestions
else:
suggestions = []
format_response(suggestions)
process_start_suggestion(request[-1], meta)
def format_response(suggestions):
help_file = os.path.join(str(Path.home()), HELP_FILE)
if isinstance(suggestions, list):
with open(help_file, 'w+') as result_file:
result_file.write(f'{os.linesep}'.join(sorted(suggestions)))
exit(0)
if isinstance(suggestions, str):
with open(help_file, 'w+') as result_file:
for each in suggestions:
result_file.write(each)
exit(0)
suggestions = dict(sorted(suggestions.items()))
response_array = []
for key, value in suggestions.items():
response_array.append(key)
response_str = f'{os.linesep}'.join(response_array)
with open(help_file, 'w+') as result_file:
result_file.write(response_str)
sys.exit(0)
if __name__ == '__main__':
if len(sys.argv) == 2:
sys.exit()
interpreter = sys.argv[1]
meta = load_meta_file()
request = sys.argv[2:]
response_str = ''
if len(request) == 1:
groups_meta = meta
suggestions = ''
if interpreter == BASH_INTERPRETER:
suggestions = [key for key in groups_meta]
if interpreter == ZSH_INTERPRETER:
suggestions = {key: value.get(HELP).split(os.linesep)[0]
for key, value in meta.items()}
format_response(suggestions=suggestions)
global_suggestion = {}
process_suggestions(request, meta)