diff options
Diffstat (limited to 'crates/client/src/shell')
| -rw-r--r-- | crates/client/src/shell/.gitattributes | 1 | ||||
| -rw-r--r-- | crates/client/src/shell/atuin.bash | 672 | ||||
| -rw-r--r-- | crates/client/src/shell/atuin.fish | 102 | ||||
| -rw-r--r-- | crates/client/src/shell/atuin.nu | 121 | ||||
| -rw-r--r-- | crates/client/src/shell/atuin.ps1 | 240 | ||||
| -rw-r--r-- | crates/client/src/shell/atuin.xsh | 86 | ||||
| -rw-r--r-- | crates/client/src/shell/atuin.zsh | 167 |
7 files changed, 0 insertions, 1389 deletions
diff --git a/crates/client/src/shell/.gitattributes b/crates/client/src/shell/.gitattributes deleted file mode 100644 index fae8897c..00000000 --- a/crates/client/src/shell/.gitattributes +++ /dev/null @@ -1 +0,0 @@ -* eol=lf diff --git a/crates/client/src/shell/atuin.bash b/crates/client/src/shell/atuin.bash deleted file mode 100644 index 703e8fe2..00000000 --- a/crates/client/src/shell/atuin.bash +++ /dev/null @@ -1,672 +0,0 @@ -# Include guard -if [[ ${__atuin_initialized-} == true ]]; then - false -elif [[ $- != *i* ]]; then - # Enable only in interactive shells - false -elif ((BASH_VERSINFO[0] < 3 || BASH_VERSINFO[0] == 3 && BASH_VERSINFO[1] < 1)); then - # Require bash >= 3.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 - - 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 - - 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 - - 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_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 - } - - 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_history'* | '__atuin_widget_run'* | '__atuin_bash42_dispatch'*) - ATUIN_HISTORY_ID=__bash_preexec_failure__ - return 0 - ;; - esac - fi - fi - - # 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-} - - __atuin_osc133_wrap_prompt - - [[ ! $ATUIN_HISTORY_ID ]] && return - - # 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 - - 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 - - [[ -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']/} - - # 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 - - # 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]}" - } - - __atuin_accept_line() { - local __atuin_command=$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" - - # Add it to the bash history - history -s "$__atuin_command" - - # 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 - - # 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 - } - - #------------------------------------------------------------------------------ - - __atuin_search_cmd() { - local -a search_args=("$@") - - ATUIN_SHELL=bash ATUIN_LOG=error ATUIN_QUERY=$READLINE_LINE atuin search "${search_args[@]}" -i 3>&1 1>&2 2>&3 3>&- - } - - __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 - - # 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="" - 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 - } - - __atuin_initialize_blesh() { - # shellcheck disable=SC2154 - [[ ${BLE_VERSION-} ]] && ((_ble_version >= 400)) || return 0 - - ble-import contrib/integration/bash-preexec - - # 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' - - # @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) - - #------------------------------------------------------------------------------ - # section: atuin-bind - - __atuin_widget=() - - __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 - } - - __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" - } - - # 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_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 - - if ((BASH_VERSINFO[0] >= 5 || BASH_VERSINFO[0] == 4 && BASH_VERSINFO[1] >= 3)); then - # In Bash >= 4.3 - - __atuin_macro_accept_line=accept-line - - __atuin_bind_impl() { - local keymap=$1 keyseq=$2 command=$3 - - # 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[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 - - bind -m "$keymap" "\"$keyseq\": \"$ikeyseq1$ikeyseq2\"" - bind -m "$keymap" -x "\"$ikeyseq1\": __atuin_widget_run $widget" - } - - __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' - - __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 - } - - __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) - - 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 - - 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_selector= - - __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_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 - m) keymap=$OPTARG ;; - *) - printf '%s\n' "atuin-bind: unrecognized option '-$flag'" >&2 - return 2 - ;; - esac - done - shift "$((OPTIND - 1))" - - 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 - emacs-meta) keymap=emacs keyseq='\e'$keyseq ;; - emacs-ctlx) keymap=emacs keyseq='\C-x'$keyseq ;; - emacs*) keymap=emacs ;; - vi-insert) ;; - vi*) keymap=vi-command ;; - *) - printf '%s\n' "atuin-bind: unknown keymap '$keymap'" >&2 - 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} ;; - 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 - - __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_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/client/src/shell/atuin.fish b/crates/client/src/shell/atuin.fish deleted file mode 100644 index 2b469383..00000000 --- a/crates/client/src/shell/atuin.fish +++ /dev/null @@ -1,102 +0,0 @@ -if not set -q ATUIN_SESSION; or test "$ATUIN_SHLVL" != "$SHLVL" - set -gx ATUIN_SESSION (atuin uuid) - set -gx ATUIN_SHLVL $SHLVL -end -set --erase ATUIN_HISTORY_ID - -function _atuin_osc133_command_executed - set -q ATUIN_PTY_PROXY_ACTIVE; or return - test -n "$ATUIN_HISTORY_ID"; or return - - printf '\033]133;C\a' -end - -function _atuin_osc133_command_finished --argument-names exit_code - set -q ATUIN_PTY_PROXY_ACTIVE; or return - test -n "$ATUIN_HISTORY_ID"; or return - - printf '\033]133;D;%s;history_id=%s;session_id=%s\a' "$exit_code" "$ATUIN_HISTORY_ID" "$ATUIN_SESSION" -end - -function _atuin_preexec --on-event fish_preexec - if not test -n "$fish_private_mode" - set -g ATUIN_HISTORY_ID (atuin history start -- "$argv[1]" 2>/dev/null) - _atuin_osc133_command_executed - end -end - -function _atuin_postexec --on-event fish_postexec - set -l s $status - - if test -n "$ATUIN_HISTORY_ID" - _atuin_osc133_command_finished $s - ATUIN_LOG=error atuin history end --exit $s -- $ATUIN_HISTORY_ID &>/dev/null & - disown - end - - set --erase ATUIN_HISTORY_ID -end - -function _atuin_search - set -l keymap_mode - switch $fish_key_bindings - case fish_vi_key_bindings fish_hybrid_key_bindings - switch $fish_bind_mode - case default - set keymap_mode vim-normal - case insert - set keymap_mode vim-insert - end - case '*' - set keymap_mode emacs - end - - set -l ATUIN_H - set -l ATUIN_STATUS 0 - - # 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 - commandline -f repaint - return "$ATUIN_STATUS" - end - - set ATUIN_H (string trim -- $ATUIN_H | string collect) # trim whitespace - - if test -n "$ATUIN_H" - if string match --quiet '__atuin_accept__:*' "$ATUIN_H" - set -l ATUIN_HIST (string replace "__atuin_accept__:" "" -- "$ATUIN_H" | string collect) - commandline -r "$ATUIN_HIST" - commandline -f repaint - commandline -f execute - return - else - commandline -r "$ATUIN_H" - end - end - - commandline -f repaint -end - -function _atuin_bind_up - # Fallback to fish's builtin up-or-search if we're in search or paging mode - if commandline --search-mode; or commandline --paging-mode - up-or-search - return - end - - # Only invoke atuin if we're on the top line of the command - set -l lineno (commandline --line) - - switch $lineno - case 1 - _atuin_search --shell-up-key-binding - case '*' - up-or-search - end -end diff --git a/crates/client/src/shell/atuin.nu b/crates/client/src/shell/atuin.nu deleted file mode 100644 index d37457e4..00000000 --- a/crates/client/src/shell/atuin.nu +++ /dev/null @@ -1,121 +0,0 @@ -# Source this in your ~/.config/nushell/config.nu -# minimum supported version = 0.93.0 -module compat { - export def --wrapped "random uuid -v 7" [...rest] { atuin uuid } -} -use (if not ( - (version).major > 0 or - (version).minor >= 103 -) { "compat" }) * - -if 'ATUIN_SESSION' not-in $env or ('ATUIN_SHLVL' not-in $env) or ($env.ATUIN_SHLVL != ($env.SHLVL? | default "")) { - $env.ATUIN_SESSION = (random uuid -v 7 | str replace -a "-" "") - $env.ATUIN_SHLVL = ($env.SHLVL? | default "") -} -hide-env -i ATUIN_HISTORY_ID - -def _atuin_osc133_command_executed [] { - if 'ATUIN_PTY_PROXY_ACTIVE' not-in $env { - return - } - if 'ATUIN_HISTORY_ID' not-in $env or ($env.ATUIN_HISTORY_ID | is-empty) { - return - } - - print -n $"(char esc)]133;C(char bel)" -} - -def _atuin_osc133_command_finished [exit_code: int] { - if 'ATUIN_PTY_PROXY_ACTIVE' not-in $env { - return - } - if 'ATUIN_HISTORY_ID' not-in $env or ($env.ATUIN_HISTORY_ID | is-empty) { - return - } - - print -n $"(char esc)]133;D;($exit_code);history_id=($env.ATUIN_HISTORY_ID);session_id=($env.ATUIN_SESSION)(char bel)" -} - -# Magic token to make sure we don't record commands run by keybindings -let ATUIN_KEYBINDING_TOKEN = $"# (random uuid)" - -let _atuin_pre_execution = {|| - if ($nu | get history-enabled?) == false { - return - } - let cmd = (commandline) - if ($cmd | is-empty) { - return - } - if not ($cmd | str starts-with $ATUIN_KEYBINDING_TOKEN) { - $env.ATUIN_HISTORY_ID = (atuin history start -- $cmd | complete | get stdout | str trim) - _atuin_osc133_command_executed - } -} - -let _atuin_pre_prompt = {|| - let last_exit = $env.LAST_EXIT_CODE - if 'ATUIN_HISTORY_ID' not-in $env { - return - } - _atuin_osc133_command_finished $last_exit - with-env { ATUIN_LOG: error } { - if (version).minor >= 104 or (version).major > 0 { - job spawn { - ^atuin history end $'--exit=($env.LAST_EXIT_CODE)' -- $env.ATUIN_HISTORY_ID | complete - } | ignore - } else { - do { atuin history end $'--exit=($last_exit)' -- $env.ATUIN_HISTORY_ID } | complete - } - - } - hide-env ATUIN_HISTORY_ID -} - -def _atuin_search_cmd [...flags: string] { - if (version).minor >= 106 or (version).major > 0 { - [ - $ATUIN_KEYBINDING_TOKEN, - ([ - `with-env { ATUIN_LOG: error, ATUIN_QUERY: (commandline), ATUIN_SHELL: nu } {`, - ([ - 'let output = (run-external atuin search', - ($flags | append [--interactive] | each {|e| $'"($e)"'}), - 'e>| str trim)', - ] | flatten | str join ' '), - 'if ($output | str starts-with "__atuin_accept__:") {', - 'commandline edit --accept ($output | str replace "__atuin_accept__:" "")', - '} else {', - 'commandline edit $output', - '}', - `}`, - ] | flatten | str join "\n"), - ] - } else { - [ - $ATUIN_KEYBINDING_TOKEN, - ([ - `with-env { ATUIN_LOG: error, ATUIN_QUERY: (commandline) } {`, - 'commandline edit', - '(run-external atuin search', - ($flags | append [--interactive] | each {|e| $'"($e)"'}), - ' e>| str trim)', - `}`, - ] | flatten | str join ' '), - ] - } | str join "\n" -} - -$env.config = ($env | default {} config).config -$env.config = ($env.config | default {} hooks) -$env.config = ( - $env.config | upsert hooks ( - $env.config.hooks - | upsert pre_execution ( - $env.config.hooks | get pre_execution? | default [] | append $_atuin_pre_execution) - | upsert pre_prompt ( - $env.config.hooks | get pre_prompt? | default [] | append $_atuin_pre_prompt) - ) -) - -$env.config = ($env.config | default [] keybindings) diff --git a/crates/client/src/shell/atuin.ps1 b/crates/client/src/shell/atuin.ps1 deleted file mode 100644 index 431ee2c3..00000000 --- a/crates/client/src/shell/atuin.ps1 +++ /dev/null @@ -1,240 +0,0 @@ -# Atuin PowerShell module -# -# This should support PowerShell 5.1 (which is shipped with Windows) and later versions, on Windows and Linux. -# -# Usage: atuin init powershell | Out-String | Invoke-Expression -# -# Settings: -# - $env:ATUIN_POWERSHELL_PROMPT_OFFSET - Number of lines to offset the prompt position after exiting search. -# This is useful when using a multi-line prompt: e.g. set this to -1 when using a 2-line prompt. -# It is initialized from the current prompt line count if not set when the first Atuin search is performed. - -if (Get-Module Atuin -ErrorAction Ignore) { - if ($PSVersionTable.PSVersion.Major -ge 7) { - Write-Warning "The Atuin module is already loaded, replacing it." - Remove-Module Atuin - } else { - Write-Warning "The Atuin module is already loaded, skipping." - return - } -} - -if (!(Get-Command atuin -ErrorAction Ignore)) { - Write-Error "The 'atuin' executable needs to be available in the PATH." - return -} - -if (!(Get-Module PSReadLine -ErrorAction Ignore)) { - Write-Error "Atuin requires the PSReadLine module to be installed." - return -} - -New-Module -Name Atuin -ScriptBlock { - if (-not $env:ATUIN_SESSION -or $env:ATUIN_PID -ne $PID) { - $env:ATUIN_SESSION = atuin uuid - $env:ATUIN_PID = $PID - } - - $script:atuinHistoryId = $null - $script:previousPSConsoleHostReadLine = $Function:PSConsoleHostReadLine - - # The ReadLine overloads changed with breaking changes over time, make sure the one we expect is available. - $script:hasExpectedReadLineOverload = ([Microsoft.PowerShell.PSConsoleReadLine]::ReadLine).OverloadDefinitions.Contains("static string ReadLine(runspace runspace, System.Management.Automation.EngineIntrinsics engineIntrinsics, System.Threading.CancellationToken cancellationToken, System.Nullable[bool] lastRunStatus)") - - function Get-CommandLine { - $commandLine = "" - [Microsoft.PowerShell.PSConsoleReadLine]::GetBufferState([ref]$commandLine, [ref]$null) - return $commandLine - } - - function Set-CommandLine { - param([string]$Text) - - $commandLine = Get-CommandLine - [Microsoft.PowerShell.PSConsoleReadLine]::Replace(0, $commandLine.Length, $Text) - } - - # This function name is called by PSReadLine to read the next command line to execute. - # We replace it with a custom implementation which adds Atuin support. - function PSConsoleHostReadLine { - ## 1. Collect the exit code of the previous command. - - # This needs to be done as the first thing because any script run will flush $?. - $lastRunStatus = $? - - # Exit statuses are maintained separately for native and PowerShell commands, this needs to be taken into account. - $lastNativeExitCode = $global:LASTEXITCODE - $exitCode = if ($lastRunStatus) { 0 } elseif ($lastNativeExitCode) { $lastNativeExitCode } else { 1 } - - ## 2. Report the status of the previous command to Atuin (atuin history end). - - if ($script:atuinHistoryId) { - try { - # The duration is not recorded in old PowerShell versions, let Atuin handle it. $null arguments are ignored. - $duration = (Get-History -Count 1).Duration.Ticks * 100 - $durationArg = if ($duration) { "--duration=$duration" } else { $null } - - # Fire and forget the atuin history end command to avoid blocking the shell during a potential sync. - $process = New-Object System.Diagnostics.Process - $process.StartInfo.FileName = "atuin" - $process.StartInfo.Arguments = "history end --exit=$exitCode $durationArg -- $script:atuinHistoryId" - $process.StartInfo.UseShellExecute = $false - $process.StartInfo.CreateNoWindow = $true - $process.StartInfo.RedirectStandardInput = $true - $process.StartInfo.RedirectStandardOutput = $true - $process.StartInfo.RedirectStandardError = $true - $process.Start() | Out-Null - $process.StandardInput.Close() - $process.BeginOutputReadLine() - $process.BeginErrorReadLine() - } - catch { - # Ignore errors to avoid breaking the shell. - # An error would occur if the user removes atuin from the PATH, for instance. - } - finally { - $script:atuinHistoryId = $null - } - } - - ## 3. Read the next command line to execute. - - # PSConsoleHostReadLine implementation from PSReadLine, adjusted to support old versions. - Microsoft.PowerShell.Core\Set-StrictMode -Off - - $line = if ($script:hasExpectedReadLineOverload) { - # When the overload we expect is available, we can pass $lastRunStatus to it. - [Microsoft.PowerShell.PSConsoleReadLine]::ReadLine($Host.Runspace, $ExecutionContext, [System.Threading.CancellationToken]::None, $lastRunStatus) - } else { - # Either PSReadLine is older than v2.2.0-beta3, or maybe newer than we expect, so use the function from PSReadLine as-is. - & $script:previousPSConsoleHostReadLine - } - - ## 4. Report the next command line to Atuin (atuin history start). - - # PowerShell doesn't handle double quotes in native command line arguments the same way depending on its version, - # and the value of $PSNativeCommandArgumentPassing - see the about_Parsing help page which explains the breaking changes. - # This makes it unreliable, so we go through an environment variable, which should always be consistent across versions. - try { - $env:ATUIN_COMMAND_LINE = $line - $script:atuinHistoryId = atuin history start --command-from-env - } - catch { - # Ignore errors to avoid breaking the shell, see above. - } - finally { - $env:ATUIN_COMMAND_LINE = $null - } - - $global:LASTEXITCODE = $lastNativeExitCode - return $line - } - - function Invoke-AtuinSearch { - param([string]$ExtraArgs = "") - - $previousOutputEncoding = [System.Console]::OutputEncoding - $resultFile = New-TemporaryFile - $suggestion = "" - $errorOutput = "" - - try { - [System.Console]::OutputEncoding = [System.Text.Encoding]::UTF8 - - # Start-Process does some crazy stuff, just use the Process class directly to have more control. - $process = New-Object System.Diagnostics.Process - $process.StartInfo.FileName = "atuin" - $process.StartInfo.Arguments = "search -i --result-file ""$($resultFile.FullName)"" $ExtraArgs" - $process.StartInfo.UseShellExecute = $false - $process.StartInfo.RedirectStandardError = $true - $process.StartInfo.StandardErrorEncoding = [System.Text.Encoding]::UTF8 - $process.StartInfo.EnvironmentVariables["ATUIN_SHELL"] = "powershell" - $process.StartInfo.EnvironmentVariables["ATUIN_QUERY"] = Get-CommandLine - # PowerShell's Set-Location (cd) doesn't update the process-level working directory, set it explicitly - $process.StartInfo.WorkingDirectory = (Get-Location -PSProvider FileSystem).ProviderPath - - try { - $process.Start() | Out-Null - - # A single stream is redirected, so we can read it synchronously, but we have to start reading it - # before waiting for the process to exit, otherwise the buffer could fill up and cause a deadlock. - $errorOutput = $process.StandardError.ReadToEnd().Trim() - $process.WaitForExit() - - $suggestion = (Get-Content -LiteralPath $resultFile.FullName -Raw -Encoding UTF8 | Out-String).Trim() - } - catch { - $errorOutput = $_ - } - - if ($errorOutput) { - Write-Host -ForegroundColor Red "Atuin error:" - Write-Host -ForegroundColor DarkRed $errorOutput - } - - # If no shell prompt offset is set, initialize it from the current prompt line count. - if ($null -eq $env:ATUIN_POWERSHELL_PROMPT_OFFSET) { - try { - $promptLines = (& $Function:prompt | Out-String | Measure-Object -Line).Lines - $env:ATUIN_POWERSHELL_PROMPT_OFFSET = -1 * ($promptLines - 1) - } - catch { - $env:ATUIN_POWERSHELL_PROMPT_OFFSET = 0 - } - } - - # PSReadLine maintains its own cursor position, which will no longer be valid if Atuin scrolls the display in inline mode. - # Fortunately, InvokePrompt can receive a new Y position and reset the internal state. - $y = $Host.UI.RawUI.CursorPosition.Y + [int]$env:ATUIN_POWERSHELL_PROMPT_OFFSET - $y = [System.Math]::Max([System.Math]::Min($y, [System.Console]::BufferHeight - 1), 0) - [Microsoft.PowerShell.PSConsoleReadLine]::InvokePrompt($null, $y) - - if ($suggestion -eq "") { - # The previous input was already rendered by InvokePrompt - return - } - - $acceptPrefix = "__atuin_accept__:" - - if ( $suggestion.StartsWith($acceptPrefix)) { - Set-CommandLine $suggestion.Substring($acceptPrefix.Length) - [Microsoft.PowerShell.PSConsoleReadLine]::AcceptLine() - } else { - Set-CommandLine $suggestion - } - } - finally { - [System.Console]::OutputEncoding = $previousOutputEncoding - $resultFile.Delete() - } - } - - function Enable-AtuinSearchKeys { - param([bool]$CtrlR = $true, [bool]$UpArrow = $true) - - if ($CtrlR) { - Set-PSReadLineKeyHandler -Chord "Ctrl+r" -BriefDescription "Runs Atuin search" -ScriptBlock { - Invoke-AtuinSearch - } - } - - if ($UpArrow) { - Set-PSReadLineKeyHandler -Chord "UpArrow" -BriefDescription "Runs Atuin search" -ScriptBlock { - $line = Get-CommandLine - - if (!$line.Contains("`n")) { - Invoke-AtuinSearch -ExtraArgs "--shell-up-key-binding" - } else { - [Microsoft.PowerShell.PSConsoleReadLine]::PreviousLine() - } - } - } - } - - $ExecutionContext.SessionState.Module.OnRemove += { - $env:ATUIN_SESSION = $null - $Function:PSConsoleHostReadLine = $script:previousPSConsoleHostReadLine - } - - Export-ModuleMember -Function @("Enable-AtuinSearchKeys", "PSConsoleHostReadLine") -} | Import-Module -Global diff --git a/crates/client/src/shell/atuin.xsh b/crates/client/src/shell/atuin.xsh deleted file mode 100644 index a0283402..00000000 --- a/crates/client/src/shell/atuin.xsh +++ /dev/null @@ -1,86 +0,0 @@ -import os -import subprocess - -from prompt_toolkit.application.current import get_app -from prompt_toolkit.filters import Condition -from prompt_toolkit.keys import Keys - - -if "ATUIN_SESSION" not in ${...} or ${...}.get("ATUIN_SHLVL", "") != ${...}.get("SHLVL", ""): - $ATUIN_SESSION=$(atuin uuid).rstrip('\n') - $ATUIN_SHLVL = ${...}.get("SHLVL", "") - -@events.on_precommand -def _atuin_precommand(cmd: str): - cmd = cmd.rstrip("\n") - try: - $ATUIN_HISTORY_ID = $(atuin history start -- @(cmd) 2>@(os.devnull)).rstrip("\n") - except: - $ATUIN_HISTORY_ID = "" - - -@events.on_postcommand -def _atuin_postcommand(cmd: str, rtn: int, out, ts): - if "ATUIN_HISTORY_ID" not in ${...}: - return - - duration = ts[1] - ts[0] - # Duration is float representing seconds, but atuin expects integer of nanoseconds - nanos = round(duration * 10 ** 9) - with ${...}.swap(ATUIN_LOG="error"): - # This causes the entire .xonshrc to be re-executed, which is incredibly slow - # This happens when using a subshell and using output redirection at the same time - # For more details, see https://github.com/xonsh/xonsh/issues/5224 - # (atuin history end --exit @(rtn) -- $ATUIN_HISTORY_ID &) > /dev/null 2>&1 - atuin history end --exit @(rtn) --duration @(nanos) -- $ATUIN_HISTORY_ID > @(os.devnull) 2>&1 - del $ATUIN_HISTORY_ID - - -def _search(event, extra_args: list[str]): - buffer = event.current_buffer - cmd = ["atuin", "search", "--interactive", *extra_args] - # We need to explicitly pass in xonsh env, in case user has set XDG_HOME or something else that matters - env = ${...}.detype() - env["ATUIN_SHELL"] = "xonsh" - env["ATUIN_QUERY"] = buffer.text - - p = subprocess.run(cmd, stderr=subprocess.PIPE, encoding="utf-8", env=env) - result = p.stderr.rstrip("\n") - # redraw prompt - necessary if atuin is configured to run inline, rather than fullscreen - event.cli.renderer.erase() - - if not result: - return - - buffer.reset() - if result.startswith("__atuin_accept__:"): - buffer.insert_text(result[17:]) - buffer.validate_and_handle() - else: - buffer.insert_text(result) - - -@events.on_ptk_create -def _custom_keybindings(bindings, **kw): - if _ATUIN_BIND_CTRL_R: - @bindings.add(Keys.ControlR) - def r_search(event): - _search(event, extra_args=[]) - - if _ATUIN_BIND_UP_ARROW: - @Condition - def should_search(): - buffer = get_app().current_buffer - # disable keybind when there is an active completion, so - # that up arrow can be used to navigate completion menu - if buffer.complete_state is not None: - return False - # similarly, disable when buffer text contains multiple lines - if '\n' in buffer.text: - return False - - return True - - @bindings.add(Keys.Up, filter=should_search) - def up_search(event): - _search(event, extra_args=["--shell-up-key-binding"]) diff --git a/crates/client/src/shell/atuin.zsh b/crates/client/src/shell/atuin.zsh deleted file mode 100644 index 7e7fef27..00000000 --- a/crates/client/src/shell/atuin.zsh +++ /dev/null @@ -1,167 +0,0 @@ -# shellcheck disable=SC2034,SC2153,SC2086,SC2155 - -# Above line is because shellcheck doesn't support zsh, per -# https://github.com/koalaman/shellcheck/wiki/SC1071, and the ignore: param in -# ludeeus/action-shellcheck only supports _directories_, not _files_. So -# instead, we manually add any error the shellcheck step finds in the file to -# the above line ... - -# Source this in your ~/.zshrc -autoload -U add-zsh-hook - -zmodload zsh/datetime 2>/dev/null - -# If zsh-autosuggestions is installed, configure it to use Atuin's search. If -# you'd like to override this, then add your config after the $(atuin init zsh) -# in your .zshrc -_zsh_autosuggest_strategy_atuin() { - # silence errors, since we don't want to spam the terminal prompt while typing. - suggestion=$(ATUIN_QUERY="$1" atuin search --cmd-only --limit 1 --search-mode prefix 2>/dev/null) -} - -if [ -n "${ZSH_AUTOSUGGEST_STRATEGY:-}" ]; then - ZSH_AUTOSUGGEST_STRATEGY=("atuin" "${ZSH_AUTOSUGGEST_STRATEGY[@]}") -else - ZSH_AUTOSUGGEST_STRATEGY=("atuin") -fi - -if [[ -z "${ATUIN_SESSION:-}" || "${ATUIN_SHLVL:-}" != "$SHLVL" ]]; then - export ATUIN_SESSION=$(atuin uuid) - export ATUIN_SHLVL=$SHLVL -fi -ATUIN_HISTORY_ID="" - -__atuin_osc133_command_executed() { - [[ -n "${ATUIN_PTY_PROXY_ACTIVE:-}" ]] || return - [[ -n "${ATUIN_HISTORY_ID:-}" ]] || return - - printf '\033]133;C\a' -} - -__atuin_osc133_command_finished() { - [[ -n "${ATUIN_PTY_PROXY_ACTIVE:-}" ]] || return - [[ -n "${ATUIN_HISTORY_ID:-}" ]] || return - - printf '\033]133;D;%s;history_id=%s;session_id=%s\a' "$1" "$ATUIN_HISTORY_ID" "${ATUIN_SESSION:-}" -} - -__atuin_osc133_prompt_start=$'%{\033]133;A;cl=line\a%}' -__atuin_osc133_prompt_end=$'%{\033]133;B\a%}' - -__atuin_osc133_wrap_prompt() { - local __atuin_prompt="${PROMPT-}" - local __atuin_rprompt="${RPROMPT-}" - - __atuin_prompt="${__atuin_prompt//$__atuin_osc133_prompt_start/}" - __atuin_prompt="${__atuin_prompt//$__atuin_osc133_prompt_end/}" - __atuin_rprompt="${__atuin_rprompt//$__atuin_osc133_prompt_start/}" - __atuin_rprompt="${__atuin_rprompt//$__atuin_osc133_prompt_end/}" - - if [[ -n "${ATUIN_PTY_PROXY_ACTIVE:-}" ]]; then - PROMPT="${__atuin_osc133_prompt_start}${__atuin_prompt}" - RPROMPT="${__atuin_rprompt}${__atuin_osc133_prompt_end}" - else - PROMPT="$__atuin_prompt" - RPROMPT="$__atuin_rprompt" - fi -} - -_atuin_preexec() { - local id - id=$(atuin history start -- "$1" 2>/dev/null) - export ATUIN_HISTORY_ID="$id" - __atuin_osc133_command_executed - __atuin_preexec_time=${EPOCHREALTIME-} -} - -_atuin_precmd() { - local EXIT="$?" __atuin_precmd_time=${EPOCHREALTIME-} - - __atuin_osc133_wrap_prompt - - [[ -z "${ATUIN_HISTORY_ID:-}" ]] && return - - local duration="" - if [[ -n $__atuin_preexec_time && -n $__atuin_precmd_time ]]; then - printf -v duration %.0f $(((__atuin_precmd_time - __atuin_preexec_time) * 1000000000)) - fi - - __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_search_cmd() { - local -a search_args=("$@") - - - ATUIN_SHELL=zsh ATUIN_LOG=error ATUIN_QUERY=$BUFFER atuin search "${search_args[@]}" -i 3>&1 1>&2 2>&3 3>&- -} - -_atuin_search() { - emulate -L zsh - zle -I - - # swap stderr and stdout, so that the tui stuff works - # TODO: not this - local output __atuin_status - # shellcheck disable=SC2048 - output=$(__atuin_search_cmd $*) - __atuin_status=$? - - zle reset-prompt - # re-enable bracketed paste - # shellcheck disable=SC2154 - echo -n ${zle_bracketed_paste[1]} >/dev/tty - - if (( __atuin_status != 0 )); then - [[ -n $output ]] && print -r -- "$output" >/dev/tty - return $__atuin_status - fi - - if [[ -n $output ]]; then - RBUFFER="" - LBUFFER=$output - - if [[ $LBUFFER == __atuin_accept__:* ]] - then - LBUFFER=${LBUFFER#__atuin_accept__:} - zle accept-line - fi - fi -} -_atuin_search_vicmd() { - _atuin_search --keymap-mode=vim-normal -} -_atuin_search_viins() { - _atuin_search --keymap-mode=vim-insert -} - -_atuin_up_search() { - # Only trigger if the buffer is a single line - if [[ ! $BUFFER == *$'\n'* ]]; then - _atuin_search --shell-up-key-binding "$@" - else - zle up-line - fi -} -_atuin_up_search_vicmd() { - _atuin_up_search --keymap-mode=vim-normal -} -_atuin_up_search_viins() { - _atuin_up_search --keymap-mode=vim-insert -} - -add-zsh-hook preexec _atuin_preexec -add-zsh-hook precmd _atuin_precmd - -zle -N atuin-search _atuin_search -zle -N atuin-search-vicmd _atuin_search_vicmd -zle -N atuin-search-viins _atuin_search_viins -zle -N atuin-up-search _atuin_up_search -zle -N atuin-up-search-vicmd _atuin_up_search_vicmd -zle -N atuin-up-search-viins _atuin_up_search_viins - -# These are compatibility widget names for "atuin <= 17.2.1" users. -zle -N _atuin_search_widget _atuin_search -zle -N _atuin_up_search_widget _atuin_up_search |
