Compare commits

...

29 Commits

Author SHA1 Message Date
Eric Freese
d7c796719e Merge pull request #332 from zsh-users/develop
v0.4.3
2018-05-21 11:40:10 -06:00
Eric Freese
aa0b10db44 v0.4.3 2018-05-21 11:38:41 -06:00
Eric Freese
72ccee33b4 Pull out separate doc for installation instructions 2018-05-21 11:35:26 -06:00
Eric Freese
c113e49fe2 Update license copyright year 2018-05-21 10:52:41 -06:00
Eric Freese
3b39b9561c Merge branch 'master' into develop 2018-05-21 10:47:20 -06:00
Eric Freese
b003b2238a Update changelog for v0.4.3 release 2018-05-21 10:46:03 -06:00
Eric Freese
df5fb858aa Destroy old pty even if it's no longer running (#249)
For unknown reasons, the pty will occasionally quit running. In these
cases, we still want to remove it so that a fresh one can be created. We
don't actually need this check because error messages from `zle` and
`zpty` are redirected to /dev/null.

One sure way to kill all currently running pty's is to run `exit` in a
subshell. Even without zsh-autosuggestions loaded, the following works:

    % zmodload zsh/zpty
    % zpty -b foo cat
    % zpty -b bar cat
    % zpty
    (31689) bar: cat
    (31666) foo: cat
    % $(exit)
    % zpty
    (finished) bar: cat
    (finished) foo: cat
2018-05-15 13:55:37 -06:00
Eric Freese
726bc4eb5c Create general spec for async behavior 2018-05-15 13:42:18 -06:00
Harm te Hennepe
59c72c6805 Don't break kill ring rotation 2018-05-15 12:54:09 -06:00
Eric Freese
393f7b8bb9 Fix vi-mode partial-accept
Issue #188. PR #324.

Thanks to @toadjaune and @IngoHeimbach.
2018-05-15 11:44:42 -06:00
Eric Freese
42f5a06f7f Need to reset the POSTDISPLAY if exiting early
Specific case where this matters is following:

Be in vi insert mode with some text in the buffer and the cursor at the
end of the buffer. Press `esc` to trigger `vi-cmd-mode widget`, then
before the cursor moves (KEYTIMEOUT), press `h` to trigger
`vi-backward-char` widget. When `vi-cmd-mode` original widget exits,
KEYS_QUEUED_COUNT will be non-zero and the suggestion will be lost.
2018-05-15 11:44:42 -06:00
Eric Freese
51fef255da Add method to connect terminal to tmux session during tests
Useful with `binding.pry` to inspect behavior of tests.
2018-05-15 11:44:18 -06:00
Eric Freese
19ad3ba7cd Add new 5.5.1 version of zsh to CI 2018-05-15 11:44:18 -06:00
Benjamin Denhartog
b2b9bf3b8c update arch linux installation instructions (now available via pacman)
closes #328
2018-05-14 10:43:45 -06:00
Eric Freese
67a364bc17 Merge pull request #321 from babaorum/fix/documentation/oh-my-zsh-install
make Oh my zsh install works without ZSH_CUSTOM defined
2018-04-17 15:00:46 -06:00
babaorum
afc14f79cc make Oh my zsh install works without ZSH_CUSTOM defined 2018-04-16 22:37:54 +02:00
Eric Freese
60aff2d944 Remove unused local $suggestion variable 2018-03-27 14:51:37 -06:00
Eric Freese
6dfe9c8cd8 Merge pull request #319 from zsh-users/fixes/async_history
Don't fetch suggestions after [up,down]-line-or-beginning-search
2018-03-23 16:15:56 -06:00
Eric Freese
3136700ccf Don't fetch suggestions after [up,down]-line-or-beginning-search
These widgets rely on `$LASTWIDGET` being set to restore the cursor
position. When asynchronous suggestions are enabled, and the widget
triggers a suggestion to be fetched, `autosuggest-suggest` will be
called and $LASTWIDGET will be set to it.
2018-03-23 16:08:11 -06:00
Eric Freese
2202ed7bac Merge pull request #304 from okdana/dana/no-beep
Avoid ringing bell when accepting suggestions
2018-01-16 14:11:06 -07:00
dana
c978004c0e ..._invoke_original_widget: Return 0 when given no arguments
`_zsh_autosuggest_widget_accept()` (&al.) passes this function's return status
on, and ZLE rings the bell if it's >0. Not having an original widget isn't an
error condition, so always returning 0 here should be OK to avoid the bell

