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

PATCH: 3.1.5-pws-8: dumping completions for speed



The following patch adds a file `dump' to the Functions/Completions
directory.  This dumps out all the state information which the `init' file
there has produced, so that for subsequent shell initialisations it can all
be read in in one go.  This speeds up my total shell startup time including
the new completions by a factor of around two, though I haven't timed it
properly.  You just dot it and put the out put in $foo.dump, where $foo is
where the file called Functions/Completions/init in the distribution lives
in your setup; sourcing $foo finds $foo.dump automatically.

A few slightly icky things:

1) you have to call it straight after running init, since the state
information changes after #array things have been loaded;

2) every time you add a new completion you have to remove init.dump
and remake it --- this is a generic problem, but made worse by 1);

3) dot-files don't have local scope, so I changed the variables in init as
well as dump to silly names and then unset them explicitly --- getting the
options right is hard for the same reason --- should { ... } maybe allow
both option and parameter localisation?

4) I just made it check for $0.dump in init, so if it had to search the
path for init, it won't find init.dump (that's why perl sets $0 to a full
path name).

On the matter of context-sensitive completions: it looks neat, but I'd be
very worried about losing command-based completion since (like the MH
example I gave) it makes it very easy to keep track of all the bits and
what commands they apply to.  If context information is simply intended as
an enhancement to that, that's fine.  Then the market can choose whether
__find looks like Functions/Completion/__find or Functions/Comp/__find .
(I don't envisage having both of those in the pws-* distributions, but I
presume they would be merged at some point.)

