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
127
128
129
130
131
132
133
|
# This set of functions implements a sort of magic history searching.
# After predict-on, typing characters causes the editor to look backward
# in the history for the first line beginning with what you have typed so
# far. After predict-off, editing returns to normal for the line found.
# In fact, you often don't even need to use predict-off, because if the
# line doesn't match something in the history, adding a key performs
# standard completion --- though editing in the middle is liable to delete
# the rest of the line.
#
# With the function based completion system (which is needed for this),
# you should be able to type TAB at almost any point to advance the cursor
# to the next "interesting" character position (usually the end of the
# current word, but sometimes somewhere in the middle of the word). And
# of course as soon as the entire line is what you want, you can accept
# with RETURN, without needing to move the cursor to the end first.
#
# To use it:
# autoload -U predict-on
# zle -N predict-on
# zle -N predict-off
# bindkey '...' predict-on
# bindkey '...' predict-off
# Note that all functions are defined when you first type the predict-on
# key, which means typing the predict-off key before that gives a harmless
# error message.
predict-on() {
zle -N self-insert insert-and-predict
zle -N magic-space insert-and-predict
zle -N backward-delete-char delete-backward-and-predict
zle -N delete-char-or-list delete-no-predict
}
predict-off() {
zle -A .self-insert self-insert
zle -A .magic-space magic-space
zle -A .backward-delete-char backward-delete-char
}
insert-and-predict () {
emulate -L zsh
if [[ ${RBUFFER[1]} = ${KEYS[-1]} ]]
then
# same as what's typed, just move on
((++CURSOR))
else
LBUFFER="$LBUFFER$KEYS"
if [[ $LASTWIDGET == (self-insert|magic-space|backward-delete-char) ]]
then
if ! zle .history-beginning-search-backward
then
RBUFFER=""
if [[ ${KEYS[-1]} != ' ' ]]
then
unsetopt automenu recexact
integer curs=$CURSOR pos nchar=${#LBUFFER//[^${KEYS[-1]}]}
local -a +h comppostfuncs
local crs curcontext="${curcontext}"
[[ -z "$curcontext" ]] && curcontext=:::
curcontext="${curcontext#*:}predict:"
comppostfuncs=( predict-limit-list )
zle complete-word
# Decide where to leave the cursor. The dummy loop is used to
# get out of that `case'.
repeat 1
do
zstyle -s ":completion:${curcontext}" cursor crs
case $crs in
(complete)
# At the place where the completion left it, if it is after
# the character typed.
[[ ${LBUFFER[-1]} = ${KEYS[-1]} ]] && break
;&
(key)
# Or maybe at the n'th occurrence of the character typed.
pos=${BUFFER[(in:nchar:)${KEYS[-1]}]}
if [[ pos -gt curs ]]
then
CURSOR=$pos
break
fi
;&
(*)
# Or else at the previous position.
CURSOR=$curs
esac
done
fi
fi
fi
fi
return 0
}
delete-backward-and-predict() {
emulate -L zsh
if [[ -n "$LBUFFER" ]]
then
# If the last widget was e.g. a motion, then probably the intent is
# to actually edit the line, not change the search prefix.
if [[ $LASTWIDGET == (self-insert|magic-space|backward-delete-char) ]]
then
((--CURSOR))
zle .history-beginning-search-forward || RBUFFER=""
return 0
else
# Depending on preference, you might call "predict-off" here.
LBUFFER="$LBUFFER[1,-2]"
fi
fi
}
delete-no-predict() {
[[ $WIDGET != delete-char-or-list || -n $RBUFFER ]] && predict-off
zle .$WIDGET "$@"
}
# This is a helper function for autocompletion to prevent long lists
# of matches from forcing a "do you wish to see all ...?" prompt.
predict-limit-list() {
if (( compstate[list_lines]+BUFFERLINES > LINES ||
( compstate[list_max] != 0 && compstate[nmatches] > compstate[list_max] ) ))
then
compstate[list]=''
compstate[force_list]=yes
elif zstyle -t ":completion:predict::::" list always
then
compstate[force_list]=yes
fi
}
# Handle zsh autoloading conventions
[[ -o kshautoload ]] || predict-on "$@"
|