This commit is contained in:
Eric Freese 2016-01-26 20:51:44 -07:00
parent 7dc9e0f926
commit fc3f368acf
15 changed files with 224 additions and 708 deletions

4
.gitignore vendored
View file

@ -1,4 +0,0 @@
/node_modules/
/build/
*.log
*~

View file

@ -1,4 +1,4 @@
Copyright (c) 2013 Thiago de Arruda Copyright (c) 2016 Thiago de Arruda, Eric Freese
Permission is hereby granted, free of charge, to any person Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation obtaining a copy of this software and associated documentation

117
README.md
View file

@ -7,45 +7,30 @@ It suggests commands as you type, based on command history.
## Installation ## Installation
If you already use [zsh-syntax-highlighting](https://github.com/zsh-users/zsh-syntax-highlighting) plugin, then make sure to be loaded **before** zsh-autosuggestions. ### Using [Antigen](https://github.com/zsh-users/antigen)
Note: _.zshrc_ is a file that contains user-specific ZSH configuration. 1. Load `tarruda/zsh-autosuggestions` using antigen in your `~/.zshrc` file, for example:
ZSH assumes this file in your home directory (i.e. `~/.zshrc`), but the location can be changed using `ZDOTDIR` variable.
### Using zgen ```
# Load the script
[Zgen](https://github.com/tarjoilija/zgen) is a simple and fast plugin manager for ZSH. antigen bundle tarruda/zsh-autosuggestions autosuggestions.zsh
If you dont use zgen, then use instructions for the manual installation.
1. Load `tarruda/zsh-autosuggestions` and `zsh-users/zsh-syntax-highlighting` using zgen in your .zshrc file, for example:
```sh
if ! zgen saved; then
echo "Creating a zgen save"
zgen load zsh-users/zsh-syntax-highlighting
# autosuggestions should be loaded last
zgen load tarruda/zsh-autosuggestions
zgen save
fi
``` ```
2. Enable zsh-autosuggestions; copy the following snippet and put it after the zgen config section in your .zshrc file: 2. Enable autosuggestions by adding the following snippet to your `~/.zshrc` file:
```sh ```
# Enable autosuggestions automatically. # Enable autosuggestions
zle-line-init() { zle-line-init() {
zle autosuggest-start autosuggest_start
} }
zle -N zle-line-init zle -N zle-line-init
``` ```
3. Run `zgen reset` and reopen your terminal. 3. Start a new terminal session or `source ~/.zshrc`
### Manually ### Install Manually
1. Clone this repository to `~/.zsh/zsh-autosuggestions` (or anywhere else): 1. Clone this repository to `~/.zsh/zsh-autosuggestions` (or anywhere else):
@ -53,90 +38,46 @@ If you dont use zgen, then use instructions for the manual installation.
git clone git://github.com/tarruda/zsh-autosuggestions ~/.zsh/zsh-autosuggestions git clone git://github.com/tarruda/zsh-autosuggestions ~/.zsh/zsh-autosuggestions
``` ```
2. Clone zsh-syntax-highlighting repository to `~/.zsh/zsh-syntax-highlighting` (or anywhere else): 2. Load and enable autosuggestions by adding the following snippet to your `~/.zshrc` file:
```sh ```sh
git clone git://github.com/zsh-users/zsh-syntax-highlighting ~/.zsh/zsh-syntax-highlighting # Load the script
```
3. Load and enable autosuggestions; copy the following snippet and put it to your .zshrc file:
```sh
# Load zsh-syntax-highlighting.
source ~/.zsh/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh
# Load zsh-autosuggestions.
source ~/.zsh/zsh-autosuggestions/autosuggestions.zsh source ~/.zsh/zsh-autosuggestions/autosuggestions.zsh
# Enable autosuggestions automatically. # Enable autosuggestions
zle-line-init() { zle-line-init() {
zle autosuggest-start autosuggest_start
} }
zle -N zle-line-init zle -N zle-line-init
``` ```
4. Reopen your terminal. 3. Start a new terminal session or `source ~/.zshrc`
## Uninstallation
Just remove the config lines from .zshrc that youve added during “installation.”
If you dont use zgen, then also delete `~/.zsh/zsh-autosuggestions` and `~/.zsh/zsh-syntax-highlighting`.
## How to use ## How to use
As you type commands, you will see a completion offered after the cursor, in a muted gray color (which can be changed, see [Configuration](#configuration)). As you type commands, you will see a completion offered after the cursor in a muted gray color. This color can be changed. See [configuration](#configuration).
To accept the autosuggestion (replacing the command line contents), hit <kbd>End</kbd>, <kbd>Alt+F</kbd>, <kbd>Ctrl+F</kbd>, or any other key that moves the cursor to the right.
If the autosuggestion is not what you want, just ignore it: it wont execute unless you accept it.
Any widget that moves the cursor to the right (forward-word, forward-char, end-of-line…) will accept parts of the suggested text. To accept the autosuggestion (replacing the command line contents), position your cursor at the end of the buffer and use the right arrow key.
For example, vi-mode users can do this:
```sh If the autosuggestion is not what you want, go ahead and edit it. It won't execute unless you accept it.
# Accept suggestions without leaving insert mode
bindkey '^f' vi-forward-word
# or
bindkey '^f' vi-forward-blank-word
```
You can also use right arrow key to accept the suggested text as in Fish shell; see [Configuration](#configuration) section to enable it.
### Exposed widgets
This plugin defines some ZLE widgets (think about them as functions) which you can bind to some key using [bindkey](http://zshwiki.org/home/zle/bindkeys).
For example, to toggle autosuggestions using <kbd>Ctrl+T</kbd> add this to your .zshrc:
```sh
bindkey '^T' autosuggest-toggle
```
List of widgets:
- `autosuggest-toggle` disable/enable autosuggestions.
- `autosuggest-execute-suggestion` accept the suggestion and execute it.
## Configuration ## Configuration
You may override default global config variables after plugin load, i.e. put it to your .zshrc after the code that loads plugins. You may override default global config variables after plugin load, i.e. put this somewhere in your .zshrc after the code that loads plugins.
- `AUTOSUGGESTION_HIGHLIGHT_COLOR` suggestion highlight color, default is `'fg=8'`. - `ZSH_AUTOSUGGEST_HIGHLIGHT_COLOR`: Color to use when highlighting the autosuggestion
- `AUTOSUGGESTION_HIGHLIGHT_CURSOR` highlight word after cursor, or not. Must be integer value `1` or `0`, default is `1`. - `ZSH_AUTOSUGGEST_CLEAR_WIDGETS`: List of widgets that clear the autosuggestion
- `AUTOSUGGESTION_ACCEPT_RIGHT_ARROW` complete entire suggestion with right arrow. Must be integer value `1` or `0`, default is `0` (right arrow completes one letter at a time). - `ZSH_AUTOSUGGEST_MODIFY_WIDGETS`: List of widgets that modify the autosuggestion
- `ZSH_AUTOSUGGEST_ACCEPT_WIDGETS`: List of widgets that accept the autosuggestion
See defaults and more info [here](tarruda/zsh-autosuggestions/blob/master/lib/config.zsh).
## Known Issues ## Uninstallation
> When I hit <kbd>Tab</kbd> and autosuggestions is enabled, it deletes the previous line, and scrolls up the terminal. Just remove the config lines from `~/.zshrc` that you added during [installation](#installation). If you installed manually, then also delete `~/.zsh/zsh-autosuggestions` or wherever you installed it.
This usually happens when autosuggestions is used along with something like [“completion waiting dots.”](http://michael.thegrebs.com/2012/09/04/zsh-completion-waiting-dots/)
Check which widget is bind to the Tab key; run `bindkey "^I"`.
If it prints something other than `"^I" expand-or-complete`, then this may be the problem.
If you use [Oh My Zsh](https://github.com/robbyrussell/oh-my-zsh), then make sure that the variable `COMPLETION_WAITING_DOTS` is not set (it enables [this](https://github.com/robbyrussell/oh-my-zsh/blob/e55c715508a2f652fed741f2047c66dda2c6e5b0/lib/completion.zsh#L56-L64) problematic code).
If you use module [editor](https://github.com/sorin-ionescu/prezto/tree/master/modules/editor) from [Prezto](https://github.com/sorin-ionescu/prezto), then you must comment out [these lines](https://github.com/sorin-ionescu/prezto/blob/a84ac5b0023d71c98bb28a68c550dc13f6c51945/modules/editor/init.zsh#L303-L304).
## License ## License

View file

@ -1 +0,0 @@
autosuggestions.zsh

View file

@ -1,294 +1,30 @@
# Fish-like autosuggestions for zsh. Some of the code was based on the code #
# for 'predict-on' # Fish-like autosuggestions for zsh
# #
# ```zsh # ```zsh
# zle-line-init() { # zle-line-init() {
# autosuggest-enable # autosuggest_start
# } # }
# zle -N zle-line-init # zle -N zle-line-init
# ``` # ```
zmodload zsh/net/socket
source "${0:a:h}/completion-client.zsh" unset _ZSH_AUTOSUGGESTION_ACTIVE
# configuration variables LIBDIR="${0:a:h}/lib"
AUTOSUGGESTION_HIGHLIGHT_COLOR='fg=8'
AUTOSUGGESTION_HIGHLIGHT_CURSOR=1
function { source "$LIBDIR/config.zsh"
if [[ -n $ZLE_DISABLE_AUTOSUGGEST ]]; then source "$LIBDIR/get_suggestion.zsh"
ZSH_HIGHLIGHT_HIGHLIGHTERS=() source "$LIBDIR/highlight.zsh"
return source "$LIBDIR/widget/widgets.zsh"
source "$LIBDIR/widget/hook.zsh"
autosuggest_start() {
_ZSH_AUTOSUGGESTION_ACTIVE=true
# Register highlighter if needed to support zsh-syntax-highlighting plugin
if _zsh_autosuggest_syntax_highlighting_enabled; then
_zsh_autosuggest_register_highlighter
fi fi
autoload -U is-at-least
# if is-at-least 5.0.3; then _zsh_autosuggest_hook_widgets
# autosuggest-ensure-server
# fi
} }
ZLE_AUTOSUGGEST_SUSPEND_WIDGETS=(
vi-cmd-mode vi-backward-char backward-char backward-word beginning-of-line
history-search-forward history-search-backward up-line-or-history
history-beginning-search-forward history-beginning-search-backward
down-line-or-history history-substring-search-up history-substring-search-down
backward-kill-word
)
ZLE_AUTOSUGGEST_COMPLETION_WIDGETS=(
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
)
ZLE_AUTOSUGGEST_ACCEPT_WIDGETS=(
vi-forward-char forward-char vi-forward-word forward-word vi-add-eol
vi-add-next vi-forward-blank-word vi-end-of-line end-of-line
)
ZLE_AUTOSUGGEST_ALL_WIDGETS=(
self-insert magic-space backward-delete-char accept-line
$ZLE_AUTOSUGGEST_ACCEPT_WIDGETS
$ZLE_AUTOSUGGEST_SUSPEND_WIDGETS
$ZLE_AUTOSUGGEST_COMPLETION_WIDGETS
)
autosuggest-pause() {
[[ -z $ZLE_AUTOSUGGESTING ]] && return
unset ZLE_AUTOSUGGESTING
# Restore standard widgets except for self-insert, which triggers resume
autosuggest-restore-widgets
zle -A autosuggest-paused-self-insert self-insert
# When autosuggestions are disabled, kill the unmaterialized part
RBUFFER=''
autosuggest-highlight-suggested-text
if [[ -n $ZLE_AUTOSUGGEST_CONNECTION ]]; then
zle -F $ZLE_AUTOSUGGEST_CONNECTION
fi
}
autosuggest-resume() {
[[ -n $ZLE_AUTOSUGGESTING ]] && return
ZLE_AUTOSUGGESTING=1
autosuggest-hook-widgets
if [[ -n $ZLE_AUTOSUGGEST_CONNECTION ]]; then
# install listen for suggestions asynchronously
zle -Fw $ZLE_AUTOSUGGEST_CONNECTION autosuggest-pop-suggestion
fi
}
autosuggest-start() {
if [[ -z $ZLE_DISABLE_AUTOSUGGEST && -n $functions[_zsh_highlight] ]]; then
if [[ ${ZSH_HIGHLIGHT_HIGHLIGHTERS[(i)autosuggest]} -gt ${#ZSH_HIGHLIGHT_HIGHLIGHTERS} ]]; then
ZSH_HIGHLIGHT_HIGHLIGHTERS+=(autosuggest)
fi
fi
autosuggest-resume
}
# Toggles autosuggestions on/off
autosuggest-toggle() {
if [[ -n $ZLE_AUTOSUGGESTING ]]; then
autosuggest-pause
zle -A .self-insert self-insert
else
autosuggest-resume
fi
}
autosuggest-highlight-suggested-text() {
if (( $+functions[_zsh_highlight_buffer_modified] > 0 )); then
_zsh_highlight
else
region_highlight=()
_zsh_highlight_autosuggest_highlighter
fi
}
_zsh_highlight_autosuggest_highlighter_predicate() {
[[ -n $ZLE_AUTOSUGGESTING ]] && (( $#RBUFFER > 0 ))
}
_zsh_highlight_autosuggest_highlighter() {
region_highlight+=("$(( $CURSOR + $AUTOSUGGESTION_HIGHLIGHT_CURSOR )) $(( $CURSOR + $#RBUFFER )) $AUTOSUGGESTION_HIGHLIGHT_COLOR")
}
autosuggest-insert-or-space() {
setopt localoptions noshwordsplit noksharrays
if [[ $LBUFFER == *$'\012'* ]] || (( PENDING )); then
# 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
((++CURSOR))
autosuggest-invalidate-highlight-cache
else
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
fi
autosuggest-highlight-suggested-text
}
autosuggest-backward-delete-char() {
if (( $#LBUFFER > 1 )); then
setopt localoptions noshwordsplit noksharrays
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
autosuggest-highlight-suggested-text
else
zle .kill-whole-line
fi
}
# When autosuggesting, ignore RBUFFER which corresponds to the 'unmaterialized'
# section when the user accepts the line
autosuggest-accept-line() {
RBUFFER=''
if ! (( $+functions[_zsh_highlight_buffer_modified] )); then
# Only clear the colors if the user doesn't have zsh-highlight installed
region_highlight=()
fi
zle .accept-line
}
autosuggest-paused-self-insert() {
if [[ $RBUFFER == '' ]]; then
# Resume autosuggestions when inserting at the end of the line
autosuggest-resume
zle self-insert
else
zle .self-insert
fi
}
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
zle .${WIDGET} "$@"
}
autosuggest-tab() {
RBUFFER=''
zle .${WIDGET} "$@"
autosuggest-invalidate-highlight-cache
autosuggest-highlight-suggested-text
}
autosuggest-accept-suggestion() {
if [[ AUTOSUGGESTION_ACCEPT_RIGHT_ARROW -eq 1 && ("$WIDGET" == 'forward-char' || "$WIDGET" == 'vi-forward-char') ]]; then
zle .end-of-line "$@"
else
zle .${WIDGET} "$@"
fi
if [[ -n $ZLE_AUTOSUGGESTING ]]; then
autosuggest-invalidate-highlight-cache
autosuggest-highlight-suggested-text
fi
}
autosuggest-execute-suggestion() {
if [[ -n $ZLE_AUTOSUGGESTING ]]; then
zle .end-of-line
autosuggest-invalidate-highlight-cache
autosuggest-highlight-suggested-text
fi
zle .accept-line
}
autosuggest-invalidate-highlight-cache() {
# invalidate the buffer for zsh-syntax-highlighting
_zsh_highlight_autosuggest_highlighter_cache=()
}
autosuggest-restore-widgets() {
for widget in $ZLE_AUTOSUGGEST_ALL_WIDGETS; do
[[ -z $widgets[$widget] ]] && continue
zle -A .${widget} ${widget}
done
}
autosuggest-hook-widgets() {
local widget
# Replace prediction widgets by versions that will also highlight RBUFFER
zle -A autosuggest-insert-or-space self-insert
zle -A autosuggest-insert-or-space magic-space
zle -A autosuggest-backward-delete-char backward-delete-char
zle -A autosuggest-accept-line accept-line
# Hook into some default widgets that should suspend autosuggestion
# automatically
for widget in $ZLE_AUTOSUGGEST_ACCEPT_WIDGETS; do
[[ -z $widgets[$widget] ]] && continue
eval "zle -A autosuggest-accept-suggestion $widget"
done
for widget in $ZLE_AUTOSUGGEST_SUSPEND_WIDGETS; do
[[ -z $widgets[$widget] ]] && continue
eval "zle -A autosuggest-suspend $widget"
done
for widget in $ZLE_AUTOSUGGEST_COMPLETION_WIDGETS; do
[[ -z $widgets[$widget] ]] && continue
eval "zle -A autosuggest-tab $widget"
done
}
zle -N autosuggest-toggle
zle -N autosuggest-start
zle -N autosuggest-accept-suggested-small-word
zle -N autosuggest-accept-suggested-word
zle -N autosuggest-execute-suggestion
zle -N autosuggest-paused-self-insert
zle -N autosuggest-insert-or-space
zle -N autosuggest-backward-delete-char
zle -N autosuggest-accept-line
zle -N autosuggest-tab
zle -N autosuggest-suspend
zle -N autosuggest-accept-suggestion
autosuggest-restore-widgets

View file

@ -1,40 +0,0 @@
#!/usr/bin/env zsh
zmodload zsh/net/socket
AUTOSUGGEST_SERVER_SCRIPT="${0:a:h}/completion-server.zsh"
autosuggest-ensure-server() {
setopt local_options no_hup
local server_dir="/tmp/zsh-autosuggest-$USER"
local pid_file="$server_dir/pid"
local socket_path="$server_dir/socket"
if [[ ! -d $server_dir || ! -r $pid_file ]] || ! kill -0 $(<$pid_file) &> /dev/null; then
if which setsid &> /dev/null; then
setsid zsh $AUTOSUGGEST_SERVER_SCRIPT $server_dir $pid_file $socket_path &!
else
zsh $AUTOSUGGEST_SERVER_SCRIPT $server_dir $pid_file $socket_path &!
fi
fi
autosuggest-server-connect
}
autosuggest-server-connect() {
unset ZLE_AUTOSUGGEST_CONNECTION
integer remaining_tries=10
while (( --remaining_tries )) && ! zsocket $socket_path &>/dev/null; do
sleep 0.3
done
[[ -z $REPLY ]] && return 1
ZLE_AUTOSUGGEST_CONNECTION=$REPLY
}
autosuggest-send-request() {
[[ -z $ZLE_AUTOSUGGEST_CONNECTION ]] && return 1
setopt local_options noglob
print -u $ZLE_AUTOSUGGEST_CONNECTION - $1 &> /dev/null || return 1
}

View file

@ -1,121 +0,0 @@
# Based on:
# https://github.com/Valodim/zsh-capture-completion/blob/master/.zshrc
ZLE_DISABLE_AUTOSUGGEST=1
# no prompt!
PROMPT=
# load completion system
autoload compinit
compinit
# never run a command
bindkey '\C-m' .kill-buffer
bindkey '\C-j' .kill-buffer
bindkey '\C-i' complete-word
# send an emtpy line before completions are output
empty-line() {
print
# handler needs to reinsert itself after being called
compprefuncs+=empty-line
}
compprefuncs+=empty-line
# send a line with null-byte after completions are output
null-line() {
print $'\0'
# handler needs to reinsert itself after being called
comppostfuncs+=null-line
}
comppostfuncs+=null-line
zstyle ':completion:*' completer _complete
# never group stuff!
zstyle ':completion:*' list-grouped false
# don't insert tab when attempting completion on empty line
zstyle ':completion:*' insert-tab false
# no list separator, this saves some stripping later on
zstyle ':completion:*' list-separator ''
# dont use matchers
zstyle -d ':completion:*' matcher-list
# dont format
zstyle -d ':completion:*' format
# no color formatting
zstyle -d ':completion:*' list-colors
# we use zparseopts
zmodload zsh/zutil
# override compadd (this our hook)
compadd() {
# check if any of -O, -A or -D are given
if [[ ${@[1,(i)(-|--)]} == *-(O|A|D)\ * ]]; then
# if that is the case, just delegate and leave
builtin compadd "$@"
return $?
fi
# be careful with namespacing here, we don't want to mess with stuff that
# should be passed to compadd!
typeset -a __hits __dscr __tmp
# do we have a description parameter?
# note we don't use zparseopts here because of combined option parameters
# with arguments like -default- confuse it.
if (( $@[(I)-d] )); then # kind of a hack, $+@[(r)-d] doesn't work because of line noise overload
# next param after -d
__tmp=${@[$[${@[(i)-d]}+1]]}
# description can be given as an array parameter name, or inline () array
if [[ $__tmp == \(* ]]; then
eval "__dscr=$__tmp"
else
__dscr=( "${(@P)__tmp}" )
fi
fi
# capture completions by injecting -A parameter into the compadd call.
# this takes care of matching for us.
builtin compadd -A __hits -D __dscr "$@"
# JESUS CHRIST IT TOOK ME FOREVER TO FIGURE OUT THIS OPTION WAS SET AND WAS MESSING WITH MY SHIT HERE
setopt localoptions norcexpandparam extendedglob
# extract prefixes and suffixes from compadd call. we can't do zsh's cool
# -r remove-func magic, but it's better than nothing.
typeset -A apre hpre hsuf asuf
zparseopts -E P:=apre p:=hpre S:=asuf s:=hsuf
# append / to directories? we are only emulating -f in a half-assed way
# here, but it's better than nothing.
integer dirsuf=0
# don't be fooled by -default- >.>
if [[ -z $hsuf && "${${@//-default-/}% -# *}" == *-[[:alnum:]]#f* ]]; then
dirsuf=1
fi
# just drop
[[ -n $__hits ]] || return
# this is the point where we have all matches in $__hits and all
# descriptions in $__dscr!
# display all matches
local dsuf dscr
for i in {1..$#__hits}; do
# add a dir suffix?
(( dirsuf )) && [[ -d $__hits[$i] ]] && dsuf=/ || dsuf=
# description to be displayed afterwards
# (( $#__dscr >= $i )) && dscr=" -- ${${__dscr[$i]}##$__hits[$i] #}" || dscr=
print - $'\1'$IPREFIX$apre$hpre$__hits[$i]$dsuf$hsuf$asuf$dscr
done
unset __hits __dscr __tmp
}
# signal the daemon we are ready for input
print $'\0'

View file

@ -1,128 +0,0 @@
#!/usr/bin/env zsh
# Based on:
# https://github.com/Valodim/zsh-capture-completion/blob/master/capture.zsh
# read everything until a line containing the byte 0 is found
read-to-null() {
while zpty -r z chunk; do
[[ $chunk == *$'\0'* ]] && break
[[ $chunk != $'\1'* ]] && continue # ignore what doesnt start with '1'
print -n - ${chunk:1}
done
}
accept-connection() {
zsocket -a $server
fds[$REPLY]=1
print "connection accepted, fd: $REPLY" >&2
}
handle-request() {
local connection=$1 current line
integer read_something=0
print "request received from fd $connection"
while read -u $connection prefix &> /dev/null; do
read_something=1
# send the prefix to be completed followed by a TAB to force
# completion
zpty -w -n z $prefix$'\t'
zpty -r z chunk &> /dev/null # read empty line before completions
current=''
# read completions one by one, storing the longest match
read-to-null | while IFS= read -r line; do
(( $#line > $#current )) && current=$line
done
# send the longest completion back to the client, strip the last
# non-printable character
if (( $#current )); then
print -u $connection - $prefix$'\2'${current:0:-1}
else
print -u $connection ''
fi
# clear input buffer
zpty -w z $'\n'
break # handle more requests/return to zselect
done
if ! (( read_something )); then
print "connection with fd $connection closed" >&2
unset fds[$connection]
exec {connection}>&- # free the file descriptor
fi
}
if [[ -n $ZLE_AUTOSUGGEST_SERVER_LOG ]]; then
exec >> "$HOME/.autosuggest-server.log"
else
exec > /dev/null
fi
if [[ -n $ZLE_AUTOSUGGEST_SERVER_LOG_ERRORS ]]; then
exec 2>> "$HOME/.autosuggest-server-errors.log"
else
exec 2> /dev/null
fi
exec < /dev/null
zmodload zsh/zpty
zmodload zsh/zselect
zmodload zsh/net/socket
setopt noglob
print "autosuggestion server started, pid: $$" >&2
# Start an interactive zsh connected to a zpty
zpty z ZLE_DISABLE_AUTOSUGGEST=1 zsh -i
print 'interactive shell started'
# Source the init script
zpty -w z "source '${0:a:h}/completion-server-init.zsh'"
# wait for ok from shell
read-to-null &> /dev/null
print 'interactive shell ready'
# listen on a socket for completion requests
server_dir=$1
pid_file=$2
socket_path=$3
cleanup() {
print 'removing socket and pid file...'
rm -f $socket_path $pid_file
print "autosuggestion server stopped, pid: $$"
exit
}
trap cleanup TERM INT HUP EXIT
mkdir -m 700 $server_dir
while ! zsocket -l $socket_path; do
if [[ ! -r $pid_file ]] || ! kill -0 $(<$pid_file); then
rm -f $socket_path
else
exit 1
fi
print "will retry listening on '$socket_path'"
done
server=$REPLY
print "server listening on '$socket_path'"
print $$ > $pid_file
typeset -A fds ready
fds[$server]=1
while zselect -A ready ${(k)fds}; do
queue=(${(k)ready})
for fd in $queue; do
if (( fd == server )); then
accept-connection
else
handle-request $fd
fi
done
done

44
install
View file

@ -1,44 +0,0 @@
#!/bin/bash
# Install script for zsh-autocomplete
config="$HOME/.zshrc"
for config in "$HOME/.zshrc" "$ZDOTDIR/.zshrc" "$1"; do
echo $config
#first checks if ~/.zshrc file exists and is readable
if [ -r "$config" ]; then
break
elif [ "$config" = "$1" ]; then
echo "\nError: Please specify as first argument the file in which to load zsh-autosuggestions (usually ~/.zshrc)!\n"
exit 1
fi
done
SOURCE="${BASH_SOURCE[0]}"
while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink
DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )"
SOURCE="$(readlink "$SOURCE")"
[[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located
done
DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )"
# appends the string to $config (usually ~/.zshrc) file
cat >> "$config" <<-EOF
# Setup zsh-autosuggestions
source $DIR/autosuggestions.zsh
# Enable autosuggestions automatically
zle-line-init() {
zle autosuggest-start
}
zle -N zle-line-init
# use ctrl+t to toggle autosuggestions(hopefully this wont be needed as
# zsh-autosuggestions is designed to be unobtrusive)
bindkey '^T' autosuggest-toggle
EOF
echo "\nSetup completed successfully!\n"
exit 0

37
lib/config.zsh Normal file
View file

@ -0,0 +1,37 @@
# Color to use when highlighting autosuggestion
# Uses format of `region_highlight`
# More info: http://zsh.sourceforge.net/Doc/Release/Zsh-Line-Editor.html#Zle-Widgets
ZSH_AUTOSUGGEST_HIGHLIGHT_COLOR='fg=8'
# Widgets that clear the autosuggestion
ZSH_AUTOSUGGEST_CLEAR_WIDGETS=(
history-search-forward
history-search-backward
history-beginning-search-forward
history-beginning-search-backward
history-substring-search-up
history-substring-search-down
accept-line
)
# Widgets that modify the autosuggestion
ZSH_AUTOSUGGEST_MODIFY_WIDGETS=(
complete-word
expand-or-complete
expand-or-complete-prefix
list-choices
menu-complete
reverse-menu-complete
menu-expand-or-complete
accept-and-menu-complete
self-insert
magic-space
backward-delete-char
bracketed-paste
)
# Widgets that accept the autosuggestion
ZSH_AUTOSUGGEST_ACCEPT_WIDGETS=(
vi-forward-char
forward-char
)

11
lib/get_suggestion.zsh Normal file
View file

@ -0,0 +1,11 @@
_zsh_autosuggest_get_suggestion() {
local prefix=$1
local history_items=(${history[(R)$prefix*]})
for cmd in $history_items; do
if [ "${cmd:0:$#prefix}" = "$prefix" ]; then
echo $cmd
break
fi
done
}

35
lib/highlight.zsh Normal file
View file

@ -0,0 +1,35 @@
_zsh_autosuggest_region_highlight() {
echo "$#BUFFER $(($#BUFFER + $#POSTDISPLAY)) $ZSH_AUTOSUGGEST_HIGHLIGHT_COLOR"
}
_zsh_autosuggest_highlight() {
if _zsh_autosuggest_syntax_highlighting_enabled; then
_zsh_highlight
else
region_highlight=("$(_zsh_autosuggest_region_highlight)")
fi
}
#-------------------------------------------------------------------------------
# Support for zsh-syntax-highlighter
#
# https://github.com/zsh-users/zsh-syntax-highlighting/blob/master/docs/highlighters.md
#-------------------------------------------------------------------------------
_zsh_autosuggest_syntax_highlighting_enabled() {
[ -n "$functions[_zsh_highlight]" ]
}
_zsh_autosuggest_register_highlighter() {
# Remove it from the list (if it exists) and re-add it
ZSH_HIGHLIGHT_HIGHLIGHTERS=("${(@)ZSH_HIGHLIGHT_HIGHLIGHTERS:#autosuggestion}")
ZSH_HIGHLIGHT_HIGHLIGHTERS+=(autosuggestion)
}
_zsh_highlight_autosuggestion_highlighter_predicate() {
[ "$_ZSH_AUTOSUGGESTION_ACTIVE" = true ]
}
_zsh_highlight_autosuggestion_highlighter() {
region_highlight+=("$(_zsh_autosuggest_region_highlight)")
}

53
lib/widget/hook.zsh Normal file
View file

@ -0,0 +1,53 @@
_zsh_autosuggest_is_defined_widget() {
[ -n "$widgets[$1]" ]
}
_zsh_autosuggest_is_built_in_widget() {
[ -n "$widgets[.$1]" ]
}
_zsh_autosuggest_is_original_widget_defined() {
_zsh_autosuggest_is_defined_widget $(_zsh_autosuggest_original_widget $1)
}
_zsh_autosuggest_original_widget() {
if _zsh_autosuggest_is_built_in_widget $1; then
echo ".$1"
else
echo "_autosuggest_original_$1"
fi
}
_zsh_autosuggest_hook_widget() {
local autosuggest_widget=$1
local widget=$2
# Skip if the widget does not exist
if ! _zsh_autosuggest_is_defined_widget $widget; then
continue
fi
# Alias if dot-prefixed alias is unavailable and we haven't already aliased it
if ! _zsh_autosuggest_is_original_widget_defined $widget; then
zle -A $widget $(_zsh_autosuggest_original_widget $widget)
fi
# Hook it
zle -A $autosuggest_widget $widget
}
_zsh_autosuggest_hook_widgets() {
local widget
for widget in $ZSH_AUTOSUGGEST_MODIFY_WIDGETS; do
_zsh_autosuggest_hook_widget _zsh_autosuggest_widget_modify $widget
done
for widget in $ZSH_AUTOSUGGEST_CLEAR_WIDGETS; do
_zsh_autosuggest_hook_widget _zsh_autosuggest_widget_clear $widget
done
for widget in $ZSH_AUTOSUGGEST_ACCEPT_WIDGETS; do
_zsh_autosuggest_hook_widget _zsh_autosuggest_widget_accept $widget
done
}

42
lib/widget/widgets.zsh Normal file
View file

@ -0,0 +1,42 @@
# Buffer was modified, update suggestion
_zsh_autosuggest_widget_modify() {
local suggestion
zle $(_zsh_autosuggest_original_widget $WIDGET) $@
if [ $#BUFFER -gt 0 ]; then
suggestion=$(_zsh_autosuggest_get_suggestion $BUFFER)
fi
if [ -n "$suggestion" ]; then
POSTDISPLAY=${suggestion#$BUFFER}
else
unset POSTDISPLAY
fi
_zsh_autosuggest_highlight
}
# Clear command triggered, hide the suggestion
_zsh_autosuggest_widget_clear() {
unset POSTDISPLAY
_zsh_autosuggest_highlight
zle $(_zsh_autosuggest_original_widget $WIDGET) $@
}
# Suggestion accepted, add it to the buffer
_zsh_autosuggest_widget_accept() {
if [ $CURSOR -eq $#BUFFER ]; then
BUFFER="$BUFFER$POSTDISPLAY"
unset POSTDISPLAY
CURSOR=${#BUFFER}
_zsh_autosuggest_highlight
else
zle $(_zsh_autosuggest_original_widget $WIDGET) $@
fi
}
# Create the widgets
zle -N _zsh_autosuggest_widget_modify
zle -N _zsh_autosuggest_widget_clear
zle -N _zsh_autosuggest_widget_accept

View file

@ -1 +0,0 @@
autosuggestions.zsh