Parent directory

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