#compdef kw

# This file holds all the native ZSH completion functions for kw and its
# sub-commands.
#
# ZSH completion functions are stored in files named _<command-to-complete> by
# convention, hence the name of this file being '_kw'.
#
# When the ZSH completion system is loaded, it looks for the first line of files
# listed in the 'fpath' variable to determine which command the file completes.
# So the first line '#compdef kw' is necessary to tell ZSH to use the completion
# functions in this file to complete kw commands.

# Main dispatcher
_kw()
{
  local -a commands

  commands=(
    'backup:Save or restore kw data'
    'bd:Build and install modules'
    'build:Build kernel'
    'clear-cache:Clear files generated by kw'
    'codestyle:Apply checkpatch on directory or file'
    'config:Set kw config options'
    'debug:Linux kernel debug utilities'
    'deploy:Deploy a new kernel image to a target machine'
    'device:Show basic hardware information'
    'diff:Diff files'
    'drm:Set of commands to work with DRM drivers '
    'env:Handle kw envs'
    'explore:Explore string patterns'
    'h:Displays this help message'
    'help:Show kw man page'
    'init:Initialize kworkflow config file'
    'kernel-config-manager:Manage config files'
    'send-patch:Send patches via email'
    'maintainers:Get maintainers and mailing list'
    'man:Show manual pages'
    'pomodoro:kw pomodoro support'
    'remote:Manage the set of test machines ("remotes")'
    'report:Show kw pomodoro reports and kw usage statistics'
    'self-update:kw self-update mechanism'
    'ssh:SSH support'
    'patch-hub: Open UI with lore.kernel.org archives'
    'version:Show kw version'
  )

  if [[ "$CURRENT" -gt 2 ]]; then
    # Remember the command name
    local command="${words[2]}"
    # Set the context for the command
    curcontext="${curcontext%:*:*}:kw-${command}"
    # Narrow the range of words we are looking at to exclude 'kw'
    ((CURRENT--))
    shift words
    # Run the completion for the command if it exists
    if [[ $(type "_kw_${command}") =~ 'not found' ]]; then
      _nothing
    else
      eval "_kw_${command}"
    fi
  else
    # Show top level kw commands
    _describe -t kw-commands 'kw command' commands
  fi
}

_kw_backup()
{
  local args='(-r --restore)1: :_files'
  local force=''
  if ((words[(I)-r|--restore])); then
    args=''
    force='--force[replace all current kw data from backup without prompting user]'
  fi

  _arguments : \
    '(--verbose)--verbose[enable verbose mode]' \
    '(-r --restore)'{-r,--restore}'[restore kw data from specified path]: :_files' \
    $force \
    $args
}

_kw_bd()
{
  _nothing
}

