Compare commits

..

No commits in common. "master" and "v0.6.4" have entirely different histories.

23 changed files with 166 additions and 254 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
## 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
- 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)

View File

@ -1,8 +1,5 @@
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 libtool
RUN apk add --no-cache libcap-dev
@ -14,8 +11,10 @@ RUN apk add --no-cache tmux
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
ADD Gemfile Gemfile.lock ./
ADD Gemfile /zsh-autosuggestions/Gemfile
ADD Gemfile.lock /zsh-autosuggestions/Gemfile.lock
RUN bundle install

View File

@ -3,21 +3,19 @@
* [Packages](#packages)
* [Antigen](#antigen)
* [Oh My Zsh](#oh-my-zsh)
* [HomeBrew](#homebrew)
* [Manual](#manual-git-clone)
## Packages
| 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) |
| 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) |
| 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) |
| 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) |
## Antigen
@ -41,25 +39,7 @@
2. Add the plugin to the list of plugins for Oh My Zsh to load (inside `~/.zshrc`):
```sh
plugins=(
# 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
plugins=(zsh-autosuggestions)
```
3. Start a new terminal session.

View File

@ -1,5 +1,5 @@
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
obtaining a copy of this software and associated documentation

View File

@ -1,4 +1,4 @@
SRC_DIR := ./src
SRC_DIR := ./src
SRC_FILES := \
$(SRC_DIR)/config.zsh \

View File

@ -6,6 +6,7 @@ It suggests commands as you type based on history and completions.
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)
<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:
- `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`.
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.
@ -78,11 +79,9 @@ Widgets that modify the buffer and are not found in any of these arrays will fet
Set `ZSH_AUTOSUGGEST_BUFFER_MAX_SIZE` to an integer value to disable autosuggestion for large buffers. The default is unset, which means that autosuggestion will be tried for any buffer size. Recommended value is 20.
This can be useful when pasting large amount of text in the terminal, to avoid triggering autosuggestion for strings that are too long.
### Asynchronous Mode
### Enable Asynchronous Mode
Suggestions are fetched asynchronously by default in zsh versions 5.0.8 and greater. To disable asynchronous suggestions and fetch them synchronously instead, `unset ZSH_AUTOSUGGEST_USE_ASYNC` after sourcing the plugin.
Alternatively, if you are using a version of zsh older than 5.0.8 and want to enable asynchronous mode, set the `ZSH_AUTOSUGGEST_USE_ASYNC` variable after sourcing the plugin (it can be set to anything). Note that there is [a bug](https://github.com/zsh-users/zsh-autosuggestions/issues/364#issuecomment-481423232) in versions of zsh older than 5.0.8 where <kbd>ctrl</kbd> + <kbd>c</kbd> will fail to reset the prompt immediately after fetching a suggestion asynchronously.
As of `v0.4.0`, suggestions can be fetched asynchronously. To enable this behavior, set the `ZSH_AUTOSUGGEST_USE_ASYNC` variable (it can be set to anything).
### Disabling automatic widget re-binding
@ -90,13 +89,13 @@ Set `ZSH_AUTOSUGGEST_MANUAL_REBIND` (it can be set to anything) to disable autom
### Ignoring history suggestions that match a pattern
Set `ZSH_AUTOSUGGEST_HISTORY_IGNORE` to a [glob pattern](http://zsh.sourceforge.net/Doc/Release/Expansion.html#Glob-Operators) to prevent offering suggestions for history entries that match the pattern. For example, set it to `"cd *"` to never suggest any `cd` commands from history. Or set to `"?(#c50,)"` to never suggest anything 50 characters or longer.
Set `ZSH_AUTOSUGGEST_HISTORY_IGNORE` to a glob pattern to prevent offering suggestions for history entries that match the pattern. For example, set it to `"cd *"` to never suggest any `cd` commands from history. Or set to `"?(#c50,)"` to never suggest anything 50 characters or longer.
**Note:** This only affects the `history` and `match_prev_cmd` suggestion strategies.
### Skipping completion suggestions for certain cases
Set `ZSH_AUTOSUGGEST_COMPLETION_IGNORE` to a [glob pattern](http://zsh.sourceforge.net/Doc/Release/Expansion.html#Glob-Operators) to prevent offering completion suggestions when the buffer matches that pattern. For example, set it to `"git *"` to disable completion suggestions for git subcommands.
Set `ZSH_AUTOSUGGEST_COMPLETION_IGNORE` to a glob pattern to prevent offering completion suggestions when the buffer matches that pattern. For example, set it to `"git *"` to disable completion suggestions for git subcommands.
**Note:** This only affects the `completion` suggestion strategy.
@ -169,16 +168,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`).
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
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
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
# 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
5.0.2
5.0.8
@ -10,5 +14,3 @@
5.5.1
5.6.2
5.7.1
5.8.1
5.9

View File

@ -2,22 +2,25 @@
set -ex
mkdir zsh-build
cd zsh-build
for v in $(grep "^[^#]" ZSH_VERSIONS); do
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
./configure --enable-pcre \
--enable-cap \
--enable-multibyte \
--with-term-lib='ncursesw tinfo' \
--with-tcsetpgrp
./Util/preconfig
./configure --enable-pcre \
--enable-cap \
--enable-multibyte \
--with-term-lib='ncursesw tinfo' \
--with-tcsetpgrp \
--program-suffix="-$v"
make install.bin
make install.modules
make install.fns
make install.bin
make install.modules
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
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')
wait_for { session.content }.to eq("echo \"\n\"")
end

View File

@ -0,0 +1,7 @@
describe 'suggestion fetching' do
it 'is performed synchronously'
context 'when ZSH_AUTOSUGGEST_USE_ASYNC is set' do
it 'is performed asynchronously'
end
end

View File

@ -1,7 +1,6 @@
require 'pry'
require 'rspec/wait'
require 'terminal_session'
require 'tempfile'
RSpec.shared_context 'terminal session' do
let(:term_opts) { {} }
@ -22,20 +21,18 @@ RSpec.shared_context 'terminal session' do
end
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}")
session.clear_screen
yield block
session.send_keys('C-c')
session.run_command('fc -P')
commands.each do |c|
c.respond_to?(:call) ? c.call : session.run_command(c)
end
session.clear_screen
yield block
session.send_keys('C-c')
session.run_command('fc -P')
end
end

View File

@ -1,71 +1,58 @@
shared_examples 'special characters' do
describe 'a special character in the buffer should be treated like any other character' do
it 'asterisk' do
describe 'a special character in the buffer' do
it 'should be treated like any other character' do
with_history('echo "hello*"', 'echo "hello."') do
session.send_string('echo "hello*')
wait_for { session.content }.to eq('echo "hello*"')
end
end
it 'question mark' do
with_history('echo "hello?"', 'echo "hello."') do
session.send_string('echo "hello?')
wait_for { session.content }.to eq('echo "hello?"')
end
end
it 'backslash' do
with_history('echo "hello\nworld"') do
session.send_string('echo "hello\\')
wait_for { session.content }.to eq('echo "hello\nworld"')
end
end
it 'double backslash' do
with_history('echo "\\\\"') do
session.send_string('echo "\\\\')
wait_for { session.content }.to eq('echo "\\\\"')
end
end
it 'tilde' do
with_history('echo ~/foo') do
session.send_string('echo ~')
wait_for { session.content }.to eq('echo ~/foo')
end
end
it 'parentheses' do
with_history('echo "$(ls foo)"') do
session.send_string('echo "$(')
wait_for { session.content }.to eq('echo "$(ls foo)"')
end
end
it 'square bracket' do
with_history('echo "$history[123]"') do
session.send_string('echo "$history[')
wait_for { session.content }.to eq('echo "$history[123]"')
session.send_string('123]')
wait_for { session.content }.to eq('echo "$history[123]"')
end
end
it 'octothorpe' do
with_history('echo "#yolo"') do
session.send_string('echo "#')
wait_for { session.content }.to eq('echo "#yolo"')
end
end
it 'caret' do
with_history('echo "#foo"', 'echo $#abc') do
session.send_string('echo "#')
wait_for { session.content }.to eq('echo "#foo"')
end
with_history('echo "^A"', 'echo "^B"') do
session.send_string('echo "^A')
wait_for { session.content }.to eq('echo "^A"')
end
end
it 'dash' do
with_history('-foo() {}') do
session.send_string('-')
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 [[ -n "$_ZSH_AUTOSUGGEST_ASYNC_FD" ]] && { true <&$_ZSH_AUTOSUGGEST_ASYNC_FD } 2>/dev/null; then
# 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
# We won't know the pid unless the user has zsh/system module installed
@ -32,7 +32,7 @@ _zsh_autosuggest_async_request() {
fi
# 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
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
# See https://github.com/zsh-users/zsh-autosuggestions/issues/364
autoload -Uz is-at-least
is-at-least 5.8 || command true
command true
# Read the pid from the child process
read _ZSH_AUTOSUGGEST_CHILD_PID <&$_ZSH_AUTOSUGGEST_ASYNC_FD
@ -68,10 +67,9 @@ _zsh_autosuggest_async_response() {
zle autosuggest-suggest -- "$suggestion"
# Close the fd
builtin exec {1}<&-
exec {1}<&-
fi
# Always remove the handler
zle -F "$1"
_ZSH_AUTOSUGGEST_ASYNC_FD=
}

View File

@ -69,7 +69,7 @@ _zsh_autosuggest_bind_widgets() {
ignore_widgets=(
.\*
_\*
${_ZSH_AUTOSUGGEST_BUILTIN_ACTIONS/#/autosuggest-}
autosuggest-\*
$ZSH_AUTOSUGGEST_ORIGINAL_WIDGET_PREFIX\*
$ZSH_AUTOSUGGEST_IGNORE_WIDGETS
)

View File

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

View File

@ -18,16 +18,6 @@ _zsh_autosuggest_start() {
_zsh_autosuggest_bind_widgets
}
# Mark for auto-loading the functions that we use
autoload -Uz add-zsh-hook is-at-least
# Automatically enable asynchronous mode in newer versions of zsh. Disable for
# older versions because there is a bug when using async mode where ^C does not
# work immediately after fetching a suggestion.
# See https://github.com/zsh-users/zsh-autosuggestions/issues/364
if is-at-least 5.0.8; then
typeset -g ZSH_AUTOSUGGEST_USE_ASYNC=
fi
# Start the autosuggestion widgets on the next precmd
autoload -Uz add-zsh-hook
add-zsh-hook precmd _zsh_autosuggest_start

View File

@ -45,6 +45,8 @@ _zsh_autosuggest_capture_completion_widget() {
zle -N autosuggest-capture-completion _zsh_autosuggest_capture_completion_widget
_zsh_autosuggest_capture_setup() {
autoload -Uz is-at-least
# There is a bug in zpty module in older zsh versions by which a
# zpty that exits will kill all zpty processes that were forked
# before it. Here we set up a zsh exit hook to SIGKILL the zpty

View File

@ -20,7 +20,7 @@ _zsh_autosuggest_enable() {
# Toggle suggestions (enable/disable)
_zsh_autosuggest_toggle() {
if (( ${+_ZSH_AUTOSUGGEST_DISABLED} )); then
if [[ -n "${_ZSH_AUTOSUGGEST_DISABLED+x}" ]]; then
_zsh_autosuggest_enable
else
_zsh_autosuggest_disable
@ -30,7 +30,7 @@ _zsh_autosuggest_toggle() {
# Clear the suggestion
_zsh_autosuggest_clear() {
# Remove the suggestion
POSTDISPLAY=
unset POSTDISPLAY
_zsh_autosuggest_invoke_original_widget $@
}
@ -47,7 +47,7 @@ _zsh_autosuggest_modify() {
local orig_postdisplay="$POSTDISPLAY"
# Clear suggestion while waiting for next one
POSTDISPLAY=
unset POSTDISPLAY
# Original widget may modify the buffer
_zsh_autosuggest_invoke_original_widget $@
@ -61,14 +61,25 @@ _zsh_autosuggest_modify() {
return $retval
fi
# Optimize if manually typing in the suggestion or if buffer hasn't changed
if [[ "$BUFFER" = "$orig_buffer"* && "$orig_postdisplay" = "${BUFFER:$#orig_buffer}"* ]]; then
POSTDISPLAY="${orig_postdisplay:$(($#BUFFER - $#orig_buffer))}"
# Optimize if manually typing in the suggestion
if (( $#BUFFER > $#orig_buffer )); then
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
fi
# Bail out if suggestions are disabled
if (( ${+_ZSH_AUTOSUGGEST_DISABLED} )); then
if [[ -n "${_ZSH_AUTOSUGGEST_DISABLED+x}" ]]; then
return $?
fi
@ -102,7 +113,7 @@ _zsh_autosuggest_suggest() {
if [[ -n "$suggestion" ]] && (( $#BUFFER )); then
POSTDISPLAY="${suggestion#$BUFFER}"
else
POSTDISPLAY=
unset POSTDISPLAY
fi
}
@ -128,7 +139,7 @@ _zsh_autosuggest_accept() {
BUFFER="$BUFFER$POSTDISPLAY"
# Remove the suggestion
POSTDISPLAY=
unset POSTDISPLAY
# Run the original widget before manually moving the cursor so that the
# cursor movement doesn't make the widget do something unexpected
@ -151,7 +162,7 @@ _zsh_autosuggest_execute() {
BUFFER="$BUFFER$POSTDISPLAY"
# Remove the suggestion
POSTDISPLAY=
unset POSTDISPLAY
# Call the original `accept-line` to handle syntax highlighting or
# other potential custom behavior
@ -194,21 +205,8 @@ _zsh_autosuggest_partial_accept() {
}
() {
typeset -ga _ZSH_AUTOSUGGEST_BUILTIN_ACTIONS
_ZSH_AUTOSUGGEST_BUILTIN_ACTIONS=(
clear
fetch
suggest
accept
execute
enable
disable
toggle
)
local action
for action in $_ZSH_AUTOSUGGEST_BUILTIN_ACTIONS modify partial_accept; do
for action in clear modify fetch suggest accept partial_accept execute enable disable toggle; do
eval "_zsh_autosuggest_widget_$action() {
local -i retval
@ -225,7 +223,12 @@ _zsh_autosuggest_partial_accept() {
}"
done
for action in $_ZSH_AUTOSUGGEST_BUILTIN_ACTIONS; do
zle -N autosuggest-$action _zsh_autosuggest_widget_$action
done
zle -N autosuggest-fetch _zsh_autosuggest_widget_fetch
zle -N autosuggest-suggest _zsh_autosuggest_widget_suggest
zle -N autosuggest-accept _zsh_autosuggest_widget_accept
zle -N autosuggest-clear _zsh_autosuggest_widget_clear
zle -N autosuggest-execute _zsh_autosuggest_widget_execute
zle -N autosuggest-enable _zsh_autosuggest_widget_enable
zle -N autosuggest-disable _zsh_autosuggest_widget_disable
zle -N autosuggest-toggle _zsh_autosuggest_widget_toggle
}

View File

@ -1,8 +1,8 @@
# Fish-like fast/unobtrusive autosuggestions for zsh.
# https://github.com/zsh-users/zsh-autosuggestions
# v0.7.1
# v0.6.4
# 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
# 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-beginning-search-forward
history-beginning-search-backward
history-beginning-search-forward-end
history-beginning-search-backward-end
history-substring-search-up
history-substring-search-down
up-line-or-beginning-search
@ -201,7 +199,7 @@ _zsh_autosuggest_bind_widgets() {
ignore_widgets=(
.\*
_\*
${_ZSH_AUTOSUGGEST_BUILTIN_ACTIONS/#/autosuggest-}
autosuggest-\*
$ZSH_AUTOSUGGEST_ORIGINAL_WIDGET_PREFIX\*
$ZSH_AUTOSUGGEST_IGNORE_WIDGETS
)
@ -284,7 +282,7 @@ _zsh_autosuggest_enable() {
# Toggle suggestions (enable/disable)
_zsh_autosuggest_toggle() {
if (( ${+_ZSH_AUTOSUGGEST_DISABLED} )); then
if [[ -n "${_ZSH_AUTOSUGGEST_DISABLED+x}" ]]; then
_zsh_autosuggest_enable
else
_zsh_autosuggest_disable
@ -294,7 +292,7 @@ _zsh_autosuggest_toggle() {
# Clear the suggestion
_zsh_autosuggest_clear() {
# Remove the suggestion
POSTDISPLAY=
unset POSTDISPLAY
_zsh_autosuggest_invoke_original_widget $@
}
@ -311,7 +309,7 @@ _zsh_autosuggest_modify() {
local orig_postdisplay="$POSTDISPLAY"
# Clear suggestion while waiting for next one
POSTDISPLAY=
unset POSTDISPLAY
# Original widget may modify the buffer
_zsh_autosuggest_invoke_original_widget $@
@ -325,14 +323,25 @@ _zsh_autosuggest_modify() {
return $retval
fi
# Optimize if manually typing in the suggestion or if buffer hasn't changed
if [[ "$BUFFER" = "$orig_buffer"* && "$orig_postdisplay" = "${BUFFER:$#orig_buffer}"* ]]; then
POSTDISPLAY="${orig_postdisplay:$(($#BUFFER - $#orig_buffer))}"
# Optimize if manually typing in the suggestion
if (( $#BUFFER > $#orig_buffer )); then
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
fi
# Bail out if suggestions are disabled
if (( ${+_ZSH_AUTOSUGGEST_DISABLED} )); then
if [[ -n "${_ZSH_AUTOSUGGEST_DISABLED+x}" ]]; then
return $?
fi
@ -366,7 +375,7 @@ _zsh_autosuggest_suggest() {
if [[ -n "$suggestion" ]] && (( $#BUFFER )); then
POSTDISPLAY="${suggestion#$BUFFER}"
else
POSTDISPLAY=
unset POSTDISPLAY
fi
}
@ -392,7 +401,7 @@ _zsh_autosuggest_accept() {
BUFFER="$BUFFER$POSTDISPLAY"
# Remove the suggestion
POSTDISPLAY=
unset POSTDISPLAY
# Run the original widget before manually moving the cursor so that the
# cursor movement doesn't make the widget do something unexpected
@ -415,7 +424,7 @@ _zsh_autosuggest_execute() {
BUFFER="$BUFFER$POSTDISPLAY"
# Remove the suggestion
POSTDISPLAY=
unset POSTDISPLAY
# Call the original `accept-line` to handle syntax highlighting or
# other potential custom behavior
@ -458,21 +467,8 @@ _zsh_autosuggest_partial_accept() {
}
() {
typeset -ga _ZSH_AUTOSUGGEST_BUILTIN_ACTIONS
_ZSH_AUTOSUGGEST_BUILTIN_ACTIONS=(
clear
fetch
suggest
accept
execute
enable
disable
toggle
)
local action
for action in $_ZSH_AUTOSUGGEST_BUILTIN_ACTIONS modify partial_accept; do
for action in clear modify fetch suggest accept partial_accept execute enable disable toggle; do
eval "_zsh_autosuggest_widget_$action() {
local -i retval
@ -489,9 +485,14 @@ _zsh_autosuggest_partial_accept() {
}"
done
for action in $_ZSH_AUTOSUGGEST_BUILTIN_ACTIONS; do
zle -N autosuggest-$action _zsh_autosuggest_widget_$action
done
zle -N autosuggest-fetch _zsh_autosuggest_widget_fetch
zle -N autosuggest-suggest _zsh_autosuggest_widget_suggest
zle -N autosuggest-accept _zsh_autosuggest_widget_accept
zle -N autosuggest-clear _zsh_autosuggest_widget_clear
zle -N autosuggest-execute _zsh_autosuggest_widget_execute
zle -N autosuggest-enable _zsh_autosuggest_widget_enable
zle -N autosuggest-disable _zsh_autosuggest_widget_disable
zle -N autosuggest-toggle _zsh_autosuggest_widget_toggle
}
#--------------------------------------------------------------------#
@ -540,6 +541,8 @@ _zsh_autosuggest_capture_completion_widget() {
zle -N autosuggest-capture-completion _zsh_autosuggest_capture_completion_widget
_zsh_autosuggest_capture_setup() {
autoload -Uz is-at-least
# There is a bug in zpty module in older zsh versions by which a
# zpty that exits will kill all zpty processes that were forked
# before it. Here we set up a zsh exit hook to SIGKILL the zpty
@ -768,7 +771,7 @@ _zsh_autosuggest_async_request() {
# If we've got a pending request, cancel it
if [[ -n "$_ZSH_AUTOSUGGEST_ASYNC_FD" ]] && { true <&$_ZSH_AUTOSUGGEST_ASYNC_FD } 2>/dev/null; then
# 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
# We won't know the pid unless the user has zsh/system module installed
@ -789,7 +792,7 @@ _zsh_autosuggest_async_request() {
fi
# 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
echo $sysparams[pid]
@ -801,8 +804,7 @@ _zsh_autosuggest_async_request() {
# 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
autoload -Uz is-at-least
is-at-least 5.8 || command true
command true
# Read the pid from the child process
read _ZSH_AUTOSUGGEST_CHILD_PID <&$_ZSH_AUTOSUGGEST_ASYNC_FD
@ -825,12 +827,11 @@ _zsh_autosuggest_async_response() {
zle autosuggest-suggest -- "$suggestion"
# Close the fd
builtin exec {1}<&-
exec {1}<&-
fi
# Always remove the handler
zle -F "$1"
_ZSH_AUTOSUGGEST_ASYNC_FD=
}
#--------------------------------------------------------------------#
@ -852,16 +853,6 @@ _zsh_autosuggest_start() {
_zsh_autosuggest_bind_widgets
}
# Mark for auto-loading the functions that we use
autoload -Uz add-zsh-hook is-at-least
# Automatically enable asynchronous mode in newer versions of zsh. Disable for
# older versions because there is a bug when using async mode where ^C does not
# work immediately after fetching a suggestion.
# See https://github.com/zsh-users/zsh-autosuggestions/issues/364
if is-at-least 5.0.8; then
typeset -g ZSH_AUTOSUGGEST_USE_ASYNC=
fi
# Start the autosuggestion widgets on the next precmd
autoload -Uz add-zsh-hook
add-zsh-hook precmd _zsh_autosuggest_start