1

I'm using zsh on MacOS El Capitan. I'm wondering how auto completion has to be parameterized to resolve aliases as well. When I used bash, my .bash_profile contained the following:

alias mdb "mongo -uadmin -pXXX --authenticationDatabase admin --host "
complete -W "$HOSTNAMES" mdb

HOSTNAMES is a list of over 4000 FQDN's. Doing so I could type mdb someHosttabtab to see a list with all hosts beginning with someHost. Once the right host selected, the command got completed to mongo -uadmin -pXXX --authenticationDatabase admin --host someHostFoo.

Right now, I want to use oh-my-zsh so I copied the above mentioned lines in my .zshrc file. However, when the hostname list exceeds round about 1500 entries, auto completion becomes very slow. For that reason I replaced complete -W "$HOSTNAMES" mdb with compctl -c "$HOSTNAMES" mdb in my .zshrc file. However, this wont work, even if I set setopt complete_aliases in my .zshrc. Today I read that one should better write completion functions for commands since compctl is deprecated. I came up with this but this will only suggest host names after having typed mdb hoststabtab when $HOSTNAMES contains very few host names:

#compdef mongo mdb
#autoload


_mongo_hosts(){
  mhosts=$HOSTNAMES
}

local -a _1st_arguments
_1st_arguments=(
  "--host:host to be connected to"
)

local expl
local -a mhosts

if (( CURRENT == 2 )); then
  _describe -t commands "mongo subcommand" _1st_arguments
  return
fi

case "$words[2]" in
    hosts)
      _mongo_hosts
      _wanted mhosts expl 'known hosts' compadd -a mhosts ;;
esac

Furthermore, by this approach, mdb is not yet replaced by mongo -uadmin -pXXX --authenticationDatabase admin --host.

Follow up

I discarded the above shown compdef approach. My current workaround is to add the following two lines to my .zshrc:

zstyle ':completion:*' completer _expand_alias _complete _ignored
zstyle ':completion:*:(ssh|scp|sftp|host):*' hosts $HOSTNAMES

The first line is to expand aliases as well, here my alias mdb.

The second line allows to cycle through all host names when commands like ssh, scp, sftp or host are used. The same could be achieved by this line:

_hosts() {compadd $(echo $HOSTNAMES | tr "\n" " ")}

So with this approach, I have to type first ssh someHosttabtab, choose the host and then replace ssh by mdb so it will complete to mongo -uadmin -pXXX --authenticationDatabase admin --host someHostFoo

This works but isn't perfect. I'd prefer to have the same auto completion experience I had using bash, implemented by the first shown two lines here in my question. How to achieve this with zsh and and more than 4000 host names? Thank you!

1

I found a solution which works exactly as I wanted. Only the following three lines are required in .zshrc:

mdb() {mongo -uadmin -pXXX --authenticationDatabase admin --host "$@"}
compctl -k "($(echo $HOSTNAMES))" mdb
zstyle ':completion:*:(ssh|scp|sftp|host):*' hosts $(echo $HOSTNAMES)

The function mdb() replaces my former alias mdb. The compctl command completes functions like mdb with the array of $HOSTNAMES. The zstyle instruction completes commands like ssh, scp, sftp and host with the array of $HOSTNAMES.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.