zsh-workers
 help / color / mirror / code / Atom feed
* PATCH: _su (was Re: Are completions in some way heavy?)
       [not found]   ` <CAKc7PVB8rH-MeCMzjgSLYi1QhBawcX4tde_SQ06DaHOYo3gDyQ@mail.gmail.com>
@ 2016-06-09 13:48     ` Oliver Kiddle
  2016-06-10  5:27       ` Alexius Ludeman
  0 siblings, 1 reply; 3+ messages in thread
From: Oliver Kiddle @ 2016-06-09 13:48 UTC (permalink / raw)
  To: Zsh Workers

On 6 Jun, Sebastian Gniazdowski wrote:
> But it doesn't complete user names when invoked as "su - <TAB>".

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)$(</etc/passwd)}:#$usr*}##*:}"
+  shell="${${(M@)${(@f)$(</etc/passwd)}:#$usr*}##*:}"
 fi
 
-[[ -z $first ]] && compset -n 2
-
-_arguments : $args[@] $first "*:${shell:t} arguments:->rest" && return
-
 case $state in
-    (command)
-        compset -q
-        _normal
-        return
-        ;;
-    (shell)
-        _wanted -C $context shells expl shell compadd ${(f)^"$(</etc/shells)"}(N)
-        return
-        ;;
-    (rest)
-        if [[ -z $shell || $shell = */(nologin|false) ]]; then
-            _arguments "-s[run the specified shell, $usr has no shell]" ||
-                _message "-s option required, $usr has no shell"
-            compstate[insert]=
-        else
-            # Something wrong here: doubles the file listing sometimes
-            _dispatch ${service}:${context} $shell $shell:t -default-
-            return
-        fi
-        ;;
+  shells)
+    _wanted -C $context shells expl shell compadd ${(f)^"$(</etc/shells)"}(N)
+    return
+  ;;
+  rest)
+    if [[ -z $shell || $shell = */(nologin|false) ]]; then
+      _message "-s option required, $usr has no shell"
+    else
+      (( strip = $#words - $#line + norm ))
+      (( CURRENT -= strip - 1 ))
+      words[2,strip]=()
+      _dispatch ${service}:${context} $shell $shell:t -default-
+      return
+    fi
+  ;;
 esac
 
 return 1


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

* Re: PATCH: _su (was Re: Are completions in some way heavy?)
  2016-06-09 13:48     ` PATCH: _su (was Re: Are completions in some way heavy?) Oliver Kiddle
@ 2016-06-10  5:27       ` Alexius Ludeman
  2016-06-17 16:50         ` Oliver Kiddle
  0 siblings, 1 reply; 3+ messages in thread
From: Alexius Ludeman @ 2016-06-10  5:27 UTC (permalink / raw)
  To: Zsh Workers

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

Hi Oliver,

The su manpage for os x is available at:

https://developer.apple.com/legacy/library/documentation/Darwin/Reference/ManPages/man1/su.1.html

Even though the page mentions the manpage is for 10.9, I'm on el
capitan(10.11.5) and the content matches exactly.

thanks

On Thu, Jun 9, 2016 at 6:48 AM, Oliver Kiddle <okiddle@yahoo.co.uk> wrote:

> On 6 Jun, Sebastian Gniazdowski wrote:
> > But it doesn't complete user names when invoked as "su - <TAB>".
>
> 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)$(</etc/passwd)}:#$usr*}##*:}"
> +  shell="${${(M@)${(@f)$(</etc/passwd)}:#$usr*}##*:}"
>  fi
>
> -[[ -z $first ]] && compset -n 2
> -
> -_arguments : $args[@] $first "*:${shell:t} arguments:->rest" && return
> -
>  case $state in
> -    (command)
> -        compset -q
> -        _normal
> -        return
> -        ;;
> -    (shell)
> -        _wanted -C $context shells expl shell compadd
> ${(f)^"$(</etc/shells)"}(N)
> -        return
> -        ;;
> -    (rest)
> -        if [[ -z $shell || $shell = */(nologin|false) ]]; then
> -            _arguments "-s[run the specified shell, $usr has no shell]" ||
> -                _message "-s option required, $usr has no shell"
> -            compstate[insert]=
> -        else
> -            # Something wrong here: doubles the file listing sometimes
> -            _dispatch ${service}:${context} $shell $shell:t -default-
> -            return
> -        fi
> -        ;;
> +  shells)
> +    _wanted -C $context shells expl shell compadd
> ${(f)^"$(</etc/shells)"}(N)
> +    return
> +  ;;
> +  rest)
> +    if [[ -z $shell || $shell = */(nologin|false) ]]; then
> +      _message "-s option required, $usr has no shell"
> +    else
> +      (( strip = $#words - $#line + norm ))
> +      (( CURRENT -= strip - 1 ))
> +      words[2,strip]=()
> +      _dispatch ${service}:${context} $shell $shell:t -default-
> +      return
> +    fi
> +  ;;
>  esac
>
>  return 1
>

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

* Re: PATCH: _su (was Re: Are completions in some way heavy?)
  2016-06-10  5:27       ` Alexius Ludeman
@ 2016-06-17 16:50         ` Oliver Kiddle
  0 siblings, 0 replies; 3+ messages in thread
From: Oliver Kiddle @ 2016-06-17 16:50 UTC (permalink / raw)
  To: Zsh Workers

On 9 Jun, Alexius Ludeman wrote:
>
> The su manpage for os x is available at:

Thanks for that. The patch to support it follows.

Oliver

diff --git a/Completion/Unix/Command/_su b/Completion/Unix/Command/_su
index 73b27ee..9009056 100644
--- a/Completion/Unix/Command/_su
+++ b/Completion/Unix/Command/_su
@@ -25,7 +25,7 @@ case $OSTYPE in
     )
     first="(--help --version)${first#???}"
   ;;
-  *bsd*|dragonfly*)
+  *bsd*|darwin*|dragonfly*)
     args+=(
       '-c[use settings from specified login class]:class'
       '-f[if the invoked shell is csh, prevent it from reading .cshrc]'


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

end of thread, other threads:[~2016-06-17 16:56 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <CAKc7PVBnpkEnkWZb4yh9BgutbBgfKS0Hh1x6e_Q-jnOyVDHQOg@mail.gmail.com>
     [not found] ` <160606090104.ZM11947@torch.brasslantern.com>
     [not found]   ` <CAKc7PVB8rH-MeCMzjgSLYi1QhBawcX4tde_SQ06DaHOYo3gDyQ@mail.gmail.com>
2016-06-09 13:48     ` PATCH: _su (was Re: Are completions in some way heavy?) Oliver Kiddle
2016-06-10  5:27       ` Alexius Ludeman
2016-06-17 16:50         ` Oliver Kiddle

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).