summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog8
-rw-r--r--Completion/Unix/Type/_list_files66
-rw-r--r--Completion/Unix/Type/_path_files39
-rw-r--r--Doc/Zsh/compsys.yo30
-rw-r--r--Doc/Zsh/compwid.yo8
-rw-r--r--Src/Zle/comp.h1
-rw-r--r--Src/Zle/compcore.c4
-rw-r--r--Src/Zle/complete.c3
8 files changed, 149 insertions, 10 deletions
diff --git a/ChangeLog b/ChangeLog
index 5a551a7a1..a1a7115fb 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,13 @@
 2006-03-07  Peter Stephenson  <pws@csr.com>
 
+	* 22328, modified: Completion/Unix/Type/_list_files,
+	Completion/Unix/Type/_path_files, Doc/Zsh/compsys.yo,
+	Doc/Zsh/compwid.yo, Src/Zle/comp.h, Src/Zle/compcore.c,
+	Src/Zle/complete.c:  Option -o to compadd uses match
+	strings rather than display strings from -d for sorting;
+	_path_files uses _list_files to handle file-list style
+	which allows long format file lists.
+
 	* unposted: Config/version.mk: belatedly update version
 	to 4.3.2-dev-1 to avoid clash with released version.
 
diff --git a/Completion/Unix/Type/_list_files b/Completion/Unix/Type/_list_files
new file mode 100644
index 000000000..2166ac6cc
--- /dev/null
+++ b/Completion/Unix/Type/_list_files
@@ -0,0 +1,66 @@
+#autoload
+
+# Helper function for _path_files to handle the file-list style.
+
+# arguments:
+#  name of parameter containing file matches
+#  directory prefix
+# Sets array listfiles to the display strings and the array
+# listopts appropriately to be added to the compadd command line.
+
+local stat f elt what
+local -a stylevals
+integer ok
+
+listfiles=()
+listopts=()
+
+zmodload -i zsh/stat 2>/dev/null || return 1
+
+zstyle -a ":completion:${curcontext}:" file-list stylevals || return 1
+
+# TODO: more flexible way of handling the following?  e.g. use $compstate?
+case $WIDGETSTYLE in
+  (*complete*)
+  what=insert
+  ;;
+
+  (*)
+  what=list
+  ;;
+esac
+
+for elt in $stylevals; do
+  case $elt in
+    (*($what|all|true|1|yes)*=<->)
+    # use long format if no more than the given number of matches
+    (( ${(P)#1} <= ${elt##*=} )) && (( ok = 1 ))
+    break
+    ;;
+
+    (*($what|all|true|1|yes)[^=]#)
+    # always use long format
+    (( ok = 1 ))
+    break
+    ;;
+  esac
+done
+
+(( ok )) || return 1
+
+for f in ${(P)1}; do
+  if [[ ! -e "${2:+$2/}$f" ]]; then
+    listfiles+=("${2:+$2/}$f")
+    continue
+  fi
+
+  # Borrowed from Functions/Example/zls
+  stat -s -H stat -F "%b %e %H:%M" - "${2:+$2/}$f" >/dev/null 2>&1
+
+  listfiles+=("$stat[mode] ${(l:3:)stat[nlink]} ${(r:8:)stat[uid]} \
+ ${(r:8:)stat[gid]} ${(l:8:)stat[size]} $stat[mtime] $f")
+done
+
+(( ${#listfiles} )) && listopts=(-d listfiles -l -o)
+
+return 0
diff --git a/Completion/Unix/Type/_path_files b/Completion/Unix/Type/_path_files
index aae248bf5..f20a941c0 100644
--- a/Completion/Unix/Type/_path_files
+++ b/Completion/Unix/Type/_path_files
@@ -7,6 +7,7 @@ local linepath realpath donepath prepath testpath exppath skips skipped
 local tmp1 tmp2 tmp3 tmp4 i orig eorig pre suf tpre tsuf opre osuf cpre
 local pats haspats ignore pfx pfxsfx sopt gopt opt sdirs ignpar cfopt listsfx
 local nm=$compstate[nmatches] menu matcher mopts sort match mid accex fake
+local listfiles listopts tmpdisp
 
 typeset -U prepaths exppaths
 
@@ -539,46 +540,65 @@ for prepath in "$prepaths[@]"; do
               ( -n "$_comp_correct" ||
                 -z "$compstate[pattern_match]" || "$SUFFIX" != */* ||
                 "${SUFFIX#*/}" = (|*[^\\])[][*?#~^\|\<\>]* ) ]] }; then
+	# We have not been told to insert the match, so we are
+	# listing, or something.
         (( tmp4 )) && zstyle -t ":completion:${curcontext}:paths" ambiguous &&
             compstate[to_end]=
         if [[ "$tmp3" = */* ]]; then
 	  if [[ -z "$listsfx" || "$tmp3" != */?* ]]; then
+	    # I think this means we are expanding some directory
+	    # back up the path.
+	    tmp1=("${(@)tmp1%%/*}")
+	    _list_files tmp1 "$prepath$realpath$testpath"
 	    compadd -Qf "$mopts[@]" -p "$linepath$tmp2" -s "/${tmp3#*/}" \
 	            -W "$prepath$realpath$testpath" \
 		    "$pfxsfx[@]" -M "r:|/=* r:|=*" \
-		    - "${(@)tmp1%%/*}"
+		    $listopts \
+	            -a tmp1
           else
+	    # Same with a non-empty suffix
+	    tmp1=("${(@)^tmp1%%/*}/${tmp3#*/}")
+	    _list_files tmp1 "$prepath$realpath$testpath"
 	    compadd -Qf "$mopts[@]" -p "$linepath$tmp2" \
 	            -W "$prepath$realpath$testpath" \
 		    "$pfxsfx[@]" -M "r:|/=* r:|=*" \
-		    - "${(@)^tmp1%%/*}/${tmp3#*/}"
+	            $listopts \
+		    -a tmp1
           fi
 	else
+	  _list_files tmp1 "$prepath$realpath$testpath"
 	  compadd -Qf "$mopts[@]" -p "$linepath$tmp2" \
 	          -W "$prepath$realpath$testpath" \
 		   "$pfxsfx[@]" -M "r:|/=* r:|=*" \
+	           $listopts \
 		   -a tmp1
 	fi
       else
+	# We are inserting the match into the command line.
         if [[ "$tmp3" = */* ]]; then
 	  tmp4=( -Qf "$mopts[@]" -p "$linepath$tmp2"
 	         -W "$prepath$realpath$testpath"
 	         "$pfxsfx[@]" -M "r:|/=* r:|=*" )
 	  if [[ -z "$listsfx" ]]; then
             for i in "$tmp1[@]"; do
-	      compadd "$tmp4[@]" -s "/${i#*/}" - "${i%%/*}"
+	      tmpdisp=("${i%%/*}")
+	      _list_files tmpdisp "$prepath$realpath$testpath"
+	      compadd "$tmp4[@]" -s "/${i#*/}" $listopts - "$tmpdisp"
 	    done
           else
             [[ -n "$compstate[pattern_match]" ]] && SUFFIX="${SUFFIX:s./.*/}*"
 
             for i in "$tmp1[@]"; do
-	      compadd "$tmp4[@]" - "$i"
+	      _list_files i "$prepath$realpath$testpath"
+	      compadd "$tmp4[@]" $listopts - "$i"
 	    done
           fi
         else
+	  _list_files tmp1 "$prepath$realpath$testpath"
 	  compadd -Qf "$mopts[@]" -p "$linepath$tmp2" \
                   -W "$prepath$realpath$testpath" \
 		  "$pfxsfx[@]" -M "r:|/=* r:|=*" \
+                  $listopts \
 		  -a tmp1
         fi
       fi
@@ -642,9 +662,10 @@ for prepath in "$prepaths[@]"; do
       fi
       compquote tmp4 tmp2 tmp1
       for i in "$tmp1[@]"; do
+	_list_files tmp2 "$prepath$realpath${mid%/*/}"
         compadd -Qf "$mopts[@]" -p "$linepath$tmp3/" -s "/$tmp4$i" \
                 -W "$prepath$realpath${mid%/*/}/" \
-	        "$pfxsfx[@]" -M "r:|/=* r:|=*" - "$tmp2"
+	        "$pfxsfx[@]" -M "r:|/=* r:|=*" $listopts - "$tmp2"
       done
     else
       if [[ "$osuf" = */* ]]; then
@@ -665,11 +686,15 @@ for prepath in "$prepaths[@]"; do
       fi
       if [[ -z "$_comp_correct" && -n "$compstate[pattern_match]" &&
             "${PREFIX#\~}$SUFFIX" = (|*[^\\])[][*?#~^\|\<\>]* ]]; then
+	tmp1=("$linepath$tmp4${(@)^tmp1}")
+	_list_files tmp1 "$prepath$realpath"
         compadd -Qf -W "$prepath$realpath" "$pfxsfx[@]" "$mopts[@]" \
-                -M "r:|/=* r:|=*" - "$linepath$tmp4${(@)^tmp1}"
+                -M "r:|/=* r:|=*" $listopts -a tmp1
       else
+	# Not a pattern match
+	_list_files tmp1 "$prepath$realpath$testpath"
         compadd -Qf -p "$linepath$tmp4" -W "$prepath$realpath$testpath" \
-	        "$pfxsfx[@]" "$mopts[@]" -M "r:|/=* r:|=*" -a tmp1
+	        "$pfxsfx[@]" "$mopts[@]" -M "r:|/=* r:|=*" $listopts -a tmp1
       fi
     fi
   fi
diff --git a/Doc/Zsh/compsys.yo b/Doc/Zsh/compsys.yo
index 11c50cf61..5c844e133 100644
--- a/Doc/Zsh/compsys.yo
+++ b/Doc/Zsh/compsys.yo
@@ -1263,6 +1263,36 @@ given, the name will only be completed if parameters of that type are
 required in the particular context.  Names for which no type is
 specified will always be completed.
 )
+kindex(file-list, completion style)
+item(tt(file-list))(
+This style controls whether files completed using the standard builtin
+mechanism are to be listed with a long list similar to tt(ls -l)
+(although note that this feature actually uses the shell module
+tt(zsh/stat) for file information).
+
+The style may either be set to a true value (or `tt(all)'), or
+one of the values `tt(insert)' or `tt(list)', indicating that files
+are to be listed in long format in all circumstances, or when
+attempting to insert a file name, or when listing file names
+without attempting to insert one.
+
+More generally, the value may be an array of any of the above values,
+optionally followed by tt(=)var(num).  If var(num) is present it
+gives the maximum number of matches for which long listing style
+will be used.  For example,
+
+example(zstyle ':completion:*' file-list list=20 insert=10)
+
+specifies that long format will be used when listing up to 20 files
+or inserting a file with up to 10 matches (assuming a listing
+is to be shown at all, for example on an ambiguous completion), else short
+format will be used.
+
+example(zstyle -e ':completion:*' file-list '(( ${+NUMERIC} )) && reply=(true)')
+
+specifies that long format will be used any time a numeric argument is
+supplied, else short format.
+)
 kindex(file-patterns, completion style)
 item(tt(file-patterns))(
 This is used by the standard function for completing filenames,
diff --git a/Doc/Zsh/compwid.yo b/Doc/Zsh/compwid.yo
index bdbdd99da..8ffc96a2e 100644
--- a/Doc/Zsh/compwid.yo
+++ b/Doc/Zsh/compwid.yo
@@ -436,7 +436,7 @@ sect(Builtin Commands)
 startitem()
 findex(compadd)
 cindex(completion widgets, adding specified matches)
-xitem(tt(compadd) [ tt(-akqQfenUl12C) ] [ tt(-F) var(array) ])
+xitem(tt(compadd) [ tt(-akqQfenUld12C) ] [ tt(-F) var(array) ])
 xitem([ tt(-P) var(prefix) ] [ tt(-S) var(suffix) ])
 xitem([ tt(-p) var(hidden-prefix) ] [ tt(-s) var(hidden-suffix) ])
 xitem([ tt(-i) var(ignored-prefix) ] [ tt(-I) var(ignored-suffix) ])
@@ -530,6 +530,12 @@ This option only has an effect if used together with the tt(-d)
 option. If it is given, the display strings are listed one per line,
 not arrayed in columns.
 )
+item(tt(-o))(
+This option only has an effect if used together with the tt(-d)
+option.  If it is given, the order of the output is determined by the
+match strings;  otherwise it is determined by the display strings
+(i.e. the strings given by the tt(-d) option).
+)
 item(tt(-J) var(name))(
 Gives the name of the group of matches the words should be stored in.
 )
diff --git a/Src/Zle/comp.h b/Src/Zle/comp.h
index 5e25cdeb6..e88f8b927 100644
--- a/Src/Zle/comp.h
+++ b/Src/Zle/comp.h
@@ -131,6 +131,7 @@ struct cmatch {
 #define CMF_FMULT    (1<<12)	/* first of multiple equal strings */
 #define CMF_ALL      (1<<13)	/* a match representing all other matches */
 #define CMF_DUMMY    (1<<14)	/* unselectable dummy match */
+#define CMF_MORDER   (1<<15)    /* order by matches, not display strings */
 
 /* Stuff for completion matcher control. */
 
diff --git a/Src/Zle/compcore.c b/Src/Zle/compcore.c
index 1caad5484..008f49185 100644
--- a/Src/Zle/compcore.c
+++ b/Src/Zle/compcore.c
@@ -2735,7 +2735,7 @@ addexpl(int always)
 static int
 matchcmp(Cmatch *a, Cmatch *b)
 {
-    if ((*a)->disp) {
+    if ((*a)->disp && !((*a)->flags & CMF_MORDER)) {
 	if ((*b)->disp) {
 	    if ((*a)->flags & CMF_DISPLINE) {
 		if ((*b)->flags & CMF_DISPLINE)
@@ -2751,7 +2751,7 @@ matchcmp(Cmatch *a, Cmatch *b)
 	}
 	return -1;
     }
-    if ((*b)->disp)
+    if ((*b)->disp && !((*b)->flags & CMF_MORDER))
 	return 1;
 
     return strbpcmp(&((*a)->str), &((*b)->str));
diff --git a/Src/Zle/complete.c b/Src/Zle/complete.c
index e246e2b8a..c70c8c191 100644
--- a/Src/Zle/complete.c
+++ b/Src/Zle/complete.c
@@ -569,6 +569,9 @@ bin_compadd(char *name, char **argv, UNUSED(Options ops), UNUSED(int func))
 	    case 'l':
 		dat.flags |= CMF_DISPLINE;
 		break;
+	    case 'o':
+		dat.flags |= CMF_MORDER;
+		break;
 	    case 'E':
                 if (p[1]) {
                     dat.dummies = atoi(p + 1);