2013-10-29 18:27:42 +01:00
# Fish-like autosuggestions for zsh. Some of the code was based on the code
2013-12-03 20:25:52 +01:00
# for 'predict-on'
2013-10-26 20:05:12 +02:00
#
# ```zsh
2013-10-26 19:11:53 +02:00
# zle-line-init() {
2013-10-29 18:27:42 +01:00
# autosuggest-enable
2013-10-26 19:11:53 +02:00
# }
# zle -N zle-line-init
2013-10-26 20:05:12 +02:00
# ```
2013-10-28 23:51:04 +01:00
zmodload zsh/net/socket
2013-10-29 09:42:03 +01:00
source " ${ 0 : a : h } /completion-client.zsh "
2013-10-28 23:51:04 +01:00
2013-12-03 20:45:56 +01:00
# configuration variables
AUTOSUGGESTION_HIGHLIGHT_COLOR = 'fg=8'
AUTOSUGGESTION_HIGHLIGHT_CURSOR = 1
2013-10-29 09:42:03 +01:00
function {
2013-11-08 00:12:33 +01:00
if [ [ -n $ZLE_DISABLE_AUTOSUGGEST ] ] ; then
ZSH_HIGHLIGHT_HIGHLIGHTERS = ( )
return
fi
2013-11-07 22:42:17 +01:00
autoload -U is-at-least
2014-09-22 15:08:24 +02:00
# if is-at-least 5.0.3; then
# autosuggest-ensure-server
# fi
2013-10-29 09:42:03 +01:00
}
2013-10-26 18:05:17 +02:00
2013-11-07 22:42:17 +01:00
ZLE_AUTOSUGGEST_SUSPEND_WIDGETS = (
2015-05-18 14:50:14 +02:00
vi-cmd-mode vi-backward-char backward-char backward-word beginning-of-line
2015-06-06 00:49:11 +02:00
history-search-forward history-search-backward history-beginning-search-forward
history-beginning-search-backward history-substring-search-up
history-substring-search-down backward-kill-word
)
ZLE_AUTOSUGGEST_MOVE_IN_HISTORY_WIDGETS = (
up-line-or-history down-line-or-history
2013-10-27 18:40:10 +01:00
)
ZLE_AUTOSUGGEST_COMPLETION_WIDGETS = (
2015-05-18 14:50:14 +02:00
complete-word expand-or-complete expand-or-complete-prefix list-choices
menu-complete reverse-menu-complete menu-expand-or-complete menu-select
accept-and-menu-complete
2013-10-27 18:40:10 +01:00
)
2013-10-26 18:05:17 +02:00
2013-11-08 12:20:57 +01:00
ZLE_AUTOSUGGEST_ACCEPT_WIDGETS = (
2015-05-18 14:50:14 +02:00
vi-forward-char forward-char vi-forward-word forward-word vi-add-eol
vi-add-next vi-forward-blank-word end-of-line
2013-11-08 12:20:57 +01:00
)
2013-10-29 18:27:42 +01:00
autosuggest-pause( ) {
[ [ -z $ZLE_AUTOSUGGESTING ] ] && return
unset ZLE_AUTOSUGGESTING
2013-10-27 18:40:10 +01:00
local widget
2013-10-26 18:05:17 +02:00
# When autosuggestions are disabled, kill the unmaterialized part
RBUFFER = ''
2013-11-07 22:42:17 +01:00
zle -A autosuggest-paused-self-insert self-insert
zle -A autosuggest-magic-space-orig magic-space
zle -A autosuggest-backward-delete-char-orig backward-delete-char
zle -A autosuggest-accept-line-orig accept-line
2015-06-06 00:49:11 +02:00
for widget in $ZLE_AUTOSUGGEST_ACCEPT_WIDGETS $ZLE_AUTOSUGGEST_SUSPEND_WIDGETS $ZLE_AUTOSUGGEST_COMPLETION_WIDGETS $ZLE_AUTOSUGGEST_MOVE_IN_HISTORY_WIDGETS ; do
2013-11-08 15:49:33 +01:00
[ [ -z $widgets [ $widget ] || -z $widgets [ autosuggest-${ widget } -orig] ] ] && \
continue
2013-11-07 22:42:17 +01:00
eval " zle -A autosuggest- ${ widget } -orig ${ widget } "
2013-10-27 18:40:10 +01:00
done
2013-10-29 14:46:39 +01:00
autosuggest-highlight-suggested-text
2013-10-29 18:27:42 +01:00
2013-11-07 22:42:17 +01:00
if [ [ -n $ZLE_AUTOSUGGEST_CONNECTION ] ] ; then
zle -F $ZLE_AUTOSUGGEST_CONNECTION
fi
2013-10-26 18:05:17 +02:00
}
2013-10-29 18:27:42 +01:00
autosuggest-resume( ) {
2013-10-27 18:40:10 +01:00
[ [ -n $ZLE_AUTOSUGGESTING ] ] && return
2013-10-26 18:05:17 +02:00
ZLE_AUTOSUGGESTING = 1
2013-10-29 18:27:42 +01:00
local widget
2013-10-26 18:05:17 +02:00
# Replace prediction widgets by versions that will also highlight RBUFFER
2013-11-07 22:42:17 +01:00
zle -A autosuggest-insert-or-space self-insert
2013-12-03 20:25:52 +01:00
zle -A autosuggest-insert-or-space magic-space
zle -A autosuggest-backward-delete-char backward-delete-char
zle -A autosuggest-accept-line accept-line
2013-11-07 22:42:17 +01:00
# Hook into some default widgets that should suspend autosuggestion
2013-12-03 20:25:52 +01:00
# automatically
2013-11-08 12:20:57 +01:00
for widget in $ZLE_AUTOSUGGEST_ACCEPT_WIDGETS ; do
[ [ -z $widgets [ $widget ] ] ] && continue
eval " zle -A autosuggest-accept-suggestion $widget "
done
2015-06-06 00:49:11 +02:00
for widget in $ZLE_AUTOSUGGEST_MOVE_IN_HISTORY_WIDGETS ; do
[ [ -z $widgets [ $widget ] ] ] && continue
eval " zle -A autosuggest-move-in-history $widget "
done
2013-11-07 22:42:17 +01:00
for widget in $ZLE_AUTOSUGGEST_SUSPEND_WIDGETS ; do
[ [ -z $widgets [ $widget ] ] ] && continue
eval " zle -A autosuggest-suspend $widget "
2013-10-27 18:40:10 +01:00
done
2013-11-07 22:42:17 +01:00
# Hook into completion widgets to trim RBUFFER before completion
2013-10-27 18:40:10 +01:00
for widget in $ZLE_AUTOSUGGEST_COMPLETION_WIDGETS ; do
2013-11-07 22:42:17 +01:00
[ [ -z $widgets [ $widget ] ] ] && continue
eval " zle -A autosuggest-tab $widget "
2013-10-27 18:40:10 +01:00
done
2013-10-29 18:27:42 +01:00
if [ [ -n $ZLE_AUTOSUGGEST_CONNECTION ] ] ; then
# install listen for suggestions asynchronously
2013-11-07 22:42:17 +01:00
zle -Fw $ZLE_AUTOSUGGEST_CONNECTION autosuggest-pop-suggestion
2013-10-26 19:11:53 +02:00
fi
2013-10-29 18:27:42 +01:00
}
autosuggest-start( ) {
2013-11-08 00:12:33 +01:00
if [ [ -z $ZLE_DISABLE_AUTOSUGGEST && -n $functions [ _zsh_highlight] ] ] ; then
2015-05-18 14:50:14 +02:00
if [ [ ${ ZSH_HIGHLIGHT_HIGHLIGHTERS [(i)autosuggest] } -gt ${# ZSH_HIGHLIGHT_HIGHLIGHTERS } ] ] ; then
ZSH_HIGHLIGHT_HIGHLIGHTERS += ( autosuggest)
fi
2013-11-08 00:12:33 +01:00
fi
2013-10-29 18:27:42 +01:00
autosuggest-resume
2013-10-26 19:11:53 +02:00
}
2013-10-26 18:05:17 +02:00
# Toggles autosuggestions on/off
2013-10-29 18:27:42 +01:00
autosuggest-toggle( ) {
if [ [ -n $ZLE_AUTOSUGGESTING ] ] ; then
autosuggest-pause
2013-11-07 22:42:17 +01:00
zle -A autosuggest-self-insert-orig self-insert
2013-10-26 18:05:17 +02:00
else
2013-10-29 18:27:42 +01:00
autosuggest-resume
2013-10-26 18:05:17 +02:00
fi
}
2013-10-29 14:46:39 +01:00
autosuggest-highlight-suggested-text( ) {
2013-11-08 00:12:33 +01:00
if ( ( $+functions[ _zsh_highlight_buffer_modified] > 0 ) ) ; then
_zsh_highlight
2013-10-26 18:05:17 +02:00
else
region_highlight = ( )
2013-11-08 00:12:33 +01:00
_zsh_highlight_autosuggest_highlighter
2013-10-26 18:05:17 +02:00
fi
}
2013-11-08 00:12:33 +01:00
_zsh_highlight_autosuggest_highlighter_predicate( ) {
[ [ -n $ZLE_AUTOSUGGESTING ] ] && ( ( $# RBUFFER > 0 ) )
}
_zsh_highlight_autosuggest_highlighter( ) {
2013-12-03 20:45:56 +01:00
region_highlight += ( " $(( $CURSOR + $AUTOSUGGESTION_HIGHLIGHT_CURSOR )) $(( $CURSOR + $# RBUFFER )) $AUTOSUGGESTION_HIGHLIGHT_COLOR " )
2013-11-08 00:12:33 +01:00
}
2013-10-29 14:46:39 +01:00
autosuggest-insert-or-space( ) {
2015-05-18 14:50:14 +02:00
setopt localoptions noshwordsplit noksharrays
2013-10-29 14:46:39 +01:00
if [ [ $LBUFFER = = *$'\012' * ] ] || ( ( PENDING ) ) ; then
2013-11-07 22:42:17 +01:00
# Editing multiline buffer or pasting a chunk of text, pause
autosuggest-suspend
return
fi
if [ [ ${ RBUFFER [1] } = = ${ KEYS [-1] } ] ] ; then
# Same as what's typed, just move on
2013-10-27 18:40:10 +01:00
( ( ++CURSOR) )
2013-11-08 00:12:33 +01:00
autosuggest-invalidate-highlight-cache
2013-10-27 18:40:10 +01:00
else
2013-11-07 22:42:17 +01:00
LBUFFER = " $LBUFFER $KEYS "
if [ [ $LASTWIDGET = = ( self-insert| magic-space| backward-delete-char) || $LASTWIDGET = = ( complete-word| accept-*| zle-line-init) ] ] ; then
if ! zle .history-beginning-search-backward; then
RBUFFER = ''
if [ [ ${ KEYS [-1] } != ' ' ] ] ; then
autosuggest-send-request ${ LBUFFER }
fi
fi
fi
2013-10-27 18:40:10 +01:00
fi
2013-11-07 22:42:17 +01:00
autosuggest-highlight-suggested-text
2013-10-27 18:40:10 +01:00
}
2013-10-29 14:46:39 +01:00
autosuggest-backward-delete-char( ) {
2013-11-07 22:42:17 +01:00
if ( ( $# LBUFFER > 1 ) ) ; then
setopt localoptions noshwordsplit noksharrays
2015-05-21 01:08:17 +02:00
if [ [ $LBUFFER = *$'\012' * || $LASTWIDGET != ( self-insert| magic-space| backward-delete-char) ] ] ; then
LBUFFER = " $LBUFFER [1,-2] "
else
( ( --CURSOR) )
autosuggest-invalidate-highlight-cache
zle .history-beginning-search-forward || RBUFFER = ''
fi
2013-11-07 22:42:17 +01:00
autosuggest-highlight-suggested-text
2013-10-27 18:40:10 +01:00
else
2013-11-07 22:42:17 +01:00
zle .kill-whole-line
2013-10-27 18:40:10 +01:00
fi
}
# When autosuggesting, ignore RBUFFER which corresponds to the 'unmaterialized'
# section when the user accepts the line
autosuggest-accept-line( ) {
RBUFFER = ''
2013-11-08 12:20:57 +01:00
if ! ( ( $+functions[ _zsh_highlight_buffer_modified] ) ) ; then
2013-11-08 00:12:33 +01:00
# Only clear the colors if the user doesn't have zsh-highlight installed
region_highlight = ( )
fi
2013-10-27 18:40:10 +01:00
zle .accept-line
}
2013-10-29 14:46:39 +01:00
autosuggest-paused-self-insert( ) {
2013-10-27 10:53:52 +01:00
if [ [ $RBUFFER = = '' ] ] ; then
# Resume autosuggestions when inserting at the end of the line
2013-11-07 22:42:17 +01:00
autosuggest-resume
zle self-insert
2013-10-27 10:53:52 +01:00
else
2013-11-07 22:42:17 +01:00
zle autosuggest-self-insert-orig
2013-10-27 10:53:52 +01:00
fi
}
2013-10-29 18:27:42 +01:00
autosuggest-pop-suggestion( ) {
local words last_word suggestion
if ! IFS = read -r -u $ZLE_AUTOSUGGEST_CONNECTION suggestion; then
# server closed the connection, stop listenting
zle -F $ZLE_AUTOSUGGEST_CONNECTION
unset ZLE_AUTOSUGGEST_CONNECTION
return
fi
if [ [ -n $suggestion ] ] ; then
local prefix = ${ suggestion % $'\2' * }
suggestion = ${ suggestion #* $'\2' }
# only use the suggestion if the prefix is still compatible with
# the suggestion(prefix should be contained in LBUFFER)
if [ [ ${ LBUFFER # $prefix * } != ${ LBUFFER } ] ] ; then
words = ( ${ (z)LBUFFER } )
last_word = ${ words [-1] }
suggestion = ${ suggestion : $# last_word }
RBUFFER = " $suggestion "
autosuggest-highlight-suggested-text
else
RBUFFER = ''
fi
else
RBUFFER = ''
fi
zle -Rc
}
autosuggest-suspend( ) {
autosuggest-pause
2013-10-27 18:40:10 +01:00
zle autosuggest-${ WIDGET } -orig " $@ "
2013-10-27 14:49:21 +01:00
}
2013-10-27 18:40:10 +01:00
autosuggest-tab( ) {
2013-10-27 14:49:21 +01:00
RBUFFER = ''
2013-10-27 18:40:10 +01:00
zle autosuggest-${ WIDGET } -orig " $@ "
2015-05-18 16:33:50 +02:00
autosuggest-invalidate-highlight-cache
2013-10-29 14:46:39 +01:00
autosuggest-highlight-suggested-text
2013-10-27 14:49:21 +01:00
}
2015-06-06 00:49:11 +02:00
autosuggest-move-in-history( ) {
if [ [ -n $RBUFFER ] ] ; then
if [ [ " $WIDGET " = = 'up-line-or-history' ] ] ; then
zle autosuggest-history-beginning-search-backward-orig
else
zle autosuggest-history-beginning-search-forward-orig
fi
else
zle autosuggest-${ WIDGET } -orig
fi
}
2013-11-08 12:20:57 +01:00
autosuggest-accept-suggestion( ) {
2015-05-18 14:50:14 +02:00
if [ [ AUTOSUGGESTION_ACCEPT_RIGHT_ARROW -eq 1 && " $WIDGET " = = 'forward-char' ] ] ; then
zle autosuggest-end-of-line-orig " $@ "
else
zle autosuggest-${ WIDGET } -orig " $@ "
fi
2013-11-08 00:12:33 +01:00
if [ [ -n $ZLE_AUTOSUGGESTING ] ] ; then
autosuggest-invalidate-highlight-cache
autosuggest-highlight-suggested-text
fi
}
2015-05-22 00:54:27 +02:00
autosuggest-execute-suggestion( ) {
if [ [ -n $ZLE_AUTOSUGGESTING ] ] ; then
zle autosuggest-end-of-line-orig
autosuggest-invalidate-highlight-cache
autosuggest-highlight-suggested-text
fi
zle .accept-line
}
2013-11-08 00:12:33 +01:00
autosuggest-invalidate-highlight-cache( ) {
# invalidate the buffer for zsh-syntax-highlighting
2015-05-16 20:35:13 +02:00
_zsh_highlight_autosuggest_highlighter_cache = ( )
2013-10-26 18:05:17 +02:00
}
2013-10-29 18:27:42 +01:00
zle -N autosuggest-toggle
zle -N autosuggest-start
zle -N autosuggest-accept-suggested-small-word
zle -N autosuggest-accept-suggested-word
2015-05-22 00:54:27 +02:00
zle -N autosuggest-execute-suggestion
2013-11-07 22:42:17 +01:00
zle -N autosuggest-paused-self-insert
zle -N autosuggest-insert-or-space
zle -N autosuggest-backward-delete-char
zle -N autosuggest-accept-line
2013-10-27 18:40:10 +01:00
zle -N autosuggest-tab
2013-11-07 22:42:17 +01:00
zle -N autosuggest-suspend
2013-11-08 12:20:57 +01:00
zle -N autosuggest-accept-suggestion
2015-06-06 00:49:11 +02:00
zle -N autosuggest-move-in-history
2013-11-07 22:42:17 +01:00
# Save all widgets
zle -A self-insert autosuggest-self-insert-orig
zle -A magic-space autosuggest-magic-space-orig
zle -A backward-delete-char autosuggest-backward-delete-char-orig
zle -A accept-line autosuggest-accept-line-orig
2013-11-08 12:20:57 +01:00
2015-06-06 00:49:11 +02:00
for widget in ${ ZLE_AUTOSUGGEST_ACCEPT_WIDGETS } ${ ZLE_AUTOSUGGEST_SUSPEND_WIDGETS } ${ ZLE_AUTOSUGGEST_COMPLETION_WIDGETS } ${ ZLE_AUTOSUGGEST_MOVE_IN_HISTORY_WIDGETS } ; do
2013-11-07 22:42:17 +01:00
[ [ -z $widgets [ $widget ] ] ] && continue
eval " zle -A $widget autosuggest- ${ widget } -orig "
done