Compare commits

..

1 Commits

Author SHA1 Message Date
Eric Freese
4ccfdb2435 Fix issue where partial accept duplicates last word
When z-sy-h is enabled after autosuggestion widgets have already been
bound, partial accepting the last part of a suggestion will result in
that string being duplicated.

I was able to reproduce using the following versions of the two plugins:
- z-sy-h: dde84e1b25f059a298ce3189cddfd0778f998df3
- z-asug: ae315ded4dba10685dbbafbfa2ff3c1aefeb490d

and running the following commands interactively one after another:

```
zsh -df
% source path/to/zsh-autosuggestions.zsh
% source path/to/zsh-syntax-highlighting.zsh
% bindkey -e
% bindkey <alt-f>         # shows 'bindkey -e-e'
```

The order of the `source` statements matters and the issue cannot be
reproduced if the two source statements are executed together on one
line.

The problem is very similar to this one:
  https://github.com/zsh-users/zsh-autosuggestions/issues/126#issuecomment-217121315

See GitHub issue #483
2020-01-29 21:47:57 -07:00
19 changed files with 135 additions and 190 deletions

15
.circleci/config.yml Normal file
View File

@ -0,0 +1,15 @@
version: 2
jobs:
build:
parallelism: 4
shell: /bin/bash --login
docker:
- image: ericfreese/zsh-autosuggestions-test:latest
steps:
- checkout
- run:
name: Running tests
command: |
for v in $(grep "^[^#]" ZSH_VERSIONS | awk "(NR + $CIRCLE_NODE_INDEX) % $CIRCLE_NODE_TOTAL == 0"); do
TEST_ZSH_BIN=zsh-$v make test || exit 1
done

View File

@ -1,51 +0,0 @@
on: [push, pull_request]
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
env:
IMAGE_CACHE_PATH: /tmp/.image-cache
IMAGE_CACHE_NAME: zsh-autosuggestions-test
jobs:
determine-versions:
runs-on: ubuntu-22.04
outputs:
versions: ${{ steps.set-versions.outputs.versions }}
steps:
- uses: actions/checkout@v3
- id: set-versions
run: |
echo "versions=$(
grep "^[^#]" ZSH_VERSIONS \
| sed -E 's/(^|$)/"/g' \
| paste -sd ',' - \
| sed -e 's/^/[/' -e 's/$/]/'
)" >> $GITHUB_OUTPUT
test:
needs: determine-versions
runs-on: ubuntu-22.04
strategy:
matrix:
version: ${{ fromJson(needs.determine-versions.outputs.versions) }}
steps:
- uses: actions/checkout@v3
- name: Docker image cache
id: image-cache
uses: actions/cache@v3
with:
path: ${{ env.IMAGE_CACHE_PATH }}
key: image-cache-${{ matrix.version }}-${{ hashFiles('Dockerfile', 'install_test_zsh.sh', 'Gemfile.lock') }}
- name: Load cached docker image if available
if: ${{ steps.image-cache.outputs.cache-hit }}
run: gunzip < $IMAGE_CACHE_PATH/$IMAGE_CACHE_NAME.tar.gz | docker load
- name: Build the docker image if necessary
if: ${{ !steps.image-cache.outputs.cache-hit }}
run: |
docker build --build-arg TEST_ZSH_VERSION=${{ matrix.version }} -t $IMAGE_CACHE_NAME .
mkdir -p $IMAGE_CACHE_PATH
docker save $IMAGE_CACHE_NAME | gzip > $IMAGE_CACHE_PATH/$IMAGE_CACHE_NAME.tar.gz
- name: Run the tests
run: |
docker run --rm \
-v $PWD:/zsh-autosuggestions \
$IMAGE_CACHE_NAME \
make test

2
.gitignore vendored
View File

@ -1,2 +0,0 @@
# zsh word code files
*.zwc

View File

