Skip to content

Commit

Permalink
edit (TRAPDEBUG_EXIT): correctly skip the current command for DEBUG (…
Browse files Browse the repository at this point in the history
…fixup f62fc04)
  • Loading branch information
akinomyoga committed Feb 23, 2022
1 parent f62fc04 commit 6fdabf3
Show file tree
Hide file tree
Showing 5 changed files with 171 additions and 33 deletions.
7 changes: 5 additions & 2 deletions ble.pp
Expand Up @@ -329,11 +329,13 @@ function ble/base/.adjust-bash-options {
if ((_ble_bash>=40100)); then
shopt=$BASHOPTS
else
shopt=
# Note: nocasematch は bash-3.1 以上
shopt -q nocasematch 2>/dev/null && shopt=nocasematch
shopt=
shopt -q extdebug 2>/dev/null && shopt=$shopt:extdebug
shopt -q nocasematch 2>/dev/null && shopt=$shopt:nocasematch
fi
[[ $2 == shopt ]] || builtin eval -- "$2=\$shopt"
shopt -u extdebug
shopt -u nocasematch 2>/dev/null
return 0
} 2>/dev/null # set -x 対策
Expand All @@ -342,6 +344,7 @@ function ble/base/.adjust-bash-options {
function ble/base/.restore-bash-options {
local set=${!1} shopt=${!2}
[[ :$shopt: == *:nocasematch:* ]] && shopt -s nocasematch
[[ :$shopt: == *:extdebug:* ]] && shopt -s extdebug
[[ $set == *B* ]] || set +B
[[ $set == *T* ]] && set -T
[[ $set == *k* ]] && set -k
Expand Down
8 changes: 4 additions & 4 deletions docs/ChangeLog.md
Expand Up @@ -145,8 +145,8 @@
- edit (`ble-bind -x`): preserve multiline prompts on execution of `bind -x` commands (requested by SuperSandro2000) `#D1755` 7d05a28
- util (`ble/util/buffer`): hide cursor in rendering `#D1758` e332dc5
- complete (`action:file`): always suffix `/` to complete symlinked directory names (reported by SuperSandro2000) `#D1759` 397ac1f
- edit (command-help): show source files for functions `#D1779` 0000000
- edit (`ble/builtin/exit`): defer exit in trap handlers (motivated by SuperSandro2000) `#D1782` 0000000
- edit (command-help): show source files for functions `#D1779` 7683ab9
- edit (`ble/builtin/exit`): defer exit in trap handlers (motivated by SuperSandro2000) `#D1782` f62fc04 0000000

## Fixes

Expand Down Expand Up @@ -271,7 +271,7 @@
- decode: cache `inputrc` translations `#D1652` 994e2a5
- complete: use `awk` for batch `quote-insert` (motivated by banoris) `#D1714` a0b2ad2 92d9734
- complete (quote-insert.batch): fix regex escaping in bracket expr of awk (reported by telometto) `#D1729` 8039b77
- prompt: reduce redundant evaluation of `PROMPT_COMMAND` on the startup `#D1778` 0000000
- prompt: reduce redundant evaluation of `PROMPT_COMMAND` on the startup `#D1778` 042376b

## Compatibility

Expand Down Expand Up @@ -323,7 +323,7 @@
- util: add identification of Windows Terminal `wt` `#D1758` e332dc5
- complete: evaluate words for `noquote` (motivated by SuperSandro2000) `#D1767` 0a42299
- edit (TRAPDEBUG): preserve original `DEBUG` trap and enabled it in `PROMPT_COMMAND` (motivated by ammarooo) `#D1772` `#D1773` ec2a67a
- main, trap: fix initialization order of `{save,restore}-BASH_REMATCH` (reported by SuperSandro2000) `#D1780` 0000000
- main, trap: fix initialization order of `{save,restore}-BASH_REMATCH` (reported by SuperSandro2000) `#D1780` 689534d
- global: work around bash-3.0 bug that single quotas remains for `"${v-$''}"` `#D1774` 9b96578

## Internal changes and fixes
Expand Down
122 changes: 117 additions & 5 deletions note.txt
Expand Up @@ -1808,6 +1808,52 @@ bash_tips

2022-02-20

* 何故か2回目の char_width_@=auto がちゃんと動いていない気がする。何故だろう
か。後で確認する。

* complete: cygwin$ pdflatex [TAB] で /usr/bin/cat: '': No such file or
directory というエラーが出力される。chat では再現しない。bash-completion は
ロードされていない。

* より一般の補完 framework に向けたインターフェイスについて
https://github.com/rsteube/carapace/issues/431

> prevent default file completion when no values returned

このオプションを提供する事にする。

* 拡張 comp_opts をまとめる。prog-trim, syntax-raw, filter_by_prefix

現在参照している comp_opts は以下の通り。

$ grc '(comp_opts|DATA):? =='

元から bash に存在しているオプションは以下の通り:
bashdefault default dirnames filenames noquote nosort nospace plusdirs

* rsteube の記事
https://dev.to/rsteube/a-pragmatic-approach-to-shell-completion-4gp0

filtering を description に対しても適用するという事が書かれている。
それは確かに便利そうである。現状の実装では対応が難しい様には思われるが。

* sabbrev を削除する機能がない

削除の仕方としては以下の2種類が考えられる。

ble-sabbrev -r a # bind, complete と同様
ble-sabbrev a=- # trap と同様

後者は本当に "-" に展開させたい時 (実際そういう場合が存在するのかは謎だが)
と衝突するので前者の方が良い気がする。

また、前者を採用するとしたら -r に対して optarg を要求するのか、或いは -r
に対して optarg を要求するのかで振る舞いが変わってくる。

* complete (action:command): function の description の quote が邪魔。最初の2
行と末尾の } は削除して良い。また、quote ではなくて text と同様の表示の仕方
にしたい気がする。

* trap (lastarg): 一応 heredoc 等を使えば eval の中から複数行の lastarg を設
定する事ができるのではないか。他に複数行で、eval されても余分な実行が起こら
ない様な方法はあるだろうか。不完全な引用符の場合には結局エラーが出力されて
Expand All @@ -1822,6 +1868,21 @@ bash_tips
と思ったらこの問題は外部コマンドではなくて builtin sleep を呼び出している時
特有の問題だった。trap INT を設定しているのは問題なのだろうか。

* bash-it から detach するとプロンプトが壊れた状態になる。oh-my-bash
から抜けても同じ状態になる。nix-shell の場合には大丈夫。

どうやら PROMPT_COMMAND に何か設定されているとこうなる様だ。何故
PROMPT_COMMAND があるかどうかで変わるのだろうか。因みに
PROMPT_COMMAND も退避されたままになっている。

* bash-it-minimal を実行すると bash-preexec の実行に失敗する。
或いは、ble.sh 自体の prompt-attach に失敗している?

* edit: 現在の TRAPDEBUG の枠組みを拡張して try/catch/finally を実装できるのでは
Ref #D1783

もしその枠組がちゃんとできるのであれば edit.sh から util.sh に移動する。

2022-02-14

* 全ての ble.sh session にコマンドを送る機能があれば screen に再 attach した
Expand Down Expand Up @@ -6174,11 +6235,62 @@ bash_tips
ると、元々の stdout/stdin を何処かに記録しておくべきなのだろうという気が
する。

* edit: 現在の TRAPDEBUG の枠組みを拡張して try/catch/finally を実装できるのでは
Ref #D1783

もしその枠組がちゃんとできるのであれば edit.sh から util.sh に移動する。

2022-02-20 exit を DEBUG return で再現しようとしても DEBUG trap の対象であ
る "現在のコマンド" は必ず実行されてその後で return/continue 等の効果が現れ
る。なので blehook 内での exit は意図した動作をしない。

% blehook の中で exit をしても trap の実行が其処で終了しない。continue が実
% 行されている筈なのに効いていないのは何故だろうか。うーん。eval の中から
% continue を実行しても効かないのだろうか。
% →それとも bash の特定の version を使っている事によるバグだろうかと思って
% 振る舞いを確認したが、4.0..dev まで全て同じ振る舞いである

→うーん。振る舞いを調べて分かったのは、DEBUG trap が呼び出された対象のコマ
ンドは結局何れにしても実行される様だという事。例えば continue を trap 内部
で実行すると、確かにその場で continue によって制御が変更され、trap 内の続き
の処理も実行されない。そしてtrap の外側にあるループを抜ける。然し、その前に
DEBUG trap の対象であるコマンドはちゃんと実行される様だという事。

? このコマンド実行をキャンセルする方法はないのだろうか。extdebug が設定され
ていれば trap の戻り値によって振る舞いが変わるらしい。特に 2 を返せばその
場で return を実行する事ができる。然し、continue をその場で実行する方法は
不明である。continue が成功すれば戻り値は 0 になるので DEBUG 対象のコマン
ドは結局実行される。逆にそれを阻止する為に戻り値を 0 以外にしようとすると
continue を失敗させるしかなく、それだと次のループに移る事ができない。或い
は BASH_COMMAND を書き換えたら実行するコマンドを書き換える事ができると言っ
た事はないのだろうか。

実際に extdebug を設定して試しても見たが、マニュアルから予想される通り、
continue が成功すればコマンドも実行するし、コマンドの実行をキャンセルする
には continue を実行する訳には行かない。continue 直前の終了ステータスを変
更しても何の効果もなかった。つまり、continue 自体の戻り値が使われる。

他に次のコマンドを無効にする手法はないのか? というか次のコマンドを無効に
したとしても更にまた次のコマンドが実行されるというのだと際限がない。なの
で、やはり extdebug を一時的に設定して 2 を返す事によって実行を中断させる
しかないのだろうか。

* extdebug を一瞬有効にして return (終了ステータス 2) でトップレベルまで戻
るしかない気がする。

? extdebug は trap の中で無効化した場合でもその trap に対して失効するのだ
ろうか。これについては振る舞いを確認する必要がある。→やはり trap の中
で shopt -u extdebug すると即座に extdebug の動作はしなくなる様だ。ちゃ
んとどの bash の version でも同様である事を確認した。

だとするとどの時点で extdebug を off にするのかについて確認が必要になる。
然し取り敢えずは sandbox の中で実行しているのであればその呼出元で解除す
る様にすれば良い。※という事は、sandbox の中では未だ DEBUG trap は
clear はしないという事になる。

うーん。取り敢えず実装した。動いている。というかそもそも元々 continue を
hook の中で実行する事を許していたのが変な気もする。或いは、continue 及び
return を使って他の hook の処理に干渉したりできるというのも一つの機能だっ
たかもしれないが、それならそれで別の枠組みを提供するべきの気もする。或い
は、もし return continue を使うとしても trap sandbox の様に終了の仕方を検
出して制御を決めるのが良いのだろうという気がする。

現在は現状のままで良い気がしている。

2022-02-19

Expand Down
47 changes: 32 additions & 15 deletions src/edit.sh
Expand Up @@ -5666,6 +5666,7 @@ function ble/builtin/exit {
# ので exit は延期して一旦元の呼び出し元まで戻る。これによって細かな動作の
# 違いが問題になる可能性はある。例えば trap の中で time で時間計測中だった
# 場合、時間計測が中止されず結果が出力される。
shopt -s extdebug
_ble_edit_exec_TRAPDEBUG_EXIT=$opt_args
ble-edit/exec:gexec/.TRAPDEBUG/trap
return 0
Expand Down Expand Up @@ -6038,44 +6039,60 @@ function ble-edit/exec:gexec/.TRAPDEBUG {
[[ ! ( ${FUNCNAME[1]-} == _ble_prompt_update__eval_prompt_command_1 && ( $bash_command == 'ble-edit/exec/.setexit '* || $bash_command == 'BASH_COMMAND='*' builtin eval -- '* ) ) ]] || return 0
[[ ! ${_ble_builtin_trap_inside-} ]] || return 0

# Handle EXIT
# Handle EXIT (#D1782)
#
# 前提: _ble_edit_exec_TRAPDEBUG_EXIT が設定される時には extdebug も設定され
# ていると仮定する。
if [[ $_ble_edit_exec_TRAPDEBUG_EXIT ]]; then
# 或る特定のレベルまでは素通りする (そもそも exit なのでユーザーの DEBUG
# trap も処理しなくて良い)。
local flag_clear= flag_exit=
local flag_clear= flag_exit= postproc=
if [[ ! $_ble_builtin_trap_processing ]] || ((${#FUNCNAME[*]}<=1)); then
# 本来は此処に来る事はない筈
flag_clear=1
flag_clear=2
flag_exit=$_ble_edit_exec_TRAPDEBUG_EXIT
else
case "${FUNCNAME[1]-} ${FUNCNAME[2]-}" in
('ble/builtin/trap/invoke.sandbox ble/builtin/trap/invoke')
# 本来は extdebug が設定されている筈なので extdebug が設定されていない時
# の対処は不要だが、念の為 extdebug が設定されていない時の動作も定義して
# おく。
case " ${FUNCNAME[*]:1} " in
(' ble/builtin/trap/invoke.sandbox ble/builtin/trap/invoke '*)
_ble_trap_done=exit
_ble_trap_lastarg=$_ble_edit_exec_TRAPDEBUG_EXIT
_ble_edit_exec_TRAPDEBUG_postproc='return 0'
flag_clear=1 ;;
('blehook/invoke ble/builtin/trap/.handler')
postproc='ble/util/setexit 2'
shopt -q extdebug || postproc='return 0' ;;
(' blehook/invoke.sandbox blehook/invoke ble/builtin/trap/.handler '*)
_ble_local_ext=$_ble_edit_exec_TRAPDEBUG_EXIT
_ble_builtin_trap_processing=exit:$_ble_edit_exec_TRAPDEBUG_EXIT
postproc='ble/util/setexit 2'
shopt -q extdebug || postproc='return 0' ;;
(' ble/builtin/trap/invoke '* | ' blehook/invoke '*)
# 此処で確実に trap DEBUG を解除する為には sandbox の呼び出しよりも後に
# 少なくとも1つコマンドが必要。現在は return が必ず両 invoke の終わりに
# 実行される様になっているので大丈夫の筈。
flag_clear=1 ;;
('ble/builtin/trap/invoke '* | 'ble/builtin/trap/.handler '* | 'ble-edit/exec:gexec/.TRAPDEBUG '*)
# 此処にも本来は来ない筈
flag_clear=1 ;;
(' ble/builtin/trap/.handler '* | ' ble-edit/exec:gexec/.TRAPDEBUG '*)
# 本来此処には来ない筈。extdebug には触れずに DEBUG trap だけ解除する。
flag_clear=2 ;;
(*)
# trap handler 内部の処理は全てスキップして呼び出し元に戻る。
_ble_edit_exec_TRAPDEBUG_postproc="{ return 130 || break; } &>/dev/null" ;;
postproc='ble/util/setexit 2'
shopt -q extdebug || postproc='return 128' ;;
esac
fi

if [[ $flag_clear ]]; then
if [[ ! ${_ble_builtin_trap_handlers[_ble_builtin_trap_DEBUG]+set} ]]; then
_ble_edit_exec_TRAPDEBUG_postproc="builtin trap - DEBUG${_ble_edit_exec_TRAPDEBUG_postproc:+;$_ble_edit_exec_TRAPDEBUG_postproc}"
fi
[[ $flag_clear == 2 ]] || shopt -u extdebug
_ble_edit_exec_TRAPDEBUG_EXIT=
[[ ${_ble_builtin_trap_handlers[_ble_builtin_trap_DEBUG]+set} ]] ||
postproc="builtin trap - DEBUG${postproc:+;$postproc}"
if [[ $flag_exit ]]; then
builtin exit "$flag_exit"
fi
fi

_ble_edit_exec_TRAPDEBUG_postproc=$postproc

elif [[ $_ble_edit_exec_TRAPDEBUG_INT ]]; then
local IFS=$_ble_term_IFS __set __shopt
ble/base/.adjust-bash-options __set __shopt
Expand Down
20 changes: 13 additions & 7 deletions src/util.sh
Expand Up @@ -1855,20 +1855,25 @@ function blehook/has-hook {
builtin eval "local count=\${#_ble_hook_h_$1[@]}"
((count))
}
## @fn blehook/invoke.sandbox
## @var[in] _ble_local_hook _ble_local_lastexit _ble_local_lastarg
function blehook/invoke.sandbox {
if type "$_ble_local_hook" &>/dev/null; then
ble/util/setexit "$_ble_local_lastexit" "$_ble_local_lastarg"
"$_ble_local_hook" "$@" 2>&3
else
ble/util/setexit "$_ble_local_lastexit" "$_ble_local_lastarg"
builtin eval -- "$_ble_local_hook" 2>&3
fi
}
function blehook/invoke {
local _ble_local_lastexit=$? _ble_local_lastarg=$_ FUNCNEST=
((_ble_hook_c_$1++))
local -a _ble_local_hooks
builtin eval "_ble_local_hooks=(\"\${_ble_hook_h_$1[@]}\")"; shift
local _ble_local_hook _ble_local_ext=0
for _ble_local_hook in "${_ble_local_hooks[@]}"; do
if type "$_ble_local_hook" &>/dev/null; then
ble/util/setexit "$_ble_local_lastexit" "$_ble_local_lastarg"
"$_ble_local_hook" "$@" 2>&3
else
ble/util/setexit "$_ble_local_lastexit" "$_ble_local_lastarg"
builtin eval -- "$_ble_local_hook" 2>&3
fi || _ble_local_ext=$?
blehook/invoke.sandbox || _ble_local_ext=$?
done
return "$_ble_local_ext"
} 3>&2 2>/dev/null # set -x 対策 #D0930
Expand Down Expand Up @@ -2169,6 +2174,7 @@ function ble/builtin/trap/invoke {
_ble_builtin_trap_user_lastarg=$_ble_trap_lastarg
fi

return 0
} 3>&2 2>/dev/null # set -x 対策 #D0930

## @fn ble/builtin/trap/.handler sig signame
Expand Down

0 comments on commit 6fdabf3

Please sign in to comment.