Commit graph

226 commits

Author SHA1 Message Date
Roman Perepelitsa
167d52e7d8 Fix bugs in async code
1. Insert `-` in `echo -nE "$suggestion"`. This is necessary to prevent
   `"$suggestion"` from being treated as an option for `echo`.
2. Close file descriptors only in `_zsh_autosuggest_async_response` to
   ensure that each file descriptor is closed only once.

It's the second bug that prompted the fix. The original code in some
cases could close the same file descriptor twice. The code relied on
an invalid assumption that `_zsh_autosuggest_async_response` cannot
fire after the file descriptor is closed. Here's a demo that shows
this assumption being violated:

    () {
      emulate -L zsh

      function callback1() {
        zle -I
        emulate -L zsh -o xtrace
        : "$@"
        zle -F $fd1
        exec {fd1}>&-
        zle -F $fd2
        exec {fd2}>&-
      }

      function callback2() {
        zle -I
        emulate -L zsh -o xtrace
        : "$@"
      }

      exec {fd1} </dev/null
      exec {fd2} </dev/null
      zle -F $fd1 callback1
      zle -F $fd2 callback2
    }

And here's the output I get if the code is pasted into an interactive zsh:

    +callback1:3> : 12
    +callback1:4> zle -F 12
    +callback1:6> zle -F 13
    +callback2:3> : 13

Note that `callback2` fires after its file descriptor has been closed
by `callback1`.

This bug was the culprit of several issues filed against powerlevel10k.
In a nutshell:

1. `_zsh_autosuggest_async_request` opens a file.
2. `_zsh_autosuggest_async_request` closes the file descriptor.
3. powerlevel10k opens a file and gets the same file descriptor as above.
4. `_zsh_autosuggest_async_response` fires and closes the same file descriptor.
5. powerlevel10k encounters errors when trying to read from the file descriptor.
2023-07-26 13:06:13 +02:00
Eric Freese
fcca87555f v0.7.0 2021-06-04 16:02:12 -06:00
Eric Freese
3ecc53dfe2 Update license copyright year 2021-06-04 16:02:12 -06:00
Eric Freese
aa05920a4a Merge remote-tracking branch 'origin/pull/541' into develop 2021-06-04 15:33:29 -06:00
Andrew Tropin
590c1cd84c
Disable ^C async workaround for zsh version 5.8 and later 2021-06-03 19:42:58 +03:00
Roman Perepelitsa
e0b96e1bd6 fix a bug in partial acceptance of suggestions
To reproduce:

1. Run `zsh -f`.
2. Run this:
  function bye() { BUFFER=bye }
  zle -N bye
  bindkey '^B' bye
  print -s 'hibye unexpected'
  source ~/zsh-autosuggestions/zsh-autosuggestions.zsh
3. Type `hi` and press Ctrl-B.

Expected: POSTBUFFER is empty.

Actual: POSTBUFFER is " unexpected".
2020-05-29 09:41:39 +02:00
Eric Freese
9ad039443f
Merge pull request #504 from zsh-users/ef/async-by-default
Enable async mode by default in newer versions of zsh
2020-01-29 20:54:46 -07:00
Eric Freese
a32fe24acc
Merge pull request #502 from zsh-users/cleanup/idiomatic-check-if-set
cleanup: Use more idiomatic method of checking if var is set
2020-01-27 21:46:14 -07:00
Eric Freese
6c634c1e35 Enable async mode by default in newer versions of zsh
Allow users to override the default by unsetting (or setting) the
ZSH_AUTOSUGGEST_USE_ASYNC variable.

See GitHub issue #498.
2020-01-26 21:18:49 -07:00
Eric Freese
19e375bbc8 cleanup: Consolidate autoloads 2020-01-26 21:15:47 -07:00
Eric Freese
c114bd2298 Be more specific about the built-in widgets we want to avoid wrapping
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.
2020-01-25 08:01:37 -07:00
Eric Freese
7682c13860 cleanup: Pull built-in widget actions into global variable 2020-01-25 08:01:37 -07:00
Eric Freese
f90d040784 cleanup: Use more idiomatic method of checking if var is set
We are already using this method in other places.

For example: `ZSH_AUTOSUGGEST_USE_ASYNC`
2020-01-25 07:46:20 -07:00
Eric Freese
a5affac6f1 v0.6.4 2020-01-06 21:06:16 -07:00
Eric Freese
cf445d08b0
Merge pull request #487 from zsh-users/features/completion-ignore
Allow skipping completion suggestions when buffer matches a pattern
2020-01-04 16:52:35 -07:00
Eric Freese
0d2c9de2ea
Merge pull request #488 from zsh-users/fixes/run-orig-before-move-cursor
Call original widget before moving cursor when accepting suggestion
2020-01-04 16:52:18 -07:00
Eric Freese
6ec95379fa Call original widget before moving cursor when accepting suggestion
The check on length of `$POSTDISPLAY` is in support of the test for
`vi-delete` on the last char of the buffer with `dl`.

