Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions crates/fig_integrations/build.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
const CLI_BINARY_NAME: &str = "q";
const CODEX_FOLDER: &str = "src/shell/inline_shell_completion";

// The order here is very specific, do no edit without understanding the implications
Expand Down Expand Up @@ -31,5 +32,14 @@ fn main() {
println!("cargo:rerun-if-changed={}", path.display());
inline_shell_completion.push_str(&std::fs::read_to_string(path).unwrap());
}

// Substitute placeholders with actual binary names
let cli_binary_name_underscore = CLI_BINARY_NAME.replace('-', "_");
let cli_binary_name_upper = cli_binary_name_underscore.to_uppercase();
inline_shell_completion = inline_shell_completion
.replace("{{CLI_BINARY_NAME}}", CLI_BINARY_NAME)
.replace("{{CLI_BINARY_NAME_UNDERSCORE}}", &cli_binary_name_underscore)
.replace("{{CLI_BINARY_NAME_UPPER}}", &cli_binary_name_upper);

std::fs::write(out_dir.join("inline_shell_completion.zsh"), inline_shell_completion).unwrap();
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,42 +3,42 @@
# Async #
#--------------------------------------------------------------------#

_q_autosuggest_async_request() {
_{{CLI_BINARY_NAME_UNDERSCORE}}_autosuggest_async_request() {
zmodload zsh/system 2>/dev/null # For `$sysparams`

typeset -g _Q_AUTOSUGGEST_ASYNC_FD _Q_AUTOSUGGEST_CHILD_PID
typeset -g _{{CLI_BINARY_NAME_UPPER}}_AUTOSUGGEST_ASYNC_FD _{{CLI_BINARY_NAME_UPPER}}_AUTOSUGGEST_CHILD_PID

# If we've got a pending request, cancel it
if [[ -n "$_Q_AUTOSUGGEST_ASYNC_FD" ]] && { true <&$_Q_AUTOSUGGEST_ASYNC_FD } 2>/dev/null; then
if [[ -n "$_{{CLI_BINARY_NAME_UPPER}}_AUTOSUGGEST_ASYNC_FD" ]] && { true <&$_{{CLI_BINARY_NAME_UPPER}}_AUTOSUGGEST_ASYNC_FD } 2>/dev/null; then
# Close the file descriptor and remove the handler
exec {_Q_AUTOSUGGEST_ASYNC_FD}<&-
zle -F $_Q_AUTOSUGGEST_ASYNC_FD
exec {_{{CLI_BINARY_NAME_UPPER}}_AUTOSUGGEST_ASYNC_FD}<&-
zle -F $_{{CLI_BINARY_NAME_UPPER}}_AUTOSUGGEST_ASYNC_FD

# We won't know the pid unless the user has zsh/system module installed
if [[ -n "$_Q_AUTOSUGGEST_CHILD_PID" ]]; then
if [[ -n "$_{{CLI_BINARY_NAME_UPPER}}_AUTOSUGGEST_CHILD_PID" ]]; then
# Zsh will make a new process group for the child process only if job
# control is enabled (MONITOR option)
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 -$_Q_AUTOSUGGEST_CHILD_PID 2>/dev/null
kill -TERM -$_{{CLI_BINARY_NAME_UPPER}}_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 $_Q_AUTOSUGGEST_CHILD_PID 2>/dev/null
kill -TERM $_{{CLI_BINARY_NAME_UPPER}}_AUTOSUGGEST_CHILD_PID 2>/dev/null
fi
fi
fi

# Fork a process to fetch a suggestion and open a pipe to read from it
exec {_Q_AUTOSUGGEST_ASYNC_FD}< <(
exec {_{{CLI_BINARY_NAME_UPPER}}_AUTOSUGGEST_ASYNC_FD}< <(
# Tell parent process our pid
echo $sysparams[pid]

# Fetch and print the suggestion
local suggestion
_q_autosuggest_fetch_suggestion "$1"
_{{CLI_BINARY_NAME_UNDERSCORE}}_autosuggest_fetch_suggestion "$1"
echo -nE "$suggestion"
)

Expand All @@ -48,16 +48,16 @@ _q_autosuggest_async_request() {
is-at-least 5.8 || command true

# Read the pid from the child process
read _Q_AUTOSUGGEST_CHILD_PID <&$_Q_AUTOSUGGEST_ASYNC_FD
read _{{CLI_BINARY_NAME_UPPER}}_AUTOSUGGEST_CHILD_PID <&$_{{CLI_BINARY_NAME_UPPER}}_AUTOSUGGEST_ASYNC_FD

# When the fd is readable, call the response handler
zle -F "$_Q_AUTOSUGGEST_ASYNC_FD" _q_autosuggest_async_response
zle -F "$_{{CLI_BINARY_NAME_UPPER}}_AUTOSUGGEST_ASYNC_FD" _{{CLI_BINARY_NAME_UNDERSCORE}}_autosuggest_async_response
}

# Called when new data is ready to be read from the pipe
# First arg will be fd ready for reading
# Second arg will be passed in case of error
_q_autosuggest_async_response() {
_{{CLI_BINARY_NAME_UNDERSCORE}}_autosuggest_async_response() {
emulate -L zsh

local suggestion
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,44 +3,44 @@
# Widget Helpers #
#--------------------------------------------------------------------#

_q_autosuggest_incr_bind_count() {
typeset -gi bind_count=$((_Q_AUTOSUGGEST_BIND_COUNTS[$1]+1))
_Q_AUTOSUGGEST_BIND_COUNTS[$1]=$bind_count
_{{CLI_BINARY_NAME_UNDERSCORE}}_autosuggest_incr_bind_count() {
typeset -gi bind_count=$((_{{CLI_BINARY_NAME_UPPER}}_AUTOSUGGEST_BIND_COUNTS[$1]+1))
_{{CLI_BINARY_NAME_UPPER}}_AUTOSUGGEST_BIND_COUNTS[$1]=$bind_count
}

# Bind a single widget to an autosuggest widget, saving a reference to the original widget
_q_autosuggest_bind_widget() {
typeset -gA _Q_AUTOSUGGEST_BIND_COUNTS
_{{CLI_BINARY_NAME_UNDERSCORE}}_autosuggest_bind_widget() {
typeset -gA _{{CLI_BINARY_NAME_UPPER}}_AUTOSUGGEST_BIND_COUNTS

local widget=$1
local autosuggest_action=$2
local prefix=$Q_AUTOSUGGEST_ORIGINAL_WIDGET_PREFIX
local prefix=${{CLI_BINARY_NAME_UPPER}}_AUTOSUGGEST_ORIGINAL_WIDGET_PREFIX

local -i bind_count

# Save a reference to the original widget
case $widgets[$widget] in
# Already bound
user:_q_autosuggest_(bound|orig)_*)
bind_count=$((_Q_AUTOSUGGEST_BIND_COUNTS[$widget]))
user:_{{CLI_BINARY_NAME_UNDERSCORE}}_autosuggest_(bound|orig)_*)
bind_count=$((_{{CLI_BINARY_NAME_UPPER}}_AUTOSUGGEST_BIND_COUNTS[$widget]))
;;

# User-defined widget
user:*)
_q_autosuggest_incr_bind_count $widget
_{{CLI_BINARY_NAME_UNDERSCORE}}_autosuggest_incr_bind_count $widget
zle -N $prefix$bind_count-$widget ${widgets[$widget]#*:}
;;

# Built-in widget
builtin)
_q_autosuggest_incr_bind_count $widget
eval "_q_autosuggest_orig_${(q)widget}() { zle .${(q)widget} }"
zle -N $prefix$bind_count-$widget _q_autosuggest_orig_$widget
_{{CLI_BINARY_NAME_UNDERSCORE}}_autosuggest_incr_bind_count $widget
eval "_{{CLI_BINARY_NAME_UNDERSCORE}}_autosuggest_orig_${(q)widget}() { zle .${(q)widget} }"
zle -N $prefix$bind_count-$widget _{{CLI_BINARY_NAME_UNDERSCORE}}_autosuggest_orig_$widget
;;

# Completion widget
completion:*)
_q_autosuggest_incr_bind_count $widget
_{{CLI_BINARY_NAME_UNDERSCORE}}_autosuggest_incr_bind_count $widget
eval "zle -C $prefix$bind_count-${(q)widget} ${${(s.:.)widgets[$widget]}[2,3]}"
;;
esac
Expand All @@ -51,16 +51,16 @@ _q_autosuggest_bind_widget() {
# correctly. $WIDGET cannot be trusted because other plugins call
# zle without the `-w` flag (e.g. `zle self-insert` instead of
# `zle self-insert -w`).
eval "_q_autosuggest_bound_${bind_count}_${(q)widget}() {
_q_autosuggest_widget_$autosuggest_action $prefix$bind_count-${(q)widget} \$@
eval "_{{CLI_BINARY_NAME_UNDERSCORE}}_autosuggest_bound_${bind_count}_${(q)widget}() {
_{{CLI_BINARY_NAME_UNDERSCORE}}_autosuggest_widget_$autosuggest_action $prefix$bind_count-${(q)widget} \$@
}"

# Create the bound widget
zle -N -- $widget _q_autosuggest_bound_${bind_count}_$widget
zle -N -- $widget _{{CLI_BINARY_NAME_UNDERSCORE}}_autosuggest_bound_${bind_count}_$widget
}

# Map all configured widgets to the right autosuggest widgets
_q_autosuggest_bind_widgets() {
_{{CLI_BINARY_NAME_UNDERSCORE}}_autosuggest_bind_widgets() {
emulate -L zsh

local widget
Expand All @@ -69,30 +69,30 @@ _q_autosuggest_bind_widgets() {
ignore_widgets=(
.\*
_\*
${_Q_AUTOSUGGEST_BUILTIN_ACTIONS/#/autosuggest-}
$Q_AUTOSUGGEST_ORIGINAL_WIDGET_PREFIX\*
$Q_AUTOSUGGEST_IGNORE_WIDGETS
${_{{CLI_BINARY_NAME_UPPER}}_AUTOSUGGEST_BUILTIN_ACTIONS/#/autosuggest-}
${{CLI_BINARY_NAME_UPPER}}_AUTOSUGGEST_ORIGINAL_WIDGET_PREFIX\*
${{CLI_BINARY_NAME_UPPER}}_AUTOSUGGEST_IGNORE_WIDGETS
)

# Find every widget we might want to bind and bind it appropriately
for widget in ${${(f)"$(builtin zle -la)"}:#${(j:|:)~ignore_widgets}}; do
if [[ -n ${Q_AUTOSUGGEST_CLEAR_WIDGETS[(r)$widget]} ]]; then
_q_autosuggest_bind_widget $widget clear
elif [[ -n ${Q_AUTOSUGGEST_ACCEPT_WIDGETS[(r)$widget]} ]]; then
_q_autosuggest_bind_widget $widget accept
elif [[ -n ${Q_AUTOSUGGEST_EXECUTE_WIDGETS[(r)$widget]} ]]; then
_q_autosuggest_bind_widget $widget execute
elif [[ -n ${Q_AUTOSUGGEST_PARTIAL_ACCEPT_WIDGETS[(r)$widget]} ]]; then
_q_autosuggest_bind_widget $widget partial_accept
if [[ -n ${{{CLI_BINARY_NAME_UPPER}}_AUTOSUGGEST_CLEAR_WIDGETS[(r)$widget]} ]]; then
_{{CLI_BINARY_NAME_UNDERSCORE}}_autosuggest_bind_widget $widget clear
elif [[ -n ${{{CLI_BINARY_NAME_UPPER}}_AUTOSUGGEST_ACCEPT_WIDGETS[(r)$widget]} ]]; then
_{{CLI_BINARY_NAME_UNDERSCORE}}_autosuggest_bind_widget $widget accept
elif [[ -n ${{{CLI_BINARY_NAME_UPPER}}_AUTOSUGGEST_EXECUTE_WIDGETS[(r)$widget]} ]]; then
_{{CLI_BINARY_NAME_UNDERSCORE}}_autosuggest_bind_widget $widget execute
elif [[ -n ${{{CLI_BINARY_NAME_UPPER}}_AUTOSUGGEST_PARTIAL_ACCEPT_WIDGETS[(r)$widget]} ]]; then
_{{CLI_BINARY_NAME_UNDERSCORE}}_autosuggest_bind_widget $widget partial_accept
else
# Assume any unspecified widget might modify the buffer
_q_autosuggest_bind_widget $widget modify
_{{CLI_BINARY_NAME_UNDERSCORE}}_autosuggest_bind_widget $widget modify
fi
done
}

# Given the name of an original widget and args, invoke it, if it exists
_q_autosuggest_invoke_original_widget() {
_{{CLI_BINARY_NAME_UNDERSCORE}}_autosuggest_invoke_original_widget() {
# Do nothing unless called with at least one arg
(( $# )) || return 0

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,24 @@
# Color to use when highlighting suggestion
# Uses format of `region_highlight`
# More info: http://zsh.sourceforge.net/Doc/Release/Zsh-Line-Editor.html#Zle-Widgets
(( ! ${+Q_AUTOSUGGEST_HIGHLIGHT_STYLE} )) &&
typeset -g Q_AUTOSUGGEST_HIGHLIGHT_STYLE='fg=8'
(( ! ${+{{CLI_BINARY_NAME_UPPER}}_AUTOSUGGEST_HIGHLIGHT_STYLE} )) &&
typeset -g {{CLI_BINARY_NAME_UPPER}}_AUTOSUGGEST_HIGHLIGHT_STYLE='fg=8'

# Prefix to use when saving original versions of bound widgets
(( ! ${+Q_AUTOSUGGEST_ORIGINAL_WIDGET_PREFIX} )) &&
typeset -g Q_AUTOSUGGEST_ORIGINAL_WIDGET_PREFIX=autosuggest-orig-
(( ! ${+{{CLI_BINARY_NAME_UPPER}}_AUTOSUGGEST_ORIGINAL_WIDGET_PREFIX} )) &&
typeset -g {{CLI_BINARY_NAME_UPPER}}_AUTOSUGGEST_ORIGINAL_WIDGET_PREFIX=autosuggest-orig-

# Strategies to use to fetch a suggestion
# Will try each strategy in order until a suggestion is returned
(( ! ${+Q_AUTOSUGGEST_STRATEGY} )) && {
typeset -ga Q_AUTOSUGGEST_STRATEGY
Q_AUTOSUGGEST_STRATEGY=(inline_shell_completion)
(( ! ${+{{CLI_BINARY_NAME_UPPER}}_AUTOSUGGEST_STRATEGY} )) && {
typeset -ga {{CLI_BINARY_NAME_UPPER}}_AUTOSUGGEST_STRATEGY
{{CLI_BINARY_NAME_UPPER}}_AUTOSUGGEST_STRATEGY=(inline_shell_completion)
}

# Widgets that clear the suggestion
(( ! ${+Q_AUTOSUGGEST_CLEAR_WIDGETS} )) && {
typeset -ga Q_AUTOSUGGEST_CLEAR_WIDGETS
Q_AUTOSUGGEST_CLEAR_WIDGETS=(
(( ! ${+{{CLI_BINARY_NAME_UPPER}}_AUTOSUGGEST_CLEAR_WIDGETS} )) && {
typeset -ga {{CLI_BINARY_NAME_UPPER}}_AUTOSUGGEST_CLEAR_WIDGETS
{{CLI_BINARY_NAME_UPPER}}_AUTOSUGGEST_CLEAR_WIDGETS=(
history-search-forward
history-search-backward
history-beginning-search-forward
Expand All @@ -40,9 +40,9 @@ typeset -g Q_AUTOSUGGEST_ORIGINAL_WIDGET_PREFIX=autosuggest-orig-
}

# Widgets that accept the entire suggestion
(( ! ${+Q_AUTOSUGGEST_ACCEPT_WIDGETS} )) && {
typeset -ga Q_AUTOSUGGEST_ACCEPT_WIDGETS
Q_AUTOSUGGEST_ACCEPT_WIDGETS=(
(( ! ${+{{CLI_BINARY_NAME_UPPER}}_AUTOSUGGEST_ACCEPT_WIDGETS} )) && {
typeset -ga {{CLI_BINARY_NAME_UPPER}}_AUTOSUGGEST_ACCEPT_WIDGETS
{{CLI_BINARY_NAME_UPPER}}_AUTOSUGGEST_ACCEPT_WIDGETS=(
forward-char
end-of-line
vi-forward-char
Expand All @@ -52,16 +52,16 @@ typeset -g Q_AUTOSUGGEST_ORIGINAL_WIDGET_PREFIX=autosuggest-orig-
}

# Widgets that accept the entire suggestion and execute it
(( ! ${+Q_AUTOSUGGEST_EXECUTE_WIDGETS} )) && {
typeset -ga Q_AUTOSUGGEST_EXECUTE_WIDGETS
Q_AUTOSUGGEST_EXECUTE_WIDGETS=(
(( ! ${+{{CLI_BINARY_NAME_UPPER}}_AUTOSUGGEST_EXECUTE_WIDGETS} )) && {
typeset -ga {{CLI_BINARY_NAME_UPPER}}_AUTOSUGGEST_EXECUTE_WIDGETS
{{CLI_BINARY_NAME_UPPER}}_AUTOSUGGEST_EXECUTE_WIDGETS=(
)
}

# Widgets that accept the suggestion as far as the cursor moves
(( ! ${+Q_AUTOSUGGEST_PARTIAL_ACCEPT_WIDGETS} )) && {
typeset -ga Q_AUTOSUGGEST_PARTIAL_ACCEPT_WIDGETS
Q_AUTOSUGGEST_PARTIAL_ACCEPT_WIDGETS=(
(( ! ${+{{CLI_BINARY_NAME_UPPER}}_AUTOSUGGEST_PARTIAL_ACCEPT_WIDGETS} )) && {
typeset -ga {{CLI_BINARY_NAME_UPPER}}_AUTOSUGGEST_PARTIAL_ACCEPT_WIDGETS
{{CLI_BINARY_NAME_UPPER}}_AUTOSUGGEST_PARTIAL_ACCEPT_WIDGETS=(
forward-word
emacs-forward-word
vi-forward-word
Expand All @@ -74,9 +74,9 @@ typeset -g Q_AUTOSUGGEST_ORIGINAL_WIDGET_PREFIX=autosuggest-orig-
}

# Widgets that should be ignored (globbing supported but must be escaped)
(( ! ${+Q_AUTOSUGGEST_IGNORE_WIDGETS} )) && {
typeset -ga Q_AUTOSUGGEST_IGNORE_WIDGETS
Q_AUTOSUGGEST_IGNORE_WIDGETS=(
(( ! ${+{{CLI_BINARY_NAME_UPPER}}_AUTOSUGGEST_IGNORE_WIDGETS} )) && {
typeset -ga {{CLI_BINARY_NAME_UPPER}}_AUTOSUGGEST_IGNORE_WIDGETS
{{CLI_BINARY_NAME_UPPER}}_AUTOSUGGEST_IGNORE_WIDGETS=(
orig-\*
beep
run-help
Expand All @@ -89,5 +89,5 @@ typeset -g Q_AUTOSUGGEST_ORIGINAL_WIDGET_PREFIX=autosuggest-orig-
}

# Pty name for capturing completions for completion suggestion strategy
(( ! ${+Q_AUTOSUGGEST_COMPLETIONS_PTY_NAME} )) &&
typeset -g Q_AUTOSUGGEST_COMPLETIONS_PTY_NAME=q_autosuggest_completion_pty
(( ! ${+{{CLI_BINARY_NAME_UPPER}}_AUTOSUGGEST_COMPLETIONS_PTY_NAME} )) &&
typeset -g {{CLI_BINARY_NAME_UPPER}}_AUTOSUGGEST_COMPLETIONS_PTY_NAME=q_autosuggest_completion_pty
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,17 @@
# from the first strategy to provide one.
#

_q_autosuggest_fetch_suggestion() {
_{{CLI_BINARY_NAME_UNDERSCORE}}_autosuggest_fetch_suggestion() {
typeset -g suggestion
local -a strategies
local strategy

# Ensure we are working with an array
strategies=(${=Q_AUTOSUGGEST_STRATEGY})
strategies=(${={{CLI_BINARY_NAME_UPPER}}_AUTOSUGGEST_STRATEGY})

for strategy in $strategies; do
# Try to get a suggestion from this strategy
_q_autosuggest_strategy_$strategy "$1"
_{{CLI_BINARY_NAME_UNDERSCORE}}_autosuggest_strategy_$strategy "$1"

# Ensure the suggestion matches the prefix
[[ "$suggestion" != "$1"* ]] && unset suggestion
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
if command -v _zsh_autosuggest_accept >/dev/null 2>&1; then
export Q_USING_ZSH_AUTOSUGGESTIONS=1
export {{CLI_BINARY_NAME_UPPER}}_USING_ZSH_AUTOSUGGESTIONS=1
else
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,23 @@
#--------------------------------------------------------------------#

# If there was a highlight, remove it
_q_autosuggest_highlight_reset() {
typeset -g _Q_AUTOSUGGEST_LAST_HIGHLIGHT
_{{CLI_BINARY_NAME_UNDERSCORE}}_autosuggest_highlight_reset() {
typeset -g _{{CLI_BINARY_NAME_UPPER}}_AUTOSUGGEST_LAST_HIGHLIGHT

if [[ -n "$_Q_AUTOSUGGEST_LAST_HIGHLIGHT" ]]; then
region_highlight=("${(@)region_highlight:#$_Q_AUTOSUGGEST_LAST_HIGHLIGHT}")
unset _Q_AUTOSUGGEST_LAST_HIGHLIGHT
if [[ -n "$_{{CLI_BINARY_NAME_UPPER}}_AUTOSUGGEST_LAST_HIGHLIGHT" ]]; then
region_highlight=("${(@)region_highlight:#$_{{CLI_BINARY_NAME_UPPER}}_AUTOSUGGEST_LAST_HIGHLIGHT}")
unset _{{CLI_BINARY_NAME_UPPER}}_AUTOSUGGEST_LAST_HIGHLIGHT
fi
}

# If there's a suggestion, highlight it
_q_autosuggest_highlight_apply() {
typeset -g _Q_AUTOSUGGEST_LAST_HIGHLIGHT
_{{CLI_BINARY_NAME_UNDERSCORE}}_autosuggest_highlight_apply() {
typeset -g _{{CLI_BINARY_NAME_UPPER}}_AUTOSUGGEST_LAST_HIGHLIGHT

if (( $#POSTDISPLAY )); then
typeset -g _Q_AUTOSUGGEST_LAST_HIGHLIGHT="$#BUFFER $(($#BUFFER + $#POSTDISPLAY)) $Q_AUTOSUGGEST_HIGHLIGHT_STYLE"
region_highlight+=("$_Q_AUTOSUGGEST_LAST_HIGHLIGHT")
typeset -g _{{CLI_BINARY_NAME_UPPER}}_AUTOSUGGEST_LAST_HIGHLIGHT="$#BUFFER $(($#BUFFER + $#POSTDISPLAY)) ${{CLI_BINARY_NAME_UPPER}}_AUTOSUGGEST_HIGHLIGHT_STYLE"
region_highlight+=("$_{{CLI_BINARY_NAME_UPPER}}_AUTOSUGGEST_LAST_HIGHLIGHT")
else
unset _Q_AUTOSUGGEST_LAST_HIGHLIGHT
unset _{{CLI_BINARY_NAME_UPPER}}_AUTOSUGGEST_LAST_HIGHLIGHT
fi
}
Loading
Loading