_kw_b() { _kw_build }
_kw_build()
{
  _arguments : \
    '(--verbose)--verbose[enable verbose mode]' \
    '(-i --info -c --clean -f --full-cleanup -n --menu -d --doc --ccache -w --warnings -S --cpu-scaling -s --save-log-to --llvm --cflags --from-sha)'{-i,--info}'[display kernel release name, version and number of modules to compile]' \
    '(-c --clean -f --full-cleanup -i --info -n --menu -d --doc --ccache -w --warnings -S --cpu-scaling -s --save-log-to --llvm --cflags --from-sha)'{-c,--clean}'[remove files generated by the kernel build system]' \
    '(-f --full-cleanup -c --clean -i --info -n --menu -d --doc --ccache -w --warnings -S --cpu-scaling -s --save-log-to --llvm --cflags --from-sha)'{-f,--full-cleanup}'[reset the kernel tree to its default option integrated into env]' \
    '(-n --menu -i --info -c --clean -f --full-cleanup -d --doc --cflags --from-sha)'{-n,--menu}'[invoke kernel menuconfig]' \
    '(-d --doc -i --info -c --clean -f --full-cleanup -n --menu --cflags --from-sha)'{-d,--doc}'[build the kernel-doc]' \
    '(-i --info -c --clean -f --full-cleanup --cflags --from-sha)--ccache[enable ccache during compilation tasks]' \
    '(-w --warnings -i --info -c --clean -f --full-cleanup --cflags --from-sha)'{-w,--warnings}'[enable compilation warnings]:log level:(1 2 3 12 13 23 123)' \
    '(-S --cpu-scaling -i --info -c --clean -f --full-cleanup --cflags --from-sha)'{-S,--cpu-scaling}'[set CPU usage]:scaling percentage: ' \
    '(-s --save-log-to -i --info -c --clean -f --full-cleanup --cflags --from-sha)'{-s,--save-log-to}'[save full compilation log with the enabled warnings to the specified path]:log path:_files' \
    '(-i --info -c --clean -f --full-cleanup --cflags --from-sha)--llvm[enable the usage of the LLVM toolchain]' \
    '(-i --info -c --clean -f --full-cleanup -n --menu -d --doc --ccache -w --warnings -S --cpu-scaling -s --save-log-to --llvm --cflags --from-sha)--cflags[customize kernel compilation with specific flags]' \
    '(-i --info -c --clean -f --full-cleanup -n --menu -d --doc --ccache -w --warnings -S --cpu-scaling -s --save-log-to --llvm --cflags --from-sha)--from-sha[Compile all commits from given sha value to branch head]: :'
}

_kw_clear-cache()
{
  _arguments : \
    '(--verbose)--verbose[enable verbose mode]'
}

_kw_c() { _kw_codestyle }
_kw_codestyle()
{
  _arguments : \
    '(--verbose)--verbose[enable verbose mode]' \
    '(--help)--help[check man page for command]' \
    '(-h)-h[print command arguments]' \
    '(*): :_files'
}

_kw_g() { _kw_config }
_kw_config()
{
  _list_configs()
  {
    local configs='(
      vm.virtualizer vm.mount_point vm.qemu_hw_options vm.qemu_net_options vm.qemu_path_image
      kworkflow.ssh_user kworkflow.ssh_ip kworkflow.ssh_port kworkflow.ssh_configfile kworkflow.hostname
      kworkflow.disable_statistics_data_track kworkflow.gui_on kworkflow.gui_off kworkflow.gui_on_after_reboot
      kworkflow.gui_off_after_reboot kworkflow.send_opts kworkflow.blocked_emails kworkflow.checkpatch_opts
      kworkflow.get_maintainer_opts notification.alert notification.sound_alert_command
      notification.visual_alert_command build.arch build.kernel_img_name build.cross_compile build.menu_config
      build.doc_type build.cflags build.cpu_scaling_factor build.enable_ccache build.warning_level build.use_llvm
      deploy.kw_files_remote_path deploy.deploy_temporary_files_path deploy.deploy_default_compression
      deploy.dtb_copy_pattern deploy.default_deploy_target deploy.reboot_after_deploy
      deploy.strip_modules_debug_option mail.send_opts mail.blocked_emails mail.default_cc_recipients
      mail.default_to_recipients
    )'

    _multi_parts . "$configs"
  }

  local args='(-s --show -g --global -l --local)1: :_list_configs'
  if ((words[(I)-s|--show])); then
    args='*: :(vm kworkflow notification build deploy mail)'
  fi

  _arguments : \
    '(--verbose)--verbose[enable verbose mode]' \
    '(-g --global -l --local -s --show)'{-g,--global}'[set global configuration]' \
    '(-l --local -g --global -s --show)'{-l,--local}'[set local configuration]' \
    '(-s --show -g --global -l --local)'{-s,--show}'[display current configurations]: :(vm kworkflow notification build deploy mail)' \
    $args
}

