aboutsummaryrefslogtreecommitdiffstats
path: root/crates/turtle/src/shell
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--crates/turtle/src/shell/atuin.bash1161
-rw-r--r--crates/turtle/src/shell/atuin.fish86
-rw-r--r--crates/turtle/src/shell/atuin.zsh56
3 files changed, 560 insertions, 743 deletions
diff --git a/crates/turtle/src/shell/atuin.bash b/crates/turtle/src/shell/atuin.bash
index 8b540bd7..703e8fe2 100644
--- a/crates/turtle/src/shell/atuin.bash
+++ b/crates/turtle/src/shell/atuin.bash
@@ -9,717 +9,664 @@ elif ((BASH_VERSINFO[0] < 3 || BASH_VERSINFO[0] == 3 && BASH_VERSINFO[1] < 1));
[[ -t 2 ]] && printf 'atuin: requires bash >= 3.1 for the integration.\n' >&2
false
else # (include guard) beginning of main content
-#------------------------------------------------------------------------------
-__atuin_initialized=true
+ #------------------------------------------------------------------------------
+ __atuin_initialized=true
-if [[ -z "${ATUIN_SESSION:-}" || "${ATUIN_SHLVL:-}" != "$SHLVL" ]]; then
- ATUIN_SESSION=$(atuin uuid)
- export ATUIN_SESSION
- export ATUIN_SHLVL=$SHLVL
-fi
-ATUIN_STTY=$(stty -g)
-ATUIN_HISTORY_ID=""
+ if [[ -z "${ATUIN_SESSION:-}" || "${ATUIN_SHLVL:-}" != "$SHLVL" ]]; then
+ ATUIN_SESSION=$(atuin uuid)
+ export ATUIN_SESSION
+ export ATUIN_SHLVL=$SHLVL
+ fi
+ ATUIN_STTY=$(stty -g)
+ ATUIN_HISTORY_ID=""
-__atuin_osc133_command_executed() {
- [[ -n "${ATUIN_PTY_PROXY_ACTIVE:-}" ]] || return
- [[ -n "${ATUIN_HISTORY_ID:-}" && "$ATUIN_HISTORY_ID" != "__bash_preexec_failure__" ]] || return
+ __atuin_osc133_command_executed() {
+ [[ -n "${ATUIN_PTY_PROXY_ACTIVE:-}" ]] || return
+ [[ -n "${ATUIN_HISTORY_ID:-}" && "$ATUIN_HISTORY_ID" != "__bash_preexec_failure__" ]] || return
- printf '\033]133;C\a'
-}
+ printf '\033]133;C\a'
+ }
-__atuin_osc133_command_finished() {
- [[ -n "${ATUIN_PTY_PROXY_ACTIVE:-}" ]] || return
- [[ -n "${ATUIN_HISTORY_ID:-}" && "$ATUIN_HISTORY_ID" != "__bash_preexec_failure__" ]] || return
+ __atuin_osc133_command_finished() {
+ [[ -n "${ATUIN_PTY_PROXY_ACTIVE:-}" ]] || return
+ [[ -n "${ATUIN_HISTORY_ID:-}" && "$ATUIN_HISTORY_ID" != "__bash_preexec_failure__" ]] || return
- printf '\033]133;D;%s;history_id=%s;session_id=%s\a' "$1" "$ATUIN_HISTORY_ID" "${ATUIN_SESSION:-}"
-}
+ printf '\033]133;D;%s;history_id=%s;session_id=%s\a' "$1" "$ATUIN_HISTORY_ID" "${ATUIN_SESSION:-}"
+ }
-__atuin_osc133_prompt_start=$'\001\033]133;A;cl=line\a\002'
-__atuin_osc133_prompt_end=$'\001\033]133;B\a\002'
+ __atuin_osc133_prompt_start=$'\001\033]133;A;cl=line\a\002'
+ __atuin_osc133_prompt_end=$'\001\033]133;B\a\002'
-__atuin_osc133_wrap_prompt() {
- local __atuin_prompt="${PS1-}"
- __atuin_prompt="${__atuin_prompt//$__atuin_osc133_prompt_start/}"
- __atuin_prompt="${__atuin_prompt//$__atuin_osc133_prompt_end/}"
+ __atuin_osc133_wrap_prompt() {
+ local __atuin_prompt="${PS1-}"
+ __atuin_prompt="${__atuin_prompt//$__atuin_osc133_prompt_start/}"
+ __atuin_prompt="${__atuin_prompt//$__atuin_osc133_prompt_end/}"
- if [[ -n "${ATUIN_PTY_PROXY_ACTIVE:-}" ]]; then
- PS1="${__atuin_osc133_prompt_start}${__atuin_prompt}${__atuin_osc133_prompt_end}"
- else
- PS1="$__atuin_prompt"
- fi
-}
+ if [[ -n "${ATUIN_PTY_PROXY_ACTIVE:-}" ]]; then
+ PS1="${__atuin_osc133_prompt_start}${__atuin_prompt}${__atuin_osc133_prompt_end}"
+ else
+ PS1="$__atuin_prompt"
+ fi
+ }
-export ATUIN_PREEXEC_BACKEND=$SHLVL:none
-__atuin_update_preexec_backend() {
- if [[ ${BLE_ATTACHED-} ]]; then
- ATUIN_PREEXEC_BACKEND=$SHLVL:blesh-${BLE_VERSION-}
- elif [[ ${bash_preexec_imported-} ]]; then
- ATUIN_PREEXEC_BACKEND=$SHLVL:bash-preexec
- elif [[ ${__bp_imported-} ]]; then
- ATUIN_PREEXEC_BACKEND="$SHLVL:bash-preexec (old)"
- else
- ATUIN_PREEXEC_BACKEND=$SHLVL:unknown
- fi
-}
+ export ATUIN_PREEXEC_BACKEND=$SHLVL:none
+ __atuin_update_preexec_backend() {
+ if [[ ${BLE_ATTACHED-} ]]; then
+ ATUIN_PREEXEC_BACKEND=$SHLVL:blesh-${BLE_VERSION-}
+ elif [[ ${bash_preexec_imported-} ]]; then
+ ATUIN_PREEXEC_BACKEND=$SHLVL:bash-preexec
+ elif [[ ${__bp_imported-} ]]; then
+ ATUIN_PREEXEC_BACKEND="$SHLVL:bash-preexec (old)"
+ else
+ ATUIN_PREEXEC_BACKEND=$SHLVL:unknown
+ fi
+ }
-__atuin_preexec() {
- # Workaround for old versions of bash-preexec
- if [[ ! ${BLE_ATTACHED-} ]]; then
- # In older versions of bash-preexec, the preexec hook may be called
- # even for the commands run by keybindings. There is no general and
- # robust way to detect the command for keybindings, but at least we
- # want to exclude Atuin's keybindings. When the preexec hook is called
- # for a keybinding, the preexec hook for the user command will not
- # fire, so we instead set a fake ATUIN_HISTORY_ID here to notify
- # __atuin_precmd of this failure.
- if [[ $BASH_COMMAND != "$1" ]]; then
- case $BASH_COMMAND in
+ __atuin_preexec() {
+ # Workaround for old versions of bash-preexec
+ if [[ ! ${BLE_ATTACHED-} ]]; then
+ # In older versions of bash-preexec, the preexec hook may be called
+ # even for the commands run by keybindings. There is no general and
+ # robust way to detect the command for keybindings, but at least we
+ # want to exclude Atuin's keybindings. When the preexec hook is called
+ # for a keybinding, the preexec hook for the user command will not
+ # fire, so we instead set a fake ATUIN_HISTORY_ID here to notify
+ # __atuin_precmd of this failure.
+ if [[ $BASH_COMMAND != "$1" ]]; then
+ case $BASH_COMMAND in
'__atuin_history'* | '__atuin_widget_run'* | '__atuin_bash42_dispatch'*)
ATUIN_HISTORY_ID=__bash_preexec_failure__
- return 0 ;;
- esac
+ return 0
+ ;;
+ esac
+ fi
fi
- fi
- # Note: We update ATUIN_PREEXEC_BACKEND on every preexec because blesh's
- # attaching state can dynamically change.
- __atuin_update_preexec_backend
+ # Note: We update ATUIN_PREEXEC_BACKEND on every preexec because blesh's
+ # attaching state can dynamically change.
+ __atuin_update_preexec_backend
- local id
- id=$(atuin history start -- "$1" 2>/dev/null)
- export ATUIN_HISTORY_ID=$id
- [[ -n ${__atuin_skip_osc133:-} ]] || __atuin_osc133_command_executed
- __atuin_preexec_time=${EPOCHREALTIME-}
-}
-
-__atuin_precmd() {
- local EXIT=$? __atuin_precmd_time=${EPOCHREALTIME-}
+ local id
+ id=$(atuin history start -- "$1" 2>/dev/null)
+ export ATUIN_HISTORY_ID=$id
+ [[ -n ${__atuin_skip_osc133:-} ]] || __atuin_osc133_command_executed
+ __atuin_preexec_time=${EPOCHREALTIME-}
+ }
- __atuin_osc133_wrap_prompt
+ __atuin_precmd() {
+ local EXIT=$? __atuin_precmd_time=${EPOCHREALTIME-}
- [[ ! $ATUIN_HISTORY_ID ]] && return
+ __atuin_osc133_wrap_prompt
- # If the previous preexec hook failed, we manually call __atuin_preexec
- local __atuin_skip_osc133=""
- if [[ $ATUIN_HISTORY_ID == __bash_preexec_failure__ ]]; then
- # This is the command extraction code taken from bash-preexec
- local previous_command
- previous_command=$(
- export LC_ALL=C HISTTIMEFORMAT=''
- builtin history 1 | sed '1 s/^ *[0-9][0-9]*[* ] //'
- )
- __atuin_skip_osc133=1
- __atuin_preexec "$previous_command"
- fi
+ [[ ! $ATUIN_HISTORY_ID ]] && return
- local duration=""
- # shellcheck disable=SC2154,SC2309
- if [[ ${BLE_ATTACHED-} && ${_ble_exec_time_ata-} ]]; then
- # With ble.sh, we utilize the shell variable `_ble_exec_time_ata`
- # recorded by ble.sh. It is more accurate than the measurements by
- # Atuin, which includes the spawn cost of Atuin. ble.sh uses the
- # special shell variable `EPOCHREALTIME` in bash >= 5.0 with the
- # microsecond resolution, or the builtin `time` in bash < 5.0 with the
- # millisecond resolution.
- duration=${_ble_exec_time_ata}000
- elif ((BASH_VERSINFO[0] >= 5)); then
- # We calculate the high-resolution duration based on EPOCHREALTIME
- # (bash >= 5.0) recorded by precmd/preexec, though it might not be as
- # accurate as `_ble_exec_time_ata` provided by ble.sh because it
- # includes the extra time of the precmd/preexec handling. Since Bash
- # does not offer floating-point arithmetic, we remove the non-digit
- # characters and perform the integral arithmetic. The fraction part of
- # EPOCHREALTIME is fixed to have 6 digits in Bash. We remove all the
- # non-digit characters because the decimal point is not necessarily a
- # period depending on the locale.
- duration=$((${__atuin_precmd_time//[!0-9]} - ${__atuin_preexec_time//[!0-9]}))
- if ((duration >= 0)); then
- duration=${duration}000
- else
- duration="" # clear the result on overflow
+ # If the previous preexec hook failed, we manually call __atuin_preexec
+ local __atuin_skip_osc133=""
+ if [[ $ATUIN_HISTORY_ID == __bash_preexec_failure__ ]]; then
+ # This is the command extraction code taken from bash-preexec
+ local previous_command
+ previous_command=$(
+ export LC_ALL=C HISTTIMEFORMAT=''
+ builtin history 1 | sed '1 s/^ *[0-9][0-9]*[* ] //'
+ )
+ __atuin_skip_osc133=1
+ __atuin_preexec "$previous_command"
fi
- fi
-
- [[ -n ${__atuin_skip_osc133:-} ]] || __atuin_osc133_command_finished "$EXIT"
- (ATUIN_LOG=error atuin history end --exit "$EXIT" ${duration:+"--duration=$duration"} -- "$ATUIN_HISTORY_ID" &) >/dev/null 2>&1
- export ATUIN_HISTORY_ID=""
-}
-__atuin_set_ret_value() {
- return ${1:+"$1"}
-}
-
-#------------------------------------------------------------------------------
-# section: __atuin_accept_line
-#
-# The function "__atuin_accept_line" is kept for backward compatibility of the
-# direct use of __atuin_history in keybindings by users.
-
-# The shell function `__atuin_evaluate_prompt` evaluates prompt sequences in
-# $PS1. We switch the implementation of the shell function
-# `__atuin_evaluate_prompt` based on the Bash version because the expansion
-# ${PS1@P} is only available in bash >= 4.4.
-if ((BASH_VERSINFO[0] >= 5 || BASH_VERSINFO[0] == 4 && BASH_VERSINFO[1] >= 4)); then
- __atuin_evaluate_prompt() {
- __atuin_set_ret_value "${__bp_last_ret_value-}" "${__bp_last_argument_prev_command-}"
- __atuin_prompt=${PS1@P}
-
- # Note: Strip the control characters ^A (\001) and ^B (\002), which
- # Bash internally uses to enclose the escape sequences. They are
- # produced by '\[' and '\]', respectively, in $PS1 and used to tell
- # Bash that the strings inbetween do not contribute to the prompt
- # width. After the prompt width calculation, Bash strips those control
- # characters before outputting it to the terminal. We here strip these
- # characters following Bash's behavior.
- __atuin_prompt=${__atuin_prompt//[$'\001\002']}
+ local duration=""
+ # shellcheck disable=SC2154,SC2309
+ if [[ ${BLE_ATTACHED-} && ${_ble_exec_time_ata-} ]]; then
+ # With ble.sh, we utilize the shell variable `_ble_exec_time_ata`
+ # recorded by ble.sh. It is more accurate than the measurements by
+ # Atuin, which includes the spawn cost of Atuin. ble.sh uses the
+ # special shell variable `EPOCHREALTIME` in bash >= 5.0 with the
+ # microsecond resolution, or the builtin `time` in bash < 5.0 with the
+ # millisecond resolution.
+ duration=${_ble_exec_time_ata}000
+ elif ((BASH_VERSINFO[0] >= 5)); then
+ # We calculate the high-resolution duration based on EPOCHREALTIME
+ # (bash >= 5.0) recorded by precmd/preexec, though it might not be as
+ # accurate as `_ble_exec_time_ata` provided by ble.sh because it
+ # includes the extra time of the precmd/preexec handling. Since Bash
+ # does not offer floating-point arithmetic, we remove the non-digit
+ # characters and perform the integral arithmetic. The fraction part of
+ # EPOCHREALTIME is fixed to have 6 digits in Bash. We remove all the
+ # non-digit characters because the decimal point is not necessarily a
+ # period depending on the locale.
+ duration=$((${__atuin_precmd_time//[!0-9]/} - ${__atuin_preexec_time//[!0-9]/}))
+ if ((duration >= 0)); then
+ duration=${duration}000
+ else
+ duration="" # clear the result on overflow
+ fi
+ fi
- # Count the number of newlines contained in $__atuin_prompt
- __atuin_prompt_offset=${__atuin_prompt//[!$'\n']}
- __atuin_prompt_offset=${#__atuin_prompt_offset}
+ [[ -n ${__atuin_skip_osc133:-} ]] || __atuin_osc133_command_finished "$EXIT"
+ (ATUIN_LOG=error atuin history end --exit "$EXIT" ${duration:+"--duration=$duration"} -- "$ATUIN_HISTORY_ID" &) >/dev/null 2>&1
+ export ATUIN_HISTORY_ID=""
}
-else
- __atuin_evaluate_prompt() {
- __atuin_prompt='$ '
- __atuin_prompt_offset=0
+
+ __atuin_set_ret_value() {
+ return ${1:+"$1"}
}
-fi
-# The shell function `__atuin_clear_prompt N` outputs terminal control
-# sequences to clear the contents of the current and N previous lines. After
-# clearing, the cursor is placed at the beginning of the N-th previous line.
-__atuin_clear_prompt_cache=()
-__atuin_clear_prompt() {
- local offset=$1
- if [[ ! ${__atuin_clear_prompt_cache[offset]+set} ]]; then
- if [[ ! ${__atuin_clear_prompt_cache[0]+set} ]]; then
- __atuin_clear_prompt_cache[0]=$'\r'$(tput el 2>/dev/null || tput ce 2>/dev/null)
- fi
- if ((offset > 0)); then
- __atuin_clear_prompt_cache[offset]=${__atuin_clear_prompt_cache[0]}$(
- tput cuu "$offset" 2>/dev/null || tput UP "$offset" 2>/dev/null
- tput dl "$offset" 2>/dev/null || tput DL "$offset" 2>/dev/null
- tput il "$offset" 2>/dev/null || tput AL "$offset" 2>/dev/null
- )
- fi
- fi
- printf '%s' "${__atuin_clear_prompt_cache[offset]}"
-}
+ #------------------------------------------------------------------------------
+ # section: __atuin_accept_line
+ #
+ # The function "__atuin_accept_line" is kept for backward compatibility of the
+ # direct use of __atuin_history in keybindings by users.
-__atuin_accept_line() {
- local __atuin_command=$1
+ # The shell function `__atuin_evaluate_prompt` evaluates prompt sequences in
+ # $PS1. We switch the implementation of the shell function
+ # `__atuin_evaluate_prompt` based on the Bash version because the expansion
+ # ${PS1@P} is only available in bash >= 4.4.
+ if ((BASH_VERSINFO[0] >= 5 || BASH_VERSINFO[0] == 4 && BASH_VERSINFO[1] >= 4)); then
+ __atuin_evaluate_prompt() {
+ __atuin_set_ret_value "${__bp_last_ret_value-}" "${__bp_last_argument_prev_command-}"
+ __atuin_prompt=${PS1@P}
- # Reprint the prompt, accounting for multiple lines
- local __atuin_prompt __atuin_prompt_offset
- __atuin_evaluate_prompt
- __atuin_clear_prompt "$__atuin_prompt_offset"
- printf '%s\n' "$__atuin_prompt$__atuin_command"
+ # Note: Strip the control characters ^A (\001) and ^B (\002), which
+ # Bash internally uses to enclose the escape sequences. They are
+ # produced by '\[' and '\]', respectively, in $PS1 and used to tell
+ # Bash that the strings inbetween do not contribute to the prompt
+ # width. After the prompt width calculation, Bash strips those control
+ # characters before outputting it to the terminal. We here strip these
+ # characters following Bash's behavior.
+ __atuin_prompt=${__atuin_prompt//[$'\001\002']/}
- # Add it to the bash history
- history -s "$__atuin_command"
+ # Count the number of newlines contained in $__atuin_prompt
+ __atuin_prompt_offset=${__atuin_prompt//[!$'\n']/}
+ __atuin_prompt_offset=${#__atuin_prompt_offset}
+ }
+ else
+ __atuin_evaluate_prompt() {
+ __atuin_prompt='$ '
+ __atuin_prompt_offset=0
+ }
+ fi
- # Assuming bash-preexec
- # Invoke every function in the preexec array
- local __atuin_preexec_function
- local __atuin_preexec_function_ret_value
- local __atuin_preexec_ret_value=0
- for __atuin_preexec_function in "${preexec_functions[@]:-}"; do
- if type -t "$__atuin_preexec_function" 1>/dev/null; then
- __atuin_set_ret_value "${__bp_last_ret_value:-}"
- "$__atuin_preexec_function" "$__atuin_command"
- __atuin_preexec_function_ret_value=$?
- if [[ $__atuin_preexec_function_ret_value != 0 ]]; then
- __atuin_preexec_ret_value=$__atuin_preexec_function_ret_value
+ # The shell function `__atuin_clear_prompt N` outputs terminal control
+ # sequences to clear the contents of the current and N previous lines. After
+ # clearing, the cursor is placed at the beginning of the N-th previous line.
+ __atuin_clear_prompt_cache=()
+ __atuin_clear_prompt() {
+ local offset=$1
+ if [[ ! ${__atuin_clear_prompt_cache[offset]+set} ]]; then
+ if [[ ! ${__atuin_clear_prompt_cache[0]+set} ]]; then
+ __atuin_clear_prompt_cache[0]=$'\r'$(tput el 2>/dev/null || tput ce 2>/dev/null)
+ fi
+ if ((offset > 0)); then
+ __atuin_clear_prompt_cache[offset]=${__atuin_clear_prompt_cache[0]}$(
+ tput cuu "$offset" 2>/dev/null || tput UP "$offset" 2>/dev/null
+ tput dl "$offset" 2>/dev/null || tput DL "$offset" 2>/dev/null
+ tput il "$offset" 2>/dev/null || tput AL "$offset" 2>/dev/null
+ )
fi
fi
- done
-
- # If extdebug is turned on and any preexec function returns non-zero
- # exit status, we do not run the user command.
- if ! { shopt -q extdebug && ((__atuin_preexec_ret_value)); }; then
- # Note: When a child Bash session is started by enter_accept, if the
- # environment variable READLINE_POINT is present, bash-preexec in the
- # child session does not fire preexec at all because it considers we
- # are inside Atuin's keybinding of the current session. To avoid
- # propagating the environment variable to the child session, we remove
- # the export attribute of READLINE_LINE and READLINE_POINT.
- export -n READLINE_LINE READLINE_POINT
-
- # Juggle the terminal settings so that the command can be interacted
- # with
- local __atuin_stty_backup
- __atuin_stty_backup=$(stty -g)
- stty "$ATUIN_STTY"
-
- # Execute the command. Note: We need to record $? and $_ after the
- # user command within the same call of "eval" because $_ is otherwise
- # overwritten by the last argument of "eval".
- __atuin_set_ret_value "${__bp_last_ret_value-}" "${__bp_last_argument_prev_command-}"
- eval -- "$__atuin_command"$'\n__bp_last_ret_value=$? __bp_last_argument_prev_command=$_'
-
- stty "$__atuin_stty_backup"
- fi
-
- # Execute preprompt commands
- local __atuin_prompt_command
- for __atuin_prompt_command in "${PROMPT_COMMAND[@]}"; do
- __atuin_set_ret_value "${__bp_last_ret_value-}" "${__bp_last_argument_prev_command-}"
- eval -- "$__atuin_prompt_command"
- done
- # Bash will redraw only the line with the prompt after we finish,
- # so to work for a multiline prompt we need to print it ourselves,
- # then go to the beginning of the last line.
- __atuin_evaluate_prompt
- printf '%s' "$__atuin_prompt"
- __atuin_clear_prompt 0
-}
+ printf '%s' "${__atuin_clear_prompt_cache[offset]}"
+ }
-#------------------------------------------------------------------------------
+ __atuin_accept_line() {
+ local __atuin_command=$1
-# Check if tmux popup is available (tmux >= 3.2)
-__atuin_tmux_popup_check() {
- [[ -n "${TMUX-}" ]] || return 1
- [[ "${ATUIN_TMUX_POPUP:-true}" != "false" ]] || return 1
+ # Reprint the prompt, accounting for multiple lines
+ local __atuin_prompt __atuin_prompt_offset
+ __atuin_evaluate_prompt
+ __atuin_clear_prompt "$__atuin_prompt_offset"
+ printf '%s\n' "$__atuin_prompt$__atuin_command"
- # https://github.com/tmux/tmux/wiki/FAQ#how-often-is-tmux-released-what-is-the-version-number-scheme
- local tmux_version
- tmux_version=$(tmux -V 2>/dev/null | sed -n 's/^[^0-9]*\([0-9][0-9]*\.[0-9][0-9]*\).*/\1/p') # Could have used grep...
- [[ -z "$tmux_version" ]] && return 1
+ # Add it to the bash history
+ history -s "$__atuin_command"
- local m1 m2
- m1=${tmux_version%%.*}
- m2=${tmux_version#*.}
- m2=${m2%%.*}
- [[ "$m1" =~ ^[0-9]+$ ]] || return 1
- [[ "$m2" =~ ^[0-9]+$ ]] || m2=0
- (( m1 > 3 || (m1 == 3 && m2 >= 2) ))
-}
+ # Assuming bash-preexec
+ # Invoke every function in the preexec array
+ local __atuin_preexec_function
+ local __atuin_preexec_function_ret_value
+ local __atuin_preexec_ret_value=0
+ for __atuin_preexec_function in "${preexec_functions[@]:-}"; do
+ if type -t "$__atuin_preexec_function" 1>/dev/null; then
+ __atuin_set_ret_value "${__bp_last_ret_value:-}"
+ "$__atuin_preexec_function" "$__atuin_command"
+ __atuin_preexec_function_ret_value=$?
+ if [[ $__atuin_preexec_function_ret_value != 0 ]]; then
+ __atuin_preexec_ret_value=$__atuin_preexec_function_ret_value
+ fi
+ fi
+ done
-# Use global variable to fix scope issues with traps
-__atuin_popup_tmpdir=""
-__atuin_tmux_popup_cleanup() {
- [[ -n "$__atuin_popup_tmpdir" && -d "$__atuin_popup_tmpdir" ]] && command rm -rf "$__atuin_popup_tmpdir"
- __atuin_popup_tmpdir=""
-}
+ # If extdebug is turned on and any preexec function returns non-zero
+ # exit status, we do not run the user command.
+ if ! { shopt -q extdebug && ((__atuin_preexec_ret_value)); }; then
+ # Note: When a child Bash session is started by enter_accept, if the
+ # environment variable READLINE_POINT is present, bash-preexec in the
+ # child session does not fire preexec at all because it considers we
+ # are inside Atuin's keybinding of the current session. To avoid
+ # propagating the environment variable to the child session, we remove
+ # the export attribute of READLINE_LINE and READLINE_POINT.
+ export -n READLINE_LINE READLINE_POINT
-__atuin_search_cmd() {
- local -a search_args=("$@")
+ # Juggle the terminal settings so that the command can be interacted
+ # with
+ local __atuin_stty_backup
+ __atuin_stty_backup=$(stty -g)
+ stty "$ATUIN_STTY"
- if __atuin_tmux_popup_check; then
- __atuin_popup_tmpdir=$(mktemp -d) || return 1
- local result_file="$__atuin_popup_tmpdir/result"
+ # Execute the command. Note: We need to record $? and $_ after the
+ # user command within the same call of "eval" because $_ is otherwise
+ # overwritten by the last argument of "eval".
+ __atuin_set_ret_value "${__bp_last_ret_value-}" "${__bp_last_argument_prev_command-}"
+ eval -- "$__atuin_command"$'\n__bp_last_ret_value=$? __bp_last_argument_prev_command=$_'
- trap '__atuin_tmux_popup_cleanup' EXIT HUP INT TERM
+ stty "$__atuin_stty_backup"
+ fi
- local escaped_query escaped_args
- escaped_query=$(printf '%s' "$READLINE_LINE" | sed "s/'/'\\\\''/g")
- escaped_args=""
- for arg in "${search_args[@]}"; do
- escaped_args+=" '$(printf '%s' "$arg" | sed "s/'/'\\\\''/g")'"
+ # Execute preprompt commands
+ local __atuin_prompt_command
+ for __atuin_prompt_command in "${PROMPT_COMMAND[@]}"; do
+ __atuin_set_ret_value "${__bp_last_ret_value-}" "${__bp_last_argument_prev_command-}"
+ eval -- "$__atuin_prompt_command"
done
+ # Bash will redraw only the line with the prompt after we finish,
+ # so to work for a multiline prompt we need to print it ourselves,
+ # then go to the beginning of the last line.
+ __atuin_evaluate_prompt
+ printf '%s' "$__atuin_prompt"
+ __atuin_clear_prompt 0
+ }
- # In the popup, atuin goes to terminal, stderr goes to file
- local cdir popup_width popup_height
- cdir=$(pwd)
- popup_width="${ATUIN_TMUX_POPUP_WIDTH:-80%}" # Keep default value anyways
- popup_height="${ATUIN_TMUX_POPUP_HEIGHT:-60%}"
- tmux display-popup -d "$cdir" -w "$popup_width" -h "$popup_height" -E -E -- \
- sh -c "PATH='$PATH' ATUIN_SESSION='$ATUIN_SESSION' ATUIN_SHELL=bash ATUIN_LOG=error ATUIN_QUERY='$escaped_query' atuin search $escaped_args -i 2>'$result_file'"
+ #------------------------------------------------------------------------------
- if [[ -f "$result_file" ]]; then
- cat "$result_file"
- fi
+ __atuin_search_cmd() {
+ local -a search_args=("$@")
- __atuin_tmux_popup_cleanup
- trap - EXIT HUP INT TERM
- else
ATUIN_SHELL=bash ATUIN_LOG=error ATUIN_QUERY=$READLINE_LINE atuin search "${search_args[@]}" -i 3>&1 1>&2 2>&3 3>&-
- fi
-}
+ }
-__atuin_history() {
- # Default action of the up key: When this function is called with the first
- # argument `--shell-up-key-binding`, we perform Atuin's history search only
- # when the up key is supposed to cause the history movement in the original
- # binding. We do this only for ble.sh because the up key always invokes
- # the history movement in the plain Bash.
- if [[ ${BLE_ATTACHED-} && ${1-} == --shell-up-key-binding ]]; then
- # When the current cursor position is not in the first line, the up key
- # should move the cursor to the previous line. While the selection is
- # performed, the up key should not start the history search.
- # shellcheck disable=SC2154 # Note: these variables are set by ble.sh
- if [[ ${_ble_edit_str::_ble_edit_ind} == *$'\n'* || $_ble_edit_mark_active ]]; then
- ble/widget/@nomarked backward-line
- local status=$?
- READLINE_LINE=$_ble_edit_str
- READLINE_POINT=$_ble_edit_ind
- READLINE_MARK=$_ble_edit_mark
- return "$status"
+ __atuin_history() {
+ # Default action of the up key: When this function is called with the first
+ # argument `--shell-up-key-binding`, we perform Atuin's history search only
+ # when the up key is supposed to cause the history movement in the original
+ # binding. We do this only for ble.sh because the up key always invokes
+ # the history movement in the plain Bash.
+ if [[ ${BLE_ATTACHED-} && ${1-} == --shell-up-key-binding ]]; then
+ # When the current cursor position is not in the first line, the up key
+ # should move the cursor to the previous line. While the selection is
+ # performed, the up key should not start the history search.
+ # shellcheck disable=SC2154 # Note: these variables are set by ble.sh
+ if [[ ${_ble_edit_str::_ble_edit_ind} == *$'\n'* || $_ble_edit_mark_active ]]; then
+ ble/widget/@nomarked backward-line
+ local status=$?
+ READLINE_LINE=$_ble_edit_str
+ READLINE_POINT=$_ble_edit_ind
+ READLINE_MARK=$_ble_edit_mark
+ return "$status"
+ fi
fi
- fi
- # READLINE_LINE and READLINE_POINT are only supported by bash >= 4.0 or
- # ble.sh. When it is not supported, we clear them to suppress strange
- # behaviors.
- [[ ${BLE_ATTACHED-} ]] || ((BASH_VERSINFO[0] >= 4)) ||
- READLINE_LINE="" READLINE_POINT=0
+ # READLINE_LINE and READLINE_POINT are only supported by bash >= 4.0 or
+ # ble.sh. When it is not supported, we clear them to suppress strange
+ # behaviors.
+ [[ ${BLE_ATTACHED-} ]] || ((BASH_VERSINFO[0] >= 4)) ||
+ READLINE_LINE="" READLINE_POINT=0
- local __atuin_output
- if ! __atuin_output=$(__atuin_search_cmd "$@"); then
- [[ $__atuin_output ]] && printf '%s\n' "$__atuin_output" >&2
- return 1
- fi
-
- # We do nothing when the search is canceled.
- [[ $__atuin_output ]] || return 0
-
- if [[ $__atuin_output == __atuin_accept__:* ]]; then
- __atuin_output=${__atuin_output#__atuin_accept__:}
-
- if [[ ${BLE_ATTACHED-} ]]; then
- ble-edit/content/reset-and-check-dirty "$__atuin_output"
- ble/widget/accept-line
- READLINE_LINE=""
- elif [[ ${__atuin_macro_chain_keymap-} ]]; then
- READLINE_LINE=$__atuin_output
- bind -m "$__atuin_macro_chain_keymap" '"'"$__atuin_macro_chain"'": '"$__atuin_macro_accept_line"
- else
- __atuin_accept_line "$__atuin_output"
- READLINE_LINE=""
+ local __atuin_output
+ if ! __atuin_output=$(__atuin_search_cmd "$@"); then
+ [[ $__atuin_output ]] && printf '%s\n' "$__atuin_output" >&2
+ return 1
fi
- READLINE_POINT=${#READLINE_LINE}
- else
- READLINE_LINE=$__atuin_output
- READLINE_POINT=${#READLINE_LINE}
- if [[ ! ${BLE_ATTACHED-} ]] && ((BASH_VERSINFO[0] < 4)) && [[ ${__atuin_macro_chain_keymap-} ]]; then
- bind -m "$__atuin_macro_chain_keymap" '"'"$__atuin_macro_chain"'": '"$__atuin_macro_insert_line"
- fi
- fi
-}
+ # We do nothing when the search is canceled.
+ [[ $__atuin_output ]] || return 0
-__atuin_initialize_blesh() {
- # shellcheck disable=SC2154
- [[ ${BLE_VERSION-} ]] && ((_ble_version >= 400)) || return 0
+ if [[ $__atuin_output == __atuin_accept__:* ]]; then
+ __atuin_output=${__atuin_output#__atuin_accept__:}
- ble-import contrib/integration/bash-preexec
+ if [[ ${BLE_ATTACHED-} ]]; then
+ ble-edit/content/reset-and-check-dirty "$__atuin_output"
+ ble/widget/accept-line
+ READLINE_LINE=""
+ elif [[ ${__atuin_macro_chain_keymap-} ]]; then
+ READLINE_LINE=$__atuin_output
+ bind -m "$__atuin_macro_chain_keymap" '"'"$__atuin_macro_chain"'": '"$__atuin_macro_accept_line"
+ else
+ __atuin_accept_line "$__atuin_output"
+ READLINE_LINE=""
+ fi
- # Define and register an autosuggestion source for ble.sh's auto-complete.
- # If you'd like to overwrite this, define the same name of shell function
- # after the $(atuin init bash) line in your .bashrc. If you do not need
- # the auto-complete source by Atuin, please add the following code to
- # remove the entry after the $(atuin init bash) line in your .bashrc:
- #
- # ble/util/import/eval-after-load core-complete '
- # ble/array#remove _ble_complete_auto_source atuin-history'
- #
- function ble/complete/auto-complete/source:atuin-history {
- local suggestion
- suggestion=$(ATUIN_QUERY="$_ble_edit_str" atuin search --cmd-only --limit 1 --search-mode prefix 2>/dev/null)
- [[ $suggestion == "$_ble_edit_str"?* ]] || return 1
- ble/complete/auto-complete/enter h 0 "${suggestion:${#_ble_edit_str}}" '' "$suggestion"
+ READLINE_POINT=${#READLINE_LINE}
+ else
+ READLINE_LINE=$__atuin_output
+ READLINE_POINT=${#READLINE_LINE}
+ if [[ ! ${BLE_ATTACHED-} ]] && ((BASH_VERSINFO[0] < 4)) && [[ ${__atuin_macro_chain_keymap-} ]]; then
+ bind -m "$__atuin_macro_chain_keymap" '"'"$__atuin_macro_chain"'": '"$__atuin_macro_insert_line"
+ fi
+ fi
}
- ble/util/import/eval-after-load core-complete '
- ble/array#unshift _ble_complete_auto_source atuin-history'
- # @env BLE_SESSION_ID: `atuin doctor` references the environment variable
- # BLE_SESSION_ID. We explicitly export the variable because it was not
- # exported in older versions of ble.sh.
- [[ ${BLE_SESSION_ID-} ]] && export BLE_SESSION_ID
-}
-__atuin_initialize_blesh
-BLE_ONLOAD+=(__atuin_initialize_blesh)
-precmd_functions+=(__atuin_precmd)
-preexec_functions+=(__atuin_preexec)
+ __atuin_initialize_blesh() {
+ # shellcheck disable=SC2154
+ [[ ${BLE_VERSION-} ]] && ((_ble_version >= 400)) || return 0
-#------------------------------------------------------------------------------
-# section: atuin-bind
+ ble-import contrib/integration/bash-preexec
-__atuin_widget=()
+ # Define and register an autosuggestion source for ble.sh's auto-complete.
+ # If you'd like to overwrite this, define the same name of shell function
+ # after the $(atuin init bash) line in your .bashrc. If you do not need
+ # the auto-complete source by Atuin, please add the following code to
+ # remove the entry after the $(atuin init bash) line in your .bashrc:
+ #
+ # ble/util/import/eval-after-load core-complete '
+ # ble/array#remove _ble_complete_auto_source atuin-history'
+ #
+ function ble/complete/auto-complete/source:atuin-history {
+ local suggestion
+ suggestion=$(ATUIN_QUERY="$_ble_edit_str" atuin search --cmd-only --limit 1 --search-mode prefix 2>/dev/null)
+ [[ $suggestion == "$_ble_edit_str"?* ]] || return 1
+ ble/complete/auto-complete/enter h 0 "${suggestion:${#_ble_edit_str}}" '' "$suggestion"
+ }
+ ble/util/import/eval-after-load core-complete '
+ ble/array#unshift _ble_complete_auto_source atuin-history'
-__atuin_widget_save() {
- local data=$1
- for REPLY in "${!__atuin_widget[@]}"; do
- if [[ ${__atuin_widget[REPLY]} == "$data" ]]; then
- return 0
- fi
- done
- # shellcheck disable=SC2154
- REPLY=${#__atuin_widget[*]}
- __atuin_widget[REPLY]=$data
-}
+ # @env BLE_SESSION_ID: `atuin doctor` references the environment variable
+ # BLE_SESSION_ID. We explicitly export the variable because it was not
+ # exported in older versions of ble.sh.
+ [[ ${BLE_SESSION_ID-} ]] && export BLE_SESSION_ID
+ }
+ __atuin_initialize_blesh
+ BLE_ONLOAD+=(__atuin_initialize_blesh)
+ precmd_functions+=(__atuin_precmd)
+ preexec_functions+=(__atuin_preexec)
-__atuin_widget_run() {
- local data=${__atuin_widget[$1]}
- local keymap=${data%%:*} widget=${data#*:}
- local __atuin_macro_chain_keymap=$keymap
- bind -m "$keymap" '"'"$__atuin_macro_chain"'": ""'
- builtin eval -- "$widget"
-}
+ #------------------------------------------------------------------------------
+ # section: atuin-bind
-# To realize the enter_accept feature in a robust way, we need to call the
-# readline bindable function `accept-line'. However, there is no way to call
-# `accept-line' from the shell script. To call the bindable function
-# `accept-line', we may utilize string macros of readline. When we bind KEYSEQ
-# to a WIDGET that wants to conditionally call `accept-line' at the end, we
-# perform two-step dispatching:
-#
-# 1. [KEYSEQ -> IKEYSEQ1 IKEYSEQ2]---We first translate KEYSEQ to two
-# intermediate key sequences IKEYSEQ1 and IKEYSEQ2 using string macros. For
-# example, when we bind `__atuin_history` to \C-r, this step can be set up by
-# `bind '"\C-r": "IKEYSEQ1IKEYSEQ2"'`.
-#
-# 2. [IKEYSEQ1 -> WIDGET]---Then, IKEYSEQ1 is bound to the WIDGET, and the
-# binding of IKEYSEQ2 is dynamically determined by WIDGET. For example, when
-# we bind `__atuin_history` to \C-r, this step can be set up by `bind -x
-# '"IKEYSEQ1": WIDGET'`.
-#
-# 3. [IKEYSEQ2 -> accept-line] or [IKEYSEQ2 -> ""]---To request the execution
-# of `accept-line', WIDGET can change the binding of IKEYSEQ2 by running
-# `bind '"IKEYSEQ2": accept-line''. Otherwise, WIDGET can change the binding
-# of IKEYSEQ2 to no-op by running `bind '"IKEYSEQ2": ""'`.
-#
-# For the choice of the intermediate key sequences, we want to choose key
-# sequences that are unlikely to conflict with others. In addition, we want to
-# avoid a key sequence containing \e because keymap "vi-insert" stops
-# processing key sequences containing \e in older versions of Bash. We have
-# used \e[0;<m>A (a variant of the [up] key with modifier <m>) in Atuin 3.10.0
-# for intermediate key sequences, but this contains \e and caused a problem.
-# Instead, we use \C-x\C-_A<n>\a, which starts with \C-x\C-_ (an unlikely
-# two-byte combination) and A (represents the initial letter of Atuin),
-# followed by the payload <n> and the terminator \a (BEL, \C-g).
+ __atuin_widget=()
-__atuin_macro_chain='\C-x\C-_A0\a'
-for __atuin_keymap in emacs vi-insert vi-command; do
- bind -m "$__atuin_keymap" "\"$__atuin_macro_chain\": \"\""
-done
-unset -v __atuin_keymap
+ __atuin_widget_save() {
+ local data=$1
+ for REPLY in "${!__atuin_widget[@]}"; do
+ if [[ ${__atuin_widget[REPLY]} == "$data" ]]; then
+ return 0
+ fi
+ done
+ # shellcheck disable=SC2154
+ REPLY=${#__atuin_widget[*]}
+ __atuin_widget[REPLY]=$data
+ }
-if ((BASH_VERSINFO[0] >= 5 || BASH_VERSINFO[0] == 4 && BASH_VERSINFO[1] >= 3)); then
- # In Bash >= 4.3
+ __atuin_widget_run() {
+ local data=${__atuin_widget[$1]}
+ local keymap=${data%%:*} widget=${data#*:}
+ local __atuin_macro_chain_keymap=$keymap
+ bind -m "$keymap" '"'"$__atuin_macro_chain"'": ""'
+ builtin eval -- "$widget"
+ }
- __atuin_macro_accept_line=accept-line
+ # To realize the enter_accept feature in a robust way, we need to call the
+ # readline bindable function `accept-line'. However, there is no way to call
+ # `accept-line' from the shell script. To call the bindable function
+ # `accept-line', we may utilize string macros of readline. When we bind KEYSEQ
+ # to a WIDGET that wants to conditionally call `accept-line' at the end, we
+ # perform two-step dispatching:
+ #
+ # 1. [KEYSEQ -> IKEYSEQ1 IKEYSEQ2]---We first translate KEYSEQ to two
+ # intermediate key sequences IKEYSEQ1 and IKEYSEQ2 using string macros. For
+ # example, when we bind `__atuin_history` to \C-r, this step can be set up by
+ # `bind '"\C-r": "IKEYSEQ1IKEYSEQ2"'`.
+ #
+ # 2. [IKEYSEQ1 -> WIDGET]---Then, IKEYSEQ1 is bound to the WIDGET, and the
+ # binding of IKEYSEQ2 is dynamically determined by WIDGET. For example, when
+ # we bind `__atuin_history` to \C-r, this step can be set up by `bind -x
+ # '"IKEYSEQ1": WIDGET'`.
+ #
+ # 3. [IKEYSEQ2 -> accept-line] or [IKEYSEQ2 -> ""]---To request the execution
+ # of `accept-line', WIDGET can change the binding of IKEYSEQ2 by running
+ # `bind '"IKEYSEQ2": accept-line''. Otherwise, WIDGET can change the binding
+ # of IKEYSEQ2 to no-op by running `bind '"IKEYSEQ2": ""'`.
+ #
+ # For the choice of the intermediate key sequences, we want to choose key
+ # sequences that are unlikely to conflict with others. In addition, we want to
+ # avoid a key sequence containing \e because keymap "vi-insert" stops
+ # processing key sequences containing \e in older versions of Bash. We have
+ # used \e[0;<m>A (a variant of the [up] key with modifier <m>) in Atuin 3.10.0
+ # for intermediate key sequences, but this contains \e and caused a problem.
+ # Instead, we use \C-x\C-_A<n>\a, which starts with \C-x\C-_ (an unlikely
+ # two-byte combination) and A (represents the initial letter of Atuin),
+ # followed by the payload <n> and the terminator \a (BEL, \C-g).
- __atuin_bind_impl() {
- local keymap=$1 keyseq=$2 command=$3
+ __atuin_macro_chain='\C-x\C-_A0\a'
+ for __atuin_keymap in emacs vi-insert vi-command; do
+ bind -m "$__atuin_keymap" "\"$__atuin_macro_chain\": \"\""
+ done
+ unset -v __atuin_keymap
- # Note: In Bash <= 5.0, the table for `bind -x` from the keyseq to the
- # command is shared by all the keymaps (emacs, vi-insert, and
- # vi-command), so one cannot safely bind different command strings to
- # the same keyseq in different keymaps. Therefore, the command string
- # and the keyseq need to be globally in one-to-one correspondence in
- # all the keymaps.
- local REPLY
- __atuin_widget_save "$keymap:$command"
- local widget=$REPLY
- local ikeyseq1='\C-x\C-_A'$((1 + widget))'\a'
- local ikeyseq2=$__atuin_macro_chain
+ if ((BASH_VERSINFO[0] >= 5 || BASH_VERSINFO[0] == 4 && BASH_VERSINFO[1] >= 3)); then
+ # In Bash >= 4.3
- if ((BASH_VERSINFO[0] == 5 && BASH_VERSINFO[1] == 1)); then
- # Workaround for Bash 5.1: Bash 5.1 has a bug that overwriting an
- # existing "bind -x" keybinding breaks other existing "bind -x"
- # keybindings [1,2]. To work around the problem, we explicitly
- # unbind an existing keybinding before overwriting it.
- #
- # [1] https://lists.gnu.org/archive/html/bug-bash/2021-04/msg00135.html
- # [2] https://github.com/atuinsh/atuin/issues/962#issuecomment-3451132291
- bind -m "$keymap" -r "$keyseq"
- fi
+ __atuin_macro_accept_line=accept-line
- bind -m "$keymap" "\"$keyseq\": \"$ikeyseq1$ikeyseq2\""
- bind -m "$keymap" -x "\"$ikeyseq1\": __atuin_widget_run $widget"
- }
+ __atuin_bind_impl() {
+ local keymap=$1 keyseq=$2 command=$3
- __atuin_bind_blesh_onload() {
- # In ble.sh, we need to enable unrecognized CSI sequences like \e[0;0A,
- # which are discarded by ble.sh by default. Note: In Bash <= 4.2, we
- # do not need to unset "decode_error_cseq_discard" because \e[0;<m>A is
- # used only for the macro chaining (which is unused by ble.sh) in Bash
- # <= 4.2.
- bleopt decode_error_cseq_discard=
- }
- if [[ ${BLE_VERSION-} ]]; then
- __atuin_bind_blesh_onload
- fi
- BLE_ONLOAD+=(__atuin_bind_blesh_onload)
-else
- # In Bash <= 4.2, "bind -x" cannot bind a shell command to a keyseq having
- # more than two bytes, so we need to work with only two-byte sequences.
- #
- # However, the number of available combinations of two-byte sequences is
- # limited. To minimize the number of key sequences used by Atuin, instead
- # of specifying a widget by its own intermediate sequence, we specify a
- # widget by a fixed-length sequence of multiple two-byte sequences. More
- # specifically, instead of IKEYSEQ1, we use IKS1 IKS2 IKS3 [IKS4 IKS5]
- # IKSX, where IKS1..IKS5 just stores its information to a global variable,
- # and IKSX collects all the information and determine and call the actual
- # widget based on the stored information. Each of IKn (n=1..5) is one of
- # the two reserved sequences, $__atuin_bash42_code0 and
- # $__atuin_bash42_code1. IKSX is fixed to be $__atuin_bash42_code2.
- #
- # For the choices of the special key sequences, we consider \C-xQ, \C-xR,
- # and \C-xS. In the emacs editing mode of Bash, \C-x is used as a prefix
- # key, i.e., it is used for the beginning key of the keybindings with
- # multiple keys, so \C-x is unlikely to be used for a single-key binding by
- # the user. Also, \C-x is not used in the vi editing mode by default. The
- # combinations \C-xQ..\C-xS are also unlikely be used because we need to
- # switch the modifier keys from Control to Shift to input these sequences,
- # and these are not easy to input.
- __atuin_bash42_code0='\C-xQ'
- __atuin_bash42_code1='\C-xR'
- __atuin_bash42_code2='\C-xS'
+ # Note: In Bash <= 5.0, the table for `bind -x` from the keyseq to the
+ # command is shared by all the keymaps (emacs, vi-insert, and
+ # vi-command), so one cannot safely bind different command strings to
+ # the same keyseq in different keymaps. Therefore, the command string
+ # and the keyseq need to be globally in one-to-one correspondence in
+ # all the keymaps.
+ local REPLY
+ __atuin_widget_save "$keymap:$command"
+ local widget=$REPLY
+ local ikeyseq1='\C-x\C-_A'$((1 + widget))'\a'
+ local ikeyseq2=$__atuin_macro_chain
- __atuin_bash42_encode() {
- REPLY=
- local n=$1 min_width=${2-}
- while
- if ((n % 2 == 0)); then
- REPLY=$__atuin_bash42_code0$REPLY
- else
- REPLY=$__atuin_bash42_code1$REPLY
+ if ((BASH_VERSINFO[0] == 5 && BASH_VERSINFO[1] == 1)); then
+ # Workaround for Bash 5.1: Bash 5.1 has a bug that overwriting an
+ # existing "bind -x" keybinding breaks other existing "bind -x"
+ # keybindings [1,2]. To work around the problem, we explicitly
+ # unbind an existing keybinding before overwriting it.
+ #
+ # [1] https://lists.gnu.org/archive/html/bug-bash/2021-04/msg00135.html
+ # [2] https://github.com/atuinsh/atuin/issues/962#issuecomment-3451132291
+ bind -m "$keymap" -r "$keyseq"
fi
- (((n /= 2) || ${#REPLY} / ${#__atuin_bash42_code0} < min_width))
- do :; done
- }
- __atuin_bash42_bind() {
- local __atuin_keymap
- for __atuin_keymap in emacs vi-insert vi-command; do
- bind -m "$__atuin_keymap" -x '"'"$__atuin_bash42_code0"'": __atuin_bash42_dispatch_selector+=0'
- bind -m "$__atuin_keymap" -x '"'"$__atuin_bash42_code1"'": __atuin_bash42_dispatch_selector+=1'
- bind -m "$__atuin_keymap" -x '"'"$__atuin_bash42_code2"'": __atuin_bash42_dispatch'
- done
- }
- __atuin_bash42_bind
- # In Bash <= 4.2, there is no way to read users' "bind -x" settings, so we
- # need to explicitly perform "bind -x" when ble.sh is loaded.
- BLE_ONLOAD+=(__atuin_bash42_bind)
+ bind -m "$keymap" "\"$keyseq\": \"$ikeyseq1$ikeyseq2\""
+ bind -m "$keymap" -x "\"$ikeyseq1\": __atuin_widget_run $widget"
+ }
- if ((BASH_VERSINFO[0] >= 4)); then
- __atuin_macro_accept_line=accept-line
+ __atuin_bind_blesh_onload() {
+ # In ble.sh, we need to enable unrecognized CSI sequences like \e[0;0A,
+ # which are discarded by ble.sh by default. Note: In Bash <= 4.2, we
+ # do not need to unset "decode_error_cseq_discard" because \e[0;<m>A is
+ # used only for the macro chaining (which is unused by ble.sh) in Bash
+ # <= 4.2.
+ bleopt decode_error_cseq_discard=
+ }
+ if [[ ${BLE_VERSION-} ]]; then
+ __atuin_bind_blesh_onload
+ fi
+ BLE_ONLOAD+=(__atuin_bind_blesh_onload)
else
- # Note: We rewrite the command line and invoke `accept-line'. In
- # bash <= 3.2, there is no way to rewrite the command line from the
- # shell script, so we rewrite it using a macro and
- # `shell-expand-line'.
+ # In Bash <= 4.2, "bind -x" cannot bind a shell command to a keyseq having
+ # more than two bytes, so we need to work with only two-byte sequences.
#
- # Note: Concerning the key sequences to invoke bindable functions
- # such as "\C-x\C-_A1\a", another option is to use
- # "\exbegginning-of-line\r", etc. to make it consistent with bash
- # >= 5.3. However, an older Bash configuration can still conflict
- # on [M-x]. The conflict is more likely than \C-x\C-_A1\a.
- for __atuin_keymap in emacs vi-insert vi-command; do
- bind -m "$__atuin_keymap" '"\C-x\C-_A1\a": beginning-of-line'
- bind -m "$__atuin_keymap" '"\C-x\C-_A2\a": kill-line'
- # shellcheck disable=SC2016
- bind -m "$__atuin_keymap" '"\C-x\C-_A3\a": "$READLINE_LINE"'
- bind -m "$__atuin_keymap" '"\C-x\C-_A4\a": shell-expand-line'
- bind -m "$__atuin_keymap" '"\C-x\C-_A5\a": accept-line'
- bind -m "$__atuin_keymap" '"\C-x\C-_A6\a": end-of-line'
- done
- unset -v __atuin_keymap
+ # However, the number of available combinations of two-byte sequences is
+ # limited. To minimize the number of key sequences used by Atuin, instead
+ # of specifying a widget by its own intermediate sequence, we specify a
+ # widget by a fixed-length sequence of multiple two-byte sequences. More
+ # specifically, instead of IKEYSEQ1, we use IKS1 IKS2 IKS3 [IKS4 IKS5]
+ # IKSX, where IKS1..IKS5 just stores its information to a global variable,
+ # and IKSX collects all the information and determine and call the actual
+ # widget based on the stored information. Each of IKn (n=1..5) is one of
+ # the two reserved sequences, $__atuin_bash42_code0 and
+ # $__atuin_bash42_code1. IKSX is fixed to be $__atuin_bash42_code2.
+ #
+ # For the choices of the special key sequences, we consider \C-xQ, \C-xR,
+ # and \C-xS. In the emacs editing mode of Bash, \C-x is used as a prefix
+ # key, i.e., it is used for the beginning key of the keybindings with
+ # multiple keys, so \C-x is unlikely to be used for a single-key binding by
+ # the user. Also, \C-x is not used in the vi editing mode by default. The
+ # combinations \C-xQ..\C-xS are also unlikely be used because we need to
+ # switch the modifier keys from Control to Shift to input these sequences,
+ # and these are not easy to input.
+ __atuin_bash42_code0='\C-xQ'
+ __atuin_bash42_code1='\C-xR'
+ __atuin_bash42_code2='\C-xS'
- bind -m vi-command '"\C-x\C-_A7\a": vi-insertion-mode'
- bind -m vi-insert '"\C-x\C-_A7\a": vi-movement-mode'
+ __atuin_bash42_encode() {
+ REPLY=
+ local n=$1 min_width=${2-}
+ while
+ if ((n % 2 == 0)); then
+ REPLY=$__atuin_bash42_code0$REPLY
+ else
+ REPLY=$__atuin_bash42_code1$REPLY
+ fi
+ (((n /= 2) || ${#REPLY} / ${#__atuin_bash42_code0} < min_width))
+ do :; done
+ }
- # "\C-x\C-_A10\a": Replace the command line with READLINE_LINE. When we are
- # in the vi-command keymap, we go to vi-insert, input
- # "$READLINE_LINE", and come back to vi-command.
- bind -m emacs '"\C-x\C-_A10\a": "\C-x\C-_A1\a\C-x\C-_A2\a\C-x\C-_A3\a\C-x\C-_A4\a"'
- bind -m vi-insert '"\C-x\C-_A10\a": "\C-x\C-_A1\a\C-x\C-_A2\a\C-x\C-_A3\a\C-x\C-_A4\a"'
- bind -m vi-command '"\C-x\C-_A10\a": "\C-x\C-_A1\a\C-x\C-_A2\a\C-x\C-_A7\a\C-x\C-_A3\a\C-x\C-_A7\a\C-x\C-_A4\a"'
+ __atuin_bash42_bind() {
+ local __atuin_keymap
+ for __atuin_keymap in emacs vi-insert vi-command; do
+ bind -m "$__atuin_keymap" -x '"'"$__atuin_bash42_code0"'": __atuin_bash42_dispatch_selector+=0'
+ bind -m "$__atuin_keymap" -x '"'"$__atuin_bash42_code1"'": __atuin_bash42_dispatch_selector+=1'
+ bind -m "$__atuin_keymap" -x '"'"$__atuin_bash42_code2"'": __atuin_bash42_dispatch'
+ done
+ }
+ __atuin_bash42_bind
+ # In Bash <= 4.2, there is no way to read users' "bind -x" settings, so we
+ # need to explicitly perform "bind -x" when ble.sh is loaded.
+ BLE_ONLOAD+=(__atuin_bash42_bind)
- __atuin_macro_accept_line='"\C-x\C-_A10\a\C-x\C-_A5\a"'
- __atuin_macro_insert_line='"\C-x\C-_A10\a\C-x\C-_A6\a"'
- fi
+ if ((BASH_VERSINFO[0] >= 4)); then
+ __atuin_macro_accept_line=accept-line
+ else
+ # Note: We rewrite the command line and invoke `accept-line'. In
+ # bash <= 3.2, there is no way to rewrite the command line from the
+ # shell script, so we rewrite it using a macro and
+ # `shell-expand-line'.
+ #
+ # Note: Concerning the key sequences to invoke bindable functions
+ # such as "\C-x\C-_A1\a", another option is to use
+ # "\exbegginning-of-line\r", etc. to make it consistent with bash
+ # >= 5.3. However, an older Bash configuration can still conflict
+ # on [M-x]. The conflict is more likely than \C-x\C-_A1\a.
+ for __atuin_keymap in emacs vi-insert vi-command; do
+ bind -m "$__atuin_keymap" '"\C-x\C-_A1\a": beginning-of-line'
+ bind -m "$__atuin_keymap" '"\C-x\C-_A2\a": kill-line'
+ # shellcheck disable=SC2016
+ bind -m "$__atuin_keymap" '"\C-x\C-_A3\a": "$READLINE_LINE"'
+ bind -m "$__atuin_keymap" '"\C-x\C-_A4\a": shell-expand-line'
+ bind -m "$__atuin_keymap" '"\C-x\C-_A5\a": accept-line'
+ bind -m "$__atuin_keymap" '"\C-x\C-_A6\a": end-of-line'
+ done
+ unset -v __atuin_keymap
- __atuin_bash42_dispatch_selector=
+ bind -m vi-command '"\C-x\C-_A7\a": vi-insertion-mode'
+ bind -m vi-insert '"\C-x\C-_A7\a": vi-movement-mode'
+
+ # "\C-x\C-_A10\a": Replace the command line with READLINE_LINE. When we are
+ # in the vi-command keymap, we go to vi-insert, input
+ # "$READLINE_LINE", and come back to vi-command.
+ bind -m emacs '"\C-x\C-_A10\a": "\C-x\C-_A1\a\C-x\C-_A2\a\C-x\C-_A3\a\C-x\C-_A4\a"'
+ bind -m vi-insert '"\C-x\C-_A10\a": "\C-x\C-_A1\a\C-x\C-_A2\a\C-x\C-_A3\a\C-x\C-_A4\a"'
+ bind -m vi-command '"\C-x\C-_A10\a": "\C-x\C-_A1\a\C-x\C-_A2\a\C-x\C-_A7\a\C-x\C-_A3\a\C-x\C-_A7\a\C-x\C-_A4\a"'
+
+ __atuin_macro_accept_line='"\C-x\C-_A10\a\C-x\C-_A5\a"'
+ __atuin_macro_insert_line='"\C-x\C-_A10\a\C-x\C-_A6\a"'
+ fi
- __atuin_bash42_dispatch() {
- local s=$__atuin_bash42_dispatch_selector
__atuin_bash42_dispatch_selector=
- __atuin_widget_run "$((2#0$s))"
- }
- __atuin_bind_impl() {
- local keymap=$1 keyseq=$2 command=$3
+ __atuin_bash42_dispatch() {
+ local s=$__atuin_bash42_dispatch_selector
+ __atuin_bash42_dispatch_selector=
+ __atuin_widget_run "$((2#0$s))"
+ }
- __atuin_widget_save "$keymap:$command"
- __atuin_bash42_encode "$REPLY"
- local macro=$REPLY$__atuin_bash42_code2$__atuin_macro_chain
+ __atuin_bind_impl() {
+ local keymap=$1 keyseq=$2 command=$3
- bind -m "$keymap" "\"$keyseq\": \"$macro\""
- }
-fi
+ __atuin_widget_save "$keymap:$command"
+ __atuin_bash42_encode "$REPLY"
+ local macro=$REPLY$__atuin_bash42_code2$__atuin_macro_chain
+
+ bind -m "$keymap" "\"$keyseq\": \"$macro\""
+ }
+ fi
-atuin-bind() {
- local keymap=
- local OPTIND=1 OPTARG="" OPTERR=0 flag
- while getopts ':m:' flag "$@"; do
- case $flag in
+ atuin-bind() {
+ local keymap=
+ local OPTIND=1 OPTARG="" OPTERR=0 flag
+ while getopts ':m:' flag "$@"; do
+ case $flag in
m) keymap=$OPTARG ;;
*)
printf '%s\n' "atuin-bind: unrecognized option '-$flag'" >&2
return 2
;;
- esac
- done
- shift "$((OPTIND - 1))"
+ esac
+ done
+ shift "$((OPTIND - 1))"
- if (($# != 2)); then
- printf '%s\n' 'usage: atuin-bind [-m keymap] keyseq widget' >&2
- return 2
- fi
+ if (($# != 2)); then
+ printf '%s\n' 'usage: atuin-bind [-m keymap] keyseq widget' >&2
+ return 2
+ fi
- local keyseq=$1
- [[ $keymap ]] || keymap=$(bind -v | awk '$2 == "keymap" { print $3 }')
- case $keymap in
+ local keyseq=$1
+ [[ $keymap ]] || keymap=$(bind -v | awk '$2 == "keymap" { print $3 }')
+ case $keymap in
emacs-meta) keymap=emacs keyseq='\e'$keyseq ;;
emacs-ctlx) keymap=emacs keyseq='\C-x'$keyseq ;;
- emacs*) keymap=emacs ;;
- vi-insert) ;;
- vi*) keymap=vi-command ;;
+ emacs*) keymap=emacs ;;
+ vi-insert) ;;
+ vi*) keymap=vi-command ;;
*)
printf '%s\n' "atuin-bind: unknown keymap '$keymap'" >&2
- return 2 ;;
- esac
+ return 2
+ ;;
+ esac
- local command=$2 widget=${2%%[[:blank:]]*}
- case $widget in
- atuin-search) command=${2/#"$widget"/__atuin_history} ;;
- atuin-search-emacs) command=${2/#"$widget"/__atuin_history --keymap-mode=emacs} ;;
- atuin-search-viins) command=${2/#"$widget"/__atuin_history --keymap-mode=vim-insert} ;;
- atuin-search-vicmd) command=${2/#"$widget"/__atuin_history --keymap-mode=vim-normal} ;;
- atuin-up-search) command=${2/#"$widget"/__atuin_history --shell-up-key-binding} ;;
+ local command=$2 widget=${2%%[[:blank:]]*}
+ case $widget in
+ atuin-search) command=${2/#"$widget"/__atuin_history} ;;
+ atuin-search-emacs) command=${2/#"$widget"/__atuin_history --keymap-mode=emacs} ;;
+ atuin-search-viins) command=${2/#"$widget"/__atuin_history --keymap-mode=vim-insert} ;;
+ atuin-search-vicmd) command=${2/#"$widget"/__atuin_history --keymap-mode=vim-normal} ;;
+ atuin-up-search) command=${2/#"$widget"/__atuin_history --shell-up-key-binding} ;;
atuin-up-search-emacs) command=${2/#"$widget"/__atuin_history --shell-up-key-binding --keymap-mode=emacs} ;;
atuin-up-search-viins) command=${2/#"$widget"/__atuin_history --shell-up-key-binding --keymap-mode=vim-insert} ;;
atuin-up-search-vicmd) command=${2/#"$widget"/__atuin_history --shell-up-key-binding --keymap-mode=vim-normal} ;;
- esac
+ esac
- __atuin_bind_impl "$keymap" "$keyseq" "$command"
-}
+ __atuin_bind_impl "$keymap" "$keyseq" "$command"
+ }
-#------------------------------------------------------------------------------
+ #------------------------------------------------------------------------------
-# shellcheck disable=SC2154
-if [[ $__atuin_bind_ctrl_r == true ]]; then
- # Note: We do not overwrite [C-r] in the vi-command keymap because we do
- # not want to overwrite "redo", which is already bound to [C-r] in the
- # vi_nmap keymap in ble.sh.
- atuin-bind -m emacs '\C-r' atuin-search-emacs
- atuin-bind -m vi-insert '\C-r' atuin-search-viins
- atuin-bind -m vi-command '/' atuin-search-emacs
-fi
+ # shellcheck disable=SC2154
+ if [[ $__atuin_bind_ctrl_r == true ]]; then
+ # Note: We do not overwrite [C-r] in the vi-command keymap because we do
+ # not want to overwrite "redo", which is already bound to [C-r] in the
+ # vi_nmap keymap in ble.sh.
+ atuin-bind -m emacs '\C-r' atuin-search-emacs
+ atuin-bind -m vi-insert '\C-r' atuin-search-viins
+ atuin-bind -m vi-command '/' atuin-search-emacs
+ fi
-# shellcheck disable=SC2154
-if [[ $__atuin_bind_up_arrow == true ]]; then
- atuin-bind -m emacs '\e[A' atuin-up-search-emacs
- atuin-bind -m emacs '\eOA' atuin-up-search-emacs
- atuin-bind -m vi-insert '\e[A' atuin-up-search-viins
- atuin-bind -m vi-insert '\eOA' atuin-up-search-viins
- atuin-bind -m vi-command '\e[A' atuin-up-search-vicmd
- atuin-bind -m vi-command '\eOA' atuin-up-search-vicmd
- atuin-bind -m vi-command 'k' atuin-up-search-vicmd
-fi
+ # shellcheck disable=SC2154
+ if [[ $__atuin_bind_up_arrow == true ]]; then
+ atuin-bind -m emacs '\e[A' atuin-up-search-emacs
+ atuin-bind -m emacs '\eOA' atuin-up-search-emacs
+ atuin-bind -m vi-insert '\e[A' atuin-up-search-viins
+ atuin-bind -m vi-insert '\eOA' atuin-up-search-viins
+ atuin-bind -m vi-command '\e[A' atuin-up-search-vicmd
+ atuin-bind -m vi-command '\eOA' atuin-up-search-vicmd
+ atuin-bind -m vi-command 'k' atuin-up-search-vicmd
+ fi
#------------------------------------------------------------------------------
fi # (include guard) end of main content
diff --git a/crates/turtle/src/shell/atuin.fish b/crates/turtle/src/shell/atuin.fish
index 15b33451..2b469383 100644
--- a/crates/turtle/src/shell/atuin.fish
+++ b/crates/turtle/src/shell/atuin.fish
@@ -37,49 +37,6 @@ function _atuin_postexec --on-event fish_postexec
set --erase ATUIN_HISTORY_ID
end
-# Check if tmux popup is available (tmux >= 3.2)
-function _atuin_tmux_popup_check
- if not test -n "$TMUX"
- echo 0
- return
- end
-
- if test "$ATUIN_TMUX_POPUP" = false
- echo 0
- return
- end
-
- set -l tmux_version (tmux -V 2>/dev/null | string match -r '\d+\.\d+')
- if not test -n "$tmux_version"
- echo 0
- return
- end
-
- set -l parts (string split '.' $tmux_version)
- set -l m1 $parts[1]
- set -l m2 0
- if test (count $parts) -ge 2
- set m2 $parts[2]
- end
-
- if not string match -rq '^[0-9]+$' -- "$m1"
- echo 0
- return
- end
-
- if not string match -rq '^[0-9]+$' -- "$m2"
- set m2 0
- end
-
- if test "$m1" -gt 3 2>/dev/null; or begin
- test "$m1" -eq 3 2>/dev/null; and test "$m2" -ge 2 2>/dev/null
- end
- echo 1
- else
- echo 0
- end
-end
-
function _atuin_search
set -l keymap_mode
switch $fish_key_bindings
@@ -94,47 +51,14 @@ function _atuin_search
set keymap_mode emacs
end
- set -l use_tmux_popup (_atuin_tmux_popup_check)
-
set -l ATUIN_H
set -l ATUIN_STATUS 0
- if test "$use_tmux_popup" -eq 1
- set -l tmpdir (mktemp -d)
- if not test -d "$tmpdir"
- # if mktemp got errors
- set ATUIN_H (ATUIN_SHELL=fish ATUIN_LOG=error ATUIN_QUERY=(commandline -b) atuin search --keymap-mode=$keymap_mode $argv -i 3>&1 1>&2 2>&3 3>&- | string collect)
- set ATUIN_STATUS $pipestatus[1]
- else
- set -l result_file "$tmpdir/result"
- set -l query (commandline -b | string replace -a "'" "'\\''")
- set -l escaped_args ""
- for arg in $argv
- set escaped_args "$escaped_args '"(string replace -a "'" "'\\''" -- $arg)"'"
- end
-
- # In the popup, atuin goes to terminal, stderr goes to file
- set -l cdir (pwd)
- # Keep default value anyways
- set -l popup_width (test -n "$ATUIN_TMUX_POPUP_WIDTH" && echo "$ATUIN_TMUX_POPUP_WIDTH" || echo "80%")
- set -l popup_height (test -n "$ATUIN_TMUX_POPUP_HEIGHT" && echo "$ATUIN_TMUX_POPUP_HEIGHT" || echo "60%")
- tmux display-popup -d "$cdir" -w "$popup_width" -h "$popup_height" -E -E -- \
- sh -c "PATH='$PATH' ATUIN_SESSION='$ATUIN_SESSION' ATUIN_SHELL=fish ATUIN_LOG=error ATUIN_QUERY='$query' atuin search --keymap-mode=$keymap_mode$escaped_args -i 2>'$result_file'"
- set ATUIN_STATUS $status
-
- if test -f "$result_file"
- set ATUIN_H (cat "$result_file" | string collect)
- end
-
- command rm -rf "$tmpdir"
- end
- else
- # In fish 3.4 and above we can use `"$(some command)"` to keep multiple lines separate;
- # but to support fish 3.3 we need to use `(some command | string collect)`.
- # https://fishshell.com/docs/current/relnotes.html#id24 (fish 3.4 "Notable improvements and fixes")
- set ATUIN_H (ATUIN_SHELL=fish ATUIN_LOG=error ATUIN_QUERY=(commandline -b) atuin search --keymap-mode=$keymap_mode $argv -i 3>&1 1>&2 2>&3 3>&- | string collect)
- set ATUIN_STATUS $pipestatus[1]
- end
+ # In fish 3.4 and above we can use `"$(some command)"` to keep multiple lines separate;
+ # but to support fish 3.3 we need to use `(some command | string collect)`.
+ # https://fishshell.com/docs/current/relnotes.html#id24 (fish 3.4 "Notable improvements and fixes")
+ set ATUIN_H (ATUIN_SHELL=fish ATUIN_LOG=error ATUIN_QUERY=(commandline -b) atuin search --keymap-mode=$keymap_mode $argv -i 3>&1 1>&2 2>&3 3>&- | string collect)
+ set ATUIN_STATUS $pipestatus[1]
if test "$ATUIN_STATUS" -ne 0
test -n "$ATUIN_H"; and printf '%s\n' "$ATUIN_H" >&2
diff --git a/crates/turtle/src/shell/atuin.zsh b/crates/turtle/src/shell/atuin.zsh
index 7a7375aa..7e7fef27 100644
--- a/crates/turtle/src/shell/atuin.zsh
+++ b/crates/turtle/src/shell/atuin.zsh
@@ -91,65 +91,11 @@ _atuin_precmd() {
export ATUIN_HISTORY_ID=""
}
-# Check if tmux popup is available (tmux >= 3.2)
-__atuin_tmux_popup_check() {
- [[ -n "${TMUX-}" ]] || return 1
- [[ "${ATUIN_TMUX_POPUP:-true}" != "false" ]] || return 1
-
- # https://github.com/tmux/tmux/wiki/FAQ#how-often-is-tmux-released-what-is-the-version-number-scheme
- local tmux_version
- tmux_version=$(tmux -V 2>/dev/null | sed -n 's/^[^0-9]*\([0-9][0-9]*\.[0-9][0-9]*\).*/\1/p') # Could have used grep...
- [[ -z "$tmux_version" ]] && return 1
-
- local m1 m2
- m1=${tmux_version%%.*}
- m2=${tmux_version#*.}
- m2=${m2%%.*}
- [[ "$m1" =~ ^[0-9]+$ ]] || return 1
- [[ "$m2" =~ ^[0-9]+$ ]] || m2=0
- (( m1 > 3 || (m1 == 3 && m2 >= 2) ))
-}
-
-# Use global variable to fix scope issues with traps
-__atuin_popup_tmpdir=""
-__atuin_tmux_popup_cleanup() {
- [[ -n "$__atuin_popup_tmpdir" && -d "$__atuin_popup_tmpdir" ]] && command rm -rf "$__atuin_popup_tmpdir"
- __atuin_popup_tmpdir=""
-}
-
__atuin_search_cmd() {
local -a search_args=("$@")
- if __atuin_tmux_popup_check; then
- __atuin_popup_tmpdir=$(mktemp -d) || return 1
- local result_file="$__atuin_popup_tmpdir/result"
-
- trap '__atuin_tmux_popup_cleanup' EXIT HUP INT TERM
- local escaped_query escaped_args
- escaped_query=$(printf '%s' "$BUFFER" | sed "s/'/'\\\\''/g")
- escaped_args=""
- for arg in "${search_args[@]}"; do
- escaped_args+=" '$(printf '%s' "$arg" | sed "s/'/'\\\\''/g")'"
- done
-
- # In the popup, atuin goes to terminal, stderr goes to file
- local cdir popup_width popup_height
- cdir=$(pwd)
- popup_width="${ATUIN_TMUX_POPUP_WIDTH:-80%}" # Keep default value anyways
- popup_height="${ATUIN_TMUX_POPUP_HEIGHT:-60%}"
- tmux display-popup -d "$cdir" -w "$popup_width" -h "$popup_height" -E -E -- \
- sh -c "PATH='$PATH' ATUIN_SESSION='$ATUIN_SESSION' ATUIN_SHELL=zsh ATUIN_LOG=error ATUIN_QUERY='$escaped_query' atuin search $escaped_args -i 2>'$result_file'"
-
- if [[ -f "$result_file" ]]; then
- cat "$result_file"
- fi
-
- __atuin_tmux_popup_cleanup
- trap - EXIT HUP INT TERM
- else
- ATUIN_SHELL=zsh ATUIN_LOG=error ATUIN_QUERY=$BUFFER atuin search "${search_args[@]}" -i 3>&1 1>&2 2>&3 3>&-
- fi
+ ATUIN_SHELL=zsh ATUIN_LOG=error ATUIN_QUERY=$BUFFER atuin search "${search_args[@]}" -i 3>&1 1>&2 2>&3 3>&-
}
_atuin_search() {