zsh-workers
 help / color / mirror / code / Atom feed
* compadd --
@ 2011-10-25 14:33 foudfou
  2011-10-25 16:04 ` Bart Schaefer
  0 siblings, 1 reply; 4+ messages in thread
From: foudfou @ 2011-10-25 14:33 UTC (permalink / raw)
  To: zsh-workers

[-- Attachment #1: Type: text/plain, Size: 900 bytes --]

Hi all,

It looks like '-' and '--' don't have the same effect in compadd.

For example, the following completion function produces "_systemctl_test:compadd:2: bad option: -.":

_systemctl_test()
{
   compadd -- -.mount boot.mount
}

Whereas it works well with '-'.
The documentation says:

   -
   --     This flag ends the list of flags and  options.  All  argu-
          ments  after  it  will  be  taken  as  the words to use as
          matches even if they begin with hyphens.

I know about -Q:

   -Q     This  flag  instructs the completion code not to quote any
          metacharacters in the words when inserting them  into  the
          command line.

which also does the trick, but I don't think that's what I need.
Besides, I can not see any kind of quoting when not specifying -Q.

Am I missing something ?

In attachment a test sample, issue: systemctl test [TAB].

Cheers,
Foudil

[-- Attachment #2: _systemctl --]
[-- Type: text/plain, Size: 9873 bytes --]

#compdef systemctl

# Copyright (c) 2011 Foudil Brétel <foudil.newbie+zshsystemctl@gmail.com>
#
# This file is released under the GPLv3.
#
# inspired from _yum and systemctl-bash-completion.sh (shipped with systemctl)
#
# TODO: enable options after commands. Ex: systemctl list-units --all --full

# Main dispatcher
_systemctl()
{
  local curcontext="$curcontext" state lstate line

  # -s for aggregated options like -aP
  _arguments -s \
    {-h,--help}'[Show help]' \
    '--version[Show package version]' \
    {-t,--type=}'[List only units of a particular type]:unit type:(automount device mount path service snapshot socket swap target timer)' \
    \*{-p,--property=}'[Show only properties by specific name]:unit property:' \
    {-a,--all}'[Show all units/properties, including dead/empty ones]' \
    '--failed[Show only failed units]' \
    "--full[Don't ellipsize unit names on output]" \
    '--fail[When queueing a new job, fail if conflicting jobs are pending]' \
    '--ignore-dependencies[When queueing a new job, ignore all its dependencies]' \
    '--kill-mode=[How to send signal]:killmode:(control-group process)' \
    '--kill-who=[Who to send signal to]:killwho:(main control all)' \
    {-s,--signal=}'[Which signal to send]:signal:_signals' \
    {-H,--host=}'[Show information for remote host]:userathost:_hosts_or_user_at_host' \
    {-P,--privileged}'[Acquire privileges before execution]' \
    {-q,--quiet}'[Suppress output]' \
    '--no-block[Do not wait until operation finished]' \
    "--no-wall[Don't send wall message before halt/power-off/reboot]" \
    "--no-reload[When enabling/disabling unit files, don't reload daemon configuration]" \
    '--no-pager[Do not pipe output into a pager]' \
    '--no-ask-password[Do not ask for system passwords]' \
    '--order[When generating graph for dot, show only order]' \
    '--require[When generating graph for dot, show only requirement]' \
    '--system[Connect to system manager]' \
    '--user[Connect to user service manager]' \
    '--global[Enable/disable unit files globally]' \
    {-f,--force}'[When enabling unit files, override existing symlinks. When shutting down, execute action immediately]' \
    '--defaults[When disabling unit files, remove default symlinks only]' \
    '*::systemctl command:_systemctl_command'
}

_hosts_or_user_at_host()
{
  _alternative \
    'users-hosts:: _user_at_host' \
    'hosts:: _hosts'
}

(( $+functions[_systemctl_command] )) || _systemctl_command()
{
  local -a _systemctl_cmds
  _systemctl_cmds=(
    "list-units:List units"
    "start:Start (activate) one or more units"
    "stop:Stop (deactivate) one or more units"
    "reload:Reload one or more units"
    "restart:Start or restart one or more units"
    "condrestart:Restart one or more units if active"
    "try-restart:Restart one or more units if active"
    "reload-or-restart:Reload one or more units is possible, otherwise start or restart"
    "force-reload:Reload one or more units is possible, otherwise restart if active"
    "reload-or-try-restart:Reload one or more units is possible, otherwise restart if active"
    "isolate:Start one unit and stop all others"
    "kill:Send signal to processes of a unit"
    "is-active:Check whether units are active"
    "status:Show runtime status of one or more units"
    "show:Show properties of one or more units/jobs or the manager"
    "reset-failed:Reset failed state for all, one, or more units"
    "enable:Enable one or more unit files"
    "disable:Disable one or more unit files"
    "is-enabled:Check whether unit files are enabled"
    "load:Load one or more units"
    "list-jobs:List jobs"
    "cancel:Cancel all, one, or more jobs"
    "monitor:Monitor unit/job changes"
    "dump:Dump server status"
    "dot:Dump dependency graph for dot(1)"
    "snapshot:Create a snapshot"
    "delete:Remove one or more snapshots"
    "daemon-reload:Reload systemd manager configuration"
    "daemon-reexec:Reexecute systemd manager"
    "show-environment:Dump environment"
    "set-environment:Set one or more environment variables"
    "unset-environment:Unset one or more environment variables"
    "default:Enter system default mode"
    "rescue:Enter system rescue mode"
    "emergency:Enter system emergency mode"
    "halt:Shut down and halt the system"
    "poweroff:Shut down and power-off the system"
    "reboot:Shut down and reboot the system"
    "kexec:Shut down and reboot the system with kexec"
    "exit:Ask for user instance termination"
    "test:ZSH testing"
  )

  if (( CURRENT == 1 )); then
    _describe -t commands 'systemctl command' _systemctl_cmds || compadd "$@"
  else
    local curcontext="$curcontext"

    cmd="${${_systemctl_cmds[(r)$words[1]:*]%%:*}}"
    # Deal with any aliases
    case $cmd in
      condrestart) cmd="try-restart";;
      force-reload) cmd="reload-or-try-restart";;
    esac

    if (( $#cmd )); then
      curcontext="${curcontext%:*:*}:systemctl-${cmd}:"

      local update_policy
      zstyle -s ":completion:${curcontext}:" cache-policy update_policy
      if [[ -z "$update_policy" ]]; then
        zstyle ":completion:${curcontext}:" cache-policy _systemctl_caching_policy
      fi

      _call_function ret _systemctl_$cmd || _message 'no more arguments'
    else
      _message "unknown systemctl command: $words[1]"
    fi
    return ret
  fi
}

# Fills the unit lists
_systemctl_all_units()
{
  if ( [[ ${+_sys_all_units} -eq 0 ]] || _cache_invalid SYS_ALL_UNITS ) &&
    ! _retrieve_cache SYS_ALL_UNITS;
  then
    _sys_all_units=( $(systemctl list-units --full --all | cut -d' ' -f1 \
      2>/dev/null) )
    _store_cache SYS_ALL_UNITS _sys_all_units
  fi
}

_systemctl_inactive_units()
{
  _sys_inactive_units=( $(systemctl list-units --full --all \
    | awk '$3 != "active" {print $1}'  2>/dev/null) )
}

_systemctl_active_units()
{
  _sys_active_units=( $(systemctl list-units --full | cut -d' ' -f1 \
    2>/dev/null) )
}

_systemctl_failed_units()
{
  _sys_failed_units=( $(systemctl list-units --full --failed | cut -d' ' -f1
    2>/dev/null) )
}

_filter_units_by_property () {
  local property=$1 value=$2 ; shift ; shift
  local -a units ; units=($*)
  local -a props ; props=( $(systemctl show --property "$property" -- \
    ${units[*]} | grep -v '^$') )
  for ((i=1; $i <= ${#units[*]}; i++)); do
    if [[ "${props[i]}" = "$property=$value" ]]; then
      echo "${units[i]}"
    fi
  done
}

# Completion functions for ALL_UNITS
for fun in enable disable is-active is-enabled status show ; do
  (( $+functions[_systemctl_$fun] )) || _systemctl_$fun()
  {
    _systemctl_all_units
    compadd "$@" -a - _sys_all_units
  }
done

# Completion functions for STARTABLE_UNITS
(( $+functions[_systemctl_start] )) || _systemctl_start()
{
  _systemctl_inactive_units
  compadd "$@" - $( _filter_units_by_property CanStart yes \
    ${_sys_inactive_units[*]} | grep -Ev '\.(device|snapshot)$' )
}

# Completion functions for RESTARTABLE_UNITS
for fun in restart reload-or-restart ; do
  (( $+functions[_systemctl_$fun] )) || _systemctl_$fun()
  {
    _systemctl_all_units
    compadd "$@" - $( _filter_units_by_property CanStart yes \
      ${_sys_all_units[*]} | grep -Ev '\.(device|snapshot|socket|timer)$' )
  }
done

# Completion functions for STOPPABLE_UNITS
for fun in stop kill try-restart condrestart ; do
  (( $+functions[_systemctl_$fun] )) || _systemctl_$fun()
  {
    _systemctl_active_units
    compadd "$@" - $( _filter_units_by_property CanStop yes \
      ${_sys_active_units[*]} )
  }
done

# Completion functions for RELOADABLE_UNITS
for fun in reload reload-or-try-restart force-reload ; do
  (( $+functions[_systemctl_$fun] )) || _systemctl_$fun()
  {
    _systemctl_active_units
    compadd "$@" - $( _filter_units_by_property CanReload yes \
      ${_sys_active_units[*]} )
  }
done

_systemctl_test()
{
  compadd -- -.mount boot.mount
}

# Completion functions for ISOLATABLE_UNITS
(( $+functions[_systemctl_isolate] )) || _systemctl_isolate()
{
  _systemctl_all_units
  compadd "$@" - $( _filter_units_by_property AllowIsolate yes \
    ${_sys_all_units[*]} )
}

# Completion functions for FAILED_UNITS
(( $+functions[_systemctl_reset-failed] )) || _systemctl_reset-failed()
{
  _systemctl_failed_units
  compadd "$@" -a - _sys_failed_units || _message "no failed-unit found"
}

# Completion functions for JOBS
(( $+functions[_systemctl_cancel] )) || _systemctl_cancel()
{
  compadd "$@" - $( systemctl list-jobs | cut -d' ' -f1  2>/dev/null ) || \
    _message "no job found"
}

# Completion functions for SNAPSHOTS
(( $+functions[_systemctl_delete] )) || _systemctl_delete()
{
  compadd "$@" - $( systemctl list-units --type snapshot --full --all \
    | cut -d' ' -f1  2>/dev/null ) || _message "no snapshot found"
}

# Completion functions for ENVS
(( $+functions[_systemctl_set-environment] )) || _systemctl_set-environment()
{
  compadd "$@" -S '' - $( systemctl show-environment \
    | sed 's_\([^=]\+=\).*_\1_' )
}
(( $+functions[_systemctl_unset-environment] )) || _systemctl_unset-environment()
{
  compadd "$@" -S '' - $( systemctl show-environment \
    | sed 's_\([^=]\+\)=.*_\1_' )
}

# no completion for:
#   [STANDALONE]='daemon-reexec daemon-reload default dot dump emergency exit
#                 halt kexec list-jobs list-units monitor poweroff reboot
#                 rescue show-environment'
#         [NAME]='snapshot load'

_systemctl_caching_policy()
{
  local _sysunits
  local -a oldcache

  # rebuild if cache is more than a day old
  oldcache=( "$1"(mh+1) )
  (( $#oldcache )) && return 0

  _sysunits=($(systemctl --full --all | cut -d' ' -f1))

  if (( $#_sysunits )); then
    for unit in $_sysunits; do
      [[ "$unit" -nt "$1" ]] && return 0
    done
  fi

  return 1
}

_systemctl "$@"

# Local Variables:
# mode: sh
# sh-indentation: 2
# indent-tabs-mode: nil
# sh-basic-offset: 2
# End:

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: compadd --
  2011-10-25 14:33 compadd -- foudfou
@ 2011-10-25 16:04 ` Bart Schaefer
  2011-10-25 16:29   ` Peter Stephenson
  0 siblings, 1 reply; 4+ messages in thread
From: Bart Schaefer @ 2011-10-25 16:04 UTC (permalink / raw)
  To: zsh-workers

On Oct 25,  4:33pm, foudfou wrote:
}
} It looks like '-' and '--' don't have the same effect in compadd.
} 
} For example, the following completion function produces "_systemctl_test:compadd:2: bad option: -.":
} 
} _systemctl_test()
} {
}    compadd -- -.mount boot.mount
} }
} 
} Whereas it works well with '-'.

Hmm.  This is a relatively new problem; here's zsh 4.2.0:

schaefer[505] compdef _systemctl_test foo
schaefer[506] foo <TAB>
-.mount     boot.mount

Here's 4.3.12-dev-1 1.5473:

torch% foo  
_systemctl_test:compadd:2: bad option: -.

The problem seems to be that the generic option parser has already
removed the "--" option before bin_compadd is even called, even though
the declaration

BUILTIN("compadd", 0, bin_compadd, 0, -1, 0, NULL, NULL)

says that compadd is going to do all its own option parsing.

This probably affects some other builtins as well.


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: compadd --
  2011-10-25 16:04 ` Bart Schaefer