_kw_debug()
{
  local disable=''
  local history=''
  local follow=''
  local cmd=''

  if ((words[(I)-e|--event|-t|--ftrace|-g|--dmesg])); then
    history='--history[create debug directory to keep track of all debugs made]'
    follow='--follow[real time output]'
    cmd='--cmd[run command]: : '
  fi

  if ((words[(I)-e|--event|-t|--ftrace])); then
    disable='--disable[disable all events]'
  fi

  _arguments : \
    '(-r --reset -e --event -l --list -t --ftrace -g --dmesg)'{-r,--reset}'[reset debug values in the target machine]' \
    '(-l --list -r --reset -g --dmesg)'{-l-,--list=-}'[list debug options]: : ' \
    '(-e --event -r --reset -l --list -t --ftrace -g --dmesg)'{-e,--event}'[events trace]: : ' \
    '(-t --ftrace -r --reset -l --list -e --event -g --dmesg)'{-t,--ftrace}'[ftrace trace]: : ' \
    '(-g --dmesg -r --reset -l --list -e --event -t --ftrace)'{-g,--dmesg}'[dmesg log]' \
    '(--verbose)--verbose[enable verbose mode]' \
    '(--remote)--local[set local machine as target]' \
    '(--local)--remote[set remote machine as target]: : ' \
    $disable \
    $history \
    $follow \
    $cmd
}

_kw_d() { _kw_deploy }
_kw_deploy()
{
  local force=''
  if ((words[(I)-u|--uninstall])); then
    force='--force[remove kernels even if they were not installed by kw]'
  fi

  if ((words[(I)-l|--list|-s|--ls-line])); then
    _arguments : \
      '(-v --verbose)'{-v,--verbose}'[show detailed output]' \
      '(--remote)--local[deploy Kernel image and/or modules to host machine]' \
      '(--local)--remote[deploy the Kernel image and/or modules to a machine in the network]: : ' \
      '(-a --list-all)'{-a,--list-all}'[list all available kernels]'
  else
    _arguments : \
      '(-v --verbose)'{-v,--verbose}'[show detailed output]' \
      '(--remote)--local[deploy Kernel image and/or modules to host machine]' \
      '(--local)--remote[deploy the Kernel image and/or modules to a machine in the network]: : ' \
      '(-r --reboot --no-reboot --setup -p --create-package)'{-r,--reboot}'[reboot machine after deploy]' \
      '(-r --reboot --setup -p --create-package)--no-reboot[do not reboot machine after deploy]' \
      '(-m --modules -u --uninstall -p --create-package --modules)'{-m,--modules}'[only install/update modules]' \
      '(-u --uninstall -l --list -s --ls-line --setup -p --create-package -F --from-package -m --modules)'{-u,--uninstall}'[uninstall given kernels]: : ' \
      $force \
      '(-l --list -u --uninstall --setup -p --create-package -F --from-package -r --reboot --no-reboot -m --modules)'{-l,--list}'[list kernels]' \
      '(-s --ls-line -u --uninstall --setup -p --create-package -F --from-package -r --reboot --no-reboot -m --modules)'{-s,--ls-line}'[list kernels separeted by commas]' \
      '(-l --list -s --ls-line -u --uninstall -p --create-package -F --from-package -r --reboot --no-reboot -m --modules)--setup[set up target machine for deploy]' \
      '(-p --create-package -l --list -s --ls-line -u --uninstall --setup -F --from-package -r --reboot --no-reboot -m --modules)'{-p,--create-package}'[create kw package]' \
      '(-F --from-package -l --list -s --ls-line -u --uninstall --setup -p --create-package)'{-F,--from-package}'[deploy from kw package]: : '
  fi
}

_kw_device()
{
  _arguments : \
    '(--verbose)--verbose[enable verbose mode]' \
    '(--remote --vm)--local[show hardware information from host machine]' \
    '(--local --vm)--remote[show hardware information from a remote machine]: :' \
    '(--remote --vm)--vm[show hardware information from a virtual machine]'
}

