mirror of
https://github.com/zsh-users/zsh-autosuggestions.git
synced 2024-11-18 09:51:06 +01:00
Revert async process substitution & completion strategy
They're not quite ready. Keep them on a feature branch for now.
This commit is contained in:
parent
4838222dde
commit
41657e3565
15 changed files with 333 additions and 340 deletions
2
Makefile
2
Makefile
|
@ -1,8 +1,10 @@
|
||||||
SRC_DIR := ./src
|
SRC_DIR := ./src
|
||||||
|
|
||||||
SRC_FILES := \
|
SRC_FILES := \
|
||||||
|
$(SRC_DIR)/setup.zsh \
|
||||||
$(SRC_DIR)/config.zsh \
|
$(SRC_DIR)/config.zsh \
|
||||||
$(SRC_DIR)/util.zsh \
|
$(SRC_DIR)/util.zsh \
|
||||||
|
$(SRC_DIR)/features.zsh \
|
||||||
$(SRC_DIR)/bind.zsh \
|
$(SRC_DIR)/bind.zsh \
|
||||||
$(SRC_DIR)/highlight.zsh \
|
$(SRC_DIR)/highlight.zsh \
|
||||||
$(SRC_DIR)/widgets.zsh \
|
$(SRC_DIR)/widgets.zsh \
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
_[Fish](http://fishshell.com/)-like fast/unobtrusive autosuggestions for zsh._
|
_[Fish](http://fishshell.com/)-like fast/unobtrusive autosuggestions for zsh._
|
||||||
|
|
||||||
It suggests commands as you type.
|
It suggests commands as you type, based on command history.
|
||||||
|
|
||||||
Requirements: Zsh v4.3.11 or later
|
Requirements: Zsh v4.3.11 or later
|
||||||
|
|
||||||
|
@ -39,13 +39,10 @@ Set `ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE` to configure the style that the suggestion
|
||||||
|
|
||||||
### Suggestion Strategy
|
### Suggestion Strategy
|
||||||
|
|
||||||
`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 two built-in strategies to choose from:
|
||||||
|
|
||||||
- `history`: Chooses the most recent match from history.
|
- `history`: Chooses the most recent match from history.
|
||||||
- `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`.
|
||||||
- `completion`: (experimental) Chooses a suggestion based on what tab-completion would suggest. (requires `zpty` module)
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
|
|
||||||
### Widget Mapping
|
### Widget Mapping
|
||||||
|
@ -70,7 +67,7 @@ This can be useful when pasting large amount of text in the terminal, to avoid t
|
||||||
|
|
||||||
### Enable Asynchronous Mode
|
### Enable Asynchronous Mode
|
||||||
|
|
||||||
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).
|
As of `v0.4.0`, suggestions can be fetched asynchronously using the `zsh/zpty` module. To enable this behavior, set the `ZSH_AUTOSUGGEST_USE_ASYNC` variable (it can be set to anything).
|
||||||
|
|
||||||
|
|
||||||
### Key Bindings
|
### Key Bindings
|
||||||
|
|
|
@ -1,4 +1,8 @@
|
||||||
context 'with asynchronous suggestions enabled' do
|
context 'with asynchronous suggestions enabled' do
|
||||||
|
before do
|
||||||
|
skip 'Async mode not supported below v5.0.8' if session.zsh_version < Gem::Version.new('5.0.8')
|
||||||
|
end
|
||||||
|
|
||||||
let(:options) { ["ZSH_AUTOSUGGEST_USE_ASYNC="] }
|
let(:options) { ["ZSH_AUTOSUGGEST_USE_ASYNC="] }
|
||||||
|
|
||||||
describe '`up-line-or-beginning-search`' do
|
describe '`up-line-or-beginning-search`' do
|
||||||
|
@ -26,6 +30,55 @@ context 'with asynchronous suggestions enabled' do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'should not add extra carriage returns before newlines' do
|
||||||
|
session.
|
||||||
|
send_string('echo "').
|
||||||
|
send_keys('escape').
|
||||||
|
send_keys('enter').
|
||||||
|
send_string('"').
|
||||||
|
send_keys('enter')
|
||||||
|
|
||||||
|
session.clear_screen
|
||||||
|
|
||||||
|
session.send_string('echo')
|
||||||
|
wait_for { session.content }.to eq("echo \"\n\"")
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'should treat carriage returns and newlines as separate characters' do
|
||||||
|
session.
|
||||||
|
send_string('echo "').
|
||||||
|
send_keys('C-v').
|
||||||
|
send_keys('enter').
|
||||||
|
send_string('foo"').
|
||||||
|
send_keys('enter')
|
||||||
|
|
||||||
|
session.
|
||||||
|
send_string('echo "').
|
||||||
|
send_keys('control').
|
||||||
|
send_keys('enter').
|
||||||
|
send_string('bar"').
|
||||||
|
send_keys('enter')
|
||||||
|
|
||||||
|
session.clear_screen
|
||||||
|
|
||||||
|
session.
|
||||||
|
send_string('echo "').
|
||||||
|
send_keys('C-v').
|
||||||
|
send_keys('enter')
|
||||||
|
|
||||||
|
wait_for { session.content }.to eq('echo "^Mfoo"')
|
||||||
|
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
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,14 +1,10 @@
|
||||||
describe 'a running zpty command' do
|
describe 'a running zpty command' do
|
||||||
let(:before_sourcing) { -> { session.run_command('zmodload zsh/zpty && zpty -b kitty cat') } }
|
let(:before_sourcing) { -> { session.run_command('zmodload zsh/zpty && zpty -b kitty cat') } }
|
||||||
|
|
||||||
context 'when using `completion` strategy' do
|
it 'is not affected by running zsh-autosuggestions' do
|
||||||
let(:options) { ["ZSH_AUTOSUGGEST_STRATEGY=completion"] }
|
sleep 1 # Give a little time for precmd hooks to run
|
||||||
|
session.run_command('zpty -t kitty; echo $?')
|
||||||
|
|
||||||
it 'is not affected' do
|
wait_for { session.content }.to end_with("\n0")
|
||||||
session.send_keys('a').send_keys('C-h')
|
|
||||||
session.run_command('zpty -t kitty; echo $?')
|
|
||||||
|
|
||||||
wait_for { session.content }.to end_with("\n0")
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
19
spec/options/async_zpty_name_spec.rb
Normal file
19
spec/options/async_zpty_name_spec.rb
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
context 'when async suggestions are enabled' do
|
||||||
|
let(:options) { ["ZSH_AUTOSUGGEST_USE_ASYNC="] }
|
||||||
|
|
||||||
|
describe 'the zpty for async suggestions' do
|
||||||
|
it 'is created with the default name' do
|
||||||
|
session.run_command('zpty -t zsh_autosuggest_pty &>/dev/null; echo $?')
|
||||||
|
wait_for { session.content }.to end_with("\n0")
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when ZSH_AUTOSUGGEST_ASYNC_PTY_NAME is set' do
|
||||||
|
let(:options) { super() + ['ZSH_AUTOSUGGEST_ASYNC_PTY_NAME=foo_pty'] }
|
||||||
|
|
||||||
|
it 'is created with the specified name' do
|
||||||
|
session.run_command('zpty -t foo_pty &>/dev/null; echo $?')
|
||||||
|
wait_for { session.content }.to end_with("\n0")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,26 +0,0 @@
|
||||||
describe 'the `completion` suggestion strategy' do
|
|
||||||
let(:options) { ['ZSH_AUTOSUGGEST_STRATEGY=completion'] }
|
|
||||||
let(:before_sourcing) do
|
|
||||||
-> do
|
|
||||||
session.
|
|
||||||
run_command('autoload compinit && compinit').
|
|
||||||
run_command('_foo() { compadd bar }').
|
|
||||||
run_command('compdef _foo baz')
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'suggests the first completion result' do
|
|
||||||
session.send_string('baz ')
|
|
||||||
wait_for { session.content }.to eq('baz bar')
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'when async mode is enabled' do
|
|
||||||
let(:options) { ['ZSH_AUTOSUGGEST_USE_ASYNC=true', 'ZSH_AUTOSUGGEST_STRATEGY=completion'] }
|
|
||||||
|
|
||||||
it 'suggests the first completion result' do
|
|
||||||
session.send_string('baz ')
|
|
||||||
wait_for { session.content }.to eq('baz bar')
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
|
@ -18,6 +18,10 @@ class TerminalSession
|
||||||
tmux_command("new-session -d -x #{opts[:width]} -y #{opts[:height]} '#{cmd}'")
|
tmux_command("new-session -d -x #{opts[:width]} -y #{opts[:height]} '#{cmd}'")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def zsh_version
|
||||||
|
@zsh_version ||= Gem::Version.new(`#{ZSH_BIN} -c 'echo -n $ZSH_VERSION'`)
|
||||||
|
end
|
||||||
|
|
||||||
def tmux_socket_name
|
def tmux_socket_name
|
||||||
@tmux_socket_name ||= SecureRandom.hex(6)
|
@tmux_socket_name ||= SecureRandom.hex(6)
|
||||||
end
|
end
|
||||||
|
|
130
src/async.zsh
130
src/async.zsh
|
@ -3,61 +3,107 @@
|
||||||
# Async #
|
# Async #
|
||||||
#--------------------------------------------------------------------#
|
#--------------------------------------------------------------------#
|
||||||
|
|
||||||
zmodload zsh/system
|
# Zpty process is spawned running this function
|
||||||
|
_zsh_autosuggest_async_server() {
|
||||||
|
emulate -R zsh
|
||||||
|
|
||||||
_zsh_autosuggest_async_request() {
|
# There is a bug in zpty module (fixed in zsh/master) by which a
|
||||||
typeset -g _ZSH_AUTOSUGGEST_ASYNC_FD _ZSH_AUTOSUGGEST_CHILD_PID
|
# 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
|
||||||
|
# process immediately, before it has a chance to kill any other
|
||||||
|
# zpty processes.
|
||||||
|
zshexit() {
|
||||||
|
kill -KILL $$
|
||||||
|
sleep 1 # Block for long enough for the signal to come through
|
||||||
|
}
|
||||||
|
|
||||||
# If we've got a pending request, cancel it
|
# Don't add any extra carriage returns
|
||||||
if [[ -n "$_ZSH_AUTOSUGGEST_ASYNC_FD" ]] && { true <&$_ZSH_AUTOSUGGEST_ASYNC_FD } 2>/dev/null; then
|
stty -onlcr
|
||||||
# Close the file descriptor and remove the handler
|
|
||||||
exec {_ZSH_AUTOSUGGEST_ASYNC_FD}<&-
|
|
||||||
zle -F $_ZSH_AUTOSUGGEST_ASYNC_FD
|
|
||||||
|
|
||||||
# Zsh will make a new process group for the child process only if job
|
# Don't translate carriage returns to newlines
|
||||||
# control is enabled (MONITOR option)
|
stty -icrnl
|
||||||
if [[ -o MONITOR ]]; then
|
|
||||||
# Send the signal to the process group to kill any processes that may
|
|
||||||
# have been forked by the suggestion strategy
|
|
||||||
kill -TERM -$_ZSH_AUTOSUGGEST_CHILD_PID 2>/dev/null
|
|
||||||
else
|
|
||||||
# Kill just the child process since it wasn't placed in a new process
|
|
||||||
# group. If the suggestion strategy forked any child processes they may
|
|
||||||
# be orphaned and left behind.
|
|
||||||
kill -TERM $_ZSH_AUTOSUGGEST_CHILD_PID 2>/dev/null
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Fork a process to fetch a suggestion and open a pipe to read from it
|
# Silence any error messages
|
||||||
exec {_ZSH_AUTOSUGGEST_ASYNC_FD}< <(
|
exec 2>/dev/null
|
||||||
# Tell parent process our pid
|
|
||||||
echo $sysparams[pid]
|
|
||||||
|
|
||||||
# Fetch and print the suggestion
|
local last_pid
|
||||||
local suggestion
|
|
||||||
_zsh_autosuggest_fetch_suggestion "$1"
|
|
||||||
echo -nE "$suggestion"
|
|
||||||
)
|
|
||||||
|
|
||||||
# Read the pid from the child process
|
while IFS='' read -r -d $'\0' query; do
|
||||||
read _ZSH_AUTOSUGGEST_CHILD_PID <&$_ZSH_AUTOSUGGEST_ASYNC_FD
|
# Kill last bg process
|
||||||
|
kill -KILL $last_pid &>/dev/null
|
||||||
|
|
||||||
# When the fd is readable, call the response handler
|
# Run suggestion search in the background
|
||||||
zle -F "$_ZSH_AUTOSUGGEST_ASYNC_FD" _zsh_autosuggest_async_response
|
(
|
||||||
|
local suggestion
|
||||||
|
_zsh_autosuggest_fetch_suggestion "$query"
|
||||||
|
echo -n -E "$suggestion"$'\0'
|
||||||
|
) &
|
||||||
|
|
||||||
|
last_pid=$!
|
||||||
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
# Called when new data is ready to be read from the pipe
|
_zsh_autosuggest_async_request() {
|
||||||
|
# Write the query to the zpty process to fetch a suggestion
|
||||||
|
zpty -w -n $ZSH_AUTOSUGGEST_ASYNC_PTY_NAME "${1}"$'\0'
|
||||||
|
}
|
||||||
|
|
||||||
|
# Called when new data is ready to be read from the pty
|
||||||
# First arg will be fd ready for reading
|
# First arg will be fd ready for reading
|
||||||
# Second arg will be passed in case of error
|
# Second arg will be passed in case of error
|
||||||
_zsh_autosuggest_async_response() {
|
_zsh_autosuggest_async_response() {
|
||||||
if [[ -z "$2" || "$2" == "hup" ]]; then
|
setopt LOCAL_OPTIONS EXTENDED_GLOB
|
||||||
# Read everything from the fd and give it as a suggestion
|
|
||||||
zle autosuggest-suggest -- "$(cat <&$1)"
|
|
||||||
|
|
||||||
# Close the fd
|
local suggestion
|
||||||
exec {1}<&-
|
|
||||||
|
zpty -rt $ZSH_AUTOSUGGEST_ASYNC_PTY_NAME suggestion '*'$'\0' 2>/dev/null
|
||||||
|
zle autosuggest-suggest -- "${suggestion%%$'\0'##}"
|
||||||
|
}
|
||||||
|
|
||||||
|
_zsh_autosuggest_async_pty_create() {
|
||||||
|
# With newer versions of zsh, REPLY stores the fd to read from
|
||||||
|
typeset -h REPLY
|
||||||
|
|
||||||
|
# If we won't get a fd back from zpty, try to guess it
|
||||||
|
if (( ! $_ZSH_AUTOSUGGEST_ZPTY_RETURNS_FD )); then
|
||||||
|
integer -l zptyfd
|
||||||
|
exec {zptyfd}>&1 # Open a new file descriptor (above 10).
|
||||||
|
exec {zptyfd}>&- # Close it so it's free to be used by zpty.
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Always remove the handler
|
# Fork a zpty process running the server function
|
||||||
zle -F "$1"
|
zpty -b $ZSH_AUTOSUGGEST_ASYNC_PTY_NAME _zsh_autosuggest_async_server
|
||||||
|
|
||||||
|
# Store the fd so we can remove the handler later
|
||||||
|
if (( REPLY )); then
|
||||||
|
_ZSH_AUTOSUGGEST_PTY_FD=$REPLY
|
||||||
|
else
|
||||||
|
_ZSH_AUTOSUGGEST_PTY_FD=$zptyfd
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Set up input handler from the zpty
|
||||||
|
zle -F $_ZSH_AUTOSUGGEST_PTY_FD _zsh_autosuggest_async_response
|
||||||
|
}
|
||||||
|
|
||||||
|
_zsh_autosuggest_async_pty_destroy() {
|
||||||
|
# Remove the input handler
|
||||||
|
zle -F $_ZSH_AUTOSUGGEST_PTY_FD &>/dev/null
|
||||||
|
|
||||||
|
# Destroy the zpty
|
||||||
|
zpty -d $ZSH_AUTOSUGGEST_ASYNC_PTY_NAME &>/dev/null
|
||||||
|
}
|
||||||
|
|
||||||
|
_zsh_autosuggest_async_pty_recreate() {
|
||||||
|
_zsh_autosuggest_async_pty_destroy
|
||||||
|
_zsh_autosuggest_async_pty_create
|
||||||
|
}
|
||||||
|
|
||||||
|
_zsh_autosuggest_async_start() {
|
||||||
|
typeset -g _ZSH_AUTOSUGGEST_PTY_FD
|
||||||
|
|
||||||
|
_zsh_autosuggest_feature_detect_zpty_returns_fd
|
||||||
|
_zsh_autosuggest_async_pty_recreate
|
||||||
|
|
||||||
|
# We recreate the pty to get a fresh list of history events
|
||||||
|
add-zsh-hook precmd _zsh_autosuggest_async_pty_recreate
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,5 +69,5 @@
|
||||||
# Max size of buffer to trigger autosuggestion. Leave null for no upper bound.
|
# Max size of buffer to trigger autosuggestion. Leave null for no upper bound.
|
||||||
: ${ZSH_AUTOSUGGEST_BUFFER_MAX_SIZE=}
|
: ${ZSH_AUTOSUGGEST_BUFFER_MAX_SIZE=}
|
||||||
|
|
||||||
# Pty name for capturing completions for completion suggestion strategy
|
# Pty name for calculating autosuggestions asynchronously
|
||||||
: ${ZSH_AUTOSUGGEST_COMPLETIONS_PTY_NAME=zsh_autosuggest_completion_pty}
|
: ${ZSH_AUTOSUGGEST_ASYNC_PTY_NAME=zsh_autosuggest_pty}
|
||||||
|
|
19
src/features.zsh
Normal file
19
src/features.zsh
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
|
||||||
|
#--------------------------------------------------------------------#
|
||||||
|
# Feature Detection #
|
||||||
|
#--------------------------------------------------------------------#
|
||||||
|
|
||||||
|
_zsh_autosuggest_feature_detect_zpty_returns_fd() {
|
||||||
|
typeset -g _ZSH_AUTOSUGGEST_ZPTY_RETURNS_FD
|
||||||
|
typeset -h REPLY
|
||||||
|
|
||||||
|
zpty zsh_autosuggest_feature_detect '{ zshexit() { kill -KILL $$; sleep 1 } }'
|
||||||
|
|
||||||
|
if (( REPLY )); then
|
||||||
|
_ZSH_AUTOSUGGEST_ZPTY_RETURNS_FD=1
|
||||||
|
else
|
||||||
|
_ZSH_AUTOSUGGEST_ZPTY_RETURNS_FD=0
|
||||||
|
fi
|
||||||
|
|
||||||
|
zpty -d zsh_autosuggest_feature_detect
|
||||||
|
}
|
10
src/setup.zsh
Normal file
10
src/setup.zsh
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
|
||||||
|
#--------------------------------------------------------------------#
|
||||||
|
# Setup #
|
||||||
|
#--------------------------------------------------------------------#
|
||||||
|
|
||||||
|
# Precmd hooks for initializing the library and starting pty's
|
||||||
|
autoload -Uz add-zsh-hook
|
||||||
|
|
||||||
|
# Asynchronous suggestions are generated in a pty
|
||||||
|
zmodload zsh/zpty
|
|
@ -14,8 +14,11 @@ _zsh_autosuggest_start() {
|
||||||
# zsh-syntax-highlighting widgets. This also allows modifications
|
# zsh-syntax-highlighting widgets. This also allows modifications
|
||||||
# to the widget list variables to take effect on the next precmd.
|
# to the widget list variables to take effect on the next precmd.
|
||||||
add-zsh-hook precmd _zsh_autosuggest_bind_widgets
|
add-zsh-hook precmd _zsh_autosuggest_bind_widgets
|
||||||
|
|
||||||
|
if [[ -n "${ZSH_AUTOSUGGEST_USE_ASYNC+x}" ]]; then
|
||||||
|
_zsh_autosuggest_async_start
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
# Start the autosuggestion widgets on the next precmd
|
# Start the autosuggestion widgets on the next precmd
|
||||||
autoload -Uz add-zsh-hook
|
|
||||||
add-zsh-hook precmd _zsh_autosuggest_start
|
add-zsh-hook precmd _zsh_autosuggest_start
|
||||||
|
|
|
@ -1,104 +0,0 @@
|
||||||
|
|
||||||
#--------------------------------------------------------------------#
|
|
||||||
# Completion Suggestion Strategy #
|
|
||||||
#--------------------------------------------------------------------#
|
|
||||||
# Fetches a suggestion from the completion engine
|
|
||||||
#
|
|
||||||
|
|
||||||
_zsh_autosuggest_capture_postcompletion() {
|
|
||||||
# Always insert the first completion into the buffer
|
|
||||||
compstate[insert]=1
|
|
||||||
|
|
||||||
# Don't list completions
|
|
||||||
unset compstate[list]
|
|
||||||
}
|
|
||||||
|
|
||||||
_zsh_autosuggest_capture_completion_widget() {
|
|
||||||
local -a +h comppostfuncs
|
|
||||||
comppostfuncs=(_zsh_autosuggest_capture_postcompletion)
|
|
||||||
|
|
||||||
# Only capture completions at the end of the buffer
|
|
||||||
CURSOR=$#BUFFER
|
|
||||||
|
|
||||||
# Run the original widget wrapping `.complete-word` so we don't
|
|
||||||
# recursively try to fetch suggestions, since our pty is forked
|
|
||||||
# after autosuggestions is initialized.
|
|
||||||
zle -- ${(k)widgets[(r)completion:.complete-word:_main_complete]}
|
|
||||||
|
|
||||||
# The completion has been added, print the buffer as the suggestion
|
|
||||||
echo -nE - $'\0'$BUFFER$'\0'
|
|
||||||
}
|
|
||||||
|
|
||||||
zle -N autosuggest-capture-completion _zsh_autosuggest_capture_completion_widget
|
|
||||||
|
|
||||||
_zsh_autosuggest_capture_setup() {
|
|
||||||
# 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
|
|
||||||
# process immediately, before it has a chance to kill any other
|
|
||||||
# zpty processes.
|
|
||||||
if ! is-at-least 5.4; then
|
|
||||||
zshexit() {
|
|
||||||
kill -KILL $$
|
|
||||||
sleep 1 # Block for long enough for the signal to come through
|
|
||||||
}
|
|
||||||
fi
|
|
||||||
|
|
||||||
bindkey '^I' autosuggest-capture-completion
|
|
||||||
}
|
|
||||||
|
|
||||||
_zsh_autosuggest_capture_completion_sync() {
|
|
||||||
_zsh_autosuggest_capture_setup
|
|
||||||
|
|
||||||
zle autosuggest-capture-completion
|
|
||||||
}
|
|
||||||
|
|
||||||
_zsh_autosuggest_capture_completion_async() {
|
|
||||||
_zsh_autosuggest_capture_setup
|
|
||||||
|
|
||||||
zmodload zsh/parameter 2>/dev/null || return # For `$functions`
|
|
||||||
|
|
||||||
# Make vared completion work as if for a normal command line
|
|
||||||
# https://stackoverflow.com/a/7057118/154703
|
|
||||||
autoload +X _complete
|
|
||||||
functions[_original_complete]=$functions[_complete]
|
|
||||||
_complete () {
|
|
||||||
unset 'compstate[vared]'
|
|
||||||
_original_complete "$@"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Open zle with buffer set so we can capture completions for it
|
|
||||||
vared 1
|
|
||||||
}
|
|
||||||
|
|
||||||
_zsh_autosuggest_strategy_completion() {
|
|
||||||
typeset -g suggestion
|
|
||||||
local line REPLY
|
|
||||||
|
|
||||||
# Exit if we don't have completions
|
|
||||||
whence compdef >/dev/null || return
|
|
||||||
|
|
||||||
# Exit if we don't have zpty
|
|
||||||
zmodload zsh/zpty 2>/dev/null || return
|
|
||||||
|
|
||||||
# Zle will be inactive if we are in async mode
|
|
||||||
if zle; then
|
|
||||||
zpty $ZSH_AUTOSUGGEST_COMPLETIONS_PTY_NAME _zsh_autosuggest_capture_completion_sync
|
|
||||||
else
|
|
||||||
zpty $ZSH_AUTOSUGGEST_COMPLETIONS_PTY_NAME _zsh_autosuggest_capture_completion_async "\$1"
|
|
||||||
zpty -w $ZSH_AUTOSUGGEST_COMPLETIONS_PTY_NAME $'\t'
|
|
||||||
fi
|
|
||||||
|
|
||||||
{
|
|
||||||
# The completion result is surrounded by null bytes, so read the
|
|
||||||
# content between the first two null bytes.
|
|
||||||
zpty -r $ZSH_AUTOSUGGEST_COMPLETIONS_PTY_NAME line '*'$'\0''*'$'\0'
|
|
||||||
|
|
||||||
# On older versions of zsh, we sometimes get extra bytes after the
|
|
||||||
# second null byte, so trim those off the end
|
|
||||||
suggestion="${${${(M)line:#*$'\0'*$'\0'*}#*$'\0'}%%$'\0'*}"
|
|
||||||
} always {
|
|
||||||
# Destroy the pty
|
|
||||||
zpty -d $ZSH_AUTOSUGGEST_COMPLETIONS_PTY_NAME
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -95,7 +95,7 @@ _zsh_autosuggest_modify() {
|
||||||
|
|
||||||
# Fetch a new suggestion based on what's currently in the buffer
|
# Fetch a new suggestion based on what's currently in the buffer
|
||||||
_zsh_autosuggest_fetch() {
|
_zsh_autosuggest_fetch() {
|
||||||
if [[ -n "${ZSH_AUTOSUGGEST_USE_ASYNC+x}" ]]; then
|
if zpty -t "$ZSH_AUTOSUGGEST_ASYNC_PTY_NAME" &>/dev/null; then
|
||||||
_zsh_autosuggest_async_request "$BUFFER"
|
_zsh_autosuggest_async_request "$BUFFER"
|
||||||
else
|
else
|
||||||
local suggestion
|
local suggestion
|
||||||
|
|
|
@ -25,6 +25,16 @@
|
||||||
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
# OTHER DEALINGS IN THE SOFTWARE.
|
# OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
#--------------------------------------------------------------------#
|
||||||
|
# Setup #
|
||||||
|
#--------------------------------------------------------------------#
|
||||||
|
|
||||||
|
# Precmd hooks for initializing the library and starting pty's
|
||||||
|
autoload -Uz add-zsh-hook
|
||||||
|
|
||||||
|
# Asynchronous suggestions are generated in a pty
|
||||||
|
zmodload zsh/zpty
|
||||||
|
|
||||||
#--------------------------------------------------------------------#
|
#--------------------------------------------------------------------#
|
||||||
# Global Configuration Variables #
|
# Global Configuration Variables #
|
||||||
#--------------------------------------------------------------------#
|
#--------------------------------------------------------------------#
|
||||||
|
@ -95,8 +105,8 @@
|
||||||
# Max size of buffer to trigger autosuggestion. Leave null for no upper bound.
|
# Max size of buffer to trigger autosuggestion. Leave null for no upper bound.
|
||||||
: ${ZSH_AUTOSUGGEST_BUFFER_MAX_SIZE=}
|
: ${ZSH_AUTOSUGGEST_BUFFER_MAX_SIZE=}
|
||||||
|
|
||||||
# Pty name for capturing completions for completion suggestion strategy
|
# Pty name for calculating autosuggestions asynchronously
|
||||||
: ${ZSH_AUTOSUGGEST_COMPLETIONS_PTY_NAME=zsh_autosuggest_completion_pty}
|
: ${ZSH_AUTOSUGGEST_ASYNC_PTY_NAME=zsh_autosuggest_pty}
|
||||||
|
|
||||||
#--------------------------------------------------------------------#
|
#--------------------------------------------------------------------#
|
||||||
# Utility Functions #
|
# Utility Functions #
|
||||||
|
@ -109,6 +119,25 @@ _zsh_autosuggest_escape_command() {
|
||||||
echo -E "${1//(#m)[\"\'\\()\[\]|*?~]/\\$MATCH}"
|
echo -E "${1//(#m)[\"\'\\()\[\]|*?~]/\\$MATCH}"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#--------------------------------------------------------------------#
|
||||||
|
# Feature Detection #
|
||||||
|
#--------------------------------------------------------------------#
|
||||||
|
|
||||||
|
_zsh_autosuggest_feature_detect_zpty_returns_fd() {
|
||||||
|
typeset -g _ZSH_AUTOSUGGEST_ZPTY_RETURNS_FD
|
||||||
|
typeset -h REPLY
|
||||||
|
|
||||||
|
zpty zsh_autosuggest_feature_detect '{ zshexit() { kill -KILL $$; sleep 1 } }'
|
||||||
|
|
||||||
|
if (( REPLY )); then
|
||||||
|
_ZSH_AUTOSUGGEST_ZPTY_RETURNS_FD=1
|
||||||
|
else
|
||||||
|
_ZSH_AUTOSUGGEST_ZPTY_RETURNS_FD=0
|
||||||
|
fi
|
||||||
|
|
||||||
|
zpty -d zsh_autosuggest_feature_detect
|
||||||
|
}
|
||||||
|
|
||||||
#--------------------------------------------------------------------#
|
#--------------------------------------------------------------------#
|
||||||
# Widget Helpers #
|
# Widget Helpers #
|
||||||
#--------------------------------------------------------------------#
|
#--------------------------------------------------------------------#
|
||||||
|
@ -351,7 +380,7 @@ _zsh_autosuggest_modify() {
|
||||||
|
|
||||||
# Fetch a new suggestion based on what's currently in the buffer
|
# Fetch a new suggestion based on what's currently in the buffer
|
||||||
_zsh_autosuggest_fetch() {
|
_zsh_autosuggest_fetch() {
|
||||||
if [[ -n "${ZSH_AUTOSUGGEST_USE_ASYNC+x}" ]]; then
|
if zpty -t "$ZSH_AUTOSUGGEST_ASYNC_PTY_NAME" &>/dev/null; then
|
||||||
_zsh_autosuggest_async_request "$BUFFER"
|
_zsh_autosuggest_async_request "$BUFFER"
|
||||||
else
|
else
|
||||||
local suggestion
|
local suggestion
|
||||||
|
@ -472,110 +501,6 @@ zle -N autosuggest-enable _zsh_autosuggest_widget_enable
|
||||||
zle -N autosuggest-disable _zsh_autosuggest_widget_disable
|
zle -N autosuggest-disable _zsh_autosuggest_widget_disable
|
||||||
zle -N autosuggest-toggle _zsh_autosuggest_widget_toggle
|
zle -N autosuggest-toggle _zsh_autosuggest_widget_toggle
|
||||||
|
|
||||||
#--------------------------------------------------------------------#
|
|
||||||
# Completion Suggestion Strategy #
|
|
||||||
#--------------------------------------------------------------------#
|
|
||||||
# Fetches a suggestion from the completion engine
|
|
||||||
#
|
|
||||||
|
|
||||||
_zsh_autosuggest_capture_postcompletion() {
|
|
||||||
# Always insert the first completion into the buffer
|
|
||||||
compstate[insert]=1
|
|
||||||
|
|
||||||
# Don't list completions
|
|
||||||
unset compstate[list]
|
|
||||||
}
|
|
||||||
|
|
||||||
_zsh_autosuggest_capture_completion_widget() {
|
|
||||||
local -a +h comppostfuncs
|
|
||||||
comppostfuncs=(_zsh_autosuggest_capture_postcompletion)
|
|
||||||
|
|
||||||
# Only capture completions at the end of the buffer
|
|
||||||
CURSOR=$#BUFFER
|
|
||||||
|
|
||||||
# Run the original widget wrapping `.complete-word` so we don't
|
|
||||||
# recursively try to fetch suggestions, since our pty is forked
|
|
||||||
# after autosuggestions is initialized.
|
|
||||||
zle -- ${(k)widgets[(r)completion:.complete-word:_main_complete]}
|
|
||||||
|
|
||||||
# The completion has been added, print the buffer as the suggestion
|
|
||||||
echo -nE - $'\0'$BUFFER$'\0'
|
|
||||||
}
|
|
||||||
|
|
||||||
zle -N autosuggest-capture-completion _zsh_autosuggest_capture_completion_widget
|
|
||||||
|
|
||||||
_zsh_autosuggest_capture_setup() {
|
|
||||||
# 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
|
|
||||||
# process immediately, before it has a chance to kill any other
|
|
||||||
# zpty processes.
|
|
||||||
if ! is-at-least 5.4; then
|
|
||||||
zshexit() {
|
|
||||||
kill -KILL $$
|
|
||||||
sleep 1 # Block for long enough for the signal to come through
|
|
||||||
}
|
|
||||||
fi
|
|
||||||
|
|
||||||
bindkey '^I' autosuggest-capture-completion
|
|
||||||
}
|
|
||||||
|
|
||||||
_zsh_autosuggest_capture_completion_sync() {
|
|
||||||
_zsh_autosuggest_capture_setup
|
|
||||||
|
|
||||||
zle autosuggest-capture-completion
|
|
||||||
}
|
|
||||||
|
|
||||||
_zsh_autosuggest_capture_completion_async() {
|
|
||||||
_zsh_autosuggest_capture_setup
|
|
||||||
|
|
||||||
zmodload zsh/parameter 2>/dev/null || return # For `$functions`
|
|
||||||
|
|
||||||
# Make vared completion work as if for a normal command line
|
|
||||||
# https://stackoverflow.com/a/7057118/154703
|
|
||||||
autoload +X _complete
|
|
||||||
functions[_original_complete]=$functions[_complete]
|
|
||||||
_complete () {
|
|
||||||
unset 'compstate[vared]'
|
|
||||||
_original_complete "$@"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Open zle with buffer set so we can capture completions for it
|
|
||||||
vared 1
|
|
||||||
}
|
|
||||||
|
|
||||||
_zsh_autosuggest_strategy_completion() {
|
|
||||||
typeset -g suggestion
|
|
||||||
local line REPLY
|
|
||||||
|
|
||||||
# Exit if we don't have completions
|
|
||||||
whence compdef >/dev/null || return
|
|
||||||
|
|
||||||
# Exit if we don't have zpty
|
|
||||||
zmodload zsh/zpty 2>/dev/null || return
|
|
||||||
|
|
||||||
# Zle will be inactive if we are in async mode
|
|
||||||
if zle; then
|
|
||||||
zpty $ZSH_AUTOSUGGEST_COMPLETIONS_PTY_NAME _zsh_autosuggest_capture_completion_sync
|
|
||||||
else
|
|
||||||
zpty $ZSH_AUTOSUGGEST_COMPLETIONS_PTY_NAME _zsh_autosuggest_capture_completion_async "\$1"
|
|
||||||
zpty -w $ZSH_AUTOSUGGEST_COMPLETIONS_PTY_NAME $'\t'
|
|
||||||
fi
|
|
||||||
|
|
||||||
{
|
|
||||||
# The completion result is surrounded by null bytes, so read the
|
|
||||||
# content between the first two null bytes.
|
|
||||||
zpty -r $ZSH_AUTOSUGGEST_COMPLETIONS_PTY_NAME line '*'$'\0''*'$'\0'
|
|
||||||
|
|
||||||
# On older versions of zsh, we sometimes get extra bytes after the
|
|
||||||
# second null byte, so trim those off the end
|
|
||||||
suggestion="${${${(M)line:#*$'\0'*$'\0'*}#*$'\0'}%%$'\0'*}"
|
|
||||||
} always {
|
|
||||||
# Destroy the pty
|
|
||||||
zpty -d $ZSH_AUTOSUGGEST_COMPLETIONS_PTY_NAME
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#--------------------------------------------------------------------#
|
#--------------------------------------------------------------------#
|
||||||
# History Suggestion Strategy #
|
# History Suggestion Strategy #
|
||||||
#--------------------------------------------------------------------#
|
#--------------------------------------------------------------------#
|
||||||
|
@ -688,63 +613,109 @@ _zsh_autosuggest_fetch_suggestion() {
|
||||||
# Async #
|
# Async #
|
||||||
#--------------------------------------------------------------------#
|
#--------------------------------------------------------------------#
|
||||||
|
|
||||||
zmodload zsh/system
|
# Zpty process is spawned running this function
|
||||||
|
_zsh_autosuggest_async_server() {
|
||||||
|
emulate -R zsh
|
||||||
|
|
||||||
_zsh_autosuggest_async_request() {
|
# There is a bug in zpty module (fixed in zsh/master) by which a
|
||||||
typeset -g _ZSH_AUTOSUGGEST_ASYNC_FD _ZSH_AUTOSUGGEST_CHILD_PID
|
# 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
|
||||||
|
# process immediately, before it has a chance to kill any other
|
||||||
|
# zpty processes.
|
||||||
|
zshexit() {
|
||||||
|
kill -KILL $$
|
||||||
|
sleep 1 # Block for long enough for the signal to come through
|
||||||
|
}
|
||||||
|
|
||||||
# If we've got a pending request, cancel it
|
# Don't add any extra carriage returns
|
||||||
if [[ -n "$_ZSH_AUTOSUGGEST_ASYNC_FD" ]] && { true <&$_ZSH_AUTOSUGGEST_ASYNC_FD } 2>/dev/null; then
|
stty -onlcr
|
||||||
# Close the file descriptor and remove the handler
|
|
||||||
exec {_ZSH_AUTOSUGGEST_ASYNC_FD}<&-
|
|
||||||
zle -F $_ZSH_AUTOSUGGEST_ASYNC_FD
|
|
||||||
|
|
||||||
# Zsh will make a new process group for the child process only if job
|
# Don't translate carriage returns to newlines
|
||||||
# control is enabled (MONITOR option)
|
stty -icrnl
|
||||||
if [[ -o MONITOR ]]; then
|
|
||||||
# Send the signal to the process group to kill any processes that may
|
|
||||||
# have been forked by the suggestion strategy
|
|
||||||
kill -TERM -$_ZSH_AUTOSUGGEST_CHILD_PID 2>/dev/null
|
|
||||||
else
|
|
||||||
# Kill just the child process since it wasn't placed in a new process
|
|
||||||
# group. If the suggestion strategy forked any child processes they may
|
|
||||||
# be orphaned and left behind.
|
|
||||||
kill -TERM $_ZSH_AUTOSUGGEST_CHILD_PID 2>/dev/null
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Fork a process to fetch a suggestion and open a pipe to read from it
|
# Silence any error messages
|
||||||
exec {_ZSH_AUTOSUGGEST_ASYNC_FD}< <(
|
exec 2>/dev/null
|
||||||
# Tell parent process our pid
|
|
||||||
echo $sysparams[pid]
|
|
||||||
|
|
||||||
# Fetch and print the suggestion
|
local last_pid
|
||||||
local suggestion
|
|
||||||
_zsh_autosuggest_fetch_suggestion "$1"
|
|
||||||
echo -nE "$suggestion"
|
|
||||||
)
|
|
||||||
|
|
||||||
# Read the pid from the child process
|
while IFS='' read -r -d $'\0' query; do
|
||||||
read _ZSH_AUTOSUGGEST_CHILD_PID <&$_ZSH_AUTOSUGGEST_ASYNC_FD
|
# Kill last bg process
|
||||||
|
kill -KILL $last_pid &>/dev/null
|
||||||
|
|
||||||
# When the fd is readable, call the response handler
|
# Run suggestion search in the background
|
||||||
zle -F "$_ZSH_AUTOSUGGEST_ASYNC_FD" _zsh_autosuggest_async_response
|
(
|
||||||
|
local suggestion
|
||||||
|
_zsh_autosuggest_fetch_suggestion "$query"
|
||||||
|
echo -n -E "$suggestion"$'\0'
|
||||||
|
) &
|
||||||
|
|
||||||
|
last_pid=$!
|
||||||
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
# Called when new data is ready to be read from the pipe
|
_zsh_autosuggest_async_request() {
|
||||||
|
# Write the query to the zpty process to fetch a suggestion
|
||||||
|
zpty -w -n $ZSH_AUTOSUGGEST_ASYNC_PTY_NAME "${1}"$'\0'
|
||||||
|
}
|
||||||
|
|
||||||
|
# Called when new data is ready to be read from the pty
|
||||||
# First arg will be fd ready for reading
|
# First arg will be fd ready for reading
|
||||||
# Second arg will be passed in case of error
|
# Second arg will be passed in case of error
|
||||||
_zsh_autosuggest_async_response() {
|
_zsh_autosuggest_async_response() {
|
||||||
if [[ -z "$2" || "$2" == "hup" ]]; then
|
setopt LOCAL_OPTIONS EXTENDED_GLOB
|
||||||
# Read everything from the fd and give it as a suggestion
|
|
||||||
zle autosuggest-suggest -- "$(cat <&$1)"
|
|
||||||
|
|
||||||
# Close the fd
|
local suggestion
|
||||||
exec {1}<&-
|
|
||||||
|
zpty -rt $ZSH_AUTOSUGGEST_ASYNC_PTY_NAME suggestion '*'$'\0' 2>/dev/null
|
||||||
|
zle autosuggest-suggest -- "${suggestion%%$'\0'##}"
|
||||||
|
}
|
||||||
|
|
||||||
|
_zsh_autosuggest_async_pty_create() {
|
||||||
|
# With newer versions of zsh, REPLY stores the fd to read from
|
||||||
|
typeset -h REPLY
|
||||||
|
|
||||||
|
# If we won't get a fd back from zpty, try to guess it
|
||||||
|
if (( ! $_ZSH_AUTOSUGGEST_ZPTY_RETURNS_FD )); then
|
||||||
|
integer -l zptyfd
|
||||||
|
exec {zptyfd}>&1 # Open a new file descriptor (above 10).
|
||||||
|
exec {zptyfd}>&- # Close it so it's free to be used by zpty.
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Always remove the handler
|
# Fork a zpty process running the server function
|
||||||
zle -F "$1"
|
zpty -b $ZSH_AUTOSUGGEST_ASYNC_PTY_NAME _zsh_autosuggest_async_server
|
||||||
|
|
||||||
|
# Store the fd so we can remove the handler later
|
||||||
|
if (( REPLY )); then
|
||||||
|
_ZSH_AUTOSUGGEST_PTY_FD=$REPLY
|
||||||
|
else
|
||||||
|
_ZSH_AUTOSUGGEST_PTY_FD=$zptyfd
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Set up input handler from the zpty
|
||||||
|
zle -F $_ZSH_AUTOSUGGEST_PTY_FD _zsh_autosuggest_async_response
|
||||||
|
}
|
||||||
|
|
||||||
|
_zsh_autosuggest_async_pty_destroy() {
|
||||||
|
# Remove the input handler
|
||||||
|
zle -F $_ZSH_AUTOSUGGEST_PTY_FD &>/dev/null
|
||||||
|
|
||||||
|
# Destroy the zpty
|
||||||
|
zpty -d $ZSH_AUTOSUGGEST_ASYNC_PTY_NAME &>/dev/null
|
||||||
|
}
|
||||||
|
|
||||||
|
_zsh_autosuggest_async_pty_recreate() {
|
||||||
|
_zsh_autosuggest_async_pty_destroy
|
||||||
|
_zsh_autosuggest_async_pty_create
|
||||||
|
}
|
||||||
|
|
||||||
|
_zsh_autosuggest_async_start() {
|
||||||
|
typeset -g _ZSH_AUTOSUGGEST_PTY_FD
|
||||||
|
|
||||||
|
_zsh_autosuggest_feature_detect_zpty_returns_fd
|
||||||
|
_zsh_autosuggest_async_pty_recreate
|
||||||
|
|
||||||
|
# We recreate the pty to get a fresh list of history events
|
||||||
|
add-zsh-hook precmd _zsh_autosuggest_async_pty_recreate
|
||||||
}
|
}
|
||||||
|
|
||||||
#--------------------------------------------------------------------#
|
#--------------------------------------------------------------------#
|
||||||
|
@ -762,8 +733,11 @@ _zsh_autosuggest_start() {
|
||||||
# zsh-syntax-highlighting widgets. This also allows modifications
|
# zsh-syntax-highlighting widgets. This also allows modifications
|
||||||
# to the widget list variables to take effect on the next precmd.
|
# to the widget list variables to take effect on the next precmd.
|
||||||
add-zsh-hook precmd _zsh_autosuggest_bind_widgets
|
add-zsh-hook precmd _zsh_autosuggest_bind_widgets
|
||||||
|
|
||||||
|
if [[ -n "${ZSH_AUTOSUGGEST_USE_ASYNC+x}" ]]; then
|
||||||
|
_zsh_autosuggest_async_start
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
# Start the autosuggestion widgets on the next precmd
|
# Start the autosuggestion widgets on the next precmd
|
||||||
autoload -Uz add-zsh-hook
|
|
||||||
add-zsh-hook precmd _zsh_autosuggest_start
|
add-zsh-hook precmd _zsh_autosuggest_start
|
||||||
|
|
Loading…
Reference in a new issue