-
Notifications
You must be signed in to change notification settings - Fork 32
/
Copy pathshorten_path
executable file
·131 lines (114 loc) · 3.45 KB
/
shorten_path
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
#!/usr/bin/zsh -f
#
# Shorten path according to hashed dir list ('hash -d' in Zsh),
# maintained in ~/.dotfiles/oh-my-zsh/lib/hash_dirs.
# This also replaces $HOME with ~.
#
# This is used from vimrc for ShortenPath.
#
# TODO:
# - relative to $cdpath?! (see also vim-flagship by tpope)
# - indicate local path, e.g. "./~omz" when in ~df?!
# Plain sh would be ~4x faster on startup, but with cat/sed etc similar slow/fast,
# and needs a cache file.
# Self-tests: run with '--test'. {{{
if [[ $1 == '--test' ]]; then
hash -d df=~/.dotfiles
set -x -e
cd ~
[[ $(shorten_path .) == '~' ]]
[[ $(shorten_path ~/.dotfiles/vimrc) == '~df/vimrc' ]]
# shellcheck disable=SC2088
[[ $(shorten_path '~/.dotfiles/vimrc') == '~/.dotfiles/vimrc' ]]
[[ $(shorten_path .dotfiles/vimrc) == '~df/vimrc' ]]
[[ $(shorten_path -a .vimrc) == '↬.vimrc' ]]
cd .dotfiles
[[ $(shorten_path ~/.dotfiles/vimrc) == 'vimrc' ]]
[[ $(shorten_path vimrc) == 'vimrc' ]]
[[ $(shorten_path ../.dotfiles/vimrc) == 'vimrc' ]]
[[ $(shorten_path ~/.dotfiles/foo/bar) == 'foo/bar' ]]
[[ $(shorten_path foo/bar) == 'foo/bar' ]]
[[ $(shorten_path ../.dotfiles/foo/bar) == 'foo/bar' ]]
[[ $(shorten_path -a ../.dotfiles/foo/bar) == 'foo/bar' ]]
# With "base" dir.
cd ~
[[ $(shorten_path .dotfiles/vimrc "$PWD") == '~df/vimrc' ]]
[[ $(shorten_path vimrc .dotfiles) == 'vimrc' ]]
[[ $(shorten_path ~/.dotfiles/vimrc /) == '~df/vimrc' ]]
[[ $(shorten_path -a ~/.dotfiles/vimrc /) == '~df/vimrc' ]]
cd .dotfiles
[[ $(shorten_path ../.vimrc) == '../.vimrc' ]]
[[ $(shorten_path ../non-existent) == '../non-existent' ]]
# Tests in temp dir.
tmpdir="$(mktemp -d)"
trap 'test -d "$tmpdir" && rm -rf "$tmpdir"' 0
cd "$tmpdir"
touch foo
ln -s foo bar
[[ $(shorten_path -a foo) == 'foo' ]]
[[ $(shorten_path -a bar) == '↬bar' ]]
[[ $(shorten_path -a "$tmpdir") == "$tmpdir" ]]
[[ $(shorten_path -a . /) == "/" ]]
[[ $(shorten_path -a "$tmpdir" /) == "$tmpdir" ]]
[[ $(shorten_path -a "$tmpdir/bar" ~) == "$tmpdir/↬bar" ]]
# Canonical path (removing empty segments).
[[ $(shorten_path .dotfiles//vimrc ~) == '~df/vimrc' ]]
[[ $(shorten_path -a "$tmpdir//bar" ~) == "$tmpdir/↬bar" ]]
[[ $(shorten_path -a ./bar) == '↬bar' ]]
set +x
time ( for i in {1..200}; do shorten_path foo; done )
exit
fi
# }}}
if [ -z "$1" ]; then
echo "Argument (path) required." >&2
exit 1
fi
if [ x"$1" = "x-a" ]; then
annotate=1; shift
else
annotate=0
fi
p=$1
if [ -n "$2" ]; then
cd "$2" || exit
fi
abs_path=${p:a}
# Keep relative dirs, which are not going back to below base/$PWD.
if [[ $p = ../* ]] && [[ $abs_path != $PWD/* ]]; then
printf %s "$p"
return
fi
test -f ~/.dotfiles/oh-my-zsh/lib/hash_dirs.zsh && \
source ~/.dotfiles/oh-my-zsh/lib/hash_dirs.zsh
test -f ~/.dotfiles/oh-my-zsh/lib/hash_dirs.local.zsh && \
source ~/.dotfiles/oh-my-zsh/lib/hash_dirs.local.zsh
pwd_short=${(D)PWD}/
# NOTE: "(Q)" is required to remove escaping of e.g. "[" from the name.
path_short=${(Q)${(D)abs_path}#$pwd_short}
if (( annotate )) && [[ $path_short != "/" ]]; then
# Annotate symlinks.
p=
for i in "${(s:/:)path_short}"; do
if [[ -z "$i" ]]; then
if [[ -z "$p" ]]; then
p="/"
fi
continue
fi
if [[ -n "$p" ]]; then
if [[ "$p" != "/" ]]; then
p="$p/"
fi
printf "/"
fi
p="$p$i"
if [[ -h $~p ]]; then
printf %s "↬$i"
else
printf %s "$i"
fi
done
else
printf %s "$path_short"
fi