Add history cycling widgets

This commit is contained in:
Marcelo Lima 2018-11-04 19:38:51 +01:00
parent ebaf409002
commit 09b6c1659f
8 changed files with 244 additions and 40 deletions

View File

@ -81,6 +81,8 @@ This plugin provides a few widgets that you can use with `bindkey`:
5. `autosuggest-disable`: Disables suggestions. 5. `autosuggest-disable`: Disables suggestions.
6. `autosuggest-enable`: Re-enables suggestions. 6. `autosuggest-enable`: Re-enables suggestions.
7. `autosuggest-toggle`: Toggles between enabled/disabled suggestions. 7. `autosuggest-toggle`: Toggles between enabled/disabled suggestions.
8. `autosuggest-next`: Suggests the next older entry from history.
9. `autosuggest-next`: Suggests the next newer entry from history.
For example, this would bind <kbd>ctrl</kbd> + <kbd>space</kbd> to accept the current suggestion. For example, this would bind <kbd>ctrl</kbd> + <kbd>space</kbd> to accept the current suggestion.

48
spec/widgets/next_spec.rb Normal file
View File

@ -0,0 +1,48 @@
describe 'the `autosuggest-next` widget' do
context 'when suggestions are disabled' do
before do
session.
run_command('bindkey ^B autosuggest-disable').
run_command('bindkey ^K autosuggest-next').
send_keys('C-b')
end
it 'will fetch and display a suggestion' do
with_history('echo hello', 'echo world', 'echo joe') do
session.send_string('echo h')
sleep 1
expect(session.content).to eq('echo h')
session.send_keys('C-k')
wait_for { session.content }.to eq('echo hello')
session.send_string('e')
wait_for { session.content }.to eq('echo hello')
end
end
end
context 'invoked on a populated history' do
before do
session.
run_command('bindkey ^K autosuggest-next')
end
it 'will cycle, fetch, and display a suggestion' do
with_history('echo hello', 'echo world', 'echo joe') do
session.send_string('echo')
sleep 1
expect(session.content).to eq('echo joe')
session.send_keys('C-k')
wait_for { session.content }.to eq('echo world')
session.send_keys('C-k')
wait_for { session.content }.to eq('echo hello')
session.send_keys('C-k')
wait_for { session.content }.to eq('echo hello')
end
end
end
end

View File

@ -0,0 +1,58 @@
describe 'the `autosuggest-previous` widget' do
context 'when suggestions are disabled' do
before do
session.
run_command('bindkey ^B autosuggest-disable').
run_command('bindkey ^J autosuggest-previous').
send_keys('C-b')
end
it 'will fetch and display a suggestion' do
with_history('echo hello', 'echo world', 'echo joe') do
session.send_string('echo h')
sleep 1
expect(session.content).to eq('echo h')
session.send_keys('C-j')
wait_for { session.content }.to eq('echo hello')
session.send_string('e')
wait_for { session.content }.to eq('echo hello')
end
end
end
context 'invoked on a populated history' do
before do
session.
run_command('bindkey ^K autosuggest-next').
run_command('bindkey ^J autosuggest-previous')
end
it 'will cycle, fetch, and display a suggestion' do
with_history('echo hello', 'echo world', 'echo joe') do
session.send_string('echo')
sleep 1
expect(session.content).to eq('echo joe')
session.send_keys('C-k')
wait_for { session.content }.to eq('echo world')
session.send_keys('C-k')
wait_for { session.content }.to eq('echo hello')
session.send_keys('C-k')
wait_for { session.content }.to eq('echo hello')
session.send_keys('C-j')
wait_for { session.content }.to eq('echo world')
session.send_keys('C-j')
wait_for { session.content }.to eq('echo joe')
session.send_keys('C-j')
wait_for { session.content }.to eq('echo joe')
end
end
end
end

View File

