From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 12481 invoked by alias); 9 Jun 2016 13:53:57 -0000 Mailing-List: contact zsh-workers-help@zsh.org; run by ezmlm Precedence: bulk X-No-Archive: yes List-Id: Zsh Workers List List-Post: List-Help: X-Seq: 38639 Received: (qmail 18660 invoked from network); 9 Jun 2016 13:53:55 -0000 X-Spam-Checker-Version: SpamAssassin 3.4.1 (2015-04-28) on f.primenet.com.au X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,FREEMAIL_FROM, T_DKIM_INVALID autolearn=ham autolearn_force=no version=3.4.1 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yahoo.co.uk; s=s2048; t=1465480100; bh=Q1DO1A+xS+TpMmnyFBeZJdE9uWH242Z5Mhqhq5Crla0=; h=In-reply-to:From:References:To:Subject:Date:From:Subject; b=CWLfHj2VtoEvLJjxSnJb6Ef9cTVCj9CA6hM/S8EeeOOKHh6J72DCVtHUSazT5nTsSpDUe9Q/VfWy9xGCtcWzZa1CakZddujLAOHj8W/RJ/6HBtmXfYeJyWr7ync6K8pR79C28YEfnUzwQ2DSnCmxY84jkDXHEduiXQDOKJ6TzNkHN+9lU+XH0X8dombNDPEnWJwiLYufz4x6RAQbolewKJsssbWXmPclvg45ANj/lB7jspGdyk9dlaOgEIe3TymZBUBrT43dn7Tu+hsefCseAWtX+K/ML+l3HX33JZU6frZhNRnNc9Okz7/pW5FxmUfhLQaYcZohP46jzhzAx33Imw== X-Yahoo-Newman-Id: 967717.40730.bm@smtp118.mail.ir2.yahoo.com X-Yahoo-Newman-Property: ymail-3 X-YMail-OSG: M1QrPLIVM1kx42SllYCtYU9xN9YrAg0ny_ZUD6MJRJzvz1U PSuK_zRu65.VvtWJa_b2PyZn91EiddDq.6d6WEhT8Q6mEHG8PMuiVEkLQFzJ e2IWWMMmgVrRyDJp_EFFrzaJ7m77LlPRRRUmn95i8fv_0Q1qImMHwP3NGplu gYOJJAbjMf7sPx.UzhvGLoagIEni_TGqNFb82b3TF5qA6Pc5KeU2B6Jv.P0_ cCiN44OzYnYR.QTYImtx3aIHcD9b1tbsgnAN0cnOiJfieYhAli7niQdwEG05 OCJNWcfhhrd0Ov_YNRnFMkD5FvJ5uadNbU17uII2iG7A5eNhHtFayO.b3gPW wc9Mi62JvQODNWlGGQFcD1wBzokzzZt7BfmIFudemlVF05f3fHjijP_Ut0AD ZL1xfEikBNyCuPP6WT_Cf7CZCkOR68qsW7cN0LfQkKgTqD7jveK_gaWZpRGy ohw2G5plh.dsJ_Cqq0fmQBmYAmWlCBQgDDbuZaPu.jMubLyHBYbbvbq_t5Qp T8uBEANjE9wWu3_nLU3VZ6YSXVHBJaw-- X-Yahoo-SMTP: opAkk_CswBAce_kJ3nIPlH80cJI- In-reply-to: From: Oliver Kiddle References: <160606090104.ZM11947@torch.brasslantern.com> To: Zsh Workers Subject: PATCH: _su (was Re: Are completions in some way heavy?) MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-ID: <1687.1465480099.1@thecus.kiddle.eu> Date: Thu, 09 Jun 2016 15:48:19 +0200 Message-ID: <1688.1465480099@thecus.kiddle.eu> On 6 Jun, Sebastian Gniazdowski wrote: > But it doesn't complete user names when invoked as "su - ". su completion is particularly tricky to get working properly in part because of that single dash option. The patch is an attempt to improve on it. _su was also broken in other regards. In particular, Linux su got moved to util-linux and removed from GNU coreutils quite a few years ago (I dug into the history in case there was still a GNU su that needed supporting). That change meant the Linux specifics were skipped. I'm not too keen on completion functions producing messages like the one for the user apparently having no shell. The function failing to determine what it is is more likely so falling back to sh might be more useful? Before dispatching to _sh etc $words and $CURRENT need to be cut down to remove su options and this wasn't being done. The usual use of _arguments' two/three colon '*:: form isn't workable on Linux: su options can be specified after the username and you need -- to pass arbitrary shell options. I tried using _arguments -n and NORMARG and concluded that that feature is badly broken. It only works in very simple cases where all options precede all normal arguments but for that it offers nothing you can't do by checking $line. It could be a useful feature but I think I got something that works by comparing $#words to $#line. I couldn't find an online manpage for su on Mac OS X. Perhaps it doesn't have an su. I have verified the function on Solaris, it just doesn't need a section in the case statement. Oliver diff --git a/Completion/Unix/Command/_su b/Completion/Unix/Command/_su index 057a413..73b27ee 100644 --- a/Completion/Unix/Command/_su +++ b/Completion/Unix/Command/_su @@ -2,79 +2,86 @@ local -A opt_args local -a args context state line expl -local shell=${words[(i)(-s|--shell=*)]} first='1:user name:_users' -local usr=root +local first='(-)${norm}:user name:_users' +integer norm=1 strip +local shell usr -if _pick_variant gnu="Free Software Foundation" unix --version; then - args=( - '(--command)-c[pass command to shell]:command string:->command' - '(-c)--command=-[pass command to shell]:command string:->command' - '-f[pass -f to shell (csh)]' - '(--login)-l[use a login shell]' - '(-l)--login[use a login shell]' - '(-p --preserve-environment)-m[do not reset environment]' - '(-m --preserve-environment)-p[do not reset environment]' - '(-m -p)--preserve-environment[do not reset environment]' - '(--shell)-s[run the specified shell]:shell:->shell' - '(-s)--shell=-[run the specified shell]:shell:->shell' - ) -else - args=( - '-l[use a login shell]' - '-s[run the specified shell]:shell:->shell' - ) - case $OSTYPE in - freebsd*) - args=( +(( $words[(i)-(l|-login)] < CURRENT )) || args=( '-[use a login shell]' ) +case $OSTYPE in + linux*) + args=( -S $args + '(-c --command --session-command *)'{-c,--command=}'[pass command to shell]:command string:_cmdstring' + "(-c --command *)--session-command=[pass command to shell and don't create a new session]:command string:_cmdstring" + '(--fast -f)'{-f,--fast}'[pass -f to shell]' + '(-l --login -m -p --preserve-environment)'{-l,--login}'[use a login shell]' + '(-l --login -m -p --preserve-environment)'{-m,-p,--preserve-environment}"[don't reset environment]" + '(-s --shell)'{-s,--shell=}'[run the specified shell]:shell:->shells' + '(-)--help[display help information]' + '(-)--version[display version information]' + ) + (( EUID )) || args+=( + '(-g --group)'{-g,--group=}'[specify primary group]:group:_groups' + \*{-G,--supp-group=}'[specify supplemental group]:group:_groups' + ) + first="(--help --version)${first#???}" + ;; + *bsd*|dragonfly*) + args+=( '-c[use settings from specified login class]:class' '-f[if the invoked shell is csh, prevent it from reading .cshrc]' - '-l[use a login shell]' - '-m[do not reset environment]' - '-s[set the MAC label]' + '(-m)-l[use a login shell]' + "(-l)-m[don't reset environment]" + ) + ;| + freebsd*) args+=( '-s[set the MAC label]' ) ;; + openbsd*) + args+=( + '(-K)-a[specify authentication type]:authentication type' + '(-a)-K[shorthand for -a passwd]' + '-s[run the specified shell]:shell:->shells' + '-L[loop until login succeeds]' ) ;; - *) args+=( '-c[pass command to shell]:command string:->command' ) ;; - esac -fi + netbsd*) + args+=( + '-d[use a login shell but retain current directory]' + "-K[don't use Kerberos]" + ) + ;; +esac -if [[ $#words -ge 2 && $words[2] != -* && CURRENT -ne 2 ]]; then - usr=$words[2] - first= +if (( $words[(i)-] < CURRENT )); then + args=( ${args:#*-(-login|l|)\[*} '1:-' ) + norm=2 fi -[[ $words[shell] == -s ]] && ((shell++)) +_arguments $args ${(e)first} "*:shell arguments:= ->rest" && return -if [[ CURRENT -ne shell && -n ${words[shell]} ]]; then - shell=${words[shell]#*=} +usr=${line[norm]/--/root} +if (( $#opt_args[(i)-(s|-shell)] )); then + shell=${(v)opt_args[(i)-(s|-shell)]} +elif (( ${+commands[getent]} )); then + shell="${$(_call_program shells getent passwd $usr)##*:}" else - shell="${${(M@)${(@f)$(rest" && return - case $state in - (command) - compset -q - _normal - return - ;; - (shell) - _wanted -C $context shells expl shell compadd ${(f)^"$(