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
Attachment:
pgpdRbPUndn66.pgp
Description: PGP signature