@ 2011-10-25 16:29   ` Peter Stephenson
  2011-10-26  2:44     ` Bart Schaefer
  0 siblings, 1 reply; 4+ messages in thread
From: Peter Stephenson @ 2011-10-25 16:29 UTC (permalink / raw)
  To: zsh-workers

On Tue, 25 Oct 2011 09:04:45 -0700
Bart Schaefer <schaefer@brasslantern.com> wrote:
> The problem seems to be that the generic option parser has already
> removed the "--" option before bin_compadd is even called, even though
> the declaration
> 
> BUILTIN("compadd", 0, bin_compadd, 0, -1, 0, NULL, NULL)
> 
> says that compadd is going to do all its own option parsing.

Except it doesn't.  Are you saying we need this?  (Possibly for other
completion functions?)

Index: Src/Zle/complete.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/Zle/complete.c,v
retrieving revision 1.46
diff -p -u -r1.46 complete.c
--- Src/Zle/complete.c	13 Jan 2009 12:19:54 -0000	1.46
+++ Src/Zle/complete.c	25 Oct 2011 16:27:41 -0000
@@ -1544,7 +1544,7 @@ cond_range(char **a, int id)
 }
 
 static struct builtin bintab[] = {
-    BUILTIN("compadd", 0, bin_compadd, 0, -1, 0, NULL, NULL),
+    BUILTIN("compadd", BINF_HANDLES_OPTS, bin_compadd, 0, -1, 0, NULL, NULL),
     BUILTIN("compset", 0, bin_compset, 1, 3, 0, NULL, NULL),
 };
 

