3

I have the following zsh function which lets me edit symbolic links using the vared ZLE builtin.

function lned {
  emulate zsh
  setopt err_return extended_glob local_options local_traps
  local -a data
  link_path=${1%%/##}
  zstat -A data -L +link $link_path
  target=$data[1]
  if [[ -z $target ]]; then
    print -rl 1>&2 "$link_path: not a symbolic link"
    return 2
  fi
  vared -p "${(q)1} -> " target
  if [[ -n $target && "$target" != "$data[1]" ]]; then
    # We can't use 'ln -sf' if $link_path is a symlink to a directory, so remove
    # it manually first.
    # Check that this is still a symlink, in case the file was changed while we
    # were editing (this leaves only a very small time interval where we might
    # remove a non-symlink).
    rm -- $link_path(@)
    ln -s -- $target $link_path
  fi
}

This is nice, but when I'm editing a relative symbolic link in a directory other than the current one, the file name completions are relative to the wrong directory. I want to fix that.

I could run pushd -- $link_path:h/ before calling vared and popd afterwards. However, this would not restore the current directory if the user interrupted the shell by pressing Ctrl+C at the wrong moment. This can be solved by setting traps exactly right, and maybe using cd rather than pushd, which is probably useful also to avoid having to detect whether the link is in the current directory (in which case pushd wouldn't push anything).

I'd like to minimize the disruption caused by the directory change, which means also locally turning off chpwd, restoring OLDPWD, and perhaps more which I'm not thinking of. Also, if I have no permission to cd back into the current directory, I'd be in a lurch — this is a very rare case but I'd prefer to support it.

It would be simpler if I could just set things up so that files are completed relative to a different directory during the vared call. How can I do that? If this is impossible, what's the best way to minimize the impact of a temporary directory change?

Your Answer

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

Browse other questions tagged or ask your own question.