Fixes #228
2018-01-16 14:10:29 -06:00
Eric Freese
c7d4a85031 Merge pull request #299 from zsh-users/develop
v0.4.2
2017-12-06 08:31:52 -07:00
Eric Freese
15931f04ff v0.4.2 2017-12-06 08:30:12 -07:00
Eric Freese
9f1046727a Merge pull request #298 from zsh-users/fixes/support_older_versions
Fixes/support older versions
2017-12-06 08:27:18 -07:00
Eric Freese
f462410b3c Add zsh version requirements to readme 2017-12-06 08:21:27 -07:00
Eric Freese
4ea825faf8 Fix #247 and #248 without using (b) flag
To support older versions of zsh (< 5.0.8).

We were missing the EXTENDED_GLOB option that allows use of `(#m)` flag.
2017-12-06 08:09:14 -07:00
Eric Freese
a1babef972 Revert "Simplify escaping of pattern and fix match_prev_cmd strategy"
This reverts commit 7f8ff2867c.
2017-12-06 08:08:53 -07:00
Eric Freese
be8bba6f38 Run CI on prominent versions of zsh back to 4.3.11
RHEL6 bundles v4.3.11
Ubuntu 14.04 and Amazon Linux bundle v5.0.2
2017-12-06 07:45:45 -07:00
Eric Freese
dda220f140 Merge pull request #295 from zsh-users/develop
v0.4.1
2017-11-28 10:14:41 -07:00
19 changed files with 336 additions and 108 deletions

View File

