when installing kiwi via pip, no alternatives setup done when installing via rpm will be performed. In order to allow the bash completion to work also the versioned binaries needs to be added in the completion script
253 lines
9.0 KiB
Python
Executable File
253 lines
9.0 KiB
Python
Executable File
#!/usr/bin/python3
|
|
|
|
from textwrap import dedent
|
|
|
|
import subprocess
|
|
import re
|
|
import sys
|
|
|
|
import collections
|
|
import pprint
|
|
|
|
|
|
class AutoVivification(dict):
|
|
def __getitem__(self, item):
|
|
try:
|
|
return dict.__getitem__(self, item)
|
|
except KeyError:
|
|
value = self[item] = type(self)()
|
|
return value
|
|
|
|
|
|
class AppHash:
|
|
def __init__(self):
|
|
tasks = [
|
|
'kiwi/cli.py',
|
|
'kiwi/tasks/*.py'
|
|
]
|
|
call_parm = ['bash', '-c', 'cat %s' % ' '.join(tasks)]
|
|
cmd = subprocess.Popen(
|
|
call_parm, stdout=subprocess.PIPE, stderr=subprocess.STDOUT
|
|
)
|
|
begin = False
|
|
cur_path = ''
|
|
self.result = AutoVivification()
|
|
for line in cmd.communicate()[0].decode().split('\n'):
|
|
usage = re.search('^usage: (.*)', line)
|
|
if usage:
|
|
begin = True
|
|
if re.match('.*--help', line):
|
|
mod_line = re.sub('[\[\]\|]', '', usage.group(1))
|
|
mod_line = re.sub('-h ', '', mod_line)
|
|
key_list = mod_line.split()
|
|
result_keys = self.validate(key_list)
|
|
cur_path = self.merge(result_keys, self.result)
|
|
else:
|
|
key_list = usage.group(1).split()
|
|
result_keys = self.validate(key_list)
|
|
cur_path = self.merge(result_keys, self.result)
|
|
elif begin:
|
|
if not line:
|
|
begin = False
|
|
else:
|
|
if re.match('.*--version', line):
|
|
mod_line = re.sub('[\[\]\|]', '', line)
|
|
mod_line = re.sub('-v ', '', mod_line)
|
|
key_list = mod_line.split()
|
|
result_keys = self.validate(key_list)
|
|
cur_path = self.merge(result_keys, self.result)
|
|
elif re.match('.*kiwi --compat', line):
|
|
mod_line = re.sub('[\[\]\|]', '', line)
|
|
mod_line = re.sub('<legacy_args>...', '', mod_line)
|
|
key_list = mod_line.split()
|
|
result_keys = self.validate(key_list)
|
|
cur_path = self.merge(result_keys, self.result)
|
|
elif re.match('.*kiwi \[', line):
|
|
line = line.replace('[', '')
|
|
line = line.replace(']', '')
|
|
line = line.replace('|', '')
|
|
key_list = line.split()
|
|
key_list.pop(0)
|
|
for global_opt in key_list:
|
|
result_keys = self.validate(
|
|
['kiwi', global_opt]
|
|
)
|
|
cur_path = self.merge(result_keys, self.result)
|
|
elif re.match(' \[', line):
|
|
line = line.replace('[', '')
|
|
line = line.replace(']', '')
|
|
line = line.replace('|', '')
|
|
key_list = line.split()
|
|
for global_opt in key_list:
|
|
result_keys = self.validate(
|
|
['kiwi', global_opt]
|
|
)
|
|
cur_path = self.merge(result_keys, self.result)
|
|
elif re.match(' \[', line):
|
|
opt_val = re.search(' \[(--.*)', line)
|
|
global_opt = opt_val.group(1)
|
|
global_opt = global_opt.replace('[', '')
|
|
global_opt = global_opt.replace(']', '')
|
|
global_opt = global_opt.replace('|', '')
|
|
result_keys = self.validate(
|
|
['kiwi', global_opt]
|
|
)
|
|
cur_path = self.merge(result_keys, self.result)
|
|
elif re.match('.*kiwi', line):
|
|
mandatory_options = re.search(
|
|
'(.*kiwi.*?) (--.*)', line
|
|
)
|
|
if mandatory_options:
|
|
line = mandatory_options.group(1)
|
|
key_list = line.split()
|
|
result_keys = self.validate(key_list)
|
|
cur_path = self.merge(result_keys, self.result)
|
|
if mandatory_options:
|
|
for option in mandatory_options.group(2).split():
|
|
mod_line = cur_path + ' ' + option
|
|
key_list = mod_line.split()
|
|
result_keys = self.validate(key_list)
|
|
self.merge(result_keys, self.result)
|
|
else:
|
|
if 'kiwi --' in cur_path:
|
|
cur_path = ''
|
|
for mod_line in line.strip().split('|'):
|
|
mod_line = cur_path + ' ' + mod_line
|
|
mod_line = re.sub('[\[\]]', '', mod_line)
|
|
mod_line = re.sub('-h ', '', mod_line)
|
|
key_list = mod_line.split()
|
|
result_keys = self.validate(key_list)
|
|
self.merge(result_keys, self.result)
|
|
|
|
def merge(self, key_list, result):
|
|
raw_key_path = " ".join(key_list)
|
|
key_path = ''
|
|
for key in key_list:
|
|
key_path += '[\'' + key + '\']'
|
|
expression = 'self.result' + key_path
|
|
exec(expression)
|
|
return raw_key_path
|
|
|
|
def validate(self, key_list):
|
|
result_keys = []
|
|
for key in key_list:
|
|
option = re.search('^\[(--.*)=|^\[(.*)\]', key)
|
|
mandatory = re.search('^(--.*)=', key)
|
|
if option:
|
|
if option.group(1):
|
|
result_keys.append(option.group(1))
|
|
elif mandatory:
|
|
if mandatory.group(1):
|
|
result_keys.append(mandatory.group(1))
|
|
elif re.search('<servicename>|<command>|<args>...', key):
|
|
pass
|
|
else:
|
|
key = key.replace('<','__')
|
|
key = key.replace('>','__')
|
|
result_keys.append(key)
|
|
return result_keys
|
|
|
|
|
|
class AppTree:
|
|
def __init__(self):
|
|
self.completion = AppHash()
|
|
self.level_dict = {}
|
|
|
|
def traverse(self, tree=None, level=0, origin=None):
|
|
if not tree:
|
|
tree = self.completion.result['kiwi']
|
|
if not origin:
|
|
origin = 'kiwi'
|
|
for key in tree:
|
|
try:
|
|
if self.level_dict[str(level)]:
|
|
pass
|
|
except KeyError:
|
|
self.level_dict[str(level)] = {}
|
|
try:
|
|
if self.level_dict[str(level)][origin]:
|
|
pass
|
|
except KeyError:
|
|
self.level_dict[str(level)][origin] = []
|
|
|
|
if not key in self.level_dict[str(level)][origin]:
|
|
self.level_dict[str(level)][origin].append(key)
|
|
|
|
if tree[key]:
|
|
self.traverse(tree[key], level + 1, key)
|
|
|
|
|
|
|
|
tree = AppTree()
|
|
tree.traverse()
|
|
|
|
# helpful for debugging
|
|
# pp = pprint.PrettyPrinter(indent=4)
|
|
# pp.pprint(tree.completion.result)
|
|
|
|
sorted_levels = collections.OrderedDict(
|
|
sorted(tree.level_dict.items())
|
|
)
|
|
|
|
print(dedent('''
|
|
#========================================
|
|
# _kiwi
|
|
#----------------------------------------
|
|
function setupCompletionLine {
|
|
local comp_line=$(echo $COMP_LINE | sed -e 's@kiwi-ng@kiwi@')
|
|
local result_comp_line
|
|
local prev_was_option=0
|
|
for item in $comp_line; do
|
|
if [ $prev_was_option = 1 ];then
|
|
prev_was_option=0
|
|
continue
|
|
fi
|
|
if [[ $item =~ -.* ]];then
|
|
prev_was_option=1
|
|
continue
|
|
fi
|
|
result_comp_line="$result_comp_line $item"
|
|
done
|
|
echo $result_comp_line
|
|
}
|
|
|
|
function _kiwi {
|
|
local cur prev opts
|
|
_get_comp_words_by_ref cur prev
|
|
local cmd=$(setupCompletionLine | awk -F ' ' '{ print $NF }')
|
|
''').strip())
|
|
|
|
print(' for comp in $prev $cmd;do')
|
|
print(' case "$comp" in')
|
|
for level in sorted_levels:
|
|
if level == '0':
|
|
continue
|
|
for sub in sorted(sorted_levels[level]):
|
|
print(' "%s")' % (sub))
|
|
print(' __comp_reply "%s"' % \
|
|
(" ".join(sorted(sorted_levels[level][sub])))
|
|
)
|
|
print(' return 0')
|
|
print(' ;;')
|
|
print(' esac')
|
|
print(' done')
|
|
print(' __comp_reply "%s"' % \
|
|
(" ".join(sorted(sorted_levels['0']['kiwi'])))
|
|
)
|
|
print(' return 0')
|
|
print('}')
|
|
print(dedent('''
|
|
#========================================
|
|
# comp_reply
|
|
#----------------------------------------
|
|
function __comp_reply {
|
|
word_list=$@
|
|
COMPREPLY=($(compgen -W "$word_list" -- ${cur}))
|
|
}
|
|
|
|
complete -F _kiwi -o default kiwi
|
|
complete -F _kiwi -o default kiwi-ng
|
|
complete -F _kiwi -o default kiwi-ng-2
|
|
complete -F _kiwi -o default kiwi-ng-3
|
|
''').strip())
|