Search this site

Metadata

Articles

Projects

Presentations

ZSH: Disable 'cd' supporting usernames

I have a directory called "lib". If I try to do "cd l<tab>", zsh will offer me "libuuid list lib" as completion candidates. The words 'libuuid' and 'list' show up because they are usernames. This is really annoying, and there doesn't seem to be an option to disable this. What happend to doing "cd ~root" to change to root's homedir? Was typing '~' too hard?

At any rate, I figured out where to fix the unfeature: A file '_tilde' in path/to//zsh/4.3.4/functions/Completion/Zsh. It happens to be /usr/share/zsh/4.3.4/functions/Completion/Zsh on my ubuntu workstation.

... around line 22 ...
while _tags; do
  _requested users && _users "$suf[@]" "$@" && ret=0

  _requested named-directories expl 'named directory' \
...
Comment out the bold line above (starting '_requested users ...') and restart zsh. This only disabled the username completion part of zsh's cd command, but that's good enough for now. If I ever accidentally typo and cd to someone's home directory, I can just popd to return to my previous location.

Better zsh xterm title function fix

Sometimes I run commands that have special characters in them, newlines, or are very long. 'xterm set title' sequence breaks on those cases. So, let's fix that.
function title() {
  # escape '%' chars in $1, make nonprintables visible
  a=${(V)1//\%/\%\%}

  # Truncate command, and join lines.
  a=$(print -Pn "%40>...>$a" | tr -d "\n")

  case $TERM in
  screen)
    print -Pn "\e]2;$a @ $2\a" # plain xterm title
    print -Pn "\ek$a\e\\"      # screen title (in ^A")
    print -Pn "\e_$2   \e\\"   # screen location
    ;;
  xterm*|rxvt)
    print -Pn "\e]2;$a @ $2\a" # plain xterm title
    ;;
  esac
}
The 3 cases are addressed individually.
  • Special characters are made printable by using the 'V' flag, ${(V)varname}. This is documented in zsh under 'Parameter Expansion Flags'
  • Long lines are truncated with "%40>...>$varname" with "print -P". The '-P' flag has print interpret in prompt-style expansion. "%40>...>whatever" will truncate 'whatever' to 40 characters, trailed with '...'
  • Multi-line entries are joined with 'tr -d "\n"' - Maybe there's a better way to do this with zsh without needing to run tr(1) every time?
The 'title' function takes 2 arguments, which get separated by a '-' in xterm titles. First argument is the 'what' and second argument is the 'where'. Separated, they can be used to tell screen what is running ina given session and where. Useful++

The only real changes to this function from the original was adding the fixes for those 3 cases. The rest of the function remains unchanged.

If you're still confused as to where this can be used, put it in a precmd and preexec function:

# precmd is called just before the prompt is printed
function precmd() {
  title "zsh" "%m(%55<...<%~)"
}

# preexec is called just before any command line is executed
function preexec() {
  title "$1" "%m(%35<...<%~)"
}
An example of this can be seen in this screenshot.