@@ -1,5 +1,18 @@
# Changelog # Changelog
## v0.4.3
- Avoid bell when accepting suggestions with `autosuggest-accept` (#228)
- Don't fetch suggestions after [up,down]-line-or-beginning-search (#227, #241)
- We are now running CI against new 5.5.1 version
- Fix partial-accept in vi mode (#188)
- Fix suggestion disappearing on fast movement after switching to `vicmd` mode (#290)
- Fix issue rotating through kill ring with `yank-pop` (#301)
- Fix issue creating new pty for async mode when previous pty is not properly cleaned up (#249)
## v0.4.2
- Fix bug in zsh versions older than 5.0.8 (#296)
- Officially support back to zsh v4.3.11
## v0.4.1 ## v0.4.1
- Switch to [[ and (( conditionals instead of [ (#257) - Switch to [[ and (( conditionals instead of [ (#257)
- Avoid warnnestedvar warnings with `typeset -g` (#275) - Avoid warnnestedvar warnings with `typeset -g` (#275)

67
INSTALL.md Normal file
View File

@@ -0,0 +1,67 @@
## Installation
### Manual (Git Clone)
1. Clone this repository somewhere on your machine. This guide will assume `~/.zsh/zsh-autosuggestions`.
```sh
git clone https://github.com/zsh-users/zsh-autosuggestions ~/.zsh/zsh-autosuggestions
```
2. Add the following to your `.zshrc`:
```sh
source ~/.zsh/zsh-autosuggestions/zsh-autosuggestions.zsh
```
3. Start a new terminal session.
### Oh My Zsh
1. Clone this repository into `$ZSH_CUSTOM/plugins` (by default `~/.oh-my-zsh/custom/plugins`)
```sh
git clone https://github.com/zsh-users/zsh-autosuggestions ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-autosuggestions
```
2. Add the plugin to the list of plugins for Oh My Zsh to load:
```sh
plugins=(zsh-autosuggestions)
```
3. Start a new terminal session.
### Arch Linux
1. Install [`zsh-autosuggestions`](https://www.archlinux.org/packages/community/any/zsh-autosuggestions/) from the `community` repository.
```sh
pacman -S zsh-autosuggestions
```
or, to use a package based on the `master` branch, install [`zsh-autosuggestions-git`](https://aur.archlinux.org/packages/zsh-autosuggestions-git/) from the [AUR](https://wiki.archlinux.org/index.php/Arch_User_Repository).
2. Add the following to your `.zshrc`:
```sh
source /usr/share/zsh/plugins/zsh-autosuggestions/zsh-autosuggestions.zsh
```
3. Start a new terminal session.
### macOS via Homebrew
1. Install the `zsh-autosuggestions` package using [Homebrew](https://brew.sh/).
```sh
brew install zsh-autosuggestions
```
2. Add the following to your `.zshrc`:
```sh
source /usr/local/share/zsh-autosuggestions/zsh-autosuggestions.zsh
```
3. Start a new terminal session.

View File

@@ -1,5 +1,5 @@
Copyright (c) 2013 Thiago de Arruda Copyright (c) 2013 Thiago de Arruda
Copyright (c) 2016-2017 Eric Freese Copyright (c) 2016-2018 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

View File

@@ -3,6 +3,7 @@ SRC_DIR := ./src
SRC_FILES := \ SRC_FILES := \
$(SRC_DIR)/setup.zsh \ $(SRC_DIR)/setup.zsh \
$(SRC_DIR)/config.zsh \ $(SRC_DIR)/config.zsh \
$(SRC_DIR)/util.zsh \
$(SRC_DIR)/features.zsh \ $(SRC_DIR)/features.zsh \
$(SRC_DIR)/bind.zsh \ $(SRC_DIR)/bind.zsh \
$(SRC_DIR)/highlight.zsh \ $(SRC_DIR)/highlight.zsh \

View File

@@ -4,6 +4,8 @@ _[Fish](http://fishshell.com/)-like fast/unobtrusive autosuggestions for zsh._
It suggests commands as you type, based on command history. It suggests commands as you type, based on command history.
Requirements: Zsh v4.3.11 or later
[![CircleCI](https://circleci.com/gh/zsh-users/zsh-autosuggestions.svg?style=svg)](https://circleci.com/gh/zsh-users/zsh-autosuggestions) [![CircleCI](https://circleci.com/gh/zsh-users/zsh-autosuggestions.svg?style=svg)](https://circleci.com/gh/zsh-users/zsh-autosuggestions)
<a href="https://asciinema.org/a/37390" target="_blank"><img src="https://asciinema.org/a/37390.png" width="400" /></a> <a href="https://asciinema.org/a/37390" target="_blank"><img src="https://asciinema.org/a/37390.png" width="400" /></a>
@@ -11,72 +13,8 @@ It suggests commands as you type, based on command history.
## Installation ## Installation
### Manual See [INSTALL.md](INSTALL.md).
1. Clone this repository somewhere on your machine. This guide will assume `~/.zsh/zsh-autosuggestions`.
```sh
git clone https://github.com/zsh-users/zsh-autosuggestions ~/.zsh/zsh-autosuggestions
```
2. Add the following to your `.zshrc`:
```sh
source ~/.zsh/zsh-autosuggestions/zsh-autosuggestions.zsh
```
3. Start a new terminal session.
### Oh My Zsh
1. Clone this repository into `$ZSH_CUSTOM/plugins` (by default `~/.oh-my-zsh/custom/plugins`)
```sh
git clone https://github.com/zsh-users/zsh-autosuggestions $ZSH_CUSTOM/plugins/zsh-autosuggestions
```
2. Add the plugin to the list of plugins for Oh My Zsh to load:
```sh
plugins=(zsh-autosuggestions)
```
3. Start a new terminal session.
### Arch Linux via the AUR
1. Install the [`zsh-autosuggestions`](https://aur.archlinux.org/packages/zsh-autosuggestions/) or the [`zsh-autosuggestions-git`](https://aur.archlinux.org/packages/zsh-autosuggestions-git/) packages from the [AUR](https://wiki.archlinux.org/index.php/Arch_User_Repository).
```sh
pacaur -S zsh-autosuggestions
```
or
```
pacaur -S zsh-autosuggestions-git
```
2. Add the following to your `.zshrc`:
```sh
source /usr/share/zsh/plugins/zsh-autosuggestions/zsh-autosuggestions.zsh
```
3. Start a new terminal session.
### macOS via Homebrew
1. Install the `zsh-autosuggestions` package using [Homebrew](https://brew.sh/).
```sh
brew install zsh-autosuggestions
```
2. Add the following to your `.zshrc`:
```sh
source /usr/local/share/zsh-autosuggestions/zsh-autosuggestions.zsh
```
3. Start a new terminal session.
## Usage ## Usage

View File

@@ -1 +1 @@
v0.4.1 v0.4.3

View File

@@ -1,12 +1,12 @@
machine: machine:
environment: environment:
ZSH_VERSIONS: 5.0.8 5.1.1 5.2 5.3.1 ZSH_VERSIONS: zsh-dev/4.3.11 zsh/5.0.2 zsh/5.0.8 zsh/5.1.1 zsh/5.2 zsh/5.3.1 zsh/5.4.2 zsh/5.5.1
dependencies: dependencies:
pre: pre:
- for v in $(echo $ZSH_VERSIONS | awk "{ for (i=$((1+CIRCLE_NODE_INDEX));i<=NF;i+=$CIRCLE_NODE_TOTAL) print \$i }"); do wget https://sourceforge.net/projects/zsh/files/zsh/$v/zsh-$v.tar.gz && tar xzf zsh-$v.tar.gz && cd zsh-$v && ./configure && sudo make install || exit 1; done - for v in $(echo $ZSH_VERSIONS | awk "{ for (i=$((1+CIRCLE_NODE_INDEX));i<=NF;i+=$CIRCLE_NODE_TOTAL) print \$i }"); do wget https://sourceforge.net/projects/zsh/files/$v/zsh-${v#*/}.tar.gz && tar xzf zsh-${v#*/}.tar.gz && pushd zsh-${v#*/} && ./configure && sudo make install && popd || exit 1; done
test: test:
override: override:
- for v in $(echo $ZSH_VERSIONS | awk "{ for (i=$((1+CIRCLE_NODE_INDEX));i<=NF;i+=$CIRCLE_NODE_TOTAL) print \$i }"); do TEST_ZSH_BIN=/usr/local/bin/zsh-$v make test || exit 1; done: - for v in $(echo $ZSH_VERSIONS | awk "{ for (i=$((1+CIRCLE_NODE_INDEX));i<=NF;i+=$CIRCLE_NODE_TOTAL) print \$i }"); do TEST_ZSH_BIN=/usr/local/bin/zsh-${v#*/} make test || exit 1; done:
parallel: true parallel: true

41
spec/async_spec.rb Normal file
View File

@@ -0,0 +1,41 @@
context 'with asynchronous suggestions enabled' do
let(:options) { ["ZSH_AUTOSUGGEST_USE_ASYNC="] }
describe '`up-line-or-beginning-search`' do
let(:before_sourcing) do
-> do
session.
run_command('autoload -U up-line-or-beginning-search').
run_command('zle -N up-line-or-beginning-search').
send_string('bindkey "').
send_keys('C-v').send_keys('up').
send_string('" up-line-or-beginning-search').
send_keys('enter')
end
end
it 'should show previous history entries' do
with_history(
'echo foo',
'echo bar',
'echo baz'
) do
session.clear_screen
3.times { session.send_keys('up') }
wait_for { session.content }.to eq("echo foo")
end
end
end
describe 'exiting a subshell' do
it 'should not cause error messages to be printed' do
session.run_command('$(exit)')
sleep 1
expect(session.content).to eq('$(exit)')
end
end
end

View File

@@ -0,0 +1,67 @@
describe 'when using vi mode' do
let(:before_sourcing) do
-> do
session.run_command('bindkey -v')
end
end
describe 'moving the cursor after exiting insert mode' do
it 'should not clear the current suggestion' do
with_history('foobar foo') do
session.
send_string('foo').
send_keys('escape').
send_keys('h')
wait_for { session.content }.to eq('foobar foo')
end
end
end
describe '`vi-forward-word-end`' do
it 'should accept through the end of the current word' do
with_history('foobar foo') do
session.
send_string('foo').
send_keys('escape').
send_keys('e'). # vi-forward-word-end
send_keys('a'). # vi-add-next
send_string('baz')
wait_for { session.content }.to eq('foobarbaz')
end
end
end
describe '`vi-forward-word`' do
it 'should accept through the first character of the next word' do
with_history('foobar foo') do
session.
send_string('foo').
send_keys('escape').
send_keys('w'). # vi-forward-word
send_keys('a'). # vi-add-next
send_string('az')
wait_for { session.content }.to eq('foobar faz')
end
end
end
describe '`vi-find-next-char`' do
it 'should accept through the next occurrence of the character' do
with_history('foobar foo') do
session.
send_string('foo').
send_keys('escape').
send_keys('f'). # vi-find-next-char
send_keys('o').
send_keys('a'). # vi-add-next
send_string('b')
wait_for { session.content }.to eq('foobar fob')
end
end
end
end

23
spec/kill_ring_spec.rb Normal file
View File

@@ -0,0 +1,23 @@
context 'with some items in the kill ring' do
before do
session.
send_string('echo foo').
send_keys('C-u').
send_string('echo bar').
send_keys('C-u')
end
describe '`yank-pop`' do
it 'should cycle through all items in the kill ring' do
session.send_keys('C-y')
wait_for { session.content }.to eq('echo bar')
session.send_keys('escape').send_keys('y')
wait_for { session.content }.to eq('echo foo')
session.send_keys('escape').send_keys('y')
wait_for { session.content }.to eq('echo bar')
end
end
end

View File

@@ -77,6 +77,10 @@ class TerminalSession
map(&:to_i) map(&:to_i)
end end
def attach!
tmux_command('attach-session')
end
private private
attr_reader :opts attr_reader :opts

View File

@@ -23,7 +23,6 @@ _zsh_autosuggest_async_server() {
# Silence any error messages # Silence any error messages
exec 2>/dev/null exec 2>/dev/null
local strategy=$1
local last_pid local last_pid
while IFS='' read -r -d $'\0' query; do while IFS='' read -r -d $'\0' query; do
@@ -70,7 +69,7 @@ _zsh_autosuggest_async_pty_create() {
fi fi
# Fork a zpty process running the server function # Fork a zpty process running the server function
zpty -b $ZSH_AUTOSUGGEST_ASYNC_PTY_NAME "_zsh_autosuggest_async_server _zsh_autosuggest_strategy_$ZSH_AUTOSUGGEST_STRATEGY" zpty -b $ZSH_AUTOSUGGEST_ASYNC_PTY_NAME _zsh_autosuggest_async_server
# Store the fd so we can remove the handler later # Store the fd so we can remove the handler later
if (( REPLY )); then if (( REPLY )); then
@@ -84,13 +83,11 @@ _zsh_autosuggest_async_pty_create() {
} }
_zsh_autosuggest_async_pty_destroy() { _zsh_autosuggest_async_pty_destroy() {
if zpty -t $ZSH_AUTOSUGGEST_ASYNC_PTY_NAME &>/dev/null; then # Remove the input handler
# Remove the input handler zle -F $_ZSH_AUTOSUGGEST_PTY_FD &>/dev/null
zle -F $_ZSH_AUTOSUGGEST_PTY_FD &>/dev/null
# Destroy the zpty # Destroy the zpty
zpty -d $ZSH_AUTOSUGGEST_ASYNC_PTY_NAME &>/dev/null zpty -d $ZSH_AUTOSUGGEST_ASYNC_PTY_NAME &>/dev/null
fi
} }
_zsh_autosuggest_async_pty_recreate() { _zsh_autosuggest_async_pty_recreate() {

View File

@@ -106,7 +106,7 @@ _zsh_autosuggest_bind_widgets() {
# Given the name of an original widget and args, invoke it, if it exists # Given the name of an original widget and args, invoke it, if it exists
_zsh_autosuggest_invoke_original_widget() { _zsh_autosuggest_invoke_original_widget() {
# Do nothing unless called with at least one arg # Do nothing unless called with at least one arg
(( $# )) || return (( $# )) || return 0
local original_widget_name="$1" local original_widget_name="$1"

View File

@@ -21,6 +21,8 @@ ZSH_AUTOSUGGEST_CLEAR_WIDGETS=(
history-beginning-search-backward history-beginning-search-backward
history-substring-search-up history-substring-search-up
history-substring-search-down history-substring-search-down
up-line-or-beginning-search
down-line-or-beginning-search
up-line-or-history up-line-or-history
down-line-or-history down-line-or-history
accept-line accept-line
@@ -47,6 +49,8 @@ ZSH_AUTOSUGGEST_PARTIAL_ACCEPT_WIDGETS=(
vi-forward-word-end vi-forward-word-end
vi-forward-blank-word vi-forward-blank-word
vi-forward-blank-word-end vi-forward-blank-word-end
vi-find-next-char
vi-find-next-char-skip
) )
# Widgets that should be ignored (globbing supported but must be escaped) # Widgets that should be ignored (globbing supported but must be escaped)
@@ -57,6 +61,7 @@ ZSH_AUTOSUGGEST_IGNORE_WIDGETS=(
set-local-history set-local-history
which-command which-command
yank yank
yank-pop
) )
# Max size of buffer to trigger autosuggestion. Leave undefined for no upper bound. # Max size of buffer to trigger autosuggestion. Leave undefined for no upper bound.

View File

@@ -7,9 +7,19 @@
# #
_zsh_autosuggest_strategy_default() { _zsh_autosuggest_strategy_default() {
local prefix="$1" # Reset options to defaults and enable LOCAL_OPTIONS
emulate -L zsh
# Enable globbing flags so that we can use (#m)
setopt EXTENDED_GLOB
# Escape backslashes and all of the glob operators so we can use
# this string as a pattern to search the $history associative array.
# - (#m) globbing flag enables setting references for match data
# TODO: Use (b) flag when we can drop support for zsh older than v5.0.8
local prefix="${1//(#m)[\\*?[\]<>()|^~#]/\\$MATCH}"
# Get the history items that match # Get the history items that match
# - (r) subscript flag makes the pattern match on values # - (r) subscript flag makes the pattern match on values
typeset -g suggestion="${history[(r)${(b)prefix}*]}" typeset -g suggestion="${history[(r)${prefix}*]}"
} }

View File

@@ -21,18 +21,25 @@
# `HIST_EXPIRE_DUPS_FIRST`. # `HIST_EXPIRE_DUPS_FIRST`.
_zsh_autosuggest_strategy_match_prev_cmd() { _zsh_autosuggest_strategy_match_prev_cmd() {
local prefix="$1" # Reset options to defaults and enable LOCAL_OPTIONS
emulate -L zsh
# Enable globbing flags so that we can use (#m)
setopt EXTENDED_GLOB
# TODO: Use (b) flag when we can drop support for zsh older than v5.0.8
local prefix="${1//(#m)[\\*?[\]<>()|^~#]/\\$MATCH}"
# Get all history event numbers that correspond to history # Get all history event numbers that correspond to history
# entries that match pattern $prefix* # entries that match pattern $prefix*
local history_match_keys local history_match_keys
history_match_keys=(${(k)history[(R)${(b)prefix}*]}) history_match_keys=(${(k)history[(R)$prefix*]})
# By default we use the first history number (most recent history entry) # By default we use the first history number (most recent history entry)
local histkey="${history_match_keys[1]}" local histkey="${history_match_keys[1]}"
# Get the previously executed command # Get the previously executed command
local prev_cmd="${history[$((HISTCMD-1))]}" local prev_cmd="$(_zsh_autosuggest_escape_command "${history[$((HISTCMD-1))]}")"
# Iterate up to the first 200 history event numbers that match $prefix # Iterate up to the first 200 history event numbers that match $prefix
for key in "${(@)history_match_keys[1,200]}"; do for key in "${(@)history_match_keys[1,200]}"; do

11
src/util.zsh Normal file
View File

@@ -0,0 +1,11 @@
#--------------------------------------------------------------------#
# Utility Functions #
#--------------------------------------------------------------------#
_zsh_autosuggest_escape_command() {
setopt localoptions EXTENDED_GLOB
# Escape special chars in the string (requires EXTENDED_GLOB)
echo -E "${1//(#m)[\"\'\\()\[\]|*?~]/\\$MATCH}"
}

View File

@@ -55,6 +55,7 @@ _zsh_autosuggest_modify() {
# Don't fetch a new suggestion if there's more input to be read immediately # Don't fetch a new suggestion if there's more input to be read immediately
if (( $PENDING > 0 )) || (( $KEYS_QUEUED_COUNT > 0 )); then if (( $PENDING > 0 )) || (( $KEYS_QUEUED_COUNT > 0 )); then
POSTDISPLAY="$orig_postdisplay"
return $retval return $retval
fi fi
@@ -152,7 +153,7 @@ _zsh_autosuggest_execute() {
# Partially accept the suggestion # Partially accept the suggestion
_zsh_autosuggest_partial_accept() { _zsh_autosuggest_partial_accept() {
local -i retval local -i retval cursor_loc
# Save the contents of the buffer so we can restore later if needed # Save the contents of the buffer so we can restore later if needed
local original_buffer="$BUFFER" local original_buffer="$BUFFER"
@@ -164,13 +165,19 @@ _zsh_autosuggest_partial_accept() {
_zsh_autosuggest_invoke_original_widget $@ _zsh_autosuggest_invoke_original_widget $@
retval=$? retval=$?
# Normalize cursor location across vi/emacs modes
cursor_loc=$CURSOR
if [[ "$KEYMAP" = "vicmd" ]]; then
cursor_loc=$((cursor_loc + 1))
fi
# If we've moved past the end of the original buffer # If we've moved past the end of the original buffer
if (( $CURSOR > $#original_buffer )); then if (( $cursor_loc > $#original_buffer )); then
# Set POSTDISPLAY to text right of the cursor # Set POSTDISPLAY to text right of the cursor
POSTDISPLAY="$RBUFFER" POSTDISPLAY="${BUFFER[$(($cursor_loc + 1)),$#BUFFER]}"
# Clip the buffer at the cursor # Clip the buffer at the cursor
BUFFER="$LBUFFER" BUFFER="${BUFFER[1,$cursor_loc]}"
else else
# Restore the original buffer # Restore the original buffer
BUFFER="$original_buffer" BUFFER="$original_buffer"

View File

@@ -1,8 +1,8 @@
# Fish-like fast/unobtrusive autosuggestions for zsh. # Fish-like fast/unobtrusive autosuggestions for zsh.
# https://github.com/zsh-users/zsh-autosuggestions # https://github.com/zsh-users/zsh-autosuggestions
# v0.4.1 # v0.4.3
# Copyright (c) 2013 Thiago de Arruda # Copyright (c) 2013 Thiago de Arruda
# Copyright (c) 2016-2017 Eric Freese # Copyright (c) 2016-2018 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
@@ -57,6 +57,8 @@ ZSH_AUTOSUGGEST_CLEAR_WIDGETS=(
history-beginning-search-backward history-beginning-search-backward
history-substring-search-up history-substring-search-up
history-substring-search-down history-substring-search-down
up-line-or-beginning-search
down-line-or-beginning-search
up-line-or-history up-line-or-history
down-line-or-history down-line-or-history
accept-line accept-line
@@ -83,6 +85,8 @@ ZSH_AUTOSUGGEST_PARTIAL_ACCEPT_WIDGETS=(
vi-forward-word-end vi-forward-word-end
vi-forward-blank-word vi-forward-blank-word
vi-forward-blank-word-end vi-forward-blank-word-end
vi-find-next-char
vi-find-next-char-skip
) )
# Widgets that should be ignored (globbing supported but must be escaped) # Widgets that should be ignored (globbing supported but must be escaped)
@@ -93,6 +97,7 @@ ZSH_AUTOSUGGEST_IGNORE_WIDGETS=(
set-local-history set-local-history
which-command which-command
yank yank
yank-pop
) )
# Max size of buffer to trigger autosuggestion. Leave undefined for no upper bound. # Max size of buffer to trigger autosuggestion. Leave undefined for no upper bound.
@@ -101,6 +106,17 @@ ZSH_AUTOSUGGEST_BUFFER_MAX_SIZE=
# Pty name for calculating autosuggestions asynchronously # Pty name for calculating autosuggestions asynchronously
ZSH_AUTOSUGGEST_ASYNC_PTY_NAME=zsh_autosuggest_pty ZSH_AUTOSUGGEST_ASYNC_PTY_NAME=zsh_autosuggest_pty
#--------------------------------------------------------------------#
# Utility Functions #
#--------------------------------------------------------------------#
_zsh_autosuggest_escape_command() {
setopt localoptions EXTENDED_GLOB
# Escape special chars in the string (requires EXTENDED_GLOB)
echo -E "${1//(#m)[\"\'\\()\[\]|*?~]/\\$MATCH}"
}
#--------------------------------------------------------------------# #--------------------------------------------------------------------#
# Feature Detection # # Feature Detection #
#--------------------------------------------------------------------# #--------------------------------------------------------------------#
@@ -227,7 +243,7 @@ _zsh_autosuggest_bind_widgets() {
# Given the name of an original widget and args, invoke it, if it exists # Given the name of an original widget and args, invoke it, if it exists
_zsh_autosuggest_invoke_original_widget() { _zsh_autosuggest_invoke_original_widget() {
# Do nothing unless called with at least one arg # Do nothing unless called with at least one arg
(( $# )) || return (( $# )) || return 0
local original_widget_name="$1" local original_widget_name="$1"
@@ -320,6 +336,7 @@ _zsh_autosuggest_modify() {
# Don't fetch a new suggestion if there's more input to be read immediately # Don't fetch a new suggestion if there's more input to be read immediately
if (( $PENDING > 0 )) || (( $KEYS_QUEUED_COUNT > 0 )); then if (( $PENDING > 0 )) || (( $KEYS_QUEUED_COUNT > 0 )); then
POSTDISPLAY="$orig_postdisplay"
return $retval return $retval
fi fi
@@ -417,7 +434,7 @@ _zsh_autosuggest_execute() {
# Partially accept the suggestion # Partially accept the suggestion
_zsh_autosuggest_partial_accept() { _zsh_autosuggest_partial_accept() {
local -i retval local -i retval cursor_loc
# Save the contents of the buffer so we can restore later if needed # Save the contents of the buffer so we can restore later if needed
local original_buffer="$BUFFER" local original_buffer="$BUFFER"
@@ -429,13 +446,19 @@ _zsh_autosuggest_partial_accept() {
_zsh_autosuggest_invoke_original_widget $@ _zsh_autosuggest_invoke_original_widget $@
retval=$? retval=$?
# Normalize cursor location across vi/emacs modes
cursor_loc=$CURSOR
if [[ "$KEYMAP" = "vicmd" ]]; then
cursor_loc=$((cursor_loc + 1))
fi
# If we've moved past the end of the original buffer # If we've moved past the end of the original buffer
if (( $CURSOR > $#original_buffer )); then if (( $cursor_loc > $#original_buffer )); then
# Set POSTDISPLAY to text right of the cursor # Set POSTDISPLAY to text right of the cursor
POSTDISPLAY="$RBUFFER" POSTDISPLAY="${BUFFER[$(($cursor_loc + 1)),$#BUFFER]}"
# Clip the buffer at the cursor # Clip the buffer at the cursor
BUFFER="$LBUFFER" BUFFER="${BUFFER[1,$cursor_loc]}"
else else
# Restore the original buffer # Restore the original buffer
BUFFER="$original_buffer" BUFFER="$original_buffer"
@@ -478,11 +501,21 @@ zle -N autosuggest-toggle _zsh_autosuggest_widget_toggle
# #
_zsh_autosuggest_strategy_default() { _zsh_autosuggest_strategy_default() {
local prefix="$1" # Reset options to defaults and enable LOCAL_OPTIONS
emulate -L zsh
# Enable globbing flags so that we can use (#m)
setopt EXTENDED_GLOB
# Escape backslashes and all of the glob operators so we can use
# this string as a pattern to search the $history associative array.
# - (#m) globbing flag enables setting references for match data
# TODO: Use (b) flag when we can drop support for zsh older than v5.0.8
local prefix="${1//(#m)[\\*?[\]<>()|^~#]/\\$MATCH}"
# Get the history items that match # Get the history items that match
# - (r) subscript flag makes the pattern match on values # - (r) subscript flag makes the pattern match on values
typeset -g suggestion="${history[(r)${(b)prefix}*]}" typeset -g suggestion="${history[(r)${prefix}*]}"
} }
#--------------------------------------------------------------------# #--------------------------------------------------------------------#
@@ -507,18 +540,25 @@ _zsh_autosuggest_strategy_default() {
# `HIST_EXPIRE_DUPS_FIRST`. # `HIST_EXPIRE_DUPS_FIRST`.
_zsh_autosuggest_strategy_match_prev_cmd() { _zsh_autosuggest_strategy_match_prev_cmd() {
local prefix="$1" # Reset options to defaults and enable LOCAL_OPTIONS
emulate -L zsh
# Enable globbing flags so that we can use (#m)
setopt EXTENDED_GLOB
# TODO: Use (b) flag when we can drop support for zsh older than v5.0.8
local prefix="${1//(#m)[\\*?[\]<>()|^~#]/\\$MATCH}"
# Get all history event numbers that correspond to history # Get all history event numbers that correspond to history
# entries that match pattern $prefix* # entries that match pattern $prefix*
local history_match_keys local history_match_keys
history_match_keys=(${(k)history[(R)${(b)prefix}*]}) history_match_keys=(${(k)history[(R)$prefix*]})
# By default we use the first history number (most recent history entry) # By default we use the first history number (most recent history entry)
local histkey="${history_match_keys[1]}" local histkey="${history_match_keys[1]}"
# Get the previously executed command # Get the previously executed command
local prev_cmd="${history[$((HISTCMD-1))]}" local prev_cmd="$(_zsh_autosuggest_escape_command "${history[$((HISTCMD-1))]}")"
# Iterate up to the first 200 history event numbers that match $prefix # Iterate up to the first 200 history event numbers that match $prefix
for key in "${(@)history_match_keys[1,200]}"; do for key in "${(@)history_match_keys[1,200]}"; do
@@ -561,7 +601,6 @@ _zsh_autosuggest_async_server() {
# Silence any error messages # Silence any error messages
exec 2>/dev/null exec 2>/dev/null
local strategy=$1
local last_pid local last_pid
while IFS='' read -r -d $'\0' query; do while IFS='' read -r -d $'\0' query; do
@@ -608,7 +647,7 @@ _zsh_autosuggest_async_pty_create() {
fi fi
# Fork a zpty process running the server function # Fork a zpty process running the server function
zpty -b $ZSH_AUTOSUGGEST_ASYNC_PTY_NAME "_zsh_autosuggest_async_server _zsh_autosuggest_strategy_$ZSH_AUTOSUGGEST_STRATEGY" zpty -b $ZSH_AUTOSUGGEST_ASYNC_PTY_NAME _zsh_autosuggest_async_server
# Store the fd so we can remove the handler later # Store the fd so we can remove the handler later
if (( REPLY )); then if (( REPLY )); then
@@ -622,13 +661,11 @@ _zsh_autosuggest_async_pty_create() {
} }
_zsh_autosuggest_async_pty_destroy() { _zsh_autosuggest_async_pty_destroy() {
if zpty -t $ZSH_AUTOSUGGEST_ASYNC_PTY_NAME &>/dev/null; then # Remove the input handler
# Remove the input handler zle -F $_ZSH_AUTOSUGGEST_PTY_FD &>/dev/null
zle -F $_ZSH_AUTOSUGGEST_PTY_FD &>/dev/null
# Destroy the zpty # Destroy the zpty
zpty -d $ZSH_AUTOSUGGEST_ASYNC_PTY_NAME &>/dev/null zpty -d $ZSH_AUTOSUGGEST_ASYNC_PTY_NAME &>/dev/null
fi
} }
_zsh_autosuggest_async_pty_recreate() { _zsh_autosuggest_async_pty_recreate() {