Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Re: [Pkg-zsh-devel] Bug#679824: zsh: Buggy perl completion with -e [origin: vincent@xxxxxxxxxx]



On 30 Jun, "Jun T." wrote:
> This is because the '::' in line 44
>     '*::args: _normal'
> will clear the array $words, and the completion system thinks that
> it is completing at the beginning of the command line and will try
> to complete a command name.

You can put an = before the action and _arguments adds a dummy word
to the start of $words.
  '*::args:= _normal'

This, combined with 1 in the exclusion list for -e isn't a solution,
though. Where you do have a script file, _normal ends up doing default completion
instead of using any completion definitions for that command (it is
getting 'argument-rest', i.e. the current context, as the command name).

I think the simplest solution is to use the = but then use something
like the following when handling the state.
  if (( ! $+opt_args[-e] )); then
    shift words
    (( CURRENT-- ))
  fi
This isn't much different from the solution you committed but it does
mean we're not hard coding filename completion for the first argument
when using -e and it is slightly fewer lines of code.

> In the case of ruby, the current _ruby contains
>   '(-)1:script file:_files'
> This means all files (foo.rb, bar.py, junk.c, etc.) are
> offered as Ruby scripts, but I didn't change this in the
> patch. I have no experience with ruby and don't know
> what most ruby users expect here.

I think the situation is no different for ruby as for python or perl. In
general it is better not to put file extensions on standalone scripts
but if you've got a directory containing .rb files, you probably want
to complete those first. And if you don't like that, you can specify
file-patterns without the globbed-files:

  zstyle ':completion:*:*:ruby:argument-1:*' file-patterns \
      '*(-/):directories *:all-files'

Anyway, the patch below makes the change I suggested above. I'm not
certain that I've done the right thing for python's -m: of the three,
I'm least familiar with Python. I also got side-tracked and updated all
the options in the three functions, particulary _ruby.

I notice that the #compdef line for python has lots of version numbers
listed. I've left that alone but for ruby, I've done this as a pattern:
  -P ruby[0-9.]#

Oliver