_kw_df() { _kw_diff }
_kw_diff()
{
  local verbose=''
  local no_interactive=''
  if [[ "$CURRENT" -gt 3 ]]; then
    verbose='(--verbose)--verbose[enable verbose mode]'
    no_interactive='--no-interactive[displays all diff in two columns at once]'
  fi

  _arguments : \
    $verbose \
    $no_interactive \
    '1: :_files' \
    '2: :_files'
}

_kw_drm()
{
  _arguments : \
    '(--verbose)--verbose[enable verbose mode]' \
    '(--unload-module)--load-module=-[specify one or more modules to be loaded with or without parameters]: : ' \
    '(--load-module)--unload-module=-[specify one or more modules to be unloaded]: : ' \
    '(--remote)--local[specify host as the target machine]' \
    '(--local)--remote[specify a remote as the target machine]: :' \
    '(--gui-off)--gui-on[turn-on the target GUI]' \
    '(--gui-on)--gui-off[turn-off the target GUI]' \
    '(--gui-off-after-reboot)--gui-on-after-reboot[turn-on the target GUI permanently]' \
    '(--gui-on-after-reboot)--gui-off-after-reboot[turn-off the target GUI permanently]' \
    '--conn-available[show all connectors available in the target machine]' \
    '--modes[show all available modes per card]'
}

_kw_env()
{
  _arguments : \
    '(--verbose)--verbose[enable verbose mode]' \
    '(-c --create -u --use -d --destroy -l --list -e --exit-env)'{-c,--create}'[create new env]: : ' \
    '(-u --use -c --create -d --destroy -l --list -e --exit-env)'{-u,--use}'[change current env to an existing env]: : ' \
    '(-d --destroy -c --create -u --use -l --list -e --exit-env)'{-d,--destroy}'[delete an existing env]: : ' \
    '(-l --list -c --create -u --use -d --destroy -e --exit-env)'{-l,--list}'[list all created envs]' \
    '(-e --exit-env -c --create -u --use -d --destroy -l --list)'{-e,--exit-env}'[exit the current env]'
}

_kw_e() { _kw_explore }
_kw_explore()
{
  _arguments : \
    '(--verbose)--verbose[enable verbose mode]' \
    '(-l --log -g --grep -a --all)'{-l,--log}'[search based on git log]' \
    '(-g --grep -l --log -a --all)'{-g,--grep}'[search for string matches using GNU grep. Also searches in .git]' \
    '(-a --all -l --log -g --grep)'{-a,--all}'[search for all matches in files under or not git management]' \
    '(-c --only-source -H --only-header)'{-c,--only-source}'[show only results from the source]' \
    '(-H --only-header -c --only-source)'{-H,--only-header}'[show only results from the header]' \
    '(-C --show-context)'{-C-,--show-context=-}'[set the context value]' \
    '1: : ' \
    '2: :_files'
}

_kw_h()
{
  _nothing
}

_kw_help()
{
  _nothing
}

_kw_init()
{
  _arguments : \
    '(--verbose)--verbose[enable verbose mode]' \
    '(-a --arch)'{-a,--arch}'[set the variable arch of kw]: : ' \
    '(-r --remote)'{-r,--remote}'[set the remote user, ip and port]: : ' \
    '(-t --target)'{-t,--target}'[set the default_deploy_target config of kw between local or remote]: :(local remote)' \
    '--template=-[pass no arguments to list all available templates or pick one by passing its name]: : '
}

