bash-preexec.bash (6014B)
1 # ble/contrib/integration/bash-preexec.bash (C) 2022-2023, akinomyoga 2 3 ## @arr[in] precmd_functions 4 ## @arr[in] preexec_functions 5 ## The functions registered to these arrays are executed on PRECMD and 6 ## PREEXEC hooks, respectively. 7 ## 8 ## @fn[in] precmd 9 ## @fn[in] preexec 10 ## If these functions are defined, they are executed on PRECMD and PREEXEC 11 ## hooks, respectively, through "precmd_functions" and "preexec_functions". 12 ## 13 ## 14 ## * Integration with bash-preexec.sh (https://github.com/rcaloras/bash-preexec) 15 ## 16 ## Although this script works without bash-preexec, it provides a better 17 ## integration with bash-preexec when bash-preexec is loaded. The 18 ## integration relies on the following public API of bash-preexec. 19 ## 20 ## @fn __bp_precmd_invoke_functions lastexit lastarg 21 ## @fn __bp_preexec_invoke_functions lastexit lastarg this_command 22 ## @fn __bp_uninstall 23 ## @var __bp_trapdebug_string 24 ## @var __bp_install_string 25 26 function ble/contrib/integration:bash-preexec/add-convenience-functions { 27 ble/array#remove precmd_functions precmd 28 ble/array#remove preexec_functions preexec 29 ble/array#unshift precmd_functions precmd 30 ble/array#unshift preexec_functions preexec 31 } 32 33 function ble/contrib/integration:bash-preexec/precmd.hook { 34 local _ble_local_lastexit=$? _ble_local_lastarg=$_ 35 36 # Emulate bash-preexec variables 37 __bp_last_ret_value=$_ble_local_lastexit 38 BP_PIPESTATUS=("${BLE_PIPESTATUS[@]}") 39 40 # local __bp_blesh_invoking_through_blesh=1 # XXX 41 if ble/is-function __bp_precmd_invoke_functions; then 42 __bp_precmd_invoke_functions "$_ble_local_lastexit" "$_ble_local_lastarg" 43 else 44 # For older bash-preexec.sh / without bash-preexec.sh 45 local _ble_local_hook 46 for _ble_local_hook in "${precmd_functions[@]}"; do 47 if builtin type -t "$_ble_local_hook" &>/dev/null; then 48 ble/util/setexit "$_ble_local_lastexit" "$_ble_local_lastarg" 49 "$_ble_local_hook" 50 fi 51 done 52 fi 53 } 54 55 function ble/contrib/integration:bash-preexec/preexec.hook { 56 local _ble_local_lastexit=$? _ble_local_lastarg=$_ _ble_local_command=$1 57 __bp_last_argument_prev_command=$_ble_local_lastarg 58 59 # local __bp_blesh_invoking_through_blesh=1 # XXX 60 if ble/is-function __bp_preexec_invoke_functions; then 61 __bp_preexec_invoke_functions "$_ble_local_lastexit" "$_ble_local_lastarg" 62 else 63 # For older bash-preexec.sh / without bash-preexec.sh 64 local _ble_local_hook 65 for _ble_local_hook in "${preexec_functions[@]}"; do 66 if builtin type -t "$_ble_local_hook" &>/dev/null; then 67 ble/util/setexit "$_ble_local_lastexit" "$_ble_local_lastarg" 68 "$_ble_local_hook" "$_ble_local_command" 69 fi 70 done 71 fi 72 } 73 74 ## @fn ble/contrib/integration:bash-preexec/attach.hook 75 ## Remove bash-preexec hooks 76 function ble/contrib/integration:bash-preexec/attach.hook { 77 local BP_TRAPDEBUG_STRING=${__bp_trapdebug_string:-'__bp_preexec_invoke_exec "$_"'} 78 79 # Remove bash-preexec preexec hook in builtin DEBUG trap. 80 local trap_string q="'" Q="'\''" 81 ble/util/assign trap_string 'builtin trap -p DEBUG' 82 if [[ $trap_string == "trap -- '${BP_TRAPDEBUG_STRING//$q/$Q}' DEBUG" ]]; then 83 if [[ ${__bp_trap_string-} ]]; then 84 builtin eval -- "builtin $__bp_trap_string" 85 else 86 builtin trap - DEBUG 87 fi 88 fi 89 90 if ble/is-function __bp_uninstall; then 91 __bp_uninstall 92 else 93 # For older bash-preexec.sh 94 95 local BP_INSTALL_STRING=${__bp_install_string:-$'__bp_trap_string="$(trap -p DEBUG)"\ntrap - DEBUG\n__bp_install'} 96 local BP_PROMPT_COMMAND_PREFIX=__bp_precmd_invoke_cmd 97 local BP_PROMPT_COMMAND_SUFFIX=__bp_interactive_mode 98 99 # Remove __bp_install hook from PROMPT_COMMAND 100 if [[ ${PROMPT_COMMAND-} == *"$__bp_install_string"* ]]; then 101 PROMPT_COMMAND="${PROMPT_COMMAND//$BP_INSTALL_STRING[;$'\n']}" # Edge case of appending to PROMPT_COMMAND 102 PROMPT_COMMAND="${PROMPT_COMMAND//$BP_INSTALL_STRING}" 103 fi 104 105 # Remove precmd hook from PROMPT_COMMAND 106 PROMPT_COMMAND=${PROMPT_COMMAND/#$BP_PROMPT_COMMAND_PREFIX$'\n'/$'\n'} 107 PROMPT_COMMAND=${PROMPT_COMMAND%$'\n'$BP_PROMPT_COMMAND_SUFFIX} 108 PROMPT_COMMAND=${PROMPT_COMMAND#$'\n'} 109 110 # Remove preexec hook in the DEBUG trap 111 local q="'" Q="'\''" trap_string 112 ble/util/assign trap_string 'trap -p DEBUG' 113 if [[ $trap_string == "trap -- '${__bp_trapdebug_string//$q/$Q}' DEBUG" ]]; then 114 if [[ ${__bp_trap_string-} ]]; then 115 eval -- "$__bp_trap_string" 116 else 117 trap - DEBUG 118 fi 119 fi 120 fi 121 } 122 123 ## @fn ble/contrib/integration:bash-preexec/detach.hook 124 function ble/contrib/integration:bash-preexec/detach.hook { 125 # Reinstall bash-preexec hooks 126 local BP_INSTALL_STRING=${__bp_install_string-} 127 [[ ! $BP_INSTALL_STRING ]] && ble/is-function __bp_install && 128 BP_INSTALL_STRING=$'__bp_trap_string="$(trap -p DEBUG)"\ntrap - DEBUG\n__bp_install' 129 130 builtin eval -- "$__bp_install_string" 131 132 # Note: 重複して登録される (古い bash-preexec.sh) かもしれないし、全 133 # く登録されない (bash-preexec.sh をロードしていない時) かもしれない 134 # ので、ble.sh 側で末尾で一回呼び出す形に修正する。 135 ble/contrib/integration:bash-preexec/add-convenience-functions 136 } 137 138 ble/contrib/integration:bash-preexec/add-convenience-functions 139 blehook PRECMD!=ble/contrib/integration:bash-preexec/precmd.hook 140 blehook PREEXEC!=ble/contrib/integration:bash-preexec/preexec.hook 141 blehook ATTACH!=ble/contrib/integration:bash-preexec/attach.hook 142 blehook DETACH!=ble/contrib/integration:bash-preexec/detach.hook 143 if [[ ${bp_imported-${__bp_imported-}} ]]; then 144 ble/contrib/integration:bash-preexec/attach.hook 145 fi 146 147 # XXX: 以下は uninstall で削除しきれなかった時の為の保険。今の所不要に思われる。 148 # __bp_blesh_check() { 149 # if [[ $BLE_ATTACHED && ! ${__bp_blesh_invoking_through_blesh-} ]]; then 150 # ble/contrib/integration:bash-preexec/attach.hook 151 # fi 152 # } 153 # precmd_function+=(__bp_blesh_check) 154 # preexec_function+=(__bp_blesh_check)