shrink-path.plugin.zsh 7.4 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
# Shrink directory paths, e.g. /home/me/foo/bar/quux -> ~/f/b/quux.
#
# For a fish-style working directory in your command prompt, add the following
# to your theme or zshrc:
#
#   setopt prompt_subst
#   PS1='%n@%m $(shrink_path -f)>'
#
# The following options are available:
#
#   -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
16
17
#                    -s, names are truncated without making them ambiguous.
#   -t, --tilde      Substitute ~ for the home directory.
#   -T, --nameddirs  Substitute named directories as well.
18
19
20
#   -#               Truncate each directly to at least this many characters inclusive of the
#                    ellipsis character(s) (defaulting to 1).
#   -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
24
25
26
27
28
29
30
31
#
# The long options can also be set via zstyle, like
#   zstyle :prompt:shrink_path fish yes
#
# Note: Directory names containing two or more consecutive spaces are not yet
# supported.
#
# Keywords: prompt directory truncate shrink collapse fish
#
# Copyright (C) 2008 by Daniel Friesel <derf@xxxxxxxxxxxxxxxxxx>
Janosch Schwalm's avatar
Janosch Schwalm committed
32
# License: WTFPL <http://www.wtfpl.net>
33
#
Janosch Schwalm's avatar
Janosch Schwalm committed
34
35
# Ref: https://www.zsh.org/mla/workers/2009/msg00415.html
#      https://www.zsh.org/mla/workers/2009/msg00419.html
36
37
38
39
40
41
42
43
44

shrink_path () {
        setopt localoptions
        setopt rc_quotes null_glob

        typeset -i lastfull=0
        typeset -i short=0
        typeset -i tilde=0
        typeset -i named=0
45
46
        typeset -i length=1
        typeset ellipsis=""
47
        typeset -i quote=0
48
        typeset -i expand=0
49
50
51
52
53
54
55
56
57
58
59
60
61

        if zstyle -t ':prompt:shrink_path' fish; then
                lastfull=1
                short=1
                tilde=1
        fi
        if zstyle -t ':prompt:shrink_path' nameddirs; then
                tilde=1
                named=1
        fi
        zstyle -t ':prompt:shrink_path' last && lastfull=1
        zstyle -t ':prompt:shrink_path' short && short=1
        zstyle -t ':prompt:shrink_path' tilde && tilde=1
62
63
        zstyle -t ':prompt:shrink_path' glob && ellipsis='*'
        zstyle -t ':prompt:shrink_path' quote && quote=1
64
        zstyle -t ':prompt:shrink_path' expand && expand=1
65
66
67

        while [[ $1 == -* ]]; do
                case $1 in
68
69
70
71
                        --)
                                shift
                                break
                        ;;
72
73
74
75
76
77
78
79
                        -f|--fish)
                                lastfull=1
                                short=1
                                tilde=1
                        ;;
                        -h|--help)
                                print 'Usage: shrink_path [-f -l -s -t] [directory]'
                                print ' -f, --fish      fish-simulation, like -l -s -t'
80
                                print ' -g, --glob      Add asterisk to allow globbing of shrunk path (equivalent to -e "*")'
81
                                print ' -l, --last      Print the last directory''s full name'
82
83
                                print ' -s, --short     Truncate directory names to the number of characters given by -#. Without'
                                print '                 -s, names are truncated without making them ambiguous.'
84
85
                                print ' -t, --tilde     Substitute ~ for the home directory'
                                print ' -T, --nameddirs Substitute named directories as well'
86
87
88
                                print ' -#              Truncate each directly to at least this many characters inclusive of the'
                                print '                 ellipsis character(s) (defaulting to 1).'
                                print ' -e SYMBOL       Postfix symbol(s) to indicate that a directory name had been truncated.'
89
                                print ' -q, --quote     Quote special characters in the shrunk path'
90
91
                                print ' -x, --expand    Print the full path. This takes precedence over the other options'
                                print ''
92
93
94
95
96
97
98
99
100
101
102
                                print 'The long options can also be set via zstyle, like'
                                print '  zstyle :prompt:shrink_path fish yes'
                                return 0
                        ;;
                        -l|--last) lastfull=1 ;;
                        -s|--short) short=1 ;;
                        -t|--tilde) tilde=1 ;;
                        -T|--nameddirs)
                                tilde=1
                                named=1
                        ;;
103
104
105
106
107
108
109
                        -[0-9]|-[0-9][0-9])
                                length=${1/-/}
                        ;;
                        -e)
                                shift
                                ellipsis="$1"
                        ;;
110
111
112
113
114
115
                        -g|--glob)
                                ellipsis='*'
                        ;;
                        -q|--quote)
                                quote=1
                        ;;
116
117
118
                        -x|--expand)
                                expand=1
                        ;;
119
120
121
122
                esac
                shift
        done

123
        typeset -i elllen=${#ellipsis}
124
125
126
127
128
129
        typeset -a tree expn
        typeset result part dir=${1-$PWD}
        typeset -i i

        [[ -d $dir ]] || return 0

130
131
132
133
134
        if (( expand )) {
                echo "$dir"
                return 0
        }

135
136
        if (( named )) {
                for part in ${(k)nameddirs}; {
137
                        [[ $dir == ${nameddirs[$part]}(/*|) ]] && dir=${dir/#${nameddirs[$part]}/\~$part}
138
139
                }
        }
140
        (( tilde )) && dir=${dir/#$HOME/\~}
141
142
143
        tree=(${(s:/:)dir})
        (
                if [[ $tree[1] == \~* ]] {
144
                        cd -q ${~tree[1]}
145
146
147
                        result=$tree[1]
                        shift tree
                } else {
148
                        cd -q /
149
150
151
152
153
154
155
156
157
                }
                for dir in $tree; {
                        if (( lastfull && $#tree == 1 )) {
                                result+="/$tree"
                                break
                        }
                        expn=(a b)
                        part=''
                        i=0
158
                        until [[ $i -gt 99 || ( $i -ge $((length - ellen)) || $dir == $part ) && ( (( ${#expn} == 1 )) || $dir = $expn ) ]]; do
159
160
161
                                (( i++ ))
                                part+=$dir[$i]
                                expn=($(echo ${part}*(-/)))
162
                                (( short )) && [[ $i -ge $((length - ellen)) ]] && break
163
                        done
164
165
166
167

                        typeset -i dif=$(( ${#dir} - ${#part} - ellen ))
                        if [[ $dif -gt 0 ]]
                        then
168
                            (( quote )) && part=${(q)part}
169
170
171
                            part+="$ellipsis"
                        else
                            part="$dir"
172
                            (( quote )) && part=${(q)part}
173
                        fi
174
                        result+="/$part"
175
                        cd -q $dir
176
177
178
179
180
181
182
                        shift tree
                }
                echo ${result:-/}
        )
}

## vim:ft=zsh