_kw_k() { _kw_kernel-config-manager }
_kw_kernel-config-manager()
{
  local -a fetch_options=()
  local description=''
  local force=''

  if ((words[(I)-s|--save|-r|--remove|--get|--fetch])); then
    force='--force[suppress warnings and/or carry on any destructive operations]'
  fi

  if ((words[(I)-s|--save])); then
    description='--description[add a description to the .config file]: : '
  fi

  if ((words[(I)--fetch])); then
    fetch_options=(
      '(-o --output)'{-o,--output}'[specify the location and name of the .config file]: : ' \
      '--remote[explicitly define which remote to fetch the .config file from]: : ' \
      '--optimize[generate an optimized .config file for the target machine using localmodconfig]'
    )
  fi

  _arguments : \
    '(--verbose)--verbose[enable verbose mode]' \
    '(-s --save -r --remove -l --list --get --fetch)'{-s,--save}'[create a snapshot of the .config file inside the current dir in kw management]: : ' \
    '(-r --remove -s --save -l --list --get --fetch)'{-r,--remove}'[remove an existing .config file in kw management]: : ' \
    '(-l --list -s --save -r --remove --get --fetch)'{-l,--list}'[lists all the .config file versions available]' \
    '(--get -s --save -r --remove -l --list --fetch)--get[get a copy of an existing .config file to the current dir]: : ' \
    '(--fetch -s --save -r --remove -l --list --get)--fetch[fetches a .config file from a target machine to your current dir]' \
    $description \
    $fetch_options \
    $force
}

_kw_send-patch()
{
  local -a send_options=()
  local global=''
  local local=''
  local force=''
  local no_interactive=''
  local args=''

  if ((words[(I)-s|--send])); then
    send_options=(
      '--to=-[specify the recipients that will receive the patch via e-mail]: : '
      '--cc=-[specify the recipients that will receive a copy of the patch via e-mail]: : '
      '--simulate[do everything without actually sending the e-mail]'
      '--private[supress auto generation of recipients]'
      '--rfc[add a request for comment prefix to the e-mail subject]'
      '-v-[specify a version number for your patch]: : '
    )
  fi

  if ((words[(I)-i|--interactive|-l|--list|--verify])); then
    global='--global[set the scope as global]'
    local='--local[set the scope as local]'
  fi

  if ((words[(I)-t|--setup|--template])); then
    global='--global[set the scope as global]'
    local='--local[set the scope as local]'
    force='--force[forces the configurations to be added]'
    no_interactive='--no-interactive[inhibits interactive properties]'
    args='*: :: '
  fi

  _arguments : \
    '(--verbose)--verbose[enable verbose mode]' \
    '(-s --send -t --setup -i --interactive -l --list --verify --template)'{-s,--send}'[send a patch by email using git send-email]' \
    '(-t --setup -s --send -i --interactive -l --list --verify --template)'{-t,--setup}'[initialize and configure mail functionality]' \
    '(-i --interactive -s --send -t --setup -l --list --verify --template)'{-i,--interactive}'[interactively prompt the user for the values of the options]' \
    '(-l --list -s --send -t --setup -i --interactive --verify --template)'{-l,--list}'[lists the settings that mail uses]' \
    '(--verify -s --send -t --setup -i --interactive -l --list --template)--verify[verify that all the settings needed are set and valid]' \
    '(--template -s --send -t --setup -i --interactive -l --list --verify)--template=[load the default configuration values based on a given template]' \
    $send_options \
    $global \
    $local \
    $force \
    $no_interactive \
    $args
}

_kw_m() { _kw_maintainers }
_kw_maintainers()
{
  _arguments : \
    '(--verbose)--verbose[enable verbose mode]' \
    '(-a --authors)'{-a,--authors}'[prints the authors of the top-level target files (non-recursively)]' \
    '(-u --update-patch)'{-u,--update-patch}'[include a To: field in the header of the patch file]' \
    '1: :_files'
}

_kw_man()
{
  _values 'kw commands' \
    'backup' 'bd' 'build' 'codestyle' 'config' 'debug' 'deploy' 'device' 'diff' 'drm' 'env' \
    'explore' 'init' 'send-patch' 'maintainers' 'pomodoro' 'remote' 'report' 'self-update' 'ssh' \
    'patch-hub' 
}

