From the documentation of %~
:
if it has a named directory as its prefix, that part is replaced by a ~
followed by the name of the directory, but only if the result is shorter than the full path
A reference follows to dynamic and static named directories. What you're seeing is a static named directory
They may also be defined if the text after the ~
is the name of a string shell parameter whose value begins with a /
.
So if the value of the variable SOME_DIR
is /home/bschlenk/some/path
then ~SOME_DIR
is a static named directory whose value is /home/bschlenk/some/path
. The prompt expansion %~
sees /home/bschlenk/some/path
and abbreviates it to ~SOME_DIR
.
But that's not the whole story. In fact, the abbreviation only happens if SOME_DIR
has been “activated” by the use of ~SOME_DIR
. This is documented under the option auto_name_dirs
, which removes the need for prior activation, but defaults off.
Any parameter that is set to the absolute name of a directory immediately becomes a name for that directory, that will be used by the %~
and related prompt sequences, and will be available when completion is performed on a word starting with ~
. (Otherwise, the parameter must be used in the form ~param
first.)
A parameter that is activated for %~
substitution (and completion after ~
) shows up as an entry in the named directory hash table which you can list with hash -d
.
We've put the pieces together to understand what's going on. How can you solve your problem? It depends what caused SOME_DIR
to be activated.
If you have the option auto_name_dirs
turned on, then obviously you should turn it off.
If you've used ~SOME_DIR
previously, you can deactivate it with
unhash -d SOME_DIR
This is not permanent: it'll pop up again if you use ~SOME_DIR
again. But given that you can use $SOME_DIR
wherever you can use ~SOME_DIR
, ~SOME_DIR
is not a very useful feature.
If you can't get rid of what makes SOME_DIR
a named directory and you want to abbreviate the current directory with nothing but $HOME
→ ~
, you can implement this transformation manually.
if [[ $PWD = $HOME ]]; then
HPWD=\~
elif [[ $PWD = $HOME/* ]]; then
HPWD=\~/${PWD#$HOME/}
else
HPWD=$PWD
fi
and then use print -rn $HPWD
instead of print -Pn %~
.
If you can't prevent SOME_DIR
from becoming a named directory and you can't change the code that uses %~
, it gets trickier. You can empty the directory hash table with hash -r
, but there's no way to make this local to a function (only to a subshell).
$functions[zsh_directory_name]
or$zsh_directory_name_functions
set by something? – thrig Dec 13 '18 at 19:21echo $functions[zsh_directory_name]
prints nothing – Brian Schlenker Dec 13 '18 at 20:04