diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 1a22f88..0000000 --- a/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -/node_modules/ -/build/ -*.log -*~ diff --git a/LICENSE b/LICENSE index ae7014d..0818167 100644 --- a/LICENSE +++ b/LICENSE @@ -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 obtaining a copy of this software and associated documentation diff --git a/README.md b/README.md index 4afb200..82264bd 100644 --- a/README.md +++ b/README.md @@ -7,45 +7,30 @@ It suggests commands as you type, based on command history. ## 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. -ZSH assumes this file in your home directory (i.e. `~/.zshrc`), but the location can be changed using `ZDOTDIR` variable. +1. Load `tarruda/zsh-autosuggestions` using antigen in your `~/.zshrc` file, for example: -### Using zgen - -[Zgen](https://github.com/tarjoilija/zgen) is a simple and fast plugin manager for ZSH. -If you don’t 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 + ``` + # Load the script + antigen bundle tarruda/zsh-autosuggestions autosuggestions.zsh ``` -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 autosuggest-start + autosuggest_start } + 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): @@ -53,90 +38,46 @@ If you don’t use zgen, then use instructions for the manual installation. 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 - git clone git://github.com/zsh-users/zsh-syntax-highlighting ~/.zsh/zsh-syntax-highlighting - ``` - -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. + # Load the script source ~/.zsh/zsh-autosuggestions/autosuggestions.zsh - # Enable autosuggestions automatically. + # Enable autosuggestions zle-line-init() { - zle autosuggest-start + autosuggest_start } + zle -N zle-line-init ``` -4. Reopen your terminal. - - -## Uninstallation - -Just remove the config lines from .zshrc that you’ve added during “installation.” -If you don’t use zgen, then also delete `~/.zsh/zsh-autosuggestions` and `~/.zsh/zsh-syntax-highlighting`. +3. Start a new terminal session or `source ~/.zshrc` ## 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)). -To accept the autosuggestion (replacing the command line contents), hit End, Alt+F, Ctrl+F, or any other key that moves the cursor to the right. -If the autosuggestion is not what you want, just ignore it: it won’t execute unless you accept it. +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). -Any widget that moves the cursor to the right (forward-word, forward-char, end-of-line…) will accept parts of the suggested text. -For example, vi-mode users can do this: +To accept the autosuggestion (replacing the command line contents), position your cursor at the end of the buffer and use the right arrow key. -```sh -# 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 Ctrl+T 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. +If the autosuggestion is not what you want, go ahead and edit it. It won't execute unless you accept it. ## 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'`. -- `AUTOSUGGESTION_HIGHLIGHT_CURSOR` – highlight word after cursor, or not. Must be integer value `1` or `0`, default is `1`. -- `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_HIGHLIGHT_COLOR`: Color to use when highlighting the autosuggestion +- `ZSH_AUTOSUGGEST_CLEAR_WIDGETS`: List of widgets that clear the autosuggestion +- `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 Tab and autosuggestions is enabled, it deletes the previous line, and scrolls up the terminal. - -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). +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. ## License diff --git a/autosuggestions.plugin.zsh b/autosuggestions.plugin.zsh deleted file mode 120000 index 65220e1..0000000 --- a/autosuggestions.plugin.zsh +++ /dev/null @@ -1 +0,0 @@ -autosuggestions.zsh \ No newline at end of file diff --git a/autosuggestions.zsh b/autosuggestions.zsh index 7a9112f..275dca7 100644 --- a/autosuggestions.zsh +++ b/autosuggestions.zsh @@ -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 # zle-line-init() { -# autosuggest-enable +# autosuggest_start # } # zle -N zle-line-init # ``` -zmodload zsh/net/socket -source "${0:a:h}/completion-client.zsh" +unset _ZSH_AUTOSUGGESTION_ACTIVE -# configuration variables -AUTOSUGGESTION_HIGHLIGHT_COLOR='fg=8' -AUTOSUGGESTION_HIGHLIGHT_CURSOR=1 +LIBDIR="${0:a:h}/lib" -function { - if [[ -n $ZLE_DISABLE_AUTOSUGGEST ]]; then - ZSH_HIGHLIGHT_HIGHLIGHTERS=() - return - fi - autoload -U is-at-least +source "$LIBDIR/config.zsh" +source "$LIBDIR/get_suggestion.zsh" +source "$LIBDIR/highlight.zsh" +source "$LIBDIR/widget/widgets.zsh" +source "$LIBDIR/widget/hook.zsh" - # if is-at-least 5.0.3; then - # autosuggest-ensure-server - # fi -} +autosuggest_start() { + _ZSH_AUTOSUGGESTION_ACTIVE=true -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 + # Register highlighter if needed to support zsh-syntax-highlighting plugin + if _zsh_autosuggest_syntax_highlighting_enabled; then + _zsh_autosuggest_register_highlighter 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 + _zsh_autosuggest_hook_widgets } - -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 diff --git a/completion-client.zsh b/completion-client.zsh deleted file mode 100755 index c8cd957..0000000 --- a/completion-client.zsh +++ /dev/null @@ -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 -} diff --git a/completion-server-init.zsh b/completion-server-init.zsh deleted file mode 100644 index 5e98dcf..0000000 --- a/completion-server-init.zsh +++ /dev/null @@ -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' diff --git a/completion-server.zsh b/completion-server.zsh deleted file mode 100755 index e8e2946..0000000 --- a/completion-server.zsh +++ /dev/null @@ -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 diff --git a/install b/install deleted file mode 100755 index 9169519..0000000 --- a/install +++ /dev/null @@ -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 diff --git a/lib/config.zsh b/lib/config.zsh new file mode 100644 index 0000000..9eff46f --- /dev/null +++ b/lib/config.zsh @@ -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 +) diff --git a/lib/get_suggestion.zsh b/lib/get_suggestion.zsh new file mode 100644 index 0000000..8357ff5 --- /dev/null +++ b/lib/get_suggestion.zsh @@ -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 +} diff --git a/lib/highlight.zsh b/lib/highlight.zsh new file mode 100644 index 0000000..3f64d18 --- /dev/null +++ b/lib/highlight.zsh @@ -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)") +} diff --git a/lib/widget/hook.zsh b/lib/widget/hook.zsh new file mode 100644 index 0000000..5de9d86 --- /dev/null +++ b/lib/widget/hook.zsh @@ -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 +} diff --git a/lib/widget/widgets.zsh b/lib/widget/widgets.zsh new file mode 100644 index 0000000..7a3dd36 --- /dev/null +++ b/lib/widget/widgets.zsh @@ -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 diff --git a/zsh-autosuggestions.plugin.zsh b/zsh-autosuggestions.plugin.zsh deleted file mode 120000 index 65220e1..0000000 --- a/zsh-autosuggestions.plugin.zsh +++ /dev/null @@ -1 +0,0 @@ -autosuggestions.zsh \ No newline at end of file