166 lines
4.4 KiB
Ruby
166 lines
4.4 KiB
Ruby
require 'open3'
|
|
|
|
HEAD = """
|
|
#compdef _vagrant vagrant
|
|
|
|
# ZSH completion for Vagrant
|
|
#
|
|
# To use this completion add this to ~/.zshrc
|
|
# fpath=(/path/to/this/dir $fpath)
|
|
# compinit
|
|
#
|
|
# For development reload the function after making changes
|
|
# unfunction _vagrant && autoload -U _vagrant
|
|
"""
|
|
|
|
BOX_LIST_FUNCTION = """
|
|
__box_list ()
|
|
{
|
|
_wanted application expl 'command' compadd $(command vagrant box list | awk '{print $1}' )
|
|
}
|
|
"""
|
|
|
|
PLUGIN_LIST_FUNCTION = """
|
|
__plugin_list ()
|
|
{
|
|
_wanted application expl 'command' compadd $(command vagrant plugin list | awk '{print $1}')
|
|
}
|
|
"""
|
|
|
|
ADD_FEATURE_FLAGS = ["remove", "repackage", "update", "repair", "uninstall"]
|
|
VAGRANT_COMMAND = "vagrant"
|
|
|
|
FLAG_REGEX = /--(\S)*/
|
|
CMDS_REGEX = /^(\s){1,}(\w)(\S)*/
|
|
|
|
def make_string_script_safe(s)
|
|
s.gsub("[","(").gsub("]",")").gsub("-","_").gsub("'", "")
|
|
end
|
|
|
|
def remove_square_brakets(s)
|
|
s.gsub("[","(").gsub("]",")")
|
|
end
|
|
|
|
def format_flags(group_name, flags)
|
|
group_name = make_string_script_safe(group_name)
|
|
opts_str = "local -a #{group_name} && #{group_name}=(\n"
|
|
flags.each do |flag, desc|
|
|
opts_str = opts_str + " '#{remove_square_brakets(flag)}=[#{make_string_script_safe(desc)}]'\n"
|
|
end
|
|
opts_str + ")"
|
|
end
|
|
|
|
def format_subcommand(group_name, cmds)
|
|
opts_str = "local -a #{group_name} && #{group_name}=(\n"
|
|
cmds.each do |cmd, desc|
|
|
opts_str = opts_str + " '#{cmd}:#{desc}'\n"
|
|
end
|
|
opts_str + ")"
|
|
end
|
|
|
|
def format_case(group_name, cmds, cmd_list, feature_string)
|
|
case_str = """case $state in
|
|
(command)
|
|
_describe -t commands 'command' #{group_name}
|
|
return
|
|
;;
|
|
|
|
(options)
|
|
case $line[1] in
|
|
"""
|
|
|
|
cmds.each do |cmd, desc|
|
|
if cmd_list.include?(cmd)
|
|
case_append = """ #{cmd})
|
|
_arguments -s -S : $#{make_string_script_safe(cmd)}_arguments #{feature_string if ADD_FEATURE_FLAGS.include?(cmd)} ;;
|
|
"""
|
|
else
|
|
case_append = """ #{cmd})
|
|
__vagrant-#{cmd} ;;
|
|
"""
|
|
end
|
|
case_str = case_str + case_append
|
|
end
|
|
|
|
case_str = case_str + """esac
|
|
;;
|
|
esac
|
|
"""
|
|
end
|
|
|
|
def extract_flags(top_level_commands)
|
|
flags = top_level_commands.map { |c| [c.match(FLAG_REGEX)[0], c.split(" ")[-1].strip] if c.strip.start_with?("--") }.compact
|
|
end
|
|
|
|
def extract_subcommand(top_level_commands)
|
|
cmds = top_level_commands.map { |c| [c.match(CMDS_REGEX)[0].strip, c.split(" ")[-1].strip] if c.match(CMDS_REGEX) }.compact
|
|
end
|
|
|
|
def get_top_level_commands(root_command, cmd_list)
|
|
stdout, stderr, status = Open3.capture3("vagrant #{root_command} -h")
|
|
top_level_commands = stdout.split("\n")
|
|
|
|
root_subcommand = extract_subcommand(top_level_commands)
|
|
commands = format_subcommand("sub_commands", root_subcommand)
|
|
if root_command == "box"
|
|
feature_string = "':feature:__box_list'"
|
|
elsif root_command == "plugin"
|
|
feature_string = "':feature:__plugin_list'"
|
|
else
|
|
feature_string = ""
|
|
end
|
|
case_string = format_case("sub_commands", root_subcommand, cmd_list, feature_string)
|
|
|
|
flags_def = ""
|
|
root_subcommand.each do |cmd, desc|
|
|
next if !cmd_list.include?(cmd)
|
|
stdout, stderr, status = Open3.capture3("vagrant #{root_command} #{cmd} -h")
|
|
cmd_help = stdout.split("\n")
|
|
flags_def = flags_def + format_flags("#{cmd}_arguments", extract_flags(cmd_help)) + "\n\n"
|
|
end
|
|
|
|
return commands, flags_def, case_string
|
|
end
|
|
|
|
def format_script(root_command, subcommands, funciton_name)
|
|
top_level_commands, top_level_args, state_case = get_top_level_commands(root_command, subcommands)
|
|
|
|
script = """
|
|
function #{funciton_name} () {
|
|
|
|
#{top_level_commands}
|
|
|
|
#{top_level_args}
|
|
|
|
_arguments -C ':command:->command' '*::options:->options'
|
|
|
|
#{state_case}
|
|
}
|
|
"""
|
|
end
|
|
|
|
def generate_script
|
|
subcommand_list = {
|
|
"" => ["cloud", "destroy", "global-status", "halt", "help", "login", "init", "package", "port", "powershell", "provision", "push", "rdp", "reload", "resume", "ssh", "ssh-config", "status", "suspend", "up", "upload", "validate", "version", "winrm", "winrm-config"],
|
|
"box" => ["add", "list", "outdated", "prune", "remove", "repackage", "update"],
|
|
"snapshot" => ["delete", "list", "pop", "push", "restore", "save"],
|
|
"plugin" => ["install", "expunge", "license", "list", "repair", "uninstall", "update"],
|
|
}
|
|
|
|
script = """#{HEAD}
|
|
#{BOX_LIST_FUNCTION}
|
|
#{PLUGIN_LIST_FUNCTION}
|
|
"""
|
|
|
|
subcommand_list.each do |cmd, opts|
|
|
if cmd != ""
|
|
function_name = "__vagrant-#{cmd}"
|
|
else
|
|
function_name = "_vagrant"
|
|
end
|
|
script = script + format_script(cmd, opts, function_name)
|
|
end
|
|
script
|
|
end
|
|
|
|
puts generate_script |