_kw_p() { _kw_pomodoro }
_kw_pomodoro()
{
  local -a set_timer_options=()
  local -a tag_options=()

  if ((words[(I)-t|--set-timer])); then
    set_timer_options=(
      '(-g --tag)'{-g,--tag}'[associate a tag to the timebox]:: : '
    )
  fi

  if ((words[(I)-g|--tag])); then
    tag_options=(
      '(-d --description)'{-d,--description}'[add a more descriptive text associated with the timer]:: : '
    )
  fi

  _arguments : \
    '(--verbose)--verbose[enable verbose mode]' \
    '(--repeat-previous -t --set-timer -c --check-timer -s --show-tags)--repeat-previous[repeats the last Pomodoro session]' \
    '(-t --set-timer -c --check-timer -s --show-tags --repeat-previous)'{-t,--set-timer}'[set the timer for the Pomodoro timebox]: : ' \
    '(-c --check-timer -t --set-timer -s --show-tags --repeat-previous)'{-c,--check-timer}'[shows information of each active Pomodoro timebox]' \
    '(-s --show-tags -c --check-timer -t --set-timer --repeat-previous)'{-s,--show-tags}'[shows registered tags]' \
    $set_timer_options \
    $tag_options
}

_kw_remote()
{
  local -a set_default=()

  set_default=(
    '(-s --set-default --add --list --remove --rename)'{-s-,--set-default=}'[set existing remote as default]:remote-name: '
  )

  if ((words[(I)--add])); then
    set_default=(
      '(-s --set-default --list --remove --rename)'{-s,--set-default}'[set remote to be added as default]'
    )
  fi

  _arguments : \
    '--global[use global configurations]' \
    '(-v --verbose)'{-v,--verbose}'[be a little more verbose and show remote url after name]' \
    '(-s --set-default --add --remove --rename)--list[list all available remotes]' \
    '(--list --remove --rename)--add[add a named remote to kw management]:remote-name: :user-ip-port: ' \
    '(--list -s --set-default --add --remove)--rename[rename an existing remote from kw management]:old-remote-name: :new-remote-name: ' \
    '(--list -s --set-default --add --rename)--remove[remove an existing remote from kw management]:remote-name: ' \
    $set_default
}

_kw_r() { _kw_report }
_kw_report()
{
  _arguments : \
    '(--verbose)--verbose[enable verbose mode]' \
    '(--month --week --day)--year=-[exhibits a yearly summary]:: : ' \
    '(--year --week --day)--month=-[exhibits a monthly summary]:: : ' \
    '(--year --month --day)--week=-[exhibits a weekly summary]:: : ' \
    '(--year --month --week)--day=-[exhibits a dayly summary]:: : ' \
    '(-p --pomodoro -a --all -s --statistics)'{-p,--pomodoro}'[display pomodoro information]' \
    '(-s --statistics -a --all -p --pomodoro)'{-s,--statistics}'[display statistics information]' \
    '(-a --all -p --pomodoro -s --statistics)'{-a,--all}'[display all information]' \
    '(-o --output)'{-o,--output}'[save the output of the report to a given file]: : '
}

_kw_u() { _kw_self-update }
_kw_self-update()
{
  _arguments : \
    '(--verbose)--verbose[enable verbose mode]' \
    '(-u --unstable)'{-u,--unstable}'[update kw based on the unstable branch]'
}

_kw_s() { _kw_ssh }
_kw_ssh()
{
  local to=''

  if ((words[(I)--send|--get])); then
    to='--to[specify the destination path]: : '
  fi

  _arguments : \
    '(--verbose)--verbose[enable verbose mode]' \
    '(-s --script -c --command --send --get)'{-s,--script}'[execute a bash command in the target machine]: : ' \
    '(-c --command -s --script --send --get)'{-c,--command}'[execute a bash script in the target machine]: : ' \
    '(-s --script -c --command --get)--send[send a file or directory to the remote machine]: : ' \
    '(-s --script -c --command --send)--get[get a file or directory from the remote machine]: : ' \
    $to
}

_kw_patch-hub()
{
  _nothing
}

_kw_version()
{
  _nothing
}

_kw "$@"
