shrink-path.plugin.zsh 6.97 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
49
50
51
52
53
54
55
56
57
58
59
60

        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
61
62
        zstyle -t ':prompt:shrink_path' glob && ellipsis='*'
        zstyle -t ':prompt:shrink_path' quote && quote=1
63
64
65

        while [[ $1 == -* ]]; do
                case $1 in
66
67
68
69
                        --)
                                shift
                                break
                        ;;
70
71
72
73
74
75
76
77
                        -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'
78
                                print ' -g, --glob      Add asterisk to allow globbing of shrunk path (equivalent to -e "*")'
79
                                print ' -l, --last      Print the last directory''s full name'
80
81
                                print ' -s, --short     Truncate directory names to the number of characters given by -#. Without'
                                print '                 -s, names are truncated without making them ambiguous.'
82
83
                                print ' -t, --tilde     Substitute ~ for the home directory'
                                print ' -T, --nameddirs Substitute named directories as well'
84
85
86
                                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.'
87
                                print ' -q, --quote     Quote special characters in the shrunk path'
88
89
90
91
92
93
94
95
96
97
98
                                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
                        ;;
99
100
101
102
103
104
105
                        -[0-9]|-[0-9][0-9])
                                length=${1/-/}
                        ;;
                        -e)
                                shift
                                ellipsis="$1"
                        ;;
106
107
108
109
110
111
                        -g|--glob)
                                ellipsis='*'
                        ;;
                        -q|--quote)
                                quote=1
                        ;;
112
113
114
115
                esac
                shift
        done

116
        typeset -i elllen=${#ellipsis}
117
118
119
120
121
122
123
124
        typeset -a tree expn
        typeset result part dir=${1-$PWD}
        typeset -i i

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

        if (( named )) {
                for part in ${(k)nameddirs}; {
125
                        [[ $dir == ${nameddirs[$part]}(/*|) ]] && dir=${dir/#${nameddirs[$part]}/\~$part}
126
127
                }
        }
128
        (( tilde )) && dir=${dir/#$HOME/\~}
129
130
131
        tree=(${(s:/:)dir})
        (
                if [[ $tree[1] == \~* ]] {
132
                        cd -q ${~tree[1]}
133
134
135
                        result=$tree[1]
                        shift tree
                } else {
136
                        cd -q /
137
138
139
140
141
142
143
144
145
                }
                for dir in $tree; {
                        if (( lastfull && $#tree == 1 )) {
                                result+="/$tree"
                                break
                        }
                        expn=(a b)
                        part=''
                        i=0
146
                        until [[ $i -gt 99 || ( $i -ge $((length - ellen)) || $dir == $part ) && ( (( ${#expn} == 1 )) || $dir = $expn ) ]]; do
147
148
149
                                (( i++ ))
                                part+=$dir[$i]
                                expn=($(echo ${part}*(-/)))
150
                                (( short )) && [[ $i -ge $((length - ellen)) ]] && break
151
                        done
152
153
154
155

                        typeset -i dif=$(( ${#dir} - ${#part} - ellen ))
                        if [[ $dif -gt 0 ]]
                        then
156
                            (( quote )) && part=${(q)part}
157
158
159
                            part+="$ellipsis"
                        else
                            part="$dir"
160
                            (( quote )) && part=${(q)part}
161
                        fi
162
                        result+="/$part"
163
                        cd -q $dir
164
165
166
167
168
169
170
                        shift tree
                }
                echo ${result:-/}
        )
}

## vim:ft=zsh