If _ZSH_AUTOSUGGEST_ASYNC_FD is not cleared, something else may open the
file descriptor pointed to by it. And then the next call into
_zsh_autosuggest_async_request will close it causing trouble.
It seems like good practice to clean up _ZSH_AUTOSUGGEST_CHILD_PID as
well, though it's not directly causing any known problems at the moment.
I was able to produce errors with ZSH_AUTOSUGGEST_MANUAL_REBIND active
and sourcing a file async-widget-setup.zsh after the first precmd with
the plugin active. If manual rebind is not active or if the widgets are
created before the first precmd, then zsh-autosuggestions wraps the
widgets and for some reason we don't seem to get any fd conflicts.
The .zshrc:
```
ZSH_AUTOSUGGEST_MANUAL_REBIND=true
source zsh-autosuggestions.zsh
```
and async-widget-setup.zsh:
```
function async-widget-fork() {
exec {fd}< <(echo foo)
zle -M "opened: $fd, autosuggest fd: $_ZSH_AUTOSUGGEST_ASYNC_FD"
}
function async-widget-read() {
zle -M "reading from $fd: $(cat <&$fd)"
}
zle -N async-widget-fork
zle -N async-widget-read
bindkey ^A async-widget-fork
bindkey ^B async-widget-read
```
Then run `ZDOTDIR=$PWD zsh` and run `source async-widget-setup.zsh`. At
the next prompt, type one character e.g. "a" to trigger an async
request/response cycle. This leaves _ZSH_AUTOSUGGEST_ASYNC_FD set to the
stale file descriptor number. Then press ^A to activate the fork. This
will set the fd parameter to the same number as
_ZSH_AUTOSUGGEST_ASYNC_FD. Then type another character e.g. "a" to
trigger an async request. This will print a "No handler installed" error
and close the file descriptor pointed to by both
_ZSH_AUTOSUGGEST_ASYNC_FD and fd. Pressing ^B at this point will fail to
read with a "bad file descriptor" error.
The testing docker image has been split up. Instead of having one image
with all supported versions of zsh installed, we now have a separate
image for each supported zsh version.
We use GitHub Action matrices to run jobs in parallel for all of the
supported versions.
We no longer need to publish images to Docker Hub. The images are just
built by CI (or developers) as needed from the Dockerfile in the repo.
There's something funny occasionally happening when `with_history` is
used twice in the same test. It seems to be happening more frequently
since asynchronous mode was enabled by default. My guess is it has
something to do with the `C-c` keys being sent toward the end not
consistently terminating the prompt. But I'm really not sure how it
would ever get into a `then` block like it seems to:
```
Failure/Error: wait_for { session.content }.to eq('echo "hello\nworld"')
expected: "echo \"hello\\nworld\""
got: "then> echo \"hello\\"
```
Sticking to only one `with_history` per terminal session (per test)
seems to fix the flakiness.
I also removed an old test case because I could not understand why it
was necessary and so couldn't write a good description for it. Could be
we'll need to add it back in at some point.
To avoid wrapping the built-in widgets (e.g. `autosuggest-fetch`,
`autosuggest-toggle`), we were ignoring all widgets whose names start
with `autosuggest-`. This had the downside of preventing wrapping of
user-defined widgets whose names happened to also start with that
prefix.
By being more specific about the exact built-in widgets we want to avoid
wrapping, we can allow users to define widgets whose names start with
`autosuggest-`.
See GitHub issue #496.
Set ZSH_AUTOSUGGEST_COMPLETION_IGNORE to a glob pattern to have the
completion suggestion strategy never make suggestions when the buffer
matches the pattern.
This can be helpful when some completion routines you have are
particularly expensive and you want to prevent them from running
automatically on every keystroke.
See GitHub issue #463.
We are getting errors on circle ci builds (e.g. see [1]):
```
CircleCI was unable to run the job runner because we were unable to
execute commands in build container.
This typically means that the build container entrypoint or command is
terminating the container prematurely, or interfering with executed
commands. Consider clearing entrypoint/command values and try again.
```
Folks in this thread [2] suggest removing the `command: /sbin/init` line
initially added by the v1 => v2 migration script.
---
1: https://circleci.com/gh/zsh-users/zsh-autosuggestions/381
2: https://discuss.circleci.com/t/circleci-was-unable-to-run-the-job-runner/31894/18
We are getting errors on circle ci builds (e.g. see [1]):
```
CircleCI was unable to run the job runner because we were unable to
execute commands in build container.
This typically means that the build container entrypoint or command is
terminating the container prematurely, or interfering with executed
commands. Consider clearing entrypoint/command values and try again.
```
Folks in this thread [2] suggest removing the `command: /sbin/init` line
initially added by the v1 => v2 migration script.
---
1: https://circleci.com/gh/zsh-users/zsh-autosuggestions/381
2: https://discuss.circleci.com/t/circleci-was-unable-to-run-the-job-runner/31894/18
Set ZSH_AUTOSUGGEST_HISTORY_IGNORE to a glob pattern to have the history
and match_prev_cmd suggestion strategies never make suggestions matching
that pattern.
For example, set to "cd *" to never suggest any `cd` commands from
history (see issues #340 and #425). Or set to "?(#c50,)" to never
suggest anything 50 characters or longer (see issue #429).
$max_cursor_pos in this case was not the correct value to use. It was
calculated based on the old length of the $BUFFER. After the suggestion
is accepted, we need to recalculate the new max cursor length and use it
to set the $CURSOR.
Fixes issue #452. Follow-up to issue #302 (PR #450).
Typing `d` and then `l` runs `vi-delete` and then `vi-forward-char`. However,
by default, `vi-forward-char` is configured to accept the suggestion. So in
that case, the suggestion was being accepted and the cursor set to the end of
the buffer before the deletion was run.
The reason the user doesn't see the suggestion accepted is that `vi-delete`
doesn't finish until the movement widget is run, so we're already inside of a
`modify` when `accept` is called. `modify` unsets `POSTDISPLAY` before calling
the original widget so when we get to the accept function, `POSTDISPLAY` is
empty and thus accepting the suggestion is a no-op.
The fix is to make sure we reset the cursor to the correct place before running
the original widget.
We skip the test for versions of zsh below 5.0.8 since there was a bug in
earlier versions where deleting the last char did not work.
See http://www.zsh.org/mla/workers/2014/msg01316.html
When using async mode, stale background processes will not be cancelled
when a new one starts. This shouldn't cause any real issues since the
processes should eventually finish and be cleaned up anyway, and
removing the handler with `zle -F` means that stale suggestions should
never be shown.
Command substitution via $() trims trailing newlines so the old approach
to reading everything from the fd was preventing suggestions from ending
with newlines.
Found the read solution here: https://stackoverflow.com/a/15184414/154703
Just remove up to and including the first null byte and after and
including the last null byte.
I also looked into using `${${(0)line}[2]}`, but it fails when `$line`
starts with a null byte, since the first split string will be empty and
thus not included in the resulting array.
Use case suggested by @romkatv uses zle-line-init to restore buffer
after running a widget to cd up one level (GitHub #431).
As far as I can tell, the ignoring of zle-line-* was added in commit
9788c2e to support some deprecation warnings that were removed some time
ago.
The pattern was then widened in commit 0c940e7 to zle-* to fix problems
encountered when wrapping zle-isearch-update.
This commit removes the hard coded ignore of all zle-* widgets and adds
zle-* to the default list of widgets to be ignored. Users who want the
plugin to wrap zle-line-init or zle-line-finish can override the
default.