diff --git a/Completion/Unix/Command/_perl b/Completion/Unix/Command/_perl
index 1921212..52559b8 100644
--- a/Completion/Unix/Command/_perl
+++ b/Completion/Unix/Command/_perl
@@ -17,8 +17,8 @@ _perl () {
     '(-d -dt     -dt:)-d\:-[run under control of a debugging/tracing module]:debugging/tracing module:_perl_modules --strip-prefix --perl-hierarchy=Devel' \
     '(-d -dt -d:     )-dt\:-[run under control of a debugging/tracing module (debugged coded uses threads)]:debugging/tracing module:_perl_modules --strip-prefix --perl-hierarchy=Devel' \
     '-D-[set debugging flags]: :_perl_debugging_flags' \
-    '(   -E)*-e+[run one line of program]:one line of program' \
-    '(-e   )*-E+[like -e but enable all optional features]:one line of program: ' \
+    '(1 -E)*-e+[run one line of program]:one line of program' \
+    '(1 -e)*-E+[like -e but enable all optional features]:one line of program' \
     '-f[disable executing $Config{sitelib}/sitecustomize.pl at startup]' \
     '-F-[split() pattern for autosplit (-a)]:split() pattern, // is optional' \
     '-h[list help summary]' \
@@ -28,32 +28,29 @@ _perl () {
     \*{-m,-M}"-[module.. executes \`use/no module...' before executing your script]:module:_perl_m_opt" \
     "-n[assume 'while (<>) { ... }' loop around your script]" \
     "-p[assume loop like -n but print line also like sed]" \
-    '-P[run script through C preprocessor before compilation (deprecated)]' \
     "-s[enable some switch parsing for switches after script name]" \
     "-S[look for the script using PATH environment variable]" \
     '(   -T)-t[turn on taint checks but only issue warnings]' \
     '(-t   )-T[turn on taint checks]' \
     "-u[dump core after parsing script]" \
     "-U[allow unsafe operations]" \
-    "-v[print version number, patchlevel plus VERY IMPORTANT perl info]" \
+    "-v[print version, patchlevel and license]" \
     "-V-[print perl configuration information]:configuration keys:_perl_config_vars" \
     '(   -W -X)-w[turn warnings on for compilation of your script (recommended)]' \
     "(-w    -X)-W[enable all warnings (ignores 'no warnings')]" \
     "(-w -W   )-X[disable all warnings (ignores 'use warnings')]" \
-    '-x-[strip off text before #!perl line and perhaps cd to directory]:directory to cd to:_files -/' \
-    '1:script or arg:_script_or_arg' \
-    '*::args: _normal'
+    '-x-[ignore text before #!perl line and optionally cd to directory]:directory to cd to:_files -/' \
+    '1:Perl script:_files -g "*.(p[ml]|PL|t)(-.)"' \
+    '*::args:= _perl_normal'
 }
 
-_script_or_arg () {
+_perl_normal() {
   local expl
-  if [[ -n "$opt_args[(I)-(e|E)]" ]]; then
-    _description arg expl 'file'
-    _files "$expl[@]"
-  else
-    _description script expl 'Perl script'
-    _files "$expl[@]" -/ -g "*.(p[ml]|PL|t)(-.)"
+  if [[ -z "$opt_args[(I)-(e|E)]" ]]; then
+    shift words
+    (( CURRENT-- ))
   fi
+  _normal && ret=0
 }
 
 _perl_m_opt () {
diff --git a/Completion/Unix/Command/_python b/Completion/Unix/Command/_python
index da84b30..8e32bdf 100644
--- a/Completion/Unix/Command/_python
+++ b/Completion/Unix/Command/_python
@@ -1,7 +1,7 @@
 #compdef python python2 python2.4 python2.5 python2.6 python2.7 python3.0 python3.1 python3.2 python3.3 python3.4
 
-# Python 2.6
-# Python 3.0
+# Python 2.7
+# Python 3.4
 
 local curcontext="$curcontext" state line expl
 typeset -A opt_args
@@ -12,9 +12,12 @@ if _pick_variant python3=Python\ 3 python2 --version; then
   args=(
     '(-bb)-b[issue warnings about str(bytes_instance), str(bytearray_instance) and comparing bytes/bytearray with str]'
     '(-b)-bb[issue errors about str(bytes_instance), str(bytearray_instance) and comparing bytes/bytearray with str]'
+    "-I[isolate Python from the user's environment]"
+    '-X[set implementation-specific option]:option'
   )
 else
   args=(
+    '-R[use a pseudo-random salt to make hash values unpredeictable]'
     '-Q+[division options]:division option:(old warn warnall new)'
     '(-tt)-t[issue warnings about inconsistent tab usage]'
     '(-t)-tt[issue errors about inconsistent tab usage]'
@@ -24,12 +27,12 @@ fi
 
 _arguments -C -s -S "$args[@]" \
   "-B[don't write .py\[co\] files on import]" \
-  '(-)-c+[program passed in as string (terminates option list)]:python command:' \
+  '(1 -)-c+[program passed in as string (terminates option list)]:python command' \
   '-d[debug output from parser]' \
   '-E[ignore PYTHON* environment variables (such as PYTHONPATH)]' \
   '(1 * -)-h[display help information]' \
   '-i[inspect interactively after running script]' \
-  '(-)-m[run library module as a script (terminates option list)]:module:->modules' \
+  '(1 -)-m[run library module as a script (terminates option list)]:module:->modules' \
   '-O[optimize generated bytecode slightly]' \
   '-OO[remove doc-strings in addition to the -O optimizations]' \
   "-s[don't add user site directory to sys.path]" \
@@ -39,8 +42,8 @@ _arguments -C -s -S "$args[@]" \
   '(1 * -)-V[display version information]' \
   '-W+[warning control]:warning filter (action\:message\:category\:module\:lineno):(default always ignore module once error)' \
   '-x[skip first line of source, allowing use of non-Unix forms of #!cmd]' \
-  '(-)1:script_or_arg:->script_or_arg' \
-  '*::script argument: _normal' && return
+  '(-)1:Python script:_files -g "*.py(|c|o)(-.)"' \
+  '*::script argument:= ->normal' && return
 
 case "$state" in
   modules)
@@ -51,14 +54,12 @@ case "$state" in
     )
     _wanted modules expl module compadd -a modules && return
     ;;
-  script_or_arg)
-    if [[ -n "$opt_args[(I)-(c|m)]" ]]; then
-      _description arg expl 'file'
-      _files "$expl[@]" && return
-    else
-      _description script expl 'Python script'
-      _files "$expl[@]" -g "*.py(|c|o)(-.)" && return
+  normal)
+    if [[ -z "$opt_args[(I)-(c|m)]" ]]; then
+      shift words
+      (( CURRENT-- ))
     fi
+    _normal && return
     ;;
 esac
 
diff --git a/Completion/Unix/Command/_ruby b/Completion/Unix/Command/_ruby
index 80f92d5..946ebe2 100644
--- a/Completion/Unix/Command/_ruby
+++ b/Completion/Unix/Command/_ruby
@@ -1,43 +1,78 @@
-#compdef ruby -P -value-,RUBY(LIB|OPT|PATH),-default-
+#compdef ruby irb erb -P (ruby|[ei]rb)[0-9.]# -value-,RUBY(LIB|OPT|PATH),-default-
 
