-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathcompletion.mksh
126 lines (122 loc) · 5.06 KB
/
completion.mksh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
# TODO:
# - something is up with escaping/quoting and the glob to get candidates
# ls Tournament\ Machu/test<__fzf_complete> -> nothing, should be test.txt^ntest2.txt
# - ./ at beginning of line (i.e. for the first word)
#
# CASES:
# - {unambig_complete, ambig_complete, no_complete} x
# {start_of_word, middle_of_word, end_of_word, empty_word} x
# {first_word, middle_word, last_word}
# - various numbers of spaces before and after the above cases
# - spaces in various parts of input, as well as returned text
# - "./" as first word (should match files, never commands)
# - "$(" or "`" before cursor (should match commands, never files)
# - other symbols: ', ", >, <, (, ), ./, shell syntax..., possibly &, etc.
# - mksh's completion is kinda broken from within quotes...
# - globbing -- handle it all!
fzf_mksh_abs="$(readlink -f $_)"
fzf_mksh_dir="$(dirname $fzf_mksh_abs)"
. "$fzf_mksh_dir/utils.mksh"
unset fzf_mksh_abs fzf_mksh_dir
function __fzf_get_completion_candidates {
local args
set -A args -- "$@"
local matches
# file completion
if [ ${#args[@]} -gt 1 ]; then
last_arg="${args[${#args[@]}-1]}"
set +o markdirs
if [[ $last_arg = *[*?]* ]]; then
eval "set -A matches -- $last_arg"
else
set -A matches -- "$last_arg"*
fi
for match in "${matches[@]}"; do
if [[ "${match}" != "$last_arg*" ]]; then
if [[ -d "${match}" ]]; then
print -r -- "${match##*/}/"
else
print -r -- "${match##*/}"
fi
fi
done
# command completion
elif [ "${#args[@]}" -eq 1 ] || [ "${#args[@]}" -eq 0 ]; then
local paths
set -o noglob; IFS=:; set -A paths -- $PATH; IFS=$' \t\n'; set +o noglob
for path in "${paths[@]}"; do
matches+=(${path:-.}/"$@"*)
done
for match in "${matches[@]}"; do
if [[ "${match##*/}" != "$@*" ]]; then
print -r -- "${match##*/}"
fi
done | LC_ALL=C sort -u
fi
}
function __fzf_complete {
local comp
local curr_0
local curr_1
local comp_y
local comp_n
set -A comp -- $1
if [ "${1: -1}" = ' ' ]; then
comp+=('')
fi
curr_0="$2"
curr_1="$3"
# comp_y is the current word post-completion
comp_y="${comp[${#comp[@]}-1]}"
# comp_n is the current word sans-completion
comp_n="${curr_0}${curr_1}"
if [ ${#comp_y} -ne ${#comp_n} ]; then
print -r -- "$1"
else
local sel
local res
local fzf_prompt_query_args
fzf_prompt_query_args="--prompt=\"${FZF_COMPLETION_PROMPT_CHAR:->} $1\""
sel=$(__fzf_get_completion_candidates "${comp[@]}")
if [[ "$sel" = '' ]]; then
print -rn -- "${1%${comp_y}}$2$3"
else
local fzf_compl_args
fzf_compl_args="--reverse --bind=ctrl-z:ignore --no-info -0 -1 +m"
res=$(
print -n "$sel" |
FZF_DEFAULT_OPTS="$FZF_DEFAULT_OPTS $fzf_compl_args $fzf_prompt_query_args" $(__fzf_cmd)
)
if [[ $res = *[![:space:]]* ]]; then
print -rn -- "${1%${comp_y##*/}}$(__mksh_escape "$res")"
if [[ ! "${res: -1}" = '/' ]]; then
print -rn -- ' '
fi
else
print -rn -- "$1"
fi
print -r -- ''
fi
fi
}
if [[ ! -o vi ]]; then
# we need kill-region to be bound to something
bind '^W'='kill-region'
# '^v^a' : special mark ^A
# '^xD F^w^y ^y' : move to left of mark, copy "current word, right of cursor", paste
# '^x^x^xC^h' : go back to beginning of word and delete the pasted special mark
# '^x^xQ' : quote the "current word, right of cursor" pasted text ($3)
# '^v^b' : special mark ^B
# '^a' : go back to the original cursor position (special mark ^A)
# '^xC B^x^x^w^y' : go to right of special mark, copy "current word, left of cursor, paste
# '^xDF ^y^hQ' : paste a quoted copy of the "current word, left of cursor" ($2)
# '^a^xC^h' : go to original cursor position and try to complete
# '^v^a' : add the ^A mark we just deleted back; had to remove it to do completion
# '^xDF ' : go to end of current word; if word was '', the ^A mark is necessary
# '^a^xC^h^x^x ' : go back to the ^A mark, remove it, go back again, and set a mark
# '^a^x^xQ' : quote from the beginning of the line to the end of the current word ($1)
# '^a __fzf_complete ': go to beginning of line, set a mark, type func name
# '^b^xC^h^e' : go back to ^B mark and delete it; evaluate
# '^a^xC^h' : __fzf_complete adds a mark indicating where the cursor needs to be
bind -m '^I'='^v^a^xD F^w^y ^y^x^x^xC^h^x^xQ^v^b^a^xC B^x^x^w^y^xDF ^y^hQ^a^xC^h^v^a^xDF ^a^xC^h^x^x ^a^x^xQ^a __fzf_complete ^b^xC^h^e^a^xC^h'
fi