diff --git a/bash/ext b/bash/ext index 16221bf..729f5ce 100644 --- a/bash/ext +++ b/bash/ext @@ -1,36 +1,106 @@ # Make Bash more like Zsh -# Hooks -# derived from http://glyf.livejournal.com/63106.html +## Hooks +# https://zsh.sourceforge.io/Doc/Release/Functions.html#Hook-Functions # TODO: support precmd_functions and chpwd_functions arrays -# default: NOOPs +### Defaults: NOOPs + function preexec { :; } + function precmd { :; } + function chpwd { :; } +### Implementations + +# Alternative cd function that calls chpwd afterwards builtin cd +# +# zsh: Executed whenever the current working directory is changed. __cd_invoke_chpwd() { builtin cd "$@" + chpwd + + # TODO: chpwd_functions array } -__preexec_invoke_exec () { +# zsh: Executed before each prompt. Note that precommand functions are not +# re-executed simply because the command line is redrawn, as happens, for +# example, when a notification about an exiting job is displayed. +__prompt_command_invoke_precmd() { + precmd + + # TODO: precmd_functions array +} + +# to properly trigger only before command exec this must be the last prompt command +__prompt_command_hook_preexec() { + trap '__debug_invoke_preexec' DEBUG +} + +__prompt_command_unhook_preexec() { + # Unfortunately there's no way to remove just one trap from a signal + trap - DEBUG +} + +# zsh: Executed just after a command has been read and is about to be executed. If +# the history mechanism is active (regardless of whether the line was discarded +# from the history buffer), the string that the user typed is passed as the +# first argument, otherwise it is an empty string. The actual command that will +# be executed (including expanded aliases) is passed in two different forms: +# the second argument is a single-line, size-limited version of the command +# (with things like function bodies elided); the third argument contains the +# full text that is being executed. +__debug_invoke_preexec () { + # somehow PROMPT_COMMAND contents seems to be still affected by the + # just-removed trap. Ignore ours. + [[ "$BASH_COMMAND" == "__prompt_command_unhook_preexec" ]] && return + [[ "$BASH_COMMAND" == "__prompt_command_invoke_precmd" ]] && return + [[ "$BASH_COMMAND" == "__prompt_command_hook_preexec" ]] && return + + # TODO: not sure this is still necessary + [[ -n "$COMP_LINE" ]] && return # completion + local this_command; - [ -n "$COMP_LINE" ] && return # completion - [ "$BASH_COMMAND" = "$PROMPT_COMMAND" ] && return # precmd - + # TODO: hack: doesn't work when command is not added to history this_command=`history 1 | sed -e "s/^[ ]*[0-9]*[ ]*//g"`; preexec "$this_command" } -# set up the hooks -PROMPT_COMMAND="precmd" -trap '__preexec_invoke_exec' DEBUG +### Set up the hooks + +# Define a function to override the cd builtin +# +# - does not apply to `bash -c 'cd foo` +# - does apply to shubshells: `(cd foo)` will call so side effects beware (env +# vars are conveniently scoped to subshell) cd() { __cd_invoke_chpwd "$@"; } +# Call on each prompt. This transitively sets preexec to work for each prompt +# +# PROMPT_COMMAND is evaluated right before PS1 is displayed. This matches zsh +# semantics for precmd. +# +# We forcefully set it instead of taking whatever was set: +# - to control order (precmd eval + preexec hooking must be last) +# - because of the trap issue +PROMPT_COMMAND=( + # this also conveniently clears DEBUG traps + __prompt_command_unhook_preexec + + # precmd hook processing + __prompt_command_invoke_precmd + + # must be last to properly have DEBUG trigger only before command exec + __prompt_command_hook_preexec +) + + +## Other bits # clears a line that was not terminated by a LF fixing the dangling prompt # issue by marking it with a reversed %, like zsh diff --git a/bash/kitty b/bash/kitty index f0b6b07..684ba21 100644 --- a/bash/kitty +++ b/bash/kitty @@ -1,5 +1,5 @@ -if test -n "$KITTY_INSTALLATION_DIR"; then - export KITTY_SHELL_INTEGRATION="enabled" - source "$KITTY_INSTALLATION_DIR/shell-integration/bash/kitty.bash" -fi +# if test -n "$KITTY_INSTALLATION_DIR"; then +# export KITTY_SHELL_INTEGRATION="enabled" +# source "$KITTY_INSTALLATION_DIR/shell-integration/bash/kitty.bash" +# fi diff --git a/zsh/kitty b/zsh/kitty index 5b9ae5f..8165ed7 100644 --- a/zsh/kitty +++ b/zsh/kitty @@ -1,6 +1,6 @@ -if test -n "$KITTY_INSTALLATION_DIR"; then - export KITTY_SHELL_INTEGRATION="enabled" - autoload -Uz -- "$KITTY_INSTALLATION_DIR"/shell-integration/zsh/kitty-integration - kitty-integration - unfunction kitty-integration -fi +# if test -n "$KITTY_INSTALLATION_DIR"; then +# export KITTY_SHELL_INTEGRATION="enabled" +# autoload -Uz -- "$KITTY_INSTALLATION_DIR"/shell-integration/zsh/kitty-integration +# kitty-integration +# unfunction kitty-integration +# fi