@ -1,18 +1,5 @@
# Changelog # Changelog
## v0.7.1
- Clear POSTDISPLAY instead of unsetting (#634)
- Always reset async file descriptor after consuming it (#630)
- Always use builtin `exec` (#628)
- Add `history-beginning-search-*-end` widgets to clear widget list (#619)
- Switch CI from Circle CI to GitHub Actions
## v0.7.0
- Enable asynchronous mode by default (#498)
- No longer wrap user widgets starting with `autosuggest-` prefix (#496)
- Fix a bug wrapping widgets that modify the buffer (#541)
## v0.6.4 ## v0.6.4
- Fix `vi-forward-char` triggering a bell when using it to accept a suggestion (#488) - Fix `vi-forward-char` triggering a bell when using it to accept a suggestion (#488)
- New configuration option to skip completion suggestions when buffer matches a pattern (#487) - New configuration option to skip completion suggestions when buffer matches a pattern (#487)

View File

@ -1,8 +1,5 @@
FROM ruby:2.5.3-alpine FROM ruby:2.5.3-alpine
ARG TEST_ZSH_VERSION
RUN : "${TEST_ZSH_VERSION:?}"
RUN apk add --no-cache autoconf RUN apk add --no-cache autoconf
RUN apk add --no-cache libtool RUN apk add --no-cache libtool
RUN apk add --no-cache libcap-dev RUN apk add --no-cache libcap-dev
@ -14,8 +11,10 @@ RUN apk add --no-cache tmux
WORKDIR /zsh-autosuggestions WORKDIR /zsh-autosuggestions
ADD install_test_zsh.sh ./ ADD ZSH_VERSIONS /zsh-autosuggestions/ZSH_VERSIONS
ADD install_test_zsh.sh /zsh-autosuggestions/install_test_zsh.sh
RUN ./install_test_zsh.sh RUN ./install_test_zsh.sh
ADD Gemfile Gemfile.lock ./ ADD Gemfile /zsh-autosuggestions/Gemfile
ADD Gemfile.lock /zsh-autosuggestions/Gemfile.lock
RUN bundle install RUN bundle install

View File

@ -3,21 +3,19 @@
* [Packages](#packages) * [Packages](#packages)
* [Antigen](#antigen) * [Antigen](#antigen)
* [Oh My Zsh](#oh-my-zsh) * [Oh My Zsh](#oh-my-zsh)
* [HomeBrew](#homebrew)
* [Manual](#manual-git-clone) * [Manual](#manual-git-clone)
## Packages ## Packages
| System | Package | | System | Package |
| ------------- | ------------- | | ------------- | ------------- |
| Alpine Linux | [zsh-autosuggestions](https://pkgs.alpinelinux.org/packages?name=zsh-autosuggestions) |
| Debian / Ubuntu | [zsh-autosuggestions OBS repository](https://software.opensuse.org/download.html?project=shells%3Azsh-users%3Azsh-autosuggestions&package=zsh-autosuggestions) | | Debian / Ubuntu | [zsh-autosuggestions OBS repository](https://software.opensuse.org/download.html?project=shells%3Azsh-users%3Azsh-autosuggestions&package=zsh-autosuggestions) |
| Fedora / CentOS / RHEL / Scientific Linux | [zsh-autosuggestions OBS repository](https://software.opensuse.org/download.html?project=shells%3Azsh-users%3Azsh-autosuggestions&package=zsh-autosuggestions) | | Fedora / CentOS / RHEL / Scientific Linux | [zsh-autosuggestions OBS repository](https://software.opensuse.org/download.html?project=shells%3Azsh-users%3Azsh-autosuggestions&package=zsh-autosuggestions) |
| OpenSUSE / SLE | [zsh-autosuggestions OBS repository](https://software.opensuse.org/download.html?project=shells%3Azsh-users%3Azsh-autosuggestions&package=zsh-autosuggestions) | | OpenSUSE / SLE | [zsh-autosuggestions OBS repository](https://software.opensuse.org/download.html?project=shells%3Azsh-users%3Azsh-autosuggestions&package=zsh-autosuggestions) |
| Arch Linux / Manjaro / Antergos / Hyperbola | [zsh-autosuggestions](https://www.archlinux.org/packages/zsh-autosuggestions), [zsh-autosuggestions-git](https://aur.archlinux.org/packages/zsh-autosuggestions-git) | | Arch Linux / Manjaro / Antergos / Hyperbola | [zsh-autosuggestions](https://www.archlinux.org/packages/zsh-autosuggestions), [zsh-autosuggestions-git](https://aur.archlinux.org/packages/zsh-autosuggestions-git) |
| NixOS | [zsh-autosuggestions](https://github.com/NixOS/nixpkgs/blob/master/pkgs/by-name/zs/zsh-autosuggestions/package.nix) | | NixOS | [zsh-autosuggestions](https://github.com/NixOS/nixpkgs/blob/master/pkgs/shells/zsh/zsh-autosuggestions/default.nix) |
| Void Linux | [zsh-autosuggestions](https://github.com/void-linux/void-packages/blob/master/srcpkgs/zsh-autosuggestions/template) | | Void Linux | [zsh-autosuggestions](https://github.com/void-linux/void-packages/blob/master/srcpkgs/zsh-autosuggestions/template) |
| Mac OS | [homebrew](https://github.com/Homebrew/homebrew-core/blob/master/Formula/z/zsh-autosuggestions.rb) | | Mac OS | [homebrew](https://github.com/Homebrew/homebrew-core/blob/master/Formula/zsh-autosuggestions.rb) |
| NetBSD | [pkgsrc](http://ftp.netbsd.org/pub/pkgsrc/current/pkgsrc/shells/zsh-autosuggestions/README.html) | | NetBSD | [pkgsrc](http://ftp.netbsd.org/pub/pkgsrc/current/pkgsrc/shells/zsh-autosuggestions/README.html) |
## Antigen ## Antigen
@ -41,25 +39,7 @@
2. Add the plugin to the list of plugins for Oh My Zsh to load (inside `~/.zshrc`): 2. Add the plugin to the list of plugins for Oh My Zsh to load (inside `~/.zshrc`):
```sh ```sh
plugins=( plugins=(zsh-autosuggestions)
# other plugins...
zsh-autosuggestions
)
```
3. Start a new terminal session.
## Homebrew
1. Install command:
```sh
brew install zsh-autosuggestions
```
2. To activate the autosuggestions, add the following at the end of your .zshrc:
```sh
source $(brew --prefix)/share/zsh-autosuggestions/zsh-autosuggestions.zsh
``` ```
3. Start a new terminal session. 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-2021 Eric Freese Copyright (c) 2016-2019 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

@ -6,6 +6,7 @@ It suggests commands as you type based on history and completions.
Requirements: Zsh v4.3.11 or later Requirements: Zsh v4.3.11 or later
[![CircleCI](https://img.shields.io/circleci/build/github/zsh-users/zsh-autosuggestions.svg)](https://circleci.com/gh/zsh-users/zsh-autosuggestions)
[![Chat on Gitter](https://img.shields.io/gitter/room/zsh-users/zsh-autosuggestions.svg)](https://gitter.im/zsh-users/zsh-autosuggestions) [![Chat on Gitter](https://img.shields.io/gitter/room/zsh-users/zsh-autosuggestions.svg)](https://gitter.im/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>
@ -52,7 +53,7 @@ For more info, read the Character Highlighting section of the zsh manual: `man z
`ZSH_AUTOSUGGEST_STRATEGY` is an array that specifies how suggestions should be generated. The strategies in the array are tried successively until a suggestion is found. There are currently three built-in strategies to choose from: `ZSH_AUTOSUGGEST_STRATEGY` is an array that specifies how suggestions should be generated. The strategies in the array are tried successively until a suggestion is found. There are currently three built-in strategies to choose from:
- `history`: Chooses the most recent match from history. - `history`: Chooses the most recent match from history.
- `completion`: Chooses a suggestion based on what tab-completion would suggest. (requires `zpty` module, which is included with zsh since 4.0.1) - `completion`: Chooses a suggestion based on what tab-completion would suggest. (requires `zpty` module)
- `match_prev_cmd`: Like `history`, but chooses the most recent match whose preceding history item matches the most recently executed command ([more info](src/strategies/match_prev_cmd.zsh)). Note that this strategy won't work as expected with ZSH options that don't preserve the history order such as `HIST_IGNORE_ALL_DUPS` or `HIST_EXPIRE_DUPS_FIRST`. - `match_prev_cmd`: Like `history`, but chooses the most recent match whose preceding history item matches the most recently executed command ([more info](src/strategies/match_prev_cmd.zsh)). Note that this strategy won't work as expected with ZSH options that don't preserve the history order such as `HIST_IGNORE_ALL_DUPS` or `HIST_EXPIRE_DUPS_FIRST`.
For example, setting `ZSH_AUTOSUGGEST_STRATEGY=(history completion)` will first try to find a suggestion from your history, but, if it can't find a match, will find a suggestion from the completion engine. For example, setting `ZSH_AUTOSUGGEST_STRATEGY=(history completion)` will first try to find a suggestion from your history, but, if it can't find a match, will find a suggestion from the completion engine.
@ -169,16 +170,18 @@ Tests are written in ruby using the [`rspec`](http://rspec.info/) framework. The
Test files live in `spec/`. To run the tests, run `make test`. To run a specific test, run `TESTS=spec/some_spec.rb make test`. You can also specify a `zsh` binary to use by setting the `TEST_ZSH_BIN` environment variable (ex: `TEST_ZSH_BIN=/bin/zsh make test`). Test files live in `spec/`. To run the tests, run `make test`. To run a specific test, run `TESTS=spec/some_spec.rb make test`. You can also specify a `zsh` binary to use by setting the `TEST_ZSH_BIN` environment variable (ex: `TEST_ZSH_BIN=/bin/zsh make test`).
It's possible to run the tests for any supported version of zsh in a Docker image by building an image from the provided Dockerfile. To build the docker image for a specific version of zsh (where `<version>` below is substituted with the contents of a line from the [`ZSH_VERSIONS`](ZSH_VERSIONS) file), run: A docker image for testing is available [on docker hub](https://hub.docker.com/r/ericfreese/zsh-autosuggestions-test). It comes with ruby, the bundler dependencies, and all supported versions of zsh installed.
Pull the docker image with:
```sh ```sh
docker build --build-arg TEST_ZSH_VERSION=<version> -t zsh-autosuggestions-test . docker pull ericfreese/zsh-autosuggestions-test
``` ```
After building the image, run the tests via: To run the tests for a specific version of zsh (where `<version>` below is substituted with the contents of a line from the [`ZSH_VERSIONS`](ZSH_VERSIONS) file):
```sh ```sh
docker run -it -v $PWD:/zsh-autosuggestions zsh-autosuggestions-test make test docker run -it -e TEST_ZSH_BIN=zsh-<version> -v $PWD:/zsh-autosuggestions zsh-autosuggestions-test make test
``` ```

View File

@ -1 +1 @@
v0.7.1 v0.6.4

View File

@ -1,5 +1,9 @@
# Zsh releases to run tests against # Zsh releases to run tests against
# See https://github.com/zsh-users/zsh/releases # See https://github.com/zsh-users/zsh/releases
#
# When modifying this file, rebuild and push docker image:
# $ docker build -t ericfreese/zsh-autosuggestions-test .
# $ docker push ericfreese/zsh-autosuggestions-test
4.3.11 4.3.11
5.0.2 5.0.2
5.0.8 5.0.8
@ -10,5 +14,3 @@
5.5.1 5.5.1
5.6.2 5.6.2
5.7.1 5.7.1
5.8.1
5.9

View File

@ -2,22 +2,25 @@
set -ex set -ex
mkdir zsh-build for v in $(grep "^[^#]" ZSH_VERSIONS); do
cd zsh-build mkdir zsh-$v
cd zsh-$v
curl -L https://api.github.com/repos/zsh-users/zsh/tarball/zsh-$TEST_ZSH_VERSION | tar xz --strip=1 curl -L https://api.github.com/repos/zsh-users/zsh/tarball/zsh-$v | tar xz --strip=1
./Util/preconfig ./Util/preconfig
./configure --enable-pcre \ ./configure --enable-pcre \
--enable-cap \ --enable-cap \
--enable-multibyte \ --enable-multibyte \
--with-term-lib='ncursesw tinfo' \ --with-term-lib='ncursesw tinfo' \
--with-tcsetpgrp --with-tcsetpgrp \
--program-suffix="-$v"
make install.bin make install.bin
make install.modules make install.modules
make install.fns make install.fns
cd .. cd ..
rm -rf zsh-build rm -rf zsh-$v
done

View File

@ -1,6 +1,11 @@
describe 'a multi-line suggestion' do describe 'a multi-line suggestion' do
it 'should be displayed on multiple lines' do it 'should be displayed on multiple lines' do
with_history("echo \"\n\"") do with_history(-> {
session.send_string('echo "')
session.send_keys('enter')
session.send_string('"')
session.send_keys('enter')
}) do
session.send_keys('e') session.send_keys('e')
wait_for { session.content }.to eq("echo \"\n\"") wait_for { session.content }.to eq("echo \"\n\"")
end end

View File

@ -1,7 +1,6 @@
require 'pry' require 'pry'
require 'rspec/wait' require 'rspec/wait'
require 'terminal_session' require 'terminal_session'
require 'tempfile'
RSpec.shared_context 'terminal session' do RSpec.shared_context 'terminal session' do
let(:term_opts) { {} } let(:term_opts) { {} }
@ -22,12 +21,11 @@ RSpec.shared_context 'terminal session' do
end end
def with_history(*commands, &block) def with_history(*commands, &block)
Tempfile.create do |f|
f.write(commands.map{|c| c.gsub("\n", "\\\n")}.join("\n"))
f.flush
session.run_command('fc -p') session.run_command('fc -p')
session.run_command("fc -R #{f.path}")
commands.each do |c|
c.respond_to?(:call) ? c.call : session.run_command(c)
end
session.clear_screen session.clear_screen
@ -36,7 +34,6 @@ RSpec.shared_context 'terminal session' do
session.send_keys('C-c') session.send_keys('C-c')
session.run_command('fc -P') session.run_command('fc -P')
end end
end
end end
RSpec.configure do |config| RSpec.configure do |config|

View File

@ -1,71 +1,58 @@
shared_examples 'special characters' do shared_examples 'special characters' do
describe 'a special character in the buffer should be treated like any other character' do describe 'a special character in the buffer' do
it 'asterisk' do it 'should be treated like any other character' do
with_history('echo "hello*"', 'echo "hello."') do with_history('echo "hello*"', 'echo "hello."') do
session.send_string('echo "hello*') session.send_string('echo "hello*')
wait_for { session.content }.to eq('echo "hello*"') wait_for { session.content }.to eq('echo "hello*"')
end end
end
it 'question mark' do
with_history('echo "hello?"', 'echo "hello."') do with_history('echo "hello?"', 'echo "hello."') do
session.send_string('echo "hello?') session.send_string('echo "hello?')
wait_for { session.content }.to eq('echo "hello?"') wait_for { session.content }.to eq('echo "hello?"')
end end
end
it 'backslash' do
with_history('echo "hello\nworld"') do with_history('echo "hello\nworld"') do
session.send_string('echo "hello\\') session.send_string('echo "hello\\')
wait_for { session.content }.to eq('echo "hello\nworld"') wait_for { session.content }.to eq('echo "hello\nworld"')
end end
end
it 'double backslash' do
with_history('echo "\\\\"') do with_history('echo "\\\\"') do
session.send_string('echo "\\\\') session.send_string('echo "\\\\')
wait_for { session.content }.to eq('echo "\\\\"') wait_for { session.content }.to eq('echo "\\\\"')
end end
end
it 'tilde' do
with_history('echo ~/foo') do with_history('echo ~/foo') do
session.send_string('echo ~') session.send_string('echo ~')
wait_for { session.content }.to eq('echo ~/foo') wait_for { session.content }.to eq('echo ~/foo')
end end
end
it 'parentheses' do
with_history('echo "$(ls foo)"') do with_history('echo "$(ls foo)"') do
session.send_string('echo "$(') session.send_string('echo "$(')
wait_for { session.content }.to eq('echo "$(ls foo)"') wait_for { session.content }.to eq('echo "$(ls foo)"')
end end
end
it 'square bracket' do
with_history('echo "$history[123]"') do with_history('echo "$history[123]"') do
session.send_string('echo "$history[') session.send_string('echo "$history[')
wait_for { session.content }.to eq('echo "$history[123]"') wait_for { session.content }.to eq('echo "$history[123]"')
session.send_string('123]') session.send_string('123]')
wait_for { session.content }.to eq('echo "$history[123]"') wait_for { session.content }.to eq('echo "$history[123]"')
end end
end
it 'octothorpe' do
with_history('echo "#yolo"') do with_history('echo "#yolo"') do
session.send_string('echo "#') session.send_string('echo "#')
wait_for { session.content }.to eq('echo "#yolo"') wait_for { session.content }.to eq('echo "#yolo"')
end end
with_history('echo "#foo"', 'echo $#abc') do
session.send_string('echo "#')
wait_for { session.content }.to eq('echo "#foo"')
end end
it 'caret' do
with_history('echo "^A"', 'echo "^B"') do with_history('echo "^A"', 'echo "^B"') do
session.send_string('echo "^A') session.send_string('echo "^A')
wait_for { session.content }.to eq('echo "^A"') wait_for { session.content }.to eq('echo "^A"')
end end
end
it 'dash' do
with_history('-foo() {}') do with_history('-foo() {}') do
session.send_string('-') session.send_string('-')
wait_for { session.content }.to eq('-foo() {}') wait_for { session.content }.to eq('-foo() {}')

View File

@ -11,7 +11,7 @@ _zsh_autosuggest_async_request() {
# If we've got a pending request, cancel it # If we've got a pending request, cancel it
if [[ -n "$_ZSH_AUTOSUGGEST_ASYNC_FD" ]] && { true <&$_ZSH_AUTOSUGGEST_ASYNC_FD } 2>/dev/null; then if [[ -n "$_ZSH_AUTOSUGGEST_ASYNC_FD" ]] && { true <&$_ZSH_AUTOSUGGEST_ASYNC_FD } 2>/dev/null; then
# Close the file descriptor and remove the handler # Close the file descriptor and remove the handler
builtin exec {_ZSH_AUTOSUGGEST_ASYNC_FD}<&- exec {_ZSH_AUTOSUGGEST_ASYNC_FD}<&-
zle -F $_ZSH_AUTOSUGGEST_ASYNC_FD zle -F $_ZSH_AUTOSUGGEST_ASYNC_FD
# We won't know the pid unless the user has zsh/system module installed # We won't know the pid unless the user has zsh/system module installed
@ -32,7 +32,7 @@ _zsh_autosuggest_async_request() {
fi fi
# Fork a process to fetch a suggestion and open a pipe to read from it # Fork a process to fetch a suggestion and open a pipe to read from it
builtin exec {_ZSH_AUTOSUGGEST_ASYNC_FD}< <( exec {_ZSH_AUTOSUGGEST_ASYNC_FD}< <(
# Tell parent process our pid # Tell parent process our pid
echo $sysparams[pid] echo $sysparams[pid]
@ -44,8 +44,7 @@ _zsh_autosuggest_async_request() {
# There's a weird bug here where ^C stops working unless we force a fork # There's a weird bug here where ^C stops working unless we force a fork
# See https://github.com/zsh-users/zsh-autosuggestions/issues/364 # See https://github.com/zsh-users/zsh-autosuggestions/issues/364
autoload -Uz is-at-least command true
is-at-least 5.8 || command true
# Read the pid from the child process # Read the pid from the child process
read _ZSH_AUTOSUGGEST_CHILD_PID <&$_ZSH_AUTOSUGGEST_ASYNC_FD read _ZSH_AUTOSUGGEST_CHILD_PID <&$_ZSH_AUTOSUGGEST_ASYNC_FD
@ -68,10 +67,9 @@ _zsh_autosuggest_async_response() {
zle autosuggest-suggest -- "$suggestion" zle autosuggest-suggest -- "$suggestion"
# Close the fd # Close the fd
builtin exec {1}<&- exec {1}<&-
fi fi
# Always remove the handler # Always remove the handler
zle -F "$1" zle -F "$1"
_ZSH_AUTOSUGGEST_ASYNC_FD=
} }

View File

@ -28,8 +28,6 @@ typeset -g ZSH_AUTOSUGGEST_ORIGINAL_WIDGET_PREFIX=autosuggest-orig-
history-search-backward history-search-backward
history-beginning-search-forward history-beginning-search-forward
history-beginning-search-backward history-beginning-search-backward
history-beginning-search-forward-end
history-beginning-search-backward-end
history-substring-search-up history-substring-search-up
history-substring-search-down history-substring-search-down
up-line-or-beginning-search up-line-or-beginning-search

View File

@ -30,7 +30,7 @@ _zsh_autosuggest_toggle() {
# Clear the suggestion # Clear the suggestion
_zsh_autosuggest_clear() { _zsh_autosuggest_clear() {
# Remove the suggestion # Remove the suggestion
POSTDISPLAY= unset POSTDISPLAY
_zsh_autosuggest_invoke_original_widget $@ _zsh_autosuggest_invoke_original_widget $@
} }
@ -47,7 +47,7 @@ _zsh_autosuggest_modify() {
local orig_postdisplay="$POSTDISPLAY" local orig_postdisplay="$POSTDISPLAY"
# Clear suggestion while waiting for next one # Clear suggestion while waiting for next one
POSTDISPLAY= unset POSTDISPLAY
# Original widget may modify the buffer # Original widget may modify the buffer
_zsh_autosuggest_invoke_original_widget $@ _zsh_autosuggest_invoke_original_widget $@
@ -61,9 +61,20 @@ _zsh_autosuggest_modify() {
return $retval return $retval
fi fi
# Optimize if manually typing in the suggestion or if buffer hasn't changed # Optimize if manually typing in the suggestion
if [[ "$BUFFER" = "$orig_buffer"* && "$orig_postdisplay" = "${BUFFER:$#orig_buffer}"* ]]; then if (( $#BUFFER > $#orig_buffer )); then
POSTDISPLAY="${orig_postdisplay:$(($#BUFFER - $#orig_buffer))}" local added=${BUFFER#$orig_buffer}
# If the string added matches the beginning of the postdisplay
if [[ "$added" = "${orig_postdisplay:0:$#added}" ]]; then
POSTDISPLAY="${orig_postdisplay:$#added}"
return $retval
fi
fi
# Don't fetch a new suggestion if the buffer hasn't changed
if [[ "$BUFFER" = "$orig_buffer" ]]; then
POSTDISPLAY="$orig_postdisplay"
return $retval return $retval
fi fi
@ -102,7 +113,7 @@ _zsh_autosuggest_suggest() {
if [[ -n "$suggestion" ]] && (( $#BUFFER )); then if [[ -n "$suggestion" ]] && (( $#BUFFER )); then
POSTDISPLAY="${suggestion#$BUFFER}" POSTDISPLAY="${suggestion#$BUFFER}"
else else
POSTDISPLAY= unset POSTDISPLAY
fi fi
} }
@ -128,7 +139,7 @@ _zsh_autosuggest_accept() {
BUFFER="$BUFFER$POSTDISPLAY" BUFFER="$BUFFER$POSTDISPLAY"
# Remove the suggestion # Remove the suggestion
POSTDISPLAY= unset POSTDISPLAY
# Run the original widget before manually moving the cursor so that the # Run the original widget before manually moving the cursor so that the
# cursor movement doesn't make the widget do something unexpected # cursor movement doesn't make the widget do something unexpected
@ -151,7 +162,7 @@ _zsh_autosuggest_execute() {
BUFFER="$BUFFER$POSTDISPLAY" BUFFER="$BUFFER$POSTDISPLAY"
# Remove the suggestion # Remove the suggestion
POSTDISPLAY= unset POSTDISPLAY
# Call the original `accept-line` to handle syntax highlighting or # Call the original `accept-line` to handle syntax highlighting or
# other potential custom behavior # other potential custom behavior
@ -162,11 +173,13 @@ _zsh_autosuggest_execute() {
_zsh_autosuggest_partial_accept() { _zsh_autosuggest_partial_accept() {
local -i retval cursor_loc local -i retval cursor_loc
# Save the contents of the buffer so we can restore later if needed # Save the original buffer/postdisplay so we can restore later if needed
local original_buffer="$BUFFER" local original_buffer="$BUFFER"
local original_postdisplay="$POSTDISPLAY"
# Temporarily accept the suggestion. # Temporarily accept the suggestion.
BUFFER="$BUFFER$POSTDISPLAY" BUFFER="$BUFFER$POSTDISPLAY"
unset POSTDISPLAY
# Original widget moves the cursor # Original widget moves the cursor
_zsh_autosuggest_invoke_original_widget $@ _zsh_autosuggest_invoke_original_widget $@
@ -186,8 +199,9 @@ _zsh_autosuggest_partial_accept() {
# Clip the buffer at the cursor # Clip the buffer at the cursor
BUFFER="${BUFFER[1,$cursor_loc]}" BUFFER="${BUFFER[1,$cursor_loc]}"
else else
# Restore the original buffer # Restore the original buffer/postdisplay
BUFFER="$original_buffer" BUFFER="$original_buffer"
POSTDISPLAY="$original_postdisplay"
fi fi
return $retval return $retval

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.7.1 # v0.6.4
# Copyright (c) 2013 Thiago de Arruda # Copyright (c) 2013 Thiago de Arruda
# Copyright (c) 2016-2021 Eric Freese # Copyright (c) 2016-2019 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
@ -54,8 +54,6 @@ typeset -g ZSH_AUTOSUGGEST_ORIGINAL_WIDGET_PREFIX=autosuggest-orig-
history-search-backward history-search-backward
history-beginning-search-forward history-beginning-search-forward
history-beginning-search-backward history-beginning-search-backward
history-beginning-search-forward-end
history-beginning-search-backward-end
history-substring-search-up history-substring-search-up
history-substring-search-down history-substring-search-down
up-line-or-beginning-search up-line-or-beginning-search
@ -294,7 +292,7 @@ _zsh_autosuggest_toggle() {
# Clear the suggestion # Clear the suggestion
_zsh_autosuggest_clear() { _zsh_autosuggest_clear() {
# Remove the suggestion # Remove the suggestion
POSTDISPLAY= unset POSTDISPLAY
_zsh_autosuggest_invoke_original_widget $@ _zsh_autosuggest_invoke_original_widget $@
} }
@ -311,7 +309,7 @@ _zsh_autosuggest_modify() {
local orig_postdisplay="$POSTDISPLAY" local orig_postdisplay="$POSTDISPLAY"
# Clear suggestion while waiting for next one # Clear suggestion while waiting for next one
POSTDISPLAY= unset POSTDISPLAY
# Original widget may modify the buffer # Original widget may modify the buffer
_zsh_autosuggest_invoke_original_widget $@ _zsh_autosuggest_invoke_original_widget $@
@ -325,9 +323,20 @@ _zsh_autosuggest_modify() {
return $retval return $retval
fi fi
# Optimize if manually typing in the suggestion or if buffer hasn't changed # Optimize if manually typing in the suggestion
if [[ "$BUFFER" = "$orig_buffer"* && "$orig_postdisplay" = "${BUFFER:$#orig_buffer}"* ]]; then if (( $#BUFFER > $#orig_buffer )); then
POSTDISPLAY="${orig_postdisplay:$(($#BUFFER - $#orig_buffer))}" local added=${BUFFER#$orig_buffer}
# If the string added matches the beginning of the postdisplay
if [[ "$added" = "${orig_postdisplay:0:$#added}" ]]; then
POSTDISPLAY="${orig_postdisplay:$#added}"
return $retval
fi
fi
# Don't fetch a new suggestion if the buffer hasn't changed
if [[ "$BUFFER" = "$orig_buffer" ]]; then
POSTDISPLAY="$orig_postdisplay"
return $retval return $retval
fi fi
@ -366,7 +375,7 @@ _zsh_autosuggest_suggest() {
if [[ -n "$suggestion" ]] && (( $#BUFFER )); then if [[ -n "$suggestion" ]] && (( $#BUFFER )); then
POSTDISPLAY="${suggestion#$BUFFER}" POSTDISPLAY="${suggestion#$BUFFER}"
else else
POSTDISPLAY= unset POSTDISPLAY
fi fi
} }
@ -392,7 +401,7 @@ _zsh_autosuggest_accept() {
BUFFER="$BUFFER$POSTDISPLAY" BUFFER="$BUFFER$POSTDISPLAY"
# Remove the suggestion # Remove the suggestion
POSTDISPLAY= unset POSTDISPLAY
# Run the original widget before manually moving the cursor so that the # Run the original widget before manually moving the cursor so that the
# cursor movement doesn't make the widget do something unexpected # cursor movement doesn't make the widget do something unexpected
@ -415,7 +424,7 @@ _zsh_autosuggest_execute() {
BUFFER="$BUFFER$POSTDISPLAY" BUFFER="$BUFFER$POSTDISPLAY"
# Remove the suggestion # Remove the suggestion
POSTDISPLAY= unset POSTDISPLAY
# Call the original `accept-line` to handle syntax highlighting or # Call the original `accept-line` to handle syntax highlighting or
# other potential custom behavior # other potential custom behavior
@ -426,11 +435,13 @@ _zsh_autosuggest_execute() {
_zsh_autosuggest_partial_accept() { _zsh_autosuggest_partial_accept() {
local -i retval cursor_loc local -i retval cursor_loc
# Save the contents of the buffer so we can restore later if needed # Save the original buffer/postdisplay so we can restore later if needed
local original_buffer="$BUFFER" local original_buffer="$BUFFER"
local original_postdisplay="$POSTDISPLAY"
# Temporarily accept the suggestion. # Temporarily accept the suggestion.
BUFFER="$BUFFER$POSTDISPLAY" BUFFER="$BUFFER$POSTDISPLAY"
unset POSTDISPLAY
# Original widget moves the cursor # Original widget moves the cursor
_zsh_autosuggest_invoke_original_widget $@ _zsh_autosuggest_invoke_original_widget $@
@ -450,8 +461,9 @@ _zsh_autosuggest_partial_accept() {
# Clip the buffer at the cursor # Clip the buffer at the cursor
BUFFER="${BUFFER[1,$cursor_loc]}" BUFFER="${BUFFER[1,$cursor_loc]}"
else else
# Restore the original buffer # Restore the original buffer/postdisplay
BUFFER="$original_buffer" BUFFER="$original_buffer"
POSTDISPLAY="$original_postdisplay"
fi fi
return $retval return $retval
@ -768,7 +780,7 @@ _zsh_autosuggest_async_request() {
# If we've got a pending request, cancel it # If we've got a pending request, cancel it
if [[ -n "$_ZSH_AUTOSUGGEST_ASYNC_FD" ]] && { true <&$_ZSH_AUTOSUGGEST_ASYNC_FD } 2>/dev/null; then if [[ -n "$_ZSH_AUTOSUGGEST_ASYNC_FD" ]] && { true <&$_ZSH_AUTOSUGGEST_ASYNC_FD } 2>/dev/null; then
# Close the file descriptor and remove the handler # Close the file descriptor and remove the handler
builtin exec {_ZSH_AUTOSUGGEST_ASYNC_FD}<&- exec {_ZSH_AUTOSUGGEST_ASYNC_FD}<&-
zle -F $_ZSH_AUTOSUGGEST_ASYNC_FD zle -F $_ZSH_AUTOSUGGEST_ASYNC_FD
# We won't know the pid unless the user has zsh/system module installed # We won't know the pid unless the user has zsh/system module installed
@ -789,7 +801,7 @@ _zsh_autosuggest_async_request() {
fi fi
# Fork a process to fetch a suggestion and open a pipe to read from it # Fork a process to fetch a suggestion and open a pipe to read from it
builtin exec {_ZSH_AUTOSUGGEST_ASYNC_FD}< <( exec {_ZSH_AUTOSUGGEST_ASYNC_FD}< <(
# Tell parent process our pid # Tell parent process our pid
echo $sysparams[pid] echo $sysparams[pid]
@ -801,8 +813,7 @@ _zsh_autosuggest_async_request() {
# There's a weird bug here where ^C stops working unless we force a fork # There's a weird bug here where ^C stops working unless we force a fork
# See https://github.com/zsh-users/zsh-autosuggestions/issues/364 # See https://github.com/zsh-users/zsh-autosuggestions/issues/364
autoload -Uz is-at-least command true
is-at-least 5.8 || command true
# Read the pid from the child process # Read the pid from the child process
read _ZSH_AUTOSUGGEST_CHILD_PID <&$_ZSH_AUTOSUGGEST_ASYNC_FD read _ZSH_AUTOSUGGEST_CHILD_PID <&$_ZSH_AUTOSUGGEST_ASYNC_FD
@ -825,12 +836,11 @@ _zsh_autosuggest_async_response() {
zle autosuggest-suggest -- "$suggestion" zle autosuggest-suggest -- "$suggestion"
# Close the fd # Close the fd
builtin exec {1}<&- exec {1}<&-
fi fi
# Always remove the handler # Always remove the handler
zle -F "$1" zle -F "$1"
_ZSH_AUTOSUGGEST_ASYNC_FD=
} }
#--------------------------------------------------------------------# #--------------------------------------------------------------------#