Fixes issue #482.
2019-12-15 08:33:20 -07:00
Eric Freese
7afb7364f1 Allow skipping completion suggestions when buffer matches a pattern
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.
2019-12-15 08:13:54 -07:00
Eric Freese
54d7a9a84c cleanup: Switch to guard clause in accept widget handler 2019-12-15 07:01:39 -07:00
Eric Freese
5217ed5269 cleanup: Switch to arithmetic comparison 2019-12-15 07:01:39 -07:00
Eric Freese
ef657cb38c cleanup: Combine two arithmetic conditionals 2019-12-15 07:01:39 -07:00
Eric Freese
0f0f221180 cleanup: Split on null bytes instead of pattern matching
Follow-up to technique tried in commit d94475c after I learned about the
`@` flag to keep empty strings in the array.
2019-09-30 12:12:52 -06:00
Eric Freese
b87a4972c8 Allow configuring to ignore history entries matching a pattern
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).
2019-07-02 21:46:17 -06:00
Eric Freese
0636a39b51 0.6.3 2019-06-24 09:10:42 -06:00
Eric Freese
78e4379711 Fix moving cursor to end of buffer when suggestion accepted
$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).
2019-06-23 12:37:08 -06:00
Eric Freese
c80605595c
Merge pull request #451 from zsh-users/develop
v0.6.2
2019-06-22 16:57:19 -06:00
Eric Freese
cb52adf429 v0.6.2 2019-06-22 16:54:32 -06:00
Eric Freese
676aebdf44 Fix deleting last character in vi mode (#302)
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
2019-06-22 16:34:42 -06:00
Eric Freese
a437544cc5 Degrade gracefully on systems missing zsh/system module
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.
2019-06-19 13:41:43 -06:00
Eric Freese
8a812bdfd2 v0.6.1 2019-06-18 11:04:24 -06:00
Eric Freese
adb02c44a2 Prefix custom _complete implementation with "function" keyword
For some reason, when `_complete` is aliased before sourcing the plugin,
zsh was blowing up with a parse error. Adding "function" keyword makes
it parse successfully.

See similar issue: https://github.com/robbyrussell/oh-my-zsh/issues/6723#issuecomment-381220834

Fixes GitHub #442
2019-06-17 22:04:31 -06:00
Eric Freese
3654b83ec0 Update license copyright year in built plugin file
Should have been committed with 19c976f
2019-06-17 21:58:31 -06:00
Eric Freese
3250778ce8 v0.6.0 2019-06-15 21:39:57 -06:00
Eric Freese
f543ba08c3 Fix cr/lf handling in completion strategy 2019-06-15 21:17:58 -06:00
Eric Freese
68343c8de4 Allow suggestions to suggest trailing newlines
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
2019-06-15 21:17:58 -06:00
Eric Freese
d94475ca1b Simplify logic to extract suggestion from between null bytes
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.
2019-06-15 21:17:58 -06:00
Eric Freese
c04e015d13 Add to explanation of extra stuff after zpty -r 2019-06-15 21:17:58 -06:00
Eric Freese
e9ce05c4c1 Ensure that kill succeeds even in older buggy versions of zsh
See https://unix.stackexchange.com/a/477647/156673
2019-06-15 21:17:58 -06:00
Eric Freese
fdf4502c5c We need to autoload is-at-least for it to be available
This error was hidden inside the zpty
2019-06-15 21:17:58 -06:00
Eric Freese
7e048c3f53 Fix error that was hidden in zpty
Without the quotes, this was blowing up with:
  _zsh_autosuggest_capture_postcompletion:unset:5: not enough arguments
2019-06-15 21:17:58 -06:00
Eric Freese
2b05f5ed2d Add a comment explaining post-completion hook 2019-06-15 21:17:58 -06:00
Eric Freese
0d3bbaf8e6 Remove hard-coded ignore of zle-* widgets and add to default config
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.
2019-06-14 16:38:28 -06:00
Henré Botha
15bcfd7126 Don't fetch suggestions after copy-earlier-word
Like {up,down}-line-or-beginning-search, this widget relies on
`$LASTWIDGET` being set to function correctly on subsequent invocations.

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.
2019-06-14 13:19:07 -06:00
Eric Freese
474c577f3c Allow setting max size to empty string (GitHub #422)
Some people have gotten used to setting ZSH_AUTOSUGGEST_BUFFER_MAX_SIZE
to an empty string rather than leaving it unset. This lets them continue
to do that without getting any warnings (e.g. "bad math expression:
operand expected at end of string").
2019-05-27 14:18:21 -06:00
Eric Freese
e9d8231ba7
Merge pull request #401 from zsh-users/features/completion-suggestions
Features/completion suggestions
2019-04-15 12:55:35 -06:00
Eric Freese
152d2c6b31 v0.5.2 2019-04-11 10:15:46 -06:00
Eric Freese
c1910348c7 Implement completion suggestion strategy (#111)
Based on https://github.com/Valodim/zsh-capture-completion

`zpty -r` with a pattern seems to have some funky behavior on older
versions, giving unpredictable results

Don't use `-s` option to `zmodload`. It is not available in zsh versions
older than 5.3

If running in sync mode and a completion takes a long time, the user can
^C out of it. We need to use `always` in the strategy function or the
pty will not be destroyed in this case and the next time we go to create
it, it will fail, making the shell unusable.

User can have many different completion styles set that will modify what
they've already typed. These styles will result in suggestions that
don't match what the user has already typed. We try our best to unset
some of the more problematic ones, but add some code to fetch to
invalidate suggestions that don't match what the user's already typed.
2019-04-11 09:53:55 -06:00
Eric Freese
b9fee8a324 Allow disabling of automatic widget re-binding
Addresses github #411
2019-04-10 11:43:21 -06:00
Eric Freese
db290c518b cleanup: Leave max size config unset by default to match other options 2019-04-10 11:43:20 -06:00
Eric Freese
d8ba53678e cleanup: Use + param expansion flag in arithmetic context 2019-04-10 11:42:25 -06:00