--- Functions/Completion/dump.bk	Mon Feb 15 15:19:57 1999
+++ Functions/Completion/dump	Mon Feb 15 15:20:17 1999
@@ -0,0 +1,108 @@
+# This is a file to be sourced to dump the definitions for new-style
+# completion defined by 'init' in the same directory.  For best results,
+# it should be run immediately after init, before any of the completions
+# have been autoloaded.  The output should be directed into the "init.dump"
+# in the same directory as init.  If you rename init, just stick .dump onto
+# the end of whatever you have called it and put it in the same directory.
+#
+# You will need to update the dump every time you add a new completion.
+# To do this, simply remove the .dump file, start a new shell, and
+# create the .dump file as before.
+#
+# It relies on KSH_ARRAYS not being set.
+
+
+# First dump the arrays comps, patcomps and keycomps; the middle one
+# is an ordinary array, the other two are associative.  The
+# quoting hieroglyphyics ensure that a single quote inside a
+# variable is itself correctly quoted.
+
+print "comps=("
+for __d_f in ${(k)comps}; do
+    print -r - "'${__d_f//\'/'\\''}'" "'${comps[$__d_f]//\'/'\\''}'"
+done
+print ")"
+
+if (( $#patcomps )); then
+  print "\npatcomps=("
+  for __d_f in $patcomps; do
+    print -r - "'${__d_f//\'/'\\''}'"
+  done
+  print ")"
+fi
+
+if (( $#keycomps )); then
+  print "\nkeycomps=("
+  for __d_f in ${(k)keycomps}; do
+    print -r - "'${__d_f//\'/'\\''}'" "'${keycomps[$__d_f]//\'/'\\''}'"
+  done
+  print ")\n"
+  # Here, we need both the zle -C's and the bindkey's to recreate.
+  __d_bks=()
+  zle -lL |
+  while read -A __d_line; do
+    if [[ ${__d_line[5]} = __main_key_complete ]]; then
+      print ${__d_line}
+      __d_bks=($__d_bks ${__d_line[3]})
+    fi
+  done
+  bindkey |
+  while read -A __d_line; do
+    if [[ ${__d_line[2]} = (${(j.|.)~__d_bks}) ]]; then
+      print "bindkey '${__d_line[1][2,-2]}' ${__d_line[2]}"
+    fi
+  done
+fi
+
+print
+
+
+# Autoloads: whence -w produces "__d_foo: function", so look for
+# all functions beginning with `__'.
+
+__d_als=($(whence -wm '__*' |
+while read -A __d_line; do
+  [[ ${__d_line[2]} = function ]] && print ${__d_line[1]%:}
+done))
+
+# print them out:  about six to a line looks neat
+
+while (( $#__d_als )); do
+  print -n autoload
+  for (( _i = 0; _i < 6; _i++ )); do
+    if (( $#__d_als )); then
+      print -n " $__d_als[1]"
+      shift __d_als
+    fi
+  done
+  print
+done
+
+print
+
+
+# Finally, the new style functions:  we look for the ones which init
+# has just bound and create bindkey and zle -C statements to remake
+# them.
+
+typeset -A __d_zle
+__d_bks=''
+
+bindkey | while read -A __d_line; do
+	    if [[ "$__d_line[2]" = \
+__complete_(expand-or-complete(-prefix|)|complete-word|list-choices\
+|delete-char-or-list|menu-(expand-or-|)complete|reverse-menu-complete) ]]; then
+# The zle statements are collected as an assoc array, to avoid generating
+# too many.
+	      __d_zle[$__d_line[2]]="zle -C $__d_line[2] \
+${__d_line[2]#__complete_} __main_complete"
+# The bindkey's are just collected as a string.
+	      __d_bks="$__d_bks
+bindkey '${__d_line[1][2,-2]}' ${__d_line[2]}"
+	    fi
+	  done
+
+print -l ${(ov)__d_zle}
+print "$__d_bks"
+
+unset __d_line __d_zle __d_bks __d_als __d_f
--- Functions/Completion/init.bk	Sat Feb 13 13:55:12 1999
+++ Functions/Completion/init	Mon Feb 15 15:20:17 1999
@@ -51,6 +51,8 @@
 #
 # Note that no white space is allowed between the `#' and the rest of
 # the string.
+#
+# See the file `dump' for how to speed up initialiation.
 
 
 # An associative array for completions definitions. The keys of the entries
@@ -207,47 +209,49 @@
 }
 
 
-# Now we make the files automatically autoloaded.
-
-local dir file line func
-
-for dir in $fpath; do
-  [[ $dir = . ]] && continue
-  for file in $dir/__*~*~(N); do
-    read -rA line < $file
-    func=$line[1]
-    shift line
-    if [[ $func = '#function' ]]; then
-      defcomp -a ${file:t} "${line[@]}"
-    elif [[ $func = '#array' ]]; then
-      defcomp " $file" "${line[@]}"
-    elif [[ $func = '#pattern-function' ]]; then
-      defpatcomp -a ${file:t} "${line[@]}"
-    elif [[ $func = '#pattern-array' ]]; then
-      defcomp " $file" "${line[@]}"
-    elif [[ $func = '#key-function' ]]; then
-      defkeycomp -a "${file:t}" "${line[@]}"
-    elif [[ $func = '#key-array' ]]; then
-      defkeycomp " $file" "${line[@]}"
-    elif [[ $func = '#helper' ]]; then
-      autoload ${file:t}
-    fi
+if [[ -f $0.dump ]]; then
+  . $0.dump
+else
+  # Now we make the files automatically autoloaded.
+  for __i_dir in $fpath; do
+    [[ $__i_dir = . ]] && continue
+    for __i_file in $__i_dir/__*~*~(N); do
+      read -rA __i_line < $__i_file
+      func=$__i_line[1]
+      shift __i_line
+      if [[ $func = '#function' ]]; then
+	defcomp -a ${__i_file:t} "${__i_line[@]}"
+      elif [[ $func = '#array' ]]; then
+	defcomp " $__i_file" "${__i_line[@]}"
+      elif [[ $func = '#pattern-function' ]]; then
+	defpatcomp -a ${__i_file:t} "${__i_line[@]}"
+      elif [[ $func = '#pattern-array' ]]; then
+	defcomp " $__i_file" "${__i_line[@]}"
+      elif [[ $func = '#key-function' ]]; then
+	defkeycomp -a "${__i_file:t}" "${__i_line[@]}"
+      elif [[ $func = '#key-array' ]]; then
+	defkeycomp " $__i_file" "${__i_line[@]}"
+      elif [[ $func = '#helper' ]]; then
+	autoload ${__i_file:t}
+      fi
+    done
   done
-done
 
+  # Finally we make all this be called by changing the key bindings.
 
-# Finally we make all this be called by changing the key bindings.
+  bindkey | while read -A __i_line; do
+	      if [[ "$__i_line[2]" = complete-word ||
+		"$__i_line[2]" = delete-char-or-list ||
+		"$__i_line[2]" = expand-or-complete ||
+		"$__i_line[2]" = expand-or-complete-prefix ||
+		"$__i_line[2]" = list-choices ||
+		"$__i_line[2]" = menu-complete ||
+		"$__i_line[2]" = menu-expand-or-complete ||
+		"$__i_line[2]" = reverse-menu-complete ]]; then
+		zle -C __complete_$__i_line[2] $__i_line[2] __main_complete
+		bindkey "${__i_line[1][2,-2]}" __complete_$__i_line[2]
+	      fi
+	    done
 
-bindkey | while read -A line; do
-            if [[ "$line[2]" = complete-word ||
-	    	  "$line[2]" = delete-char-or-list ||
-	    	  "$line[2]" = expand-or-complete ||
-	    	  "$line[2]" = expand-or-complete-prefix ||
-	    	  "$line[2]" = list-choices ||
-	    	  "$line[2]" = menu-complete ||
-	    	  "$line[2]" = menu-expand-or-complete ||
-	    	  "$line[2]" = reverse-menu-complete ]]; then
-              zle -C __complete_$line[2] $line[2] __main_complete
-              bindkey "${line[1][2,-2]}" __complete_$line[2]
-            fi
-          done
+  unset __i_dir __i_line __i_file
+fi

-- 
Peter Stephenson <pws@xxxxxxxxxxxxxxxxx>       Tel: +39 050 844536
WWW:  http://www.ifh.de/~pws/
Dipartimento di Fisica, Via Buonarroti 2, 56127 Pisa, Italy



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