Add zsh-interactive-cd
This commit is contained in:
parent
b908feebcf
commit
12406647d9
21
plugins/zsh-interactive-cd/LICENSE
Normal file
21
plugins/zsh-interactive-cd/LICENSE
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2017 Henry Chang
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
15
plugins/zsh-interactive-cd/README.md
Normal file
15
plugins/zsh-interactive-cd/README.md
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
# zsh-interactive-cd
|
||||||
|
|
||||||
|
## Demo
|
||||||
|
|
||||||
|
![demo](demo.gif)
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
1. Install [fzf](https://github.com/junegunn/fzf) by following its [installation instruction](https://github.com/junegunn/fzf#installation).
|
||||||
|
|
||||||
|
2. Source `zsh-interactive-cd.plugin.zsh` in `.zshrc`.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
Press tab for completion as usual, it'll launch fzf automatically. Check fzf’s [readme](https://github.com/junegunn/fzf#search-syntax) for more search syntax usage.
|
BIN
plugins/zsh-interactive-cd/demo.gif
Normal file
BIN
plugins/zsh-interactive-cd/demo.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.4 MiB |
147
plugins/zsh-interactive-cd/zsh-interactive-cd.plugin.zsh
Normal file
147
plugins/zsh-interactive-cd/zsh-interactive-cd.plugin.zsh
Normal file
@ -0,0 +1,147 @@
|
|||||||
|
#!/usr/bin/env zsh
|
||||||
|
|
||||||
|
__zic_fzf_prog() {
|
||||||
|
[ -n "$TMUX_PANE" ] && [ "${FZF_TMUX:-0}" != 0 ] && [ ${LINES:-40} -gt 15 ] \
|
||||||
|
&& echo "fzf-tmux -d${FZF_TMUX_HEIGHT:-40%}" || echo "fzf"
|
||||||
|
}
|
||||||
|
|
||||||
|
__zic_matched_subdir_list() {
|
||||||
|
local dir length seg starts_with_dir
|
||||||
|
if [[ "$1" == */ ]]; then
|
||||||
|
dir="$1"
|
||||||
|
if [[ "$dir" != / ]]; then
|
||||||
|
dir="${dir: : -1}"
|
||||||
|
fi
|
||||||
|
length=$(echo -n "$dir" | wc -c)
|
||||||
|
if [ "$dir" = "/" ]; then
|
||||||
|
length=0
|
||||||
|
fi
|
||||||
|
find -L "$dir" -mindepth 1 -maxdepth 1 -type d 2>/dev/null \
|
||||||
|
| cut -b $(( ${length} + 2 ))- | sed '/^$/d' | while read -r line; do
|
||||||
|
if [[ "${line[1]}" == "." ]]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
echo "$line"
|
||||||
|
done
|
||||||
|
else
|
||||||
|
dir=$(dirname -- "$1")
|
||||||
|
length=$(echo -n "$dir" | wc -c)
|
||||||
|
if [ "$dir" = "/" ]; then
|
||||||
|
length=0
|
||||||
|
fi
|
||||||
|
seg=$(basename -- "$1")
|
||||||
|
starts_with_dir=$( \
|
||||||
|
find -L "$dir" -mindepth 1 -maxdepth 1 -type d \
|
||||||
|
2>/dev/null | cut -b $(( ${length} + 2 ))- | sed '/^$/d' \
|
||||||
|
| while read -r line; do
|
||||||
|
if [[ "${seg[1]}" != "." && "${line[1]}" == "." ]]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
if [[ "$line" == "$seg"* ]]; then
|
||||||
|
echo "$line"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
)
|
||||||
|
if [ -n "$starts_with_dir" ]; then
|
||||||
|
echo "$starts_with_dir"
|
||||||
|
else
|
||||||
|
find -L "$dir" -mindepth 1 -maxdepth 1 -type d \
|
||||||
|
2>/dev/null | cut -b $(( ${length} + 2 ))- | sed '/^$/d' \
|
||||||
|
| while read -r line; do
|
||||||
|
if [[ "${seg[1]}" != "." && "${line[1]}" == "." ]]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
if [[ "$line" == *"$seg"* ]]; then
|
||||||
|
echo "$line"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
_zic_list_generator() {
|
||||||
|
__zic_matched_subdir_list "${(Q)@[-1]}" | sort
|
||||||
|
}
|
||||||
|
|
||||||
|
_zic_complete() {
|
||||||
|
setopt localoptions nonomatch
|
||||||
|
local l matches fzf tokens base
|
||||||
|
|
||||||
|
l=$(_zic_list_generator $@)
|
||||||
|
|
||||||
|
if [ -z "$l" ]; then
|
||||||
|
zle ${__zic_default_completion:-expand-or-complete}
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
fzf=$(__zic_fzf_prog)
|
||||||
|
|
||||||
|
if [ $(echo $l | wc -l) -eq 1 ]; then
|
||||||
|
matches=${(q)l}
|
||||||
|
else
|
||||||
|
matches=$(echo $l \
|
||||||
|
| FZF_DEFAULT_OPTS="--height ${FZF_TMUX_HEIGHT:-40%} \
|
||||||
|
--reverse $FZF_DEFAULT_OPTS $FZF_COMPLETION_OPTS \
|
||||||
|
--bind 'shift-tab:up,tab:down'" ${=fzf} \
|
||||||
|
| while read -r item; do
|
||||||
|
echo -n "${(q)item} "
|
||||||
|
done)
|
||||||
|
fi
|
||||||
|
|
||||||
|
matches=${matches% }
|
||||||
|
if [ -n "$matches" ]; then
|
||||||
|
tokens=(${(z)LBUFFER})
|
||||||
|
base="${(Q)@[-1]}"
|
||||||
|
if [[ "$base" != */ ]]; then
|
||||||
|
if [[ "$base" == */* ]]; then
|
||||||
|
base="$(dirname -- "$base")"
|
||||||
|
if [[ ${base[-1]} != / ]]; then
|
||||||
|
base="$base/"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
base=""
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
LBUFFER="${tokens[1]} "
|
||||||
|
if [ -n "$base" ]; then
|
||||||
|
base="${(q)base}"
|
||||||
|
if [ "${tokens[2][1]}" = "~" ]; then
|
||||||
|
base="${base/#$HOME/~}"
|
||||||
|
fi
|
||||||
|
LBUFFER="${LBUFFER}${base}"
|
||||||
|
fi
|
||||||
|
LBUFFER="${LBUFFER}${matches}/"
|
||||||
|
fi
|
||||||
|
zle redisplay
|
||||||
|
typeset -f zle-line-init >/dev/null && zle zle-line-init
|
||||||
|
}
|
||||||
|
|
||||||
|
zic-completion() {
|
||||||
|
setopt localoptions noshwordsplit noksh_arrays noposixbuiltins
|
||||||
|
local tokens cmd
|
||||||
|
|
||||||
|
tokens=(${(z)LBUFFER})
|
||||||
|
cmd=${tokens[1]}
|
||||||
|
|
||||||
|
if [[ "$LBUFFER" =~ "^\ *cd$" ]]; then
|
||||||
|
zle ${__zic_default_completion:-expand-or-complete}
|
||||||
|
elif [ "$cmd" = cd ]; then
|
||||||
|
_zic_complete ${tokens[2,${#tokens}]/#\~/$HOME}
|
||||||
|
else
|
||||||
|
zle ${__zic_default_completion:-expand-or-complete}
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
[ -z "$__zic_default_completion" ] && {
|
||||||
|
binding=$(bindkey '^I')
|
||||||
|
# $binding[(s: :w)2]
|
||||||
|
# The command substitution and following word splitting to determine the
|
||||||
|
# default zle widget for ^I formerly only works if the IFS parameter contains
|
||||||
|
# a space via $binding[(w)2]. Now it specifically splits at spaces, regardless
|
||||||
|
# of IFS.
|
||||||
|
[[ $binding =~ 'undefined-key' ]] || __zic_default_completion=$binding[(s: :w)2]
|
||||||
|
unset binding
|
||||||
|
}
|
||||||
|
|
||||||
|
zle -N zic-completion
|
||||||
|
bindkey '^I' zic-completion
|
Loading…
Reference in New Issue
Block a user