@ -25,15 +25,21 @@ _zsh_autosuggest_async_server() {
local last_pid local last_pid
while IFS='' read -r -d $'\0' query; do while IFS='' read -r -d $'\0' input; do
# Kill last bg process # Kill last bg process
kill -KILL $last_pid &>/dev/null kill -KILL $last_pid &>/dev/null
# Break up the input into a list
# - (p) recognize the same escape sequences as the print builtin
# - (s) force field splitting at the separator given '\1'
local query=( ${(ps:\1:)input} )
# Run suggestion search in the background # Run suggestion search in the background
( (
local suggestion local suggestion
_zsh_autosuggest_strategy_$ZSH_AUTOSUGGEST_STRATEGY "$query" local capped_history_index
echo -n -E "$suggestion"$'\0' _zsh_autosuggest_strategy_$ZSH_AUTOSUGGEST_STRATEGY "${query[1]}" "${query[2]}"
echo -n -E "$capped_history_index"$'\1'"$suggestion"$'\0'
) & ) &
last_pid=$! last_pid=$!
@ -42,7 +48,7 @@ _zsh_autosuggest_async_server() {
_zsh_autosuggest_async_request() { _zsh_autosuggest_async_request() {
# Write the query to the zpty process to fetch a suggestion # Write the query to the zpty process to fetch a suggestion
zpty -w -n $ZSH_AUTOSUGGEST_ASYNC_PTY_NAME "${1}"$'\0' zpty -w -n $ZSH_AUTOSUGGEST_ASYNC_PTY_NAME "${1}"$'\1'"${2}"$'\0'
} }
# Called when new data is ready to be read from the pty # Called when new data is ready to be read from the pty
@ -51,10 +57,15 @@ _zsh_autosuggest_async_request() {
_zsh_autosuggest_async_response() { _zsh_autosuggest_async_response() {
setopt LOCAL_OPTIONS EXTENDED_GLOB setopt LOCAL_OPTIONS EXTENDED_GLOB
local suggestion local raw_input
zpty -rt $ZSH_AUTOSUGGEST_ASYNC_PTY_NAME suggestion '*'$'\0' 2>/dev/null zpty -rt $ZSH_AUTOSUGGEST_ASYNC_PTY_NAME raw_input '*'$'\0' 2>/dev/null
zle autosuggest-suggest -- "${suggestion%%$'\0'##}"
local input=( ${(ps:\1:)raw_input%%$'\0'##} )
local capped_history_index="${input[1]}"
local suggestion="${input[2]}"
zle autosuggest-suggest -- "${capped_history_index}" "${suggestion}"
} }
_zsh_autosuggest_async_pty_create() { _zsh_autosuggest_async_pty_create() {

View File

@ -2,8 +2,8 @@
#--------------------------------------------------------------------# #--------------------------------------------------------------------#
# Default Suggestion Strategy # # Default Suggestion Strategy #
#--------------------------------------------------------------------# #--------------------------------------------------------------------#
# Suggests the most recent history item that matches the given # Suggests the history item that matches the given prefix and history
# prefix. # index
# #
_zsh_autosuggest_strategy_default() { _zsh_autosuggest_strategy_default() {
@ -13,13 +13,21 @@ _zsh_autosuggest_strategy_default() {
# Enable globbing flags so that we can use (#m) # Enable globbing flags so that we can use (#m)
setopt EXTENDED_GLOB setopt EXTENDED_GLOB
# Extract the paramenters for this function
typeset -g capped_history_index="${1}"
local query="${2}"
# Escape backslashes and all of the glob operators so we can use # Escape backslashes and all of the glob operators so we can use
# this string as a pattern to search the $history associative array. # this string as a pattern to search the $history associative array.
# - (#m) globbing flag enables setting references for match data # - (#m) globbing flag enables setting references for match data
# TODO: Use (b) flag when we can drop support for zsh older than v5.0.8 # TODO: Use (b) flag when we can drop support for zsh older than v5.0.8
local prefix="${1//(#m)[\\*?[\]<>()|^~#]/\\$MATCH}" local prefix="${query//(#m)[\\*?[\]<>()|^~#]/\\$MATCH}"
# Get the history items that match # Get the history items that match
# - (r) subscript flag makes the pattern match on values # - (R) subscript flag makes the pattern match on values
typeset -g suggestion="${history[(r)${prefix}*]}" # - (k) returns the entry indices instead of values
local suggestions=(${(k)history[(R)$prefix*]})
(( capped_history_index > $#suggestions )) && capped_history_index=${#suggestions}
typeset -g suggestion="${history[${suggestions[${capped_history_index}]}]}"
} }

View File

@ -27,8 +27,12 @@ _zsh_autosuggest_strategy_match_prev_cmd() {
# Enable globbing flags so that we can use (#m) # Enable globbing flags so that we can use (#m)
setopt EXTENDED_GLOB setopt EXTENDED_GLOB
# Extract the paramenters for this function
typeset -g capped_history_index="${1}"
local query="${2}"
# TODO: Use (b) flag when we can drop support for zsh older than v5.0.8 # TODO: Use (b) flag when we can drop support for zsh older than v5.0.8
local prefix="${1//(#m)[\\*?[\]<>()|^~#]/\\$MATCH}" local prefix="${query//(#m)[\\*?[\]<>()|^~#]/\\$MATCH}"
# Get all history event numbers that correspond to history # Get all history event numbers that correspond to history
# entries that match pattern $prefix* # entries that match pattern $prefix*
@ -36,13 +40,13 @@ _zsh_autosuggest_strategy_match_prev_cmd() {
history_match_keys=(${(k)history[(R)$prefix*]}) history_match_keys=(${(k)history[(R)$prefix*]})
# By default we use the first history number (most recent history entry) # By default we use the first history number (most recent history entry)
local histkey="${history_match_keys[1]}" local histkey="${history_match_keys[capped_history_index]}"
# Get the previously executed command # Get the previously executed command
local prev_cmd="$(_zsh_autosuggest_escape_command "${history[$((HISTCMD-1))]}")" local prev_cmd="$(_zsh_autosuggest_escape_command "${history[$((HISTCMD-1))]}")"
# Iterate up to the first 200 history event numbers that match $prefix # Iterate up to the first 200 history event numbers that match $prefix
for key in "${(@)history_match_keys[1,200]}"; do for key in "${(@)history_match_keys[capped_history_index,200]}"; do
# Stop if we ran out of history # Stop if we ran out of history
[[ $key -gt 1 ]] || break [[ $key -gt 1 ]] || break

View File

@ -31,6 +31,7 @@ _zsh_autosuggest_toggle() {
_zsh_autosuggest_clear() { _zsh_autosuggest_clear() {
# Remove the suggestion # Remove the suggestion
unset POSTDISPLAY unset POSTDISPLAY
history_index=1
_zsh_autosuggest_invoke_original_widget $@ _zsh_autosuggest_invoke_original_widget $@
} }
@ -91,25 +92,45 @@ _zsh_autosuggest_modify() {
return $retval return $retval
} }
# Navigate to the next suggestion in the suggestion list
_zsh_autosuggest_next() {
history_index=$(( history_index + 1 ))
_zsh_autosuggest_fetch
}
# Navigate to the previous suggestion in the suggestion list
_zsh_autosuggest_previous() {
(( history_index > 1 )) && history_index=$(( history_index - 1 ))
_zsh_autosuggest_fetch
}
# 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 ! (( history_index > 0 )); then
history_index=1
fi
if zpty -t "$ZSH_AUTOSUGGEST_ASYNC_PTY_NAME" &>/dev/null; then if zpty -t "$ZSH_AUTOSUGGEST_ASYNC_PTY_NAME" &>/dev/null; then
_zsh_autosuggest_async_request "$BUFFER" _zsh_autosuggest_async_request ${history_index} "$BUFFER"
else else
local suggestion local suggestion
_zsh_autosuggest_strategy_$ZSH_AUTOSUGGEST_STRATEGY "$BUFFER" local capped_history_index
_zsh_autosuggest_suggest "$suggestion" _zsh_autosuggest_strategy_$ZSH_AUTOSUGGEST_STRATEGY ${history_index} "$BUFFER"
_zsh_autosuggest_suggest "$capped_history_index" "$suggestion"
fi fi
} }
# Offer a suggestion # Offer a suggestion
_zsh_autosuggest_suggest() { _zsh_autosuggest_suggest() {
local suggestion="$1" local capped_history_index="$1"
local suggestion="$2"
if [[ -n "$suggestion" ]] && (( $#BUFFER )); then if [[ -n "$suggestion" ]] && (( $#BUFFER )); then
POSTDISPLAY="${suggestion#$BUFFER}" POSTDISPLAY="${suggestion#$BUFFER}"
history_index="${capped_history_index}"
else else
unset POSTDISPLAY unset POSTDISPLAY
history_index=1
fi fi
} }
@ -130,6 +151,7 @@ _zsh_autosuggest_accept() {
# Remove the suggestion # Remove the suggestion
unset POSTDISPLAY unset POSTDISPLAY
history_index=1
# Move the cursor to the end of the buffer # Move the cursor to the end of the buffer
CURSOR=${#BUFFER} CURSOR=${#BUFFER}
@ -145,6 +167,7 @@ _zsh_autosuggest_execute() {
# Remove the suggestion # Remove the suggestion
unset POSTDISPLAY unset POSTDISPLAY
history_index=1
# 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
@ -186,7 +209,7 @@ _zsh_autosuggest_partial_accept() {
return $retval return $retval
} }
for action in clear modify fetch suggest accept partial_accept execute enable disable toggle; do for action in clear modify fetch suggest accept partial_accept execute enable disable toggle next previous; do
eval "_zsh_autosuggest_widget_$action() { eval "_zsh_autosuggest_widget_$action() {
local -i retval local -i retval
@ -211,3 +234,5 @@ zle -N autosuggest-execute _zsh_autosuggest_widget_execute
zle -N autosuggest-enable _zsh_autosuggest_widget_enable 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
zle -N autosuggest-next _zsh_autosuggest_widget_next
zle -N autosuggest-previous _zsh_autosuggest_widget_previous

View File

@ -312,6 +312,7 @@ _zsh_autosuggest_toggle() {
_zsh_autosuggest_clear() { _zsh_autosuggest_clear() {
# Remove the suggestion # Remove the suggestion
unset POSTDISPLAY unset POSTDISPLAY
history_index=1
_zsh_autosuggest_invoke_original_widget $@ _zsh_autosuggest_invoke_original_widget $@
} }
@ -372,25 +373,45 @@ _zsh_autosuggest_modify() {
return $retval return $retval
} }
# Navigate to the next suggestion in the suggestion list
_zsh_autosuggest_next() {
history_index=$(( history_index + 1 ))
_zsh_autosuggest_fetch
}
# Navigate to the previous suggestion in the suggestion list
_zsh_autosuggest_previous() {
(( history_index > 1 )) && history_index=$(( history_index - 1 ))
_zsh_autosuggest_fetch
}
# 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 ! (( history_index > 0 )); then
history_index=1
fi
if zpty -t "$ZSH_AUTOSUGGEST_ASYNC_PTY_NAME" &>/dev/null; then if zpty -t "$ZSH_AUTOSUGGEST_ASYNC_PTY_NAME" &>/dev/null; then
_zsh_autosuggest_async_request "$BUFFER" _zsh_autosuggest_async_request ${history_index} "$BUFFER"
else else
local suggestion local suggestion
_zsh_autosuggest_strategy_$ZSH_AUTOSUGGEST_STRATEGY "$BUFFER" local capped_history_index
_zsh_autosuggest_suggest "$suggestion" _zsh_autosuggest_strategy_$ZSH_AUTOSUGGEST_STRATEGY ${history_index} "$BUFFER"
_zsh_autosuggest_suggest "$capped_history_index" "$suggestion"
fi fi
} }
# Offer a suggestion # Offer a suggestion
_zsh_autosuggest_suggest() { _zsh_autosuggest_suggest() {
local suggestion="$1" local capped_history_index="$1"
local suggestion="$2"
if [[ -n "$suggestion" ]] && (( $#BUFFER )); then if [[ -n "$suggestion" ]] && (( $#BUFFER )); then
POSTDISPLAY="${suggestion#$BUFFER}" POSTDISPLAY="${suggestion#$BUFFER}"
history_index="${capped_history_index}"
else else
unset POSTDISPLAY unset POSTDISPLAY
history_index=1
fi fi
} }
@ -411,6 +432,7 @@ _zsh_autosuggest_accept() {
# Remove the suggestion # Remove the suggestion
unset POSTDISPLAY unset POSTDISPLAY
history_index=1
# Move the cursor to the end of the buffer # Move the cursor to the end of the buffer
CURSOR=${#BUFFER} CURSOR=${#BUFFER}
@ -426,6 +448,7 @@ _zsh_autosuggest_execute() {
# Remove the suggestion # Remove the suggestion
unset POSTDISPLAY unset POSTDISPLAY
history_index=1
# 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
@ -467,7 +490,7 @@ _zsh_autosuggest_partial_accept() {
return $retval return $retval
} }
for action in clear modify fetch suggest accept partial_accept execute enable disable toggle; do for action in clear modify fetch suggest accept partial_accept execute enable disable toggle next previous; do
eval "_zsh_autosuggest_widget_$action() { eval "_zsh_autosuggest_widget_$action() {
local -i retval local -i retval
@ -492,12 +515,14 @@ zle -N autosuggest-execute _zsh_autosuggest_widget_execute
zle -N autosuggest-enable _zsh_autosuggest_widget_enable 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
zle -N autosuggest-next _zsh_autosuggest_widget_next
zle -N autosuggest-previous _zsh_autosuggest_widget_previous
#--------------------------------------------------------------------# #--------------------------------------------------------------------#
# Default Suggestion Strategy # # Default Suggestion Strategy #
#--------------------------------------------------------------------# #--------------------------------------------------------------------#
# Suggests the most recent history item that matches the given # Suggests the history item that matches the given prefix and history
# prefix. # index
# #
_zsh_autosuggest_strategy_default() { _zsh_autosuggest_strategy_default() {
@ -507,15 +532,23 @@ _zsh_autosuggest_strategy_default() {
# Enable globbing flags so that we can use (#m) # Enable globbing flags so that we can use (#m)
setopt EXTENDED_GLOB setopt EXTENDED_GLOB
# Extract the paramenters for this function
typeset -g capped_history_index="${1}"
local query="${2}"
# Escape backslashes and all of the glob operators so we can use # Escape backslashes and all of the glob operators so we can use
# this string as a pattern to search the $history associative array. # this string as a pattern to search the $history associative array.
# - (#m) globbing flag enables setting references for match data # - (#m) globbing flag enables setting references for match data
# TODO: Use (b) flag when we can drop support for zsh older than v5.0.8 # TODO: Use (b) flag when we can drop support for zsh older than v5.0.8
local prefix="${1//(#m)[\\*?[\]<>()|^~#]/\\$MATCH}" local prefix="${query//(#m)[\\*?[\]<>()|^~#]/\\$MATCH}"
# Get the history items that match # Get the history items that match
# - (r) subscript flag makes the pattern match on values # - (R) subscript flag makes the pattern match on values
typeset -g suggestion="${history[(r)${prefix}*]}" # - (k) returns the entry indices instead of values
local suggestions=(${(k)history[(R)$prefix*]})
(( capped_history_index > $#suggestions )) && capped_history_index=${#suggestions}
typeset -g suggestion="${history[${suggestions[${capped_history_index}]}]}"
} }
#--------------------------------------------------------------------# #--------------------------------------------------------------------#
@ -546,8 +579,12 @@ _zsh_autosuggest_strategy_match_prev_cmd() {
# Enable globbing flags so that we can use (#m) # Enable globbing flags so that we can use (#m)
setopt EXTENDED_GLOB setopt EXTENDED_GLOB
# Extract the paramenters for this function
typeset -g capped_history_index="${1}"
local query="${2}"
# TODO: Use (b) flag when we can drop support for zsh older than v5.0.8 # TODO: Use (b) flag when we can drop support for zsh older than v5.0.8
local prefix="${1//(#m)[\\*?[\]<>()|^~#]/\\$MATCH}" local prefix="${query//(#m)[\\*?[\]<>()|^~#]/\\$MATCH}"
# Get all history event numbers that correspond to history # Get all history event numbers that correspond to history
# entries that match pattern $prefix* # entries that match pattern $prefix*
@ -555,13 +592,13 @@ _zsh_autosuggest_strategy_match_prev_cmd() {
history_match_keys=(${(k)history[(R)$prefix*]}) history_match_keys=(${(k)history[(R)$prefix*]})
# By default we use the first history number (most recent history entry) # By default we use the first history number (most recent history entry)
local histkey="${history_match_keys[1]}" local histkey="${history_match_keys[capped_history_index]}"
# Get the previously executed command # Get the previously executed command
local prev_cmd="$(_zsh_autosuggest_escape_command "${history[$((HISTCMD-1))]}")" local prev_cmd="$(_zsh_autosuggest_escape_command "${history[$((HISTCMD-1))]}")"
# Iterate up to the first 200 history event numbers that match $prefix # Iterate up to the first 200 history event numbers that match $prefix
for key in "${(@)history_match_keys[1,200]}"; do for key in "${(@)history_match_keys[capped_history_index,200]}"; do
# Stop if we ran out of history # Stop if we ran out of history
[[ $key -gt 1 ]] || break [[ $key -gt 1 ]] || break
@ -603,15 +640,21 @@ _zsh_autosuggest_async_server() {
local last_pid local last_pid
while IFS='' read -r -d $'\0' query; do while IFS='' read -r -d $'\0' input; do
# Kill last bg process # Kill last bg process
kill -KILL $last_pid &>/dev/null kill -KILL $last_pid &>/dev/null
# Break up the input into a list
# - (p) recognize the same escape sequences as the print builtin
# - (s) force field splitting at the separator given '\1'
local query=( ${(ps:\1:)input} )
# Run suggestion search in the background # Run suggestion search in the background
( (
local suggestion local suggestion
_zsh_autosuggest_strategy_$ZSH_AUTOSUGGEST_STRATEGY "$query" local capped_history_index
echo -n -E "$suggestion"$'\0' _zsh_autosuggest_strategy_$ZSH_AUTOSUGGEST_STRATEGY "${query[1]}" "${query[2]}"
echo -n -E "$capped_history_index"$'\1'"$suggestion"$'\0'
) & ) &
last_pid=$! last_pid=$!
@ -620,7 +663,7 @@ _zsh_autosuggest_async_server() {
_zsh_autosuggest_async_request() { _zsh_autosuggest_async_request() {
# Write the query to the zpty process to fetch a suggestion # Write the query to the zpty process to fetch a suggestion
zpty -w -n $ZSH_AUTOSUGGEST_ASYNC_PTY_NAME "${1}"$'\0' zpty -w -n $ZSH_AUTOSUGGEST_ASYNC_PTY_NAME "${1}"$'\1'"${2}"$'\0'
} }
# Called when new data is ready to be read from the pty # Called when new data is ready to be read from the pty
@ -629,10 +672,15 @@ _zsh_autosuggest_async_request() {
_zsh_autosuggest_async_response() { _zsh_autosuggest_async_response() {
setopt LOCAL_OPTIONS EXTENDED_GLOB setopt LOCAL_OPTIONS EXTENDED_GLOB
local suggestion local raw_input
zpty -rt $ZSH_AUTOSUGGEST_ASYNC_PTY_NAME suggestion '*'$'\0' 2>/dev/null zpty -rt $ZSH_AUTOSUGGEST_ASYNC_PTY_NAME raw_input '*'$'\0' 2>/dev/null
zle autosuggest-suggest -- "${suggestion%%$'\0'##}"
local input=( ${(ps:\1:)raw_input%%$'\0'##} )
local capped_history_index="${input[1]}"
local suggestion="${input[2]}"
zle autosuggest-suggest -- "${capped_history_index}" "${suggestion}"
} }
_zsh_autosuggest_async_pty_create() { _zsh_autosuggest_async_pty_create() {