shrink-path.plugin.zsh
8037 bytes
1# Shrink directory paths, e.g. /home/me/foo/bar/quux -> ~/f/b/quux.
2#
3# For a fish-style working directory in your command prompt, add the following
4# to your theme or zshrc:
5#
6# setopt prompt_subst
7# PS1='%n@%m $(shrink_path -f)>'
8#
9# The following options are available:
10#
11# -f, --fish fish simulation, equivalent to -l -s -t.
12# -g, --glob Add asterisk to allow globbing of shrunk path (equivalent to -e "*")
13# -l, --last Print the last directory's full name.
14# -s, --short Truncate directory names to the number of characters given by -#. Without
15# -s, names are truncated without making them ambiguous.
16# -t, --tilde Substitute ~ for the home directory.
17# -T, --nameddirs Substitute named directories as well.
18# -# Truncate each directly to at least this many characters inclusive of the
19# ellipsis character(s) (defaulting to 1).
20# -e SYMBOL Postfix symbol(s) to indicate that a directory name had been truncated.
21# -q, --quote Quote special characters in the shrunk path
22#
23# The long options can also be set via zstyle, like
24# zstyle :prompt:shrink_path fish yes
25#
26# Note: Directory names containing two or more consecutive spaces are not yet
27# supported.
28#
29# Keywords: prompt directory truncate shrink collapse fish
30#
31# Copyright (C) 2008 by Daniel Friesel <derf@xxxxxxxxxxxxxxxxxx>
32# License: WTFPL <http://www.wtfpl.net>
33#
34# Ref: https://www.zsh.org/mla/workers/2009/msg00415.html
35# https://www.zsh.org/mla/workers/2009/msg00419.html
36
37shrink_path () {
38 setopt localoptions
39 setopt rc_quotes null_glob
40
41 typeset -i lastfull=0
42 typeset -i short=0
43 typeset -i tilde=0
44 typeset -i named=0
45 typeset -i length=1
46 typeset ellipsis=""
47 typeset -i quote=0
48 typeset -i expand=0
49
50 if zstyle -t ':prompt:shrink_path' fish; then
51 lastfull=1
52 short=1
53 tilde=1
54 fi
55 if zstyle -t ':prompt:shrink_path' nameddirs; then
56 tilde=1
57 named=1
58 fi
59
60 local last
61 zstyle -s ':prompt:shrink_path' last last
62 case "$last" in
63 (false|no|off|0) lastfull=0 ;;
64 (true|yes|on|1) lastfull=1 ;;
65 (""|*[^0-9]*) lastfull=0 ;;
66 (*) lastfull=$last ;;
67 esac
68
69 zstyle -t ':prompt:shrink_path' short && short=1
70 zstyle -t ':prompt:shrink_path' tilde && tilde=1
71 zstyle -t ':prompt:shrink_path' glob && ellipsis='*'
72 zstyle -t ':prompt:shrink_path' quote && quote=1
73 zstyle -t ':prompt:shrink_path' expand && expand=1
74
75 while [[ $1 == -* ]]; do
76 case $1 in
77 --)
78 shift
79 break
80 ;;
81 -f|--fish)
82 lastfull=1
83 short=1
84 tilde=1
85 ;;
86 -h|--help)
87 print 'Usage: shrink_path [-f -l -s -t] [directory]'
88 print ' -f, --fish fish-simulation, like -l -s -t'
89 print ' -g, --glob Add asterisk to allow globbing of shrunk path (equivalent to -e "*")'
90 print ' -l, --last [#] Print the last n directory''s full name (default 1).'
91 print ' -s, --short Truncate directory names to the number of characters given by -#. Without'
92 print ' -s, names are truncated without making them ambiguous.'
93 print ' -t, --tilde Substitute ~ for the home directory'
94 print ' -T, --nameddirs Substitute named directories as well'
95 print ' -# Truncate each directly to at least this many characters inclusive of the'
96 print ' ellipsis character(s) (defaulting to 1).'
97 print ' -e SYMBOL Postfix symbol(s) to indicate that a directory name had been truncated.'
98 print ' -q, --quote Quote special characters in the shrunk path'
99 print ' -x, --expand Print the full path. This takes precedence over the other options'
100 print ''
101 print 'The long options can also be set via zstyle, like'
102 print ' zstyle :prompt:shrink_path fish yes'
103 return 0
104 ;;
105 -l|--last)
106 lastfull=1
107 if [[ -n "$2" && "$2" != *[^0-9]* ]]; then
108 shift
109 lastfull=$1
110 fi
111 ;;
112 -s|--short) short=1 ;;
113 -t|--tilde) tilde=1 ;;
114 -T|--nameddirs)
115 tilde=1
116 named=1
117 ;;
118 -[0-9]|-[0-9][0-9])
119 length=${1/-/}
120 ;;
121 -e)
122 shift
123 ellipsis="$1"
124 ;;
125 -g|--glob)
126 ellipsis='*'
127 ;;
128 -q|--quote)
129 quote=1
130 ;;
131 -x|--expand)
132 expand=1
133 ;;
134 esac
135 shift
136 done
137
138 typeset -i elllen=${#ellipsis}
139 typeset -a tree expn
140 typeset result part dir=${1-$PWD}
141 typeset -i i
142
143 [[ -d $dir ]] || return 0
144
145 if (( expand )) {
146 echo "$dir"
147 return 0
148 }
149
150 if (( named )) {
151 for part in ${(k)nameddirs}; {
152 [[ $dir == ${nameddirs[$part]}(/*|) ]] && dir=${dir/#${nameddirs[$part]}/\~$part}
153 }
154 }
155 (( tilde )) && dir=${dir/#$HOME/\~}
156 tree=(${(s:/:)dir})
157 (
158 if [[ $tree[1] == \~* ]] {
159 cd -q ${~tree[1]}
160 result=$tree[1]
161 shift tree
162 } else {
163 cd -q /
164 }
165 for dir in $tree; {
166 if (( lastfull && $#tree <= lastfull )) {
167 result+="/${(j:/:)tree[@]}"
168 break
169 }
170 expn=(a b)
171 part=''
172 i=0
173 until [[ $i -gt 99 || ( $i -ge $((length - ellen)) || $dir == $part ) && ( (( ${#expn} == 1 )) || $dir = $expn ) ]]; do
174 (( i++ ))
175 part+=$dir[$i]
176 expn=($(echo ${part}*(-/)))
177 (( short )) && [[ $i -ge $((length - ellen)) ]] && break
178 done
179
180 typeset -i dif=$(( ${#dir} - ${#part} - ellen ))
181 if [[ $dif -gt 0 ]]
182 then
183 (( quote )) && part=${(q)part}
184 part+="$ellipsis"
185 else
186 part="$dir"
187 (( quote )) && part=${(q)part}
188 fi
189 result+="/$part"
190 cd -q $dir
191 shift tree
192 }
193 echo ${result:-/}
194 )
195}
196
197## vim:ft=zsh