-# ruby 1.8.2 (2004-12-25) [i686-linux]
-
-local curcontext="$curcontext" state line expl ret=1
+local curcontext="$curcontext" state line expl desc RUBY ret=1
 typeset -A opt_args
+local -a opts irb all common charsets suf
 
-local -a args opts
+all=(
+  '*-r+[require the library before executing your script]:library name:->library'
+  '(--internal-encoding)-U[set internal encoding to UTF-8]'
+  '(-E --encoding -K --external-encoding)'{-E+,--encoding=}'[specify default external and internal character encodings]:charset:->charsets'
+  '(1 * -)'{-h,--help}'[print help message]'
+  '(1 * -)--version[print the version]'
+)
 
-args=(
-  '(-)1:script or argument:->script_or_arg'
-  '*::script argument: _normal'
+common=(
+  '*-I+[specify $LOAD_PATH directory (may be used more than once)]:library directory:_files -/'
+  '-w[turn warnings on for your script]'
+  '-W-[set warning level]:warning level:((0\:silent 1\:medium 2\:verbose))'
+  '(-)1:ruby script:_files -g "*.rb(-.)"'
+  '*::script argument:= ->normal'
 )
 
 opts=(
-  '-0-[specify record separator]:input record separator in octal (default \0):'
+  '-0-[specify record separator]:input record separator in octal [default \0]'
   '-a[autosplit mode with -n or -p (splits $_ into $F)]'
   '-c[check syntax only]'
-  '-C+[cd to directory, before executing your script]:directory:_files -/'
+  '-C+[cd to directory before executing your script]:directory:_files -/'
   '(-d --debug)'{-d,--debug}'[set debugging flags (set $DEBUG to true)]'
-  "*-e+[one line of script (several -e's allowed, omit program file)]:one line of script:"
+  "(1)*-e+[one line script (several -e's allowed, omit program file)]:one line of script"
   '-F-[split() pattern for autosplit (-a)]:input field separator:'
   '-i-[edit ARGV files in place (make backup if extension supplied)]:suffix for in-place-edit mode:(.bak)'
-  '*-I+[specify $LOAD_PATH directory (may be used more than once)]:library directory:_files -/'
   '-K-[specifies KANJI (Japanese) code-set]:KANJI encoding:((e\:EUC-JP s\:Shift_JIS u\:UTF-8 N\:None))'
   "-l[assume 'while gets(); ... end' loop around your script]"
   "(-p)-n[assume 'while gets(); ... end' loop around your script]"
   '(-n)-p[assume loop like -n but print line also like sed]'
-  '*-r+[require the library, before executing your script]:library name:->library'
   '-s[enable some switch parsing for switches after script name]'
   '-S[look for the script using PATH environment variable]'
-  '-T-[turn on tainting checks]:taint level (default 0):((0\:strings\ from\ streams/environment/ARGV\ are\ tainted 1\:no\ dangerous\ operation\ by\ tainted\ value 2\:process/file\ operations\ prohibited 3\:all\ generated\ objects\ are\ tainted 4\:no\ global\ \(non-tainted\)\ variable\ modification/no\ direct\ output))'
+  '-T-[turn on tainting checks]:taint level:((0\:strings\ from\ streams/environment/ARGV\ are\ tainted 1\:no\ dangerous\ operation\ by\ tainted\ value 2\:process/file\ operations\ prohibited 3\:all\ generated\ objects\ are\ tainted 4\:no\ global\ \(non-tainted\)\ variable\ modification/no\ direct\ output))'
   '(-v --verbose)'{-v,--verbose}'[print version number, then turn on verbose mode]'
-  '-w[turn warnings on for your script]'
-  '-W-[set warning level]:warning level (default 2):((0\:silent 1\:medium 2\:verbose))'
-  '(-y --yydebug)'{-y,--yydebug}'[enable yacc debugging in the parser]'
   '-x-[strip off text before #!ruby line and perhaps cd to directory]:directory:_files -/'
   '(1 * -)--copyright[print the copyright]'
-  '(1 * -)'{-h,--help}'[print help message]'
-  '(1 * -)--version[print the version]'
+  --{en,dis}able-{gems,rubyopt,all}
+  --{external,internal}'-encoding=:charset:->charsets'
+  '!'{-y,--yydebug}
+  '!--dump=:target:(version copyright usage yydebug syntax parsetree parsetree_with_comment insns)'
+)
+
+irb=(
+  '-f[suppress read of ~/.irbrc]'
+  '(--noinspect)-m[bc mode (load mathn, fraction, matrix)]'
+  $opts[(r)*-d\[*]
+  '(--noinspect)--inspect[use inspect for output]'
+  "(--inspect)--noinspect[don't use inspect for output]"
+  '(--noreadline)--readline[use readline extension]'
+  "(--readline)--noreadline[don't use readline extension]"
+  '(--prompt --prompt-mode --inf-ruby-mode --simple-prompt --noprompt)'{--prompt,--prompt-mode}'[switch prompt mode]:prompt mode:(default simple xmp inf-ruby)'
+  '(--prompt --prompt-mode --inf-ruby-mode --simple-prompt --noprompt)'{--inf-ruby-mode,--simple-prompt,--noprompt}
+  '--tracer[display trace for each command execution]'
+  '--back-trace-limit[set limit for backtraces]:limit [16]:'
+  '!--irb_debug:level'
+  '--context-mode:n'
+  '(--noecho)--echo[show result]'
+  "(--echo)--noecho[don't show result]"
+  '--single-irb[share self with sub-irb]'
+  '(--noverbose)--verbose[show details]'
+  "(--verbose)--noverbose[don't show details]"
+)
+
+erb=(
+  "-P[don't evaluate lines which start with %]"
+  '-S[specify safe level for running script]:level:(1 2 3 4)'
+  '-T[specify trim mode]:mode [0]:((0\:EOL\ remains 1\:EOL\ removed\ if\ line\ ends\ with\ %\> 2\:EOL\ removed\ if\ line\ starts\ with\ \<%\ and\ ends\ with\ %\> -\:EOL\ is\ removed\ if\ line\ ends\ with\ -%\>,\ leading\ whitespace\ removed\ after\ \<%-))'
+  '(-d --debug)'{-d,--debug}'[set debugging flags (set $DEBUG to true)]'
+  '-n[used with -x, prepends line number to output]'
+  '-x[convert eRuby to Ruby]'
 )
 
 case "$service" in
@@ -49,34 +84,50 @@ case "$service" in
     words=( fake "$words[@]" )
     (( CURRENT++ ))
     _arguments -C -s : "${(@M)opts:#*-[IdvwrK](|[-+])\[*}" && ret=0
+    RUBY=ruby
   ;;
-  ruby)
-    _arguments -C -s -S : "$opts[@]" "$args[@]" && ret=0
+  ruby[0-9.]#)
+    RUBY=$words[1]
+    _arguments -C -s -S : $opts $all $common && ret=0
+  ;;
+  irb[0-9.]#)
+    RUBY=${words[1]/irb/ruby}
+    _arguments -C -s : $irb $all $common && ret=0
+  ;;
+  erb[0-9.]#)
+    RUBY=${words[1]/irb/ruby}
+    _arguments -C -s : $erb $all \
+      '*:erb file:_files -g "*.erb(-.)"' && ret=0
   ;;
 esac
 
 case "$state" in
+  normal)
+    if (( ! $+opt_args[-e] )); then
+      shift words
+      (( CURRENT-- ))
+    fi
+    _normal && ret=0
+  ;;
+  charsets)
+    charsets=( $(_call_program charsets $RUBY -e 'puts\ Encoding.list' 2>/dev/null) )
+    # could also add Encoding.aliases.map(&:first) for aliases
+    desc='charset'
+    if [[ $curcontext = *option-E-1 ]]; then
+      if compset -P '*:'; then
+	desc='internal charset'
+      else
+	desc='external charset'
+	compset -S ':*' || suf=( -S: )
+      fi
+    fi
+    _wanted charsets expl $desc compadd $suf -a charsets && ret=0
+  ;;
   library)
     local -a dirs
-    local cmd
-    if [[ "$service" = *RUBYOPT* ]]; then
-      cmd=ruby
-    else
-      cmd=$words[1]
-    fi
-    dirs=( $(_call_program directories $cmd -e 'puts\ \$:' 2>/dev/null) ${(s.:.)opt_args[-I]} )
+    dirs=( $(_call_program libraries $RUBY -e 'puts\ \$:' 2>/dev/null) ${(s.:.)opt_args[-I]} )
     _wanted libraries expl library _path_files -W dirs && ret=0
   ;;
-  script_or_arg)
-    if [[ -n "$opt_args[(I)-e]" ]]; then
-      _description arg expl 'file'
-      _files "$expl[@]" && ret=0
-    else
-      _description script expl 'Ruby script'
-      _files "$expl[@]" && ret=0
-      #_files "$expl[@]" -g "*.rb(-.)" && ret=0
-    fi
-    ;;
 esac
 
 return ret



Messages sorted by: Reverse Date, Date, Thread, Author