]> src.twobees.de Git - dotfiles.git/blob - stow/oh-my-zsh/.oh-my-zsh/plugins/zsh-interactive-cd/zsh-interactive-cd.plugin.zsh
initial
[dotfiles.git] / stow / oh-my-zsh / .oh-my-zsh / plugins / zsh-interactive-cd / zsh-interactive-cd.plugin.zsh
1 # Copyright (c) 2017 Henry Chang
2
3 __zic_fzf_prog() {
4   [ -n "$TMUX_PANE" ] && [ "${FZF_TMUX:-0}" != 0 ] && [ ${LINES:-40} -gt 15 ] \
5     && echo "fzf-tmux -d${FZF_TMUX_HEIGHT:-40%}" || echo "fzf"
6 }
7
8 __zic_matched_subdir_list() {
9   local dir length seg starts_with_dir
10   if [[ "$1" == */ ]]; then
11     dir="$1"
12     if [[ "$dir" != / ]]; then
13       dir="${dir: : -1}"
14     fi
15     length=$(echo -n "$dir" | wc -c)
16     if [ "$dir" = "/" ]; then
17       length=0
18     fi
19     find -L "$dir" -mindepth 1 -maxdepth 1 -type d 2>/dev/null \
20         | cut -b $(( ${length} + 2 ))- | sed '/^$/d' | while read -r line; do
21       if [[ "${line[1]}" == "." ]]; then
22         continue
23       fi
24       echo "$line"
25     done
26   else
27     dir=$(dirname -- "$1")
28     length=$(echo -n "$dir" | wc -c)
29     if [ "$dir" = "/" ]; then
30       length=0
31     fi
32     seg=$(basename -- "$1")
33     starts_with_dir=$( \
34       find -L "$dir" -mindepth 1 -maxdepth 1 -type d \
35           2>/dev/null | cut -b $(( ${length} + 2 ))- | sed '/^$/d' \
36           | while read -r line; do
37         if [[ "${seg[1]}" != "." && "${line[1]}" == "." ]]; then
38           continue
39         fi
40         if [[ "$line" == "$seg"* ]]; then
41           echo "$line"
42         fi
43       done
44     )
45     if [ -n "$starts_with_dir" ]; then
46       echo "$starts_with_dir"
47     else
48       find -L "$dir" -mindepth 1 -maxdepth 1 -type d \
49           2>/dev/null | cut -b $(( ${length} + 2 ))- | sed '/^$/d' \
50           | while read -r line; do
51         if [[ "${seg[1]}" != "." && "${line[1]}" == "." ]]; then
52           continue
53         fi
54         if [[ "$line" == *"$seg"* ]]; then
55           echo "$line"
56         fi
57       done
58     fi
59   fi
60 }
61
62 _zic_list_generator() {
63   __zic_matched_subdir_list "${(Q)@[-1]}" | sort
64 }
65
66 _zic_complete() {
67   setopt localoptions nonomatch
68   local l matches fzf tokens base
69
70   l=$(_zic_list_generator $@)
71
72   if [ -z "$l" ]; then
73     zle ${__zic_default_completion:-expand-or-complete}
74     return
75   fi
76
77   fzf=$(__zic_fzf_prog)
78
79   if [ $(echo $l | wc -l) -eq 1 ]; then
80     matches=${(q)l}
81   else
82     matches=$(echo $l \
83         | FZF_DEFAULT_OPTS="--height ${FZF_TMUX_HEIGHT:-40%} \
84           --reverse $FZF_DEFAULT_OPTS $FZF_COMPLETION_OPTS \
85           --bind 'shift-tab:up,tab:down'" ${=fzf} \
86         | while read -r item; do
87       echo -n "${(q)item} "
88     done)
89   fi
90
91   matches=${matches% }
92   if [ -n "$matches" ]; then
93     tokens=(${(z)LBUFFER})
94     base="${(Q)@[-1]}"
95     if [[ "$base" != */ ]]; then
96       if [[ "$base" == */* ]]; then
97         base="$(dirname -- "$base")"
98         if [[ ${base[-1]} != / ]]; then
99           base="$base/"
100         fi
101       else
102         base=""
103       fi
104     fi
105     LBUFFER="${tokens[1]} "
106     if [ -n "$base" ]; then
107       base="${(q)base}"
108       if [ "${tokens[2][1]}" = "~" ]; then
109         base="${base/#$HOME/~}"
110       fi
111       LBUFFER="${LBUFFER}${base}"
112     fi
113     LBUFFER="${LBUFFER}${matches}/"
114   fi
115   zle redisplay
116   typeset -f zle-line-init >/dev/null && zle zle-line-init
117 }
118
119 zic-completion() {
120   setopt localoptions noshwordsplit noksh_arrays noposixbuiltins
121   local tokens cmd
122
123   tokens=(${(z)LBUFFER})
124   cmd=${tokens[1]}
125
126   if [[ "$LBUFFER" =~ "^\ *cd$" ]]; then
127     zle ${__zic_default_completion:-expand-or-complete}
128   elif [ "$cmd" = cd ]; then
129     _zic_complete ${tokens[2,${#tokens}]/#\~/$HOME}
130   else
131     zle ${__zic_default_completion:-expand-or-complete}
132   fi
133 }
134
135 [ -z "$__zic_default_completion" ] && {
136   binding=$(bindkey '^I')
137   # $binding[(s: :w)2]
138   # The command substitution and following word splitting to determine the
139   # default zle widget for ^I formerly only works if the IFS parameter contains
140   # a space via $binding[(w)2]. Now it specifically splits at spaces, regardless
141   # of IFS.
142   [[ $binding =~ 'undefined-key' ]] || __zic_default_completion=$binding[(s: :w)2]
143   unset binding
144 }
145
146 zle -N zic-completion
147 bindkey -M emacs '^I' zic-completion
148 bindkey -M viins '^I' zic-completion