On 2008-08-08 at 11:16 -0700, Eric D. Friedman wrote:
I was the original poster with that long completion pause and none of
the suggested solutions actually worked out. Following the advice in
this thread, I ran a shell with -l -x on and captured the relavant
bits.
Working in an NFS/LDAP/Kerberos environment with a largish number of
users (>10k), I periodically have to debug "what's gone wrong now?".
In ~/.zshenv I set:
----------------------------8< cut here
>8------------------------------
[[ -n $TRACE_ZSH_TIME ]] && PS4='+[%D{%M:%S}]%N:%i> '
if [[ -n $TRACE_ZSH ]]; then
[[ -n "$TRACE_ZSH_FILE" ]] && exec 2> "${TRACE_ZSH_FILE}"
setopt xtrace
fi
----------------------------8< cut here
>8------------------------------
% TRACE_ZSH_TIME=t TRACE_ZSH=t TRACE_ZSH_FILE=$HOME/ztrace.out zsh
This is often informative.
The big pause occurs at the last line in the following. Any
ideas as to what else I could try? My goal is to not have the
completion system show me every user in my company's home dir when I
do the first cd<TAB>; I'd never use that completion and it takes far
too long to get it anyway.
[...]
+_all_labels:39> compadd -F _comp_ignore -J -default- -qS/ -k
userdirs
Various things I tried were never sufficient, as userdirs would always
get populated somehow. Until I cheated.
The short version: ensure that 'userdirs' is a local variable inside
the
completion system, populated with the values you want. I do this by
adding to $_comp_setup -- making sure that none of the rest of the
things that hit LDAP cause slow-downs have led to what I have below.
I keep the users I want to tab-complete in a file, ~/.userdirs and
then
hack things so that only that is used. My code uses
zfilter_comments()
which is a function I frequently use to pull in files for data and
skip
comments, etc. Comments in files are handy, reading those files
efficiently in zsh also handy.
The main things are to avoid the automatic population of userdirs when
it's empty and to ensure that things like ssh, scp, etc don't hit LDAP
either. I have ~/.sshusers contain things like my own usercode,
"root"
and various production accounts. ~/.sshhosts contains hostnames.
Note that I have "users whose home-directories I care about" and
"users
I ssh to the accounts of" and these are very different; the former
includes colleagues and the latter includes role accounts. Because of
this split, we have the loop setting completion of users to $sshusers
for only some commands. Hrm, wonder why 'users' is used, not
'accounts'?
Note that using "zstyle -e" and "reply=($array)" lets me modify the
array at run-time and have it immediately affect completion.
"is-at-least" is one of the Misc/ functions provided, I autoload it
before this point.
I make sure that I split up the completion dumps by host since
different
hosts have different versions of zsh, etc etc, so I don't want that
continually getting trashed within NFS.
Here's hoping that I'm not missing anything relevant when looking over
my config now. Believe it or not, this is simplified.
----------------------------8< cut here
>8------------------------------
function zfilter_comments {
local f infile="$1"
while read f; do
[[ -n ${f%%[$' \t']*\#*} && ${f#[#;]} == $f ]] ||
continue
print -r -- ${f%%[$' \t']*\#*}
done < "$infile"
}
typeset -a sshhosts sshusers
[[ -f ~/.sshhosts ]] && sshhosts=( $(zfilter_comments ~/.sshhosts) )
[[ -f ~/.sshusers ]] && sshusers=( $(zfilter_comments ~/.sshusers) )
local c
for c in ssh rsync sftp scp slogin
do
[[ ${#sshhosts} -gt 0 ]] && \
zstyle -e ':completion:*:'"$c"':*' hosts 'reply=($sshhosts)'
[[ ${#sshusers} -gt 0 ]] && \
zstyle -e ':completion:*:'"$c"':*' users 'reply=($sshusers)'
done
unset c
zstyle -e ':completion:*' my-accounts 'reply=($sshusers)'
zstyle ':completion:*' other-accounts ''
zstyle -e ':completion:*' accounts 'reply=($sshusers)'
function reset_userdirs {
# There is a zsh internal map, userdirs, exposed by zsh/parameter;
# it's read-only though.
[[ -f ~/.userdirs ]] || return
local _u
local -a _ud
_ud=( $(zfilter_comments ~/.userdirs) )
for _u in $_ud; do hash -d $_u="/home/$_u"; done
}
if is-at-least 4.2.0; then autoload -Uz compinit ; else autoload -U
compinit ; fi
[[ -d "${ZDOTDIR:-$HOME}/.zcompdumps" ]] || mkdir -m 0700 -p "$
{ZDOTDIR:-$HOME}/.zcompdumps"
compinit -u -d "${ZDOTDIR:-$HOME}/.zcompdumps/${HOST%%.*}"
# Hack to turn off userdirs completion by overriding userdirs.
# This overrides userdirs as a local variable inside the completion
# system, not touching the global variable. We don't need to load
# zsh/parameter to achieve this.
_comp_setup+=$'\ntypeset -a userdirs\nreset_userdirs'
reset_userdirs
----------------------------8< cut here
>8------------------------------
-Phil