-- 
Peter Stephenson <pws@csr.com>            Software Engineer
Tel: +44 (0)1223 692070                   Cambridge Silicon Radio Limited
Churchill House, Cambridge Business Park, Cowley Road, Cambridge, CB4 0WZ, UK


Member of the CSR plc group of companies. CSR plc registered in England and Wales, registered number 4187346, registered office Churchill House, Cambridge Business Park, Cowley Road, Cambridge, CB4 0WZ, United Kingdom
More information can be found at www.csr.com. Follow CSR on Twitter at http://twitter.com/CSR_PLC and read our blog at www.csr.com/blog


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: compadd --
  2011-10-25 16:29   ` Peter Stephenson
@ 2011-10-26  2:44     ` Bart Schaefer
  0 siblings, 0 replies; 4+ messages in thread
From: Bart Schaefer @ 2011-10-26  2:44 UTC (permalink / raw)
  To: zsh-workers

On Oct 25,  5:29pm, Peter Stephenson wrote:
} Subject: Re: compadd --
}
} On Tue, 25 Oct 2011 09:04:45 -0700
} Bart Schaefer <schaefer@brasslantern.com> wrote:
} > BUILTIN("compadd", 0, bin_compadd, 0, -1, 0, NULL, NULL)
} > 
} > says that compadd is going to do all its own option parsing.
} 
} Except it doesn't.  Are you saying we need this?

Oops, I'd forgotten about BINF_HANDLES_OPTS; I thought a NULL in the
opts slot meant there were no options and therefore the parser should
not remove any (including not removing "--").

Anyway that patch does appear to fix it.
 
} (Possibly for other completion functions?)

Well, having the generic option parser handle "--" was a change dating
from ... when?  Sometime after 4.2.x ... and if we missed this one, we
may have missed others.  But I'm having a hard time coming up with any
reasonable way to check other than going through it all by eye.


^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2011-10-26  2:44 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-10-25 14:33 compadd -- foudfou
2011-10-25 16:04 ` Bart Schaefer
2011-10-25 16:29   ` Peter Stephenson
2011-10-26  2:44     ` Bart Schaefer

Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).