Skip to content

Commit

Permalink
syntax: support escape "\?" and history expansions in here documents
Browse files Browse the repository at this point in the history
  • Loading branch information
akinomyoga committed Feb 19, 2023
1 parent 651c70c commit e619e73
Show file tree
Hide file tree
Showing 5 changed files with 130 additions and 18 deletions.
2 changes: 2 additions & 0 deletions docs/ChangeLog.md
Expand Up @@ -120,6 +120,8 @@
- main: support `BLE_SESSION_ID` and `BLE_COMMAND_ID` `#D1925` 44d9e10 `#D1947` 46ac426 `#D1954` xxxxxxx
- main: support an option `--inputrc={diff,all,user,none}` `#D1926` 92f2006
- util (`ble/builtin/trap`): support Bash 5.2 `trap -P` `#D1937` 826a275
- syntax: highlight `\?` in here documents `#D1959` xxxxxxx
- syntax: recognize history expansion in here documents, `"...!"` (bash <= 4.2), and `$!` (bash <= 4.1) `#D1959` xxxxxxx

## Changes

Expand Down
36 changes: 26 additions & 10 deletions lib/core-syntax.sh
Expand Up @@ -1038,6 +1038,7 @@ function ble/syntax:bash/cclass/initialize {
_ble_syntax_bash_charsDef[CTX_PWORDE]="}$expansions$glob!" # パラメータ展開 ${~} エラー
_ble_syntax_bash_charsDef[CTX_PWORDR]="}/$expansions$glob!" # パラメータ展開 ${~} 置換前
_ble_syntax_bash_charsDef[CTX_RDRH]="$delimiters$expansions"
_ble_syntax_bash_charsDef[CTX_HERE1]="\\\$\`$_ble_term_nl!"

# templates
_ble_syntax_bash_charsFmt[CTX_ARGI]="$delimiters$expansions$glob{$tilde@q@h"
Expand All @@ -1048,6 +1049,7 @@ function ble/syntax:bash/cclass/initialize {
_ble_syntax_bash_charsFmt[CTX_PWORDE]="}$expansions$glob@h"
_ble_syntax_bash_charsFmt[CTX_PWORDR]="}/$expansions$glob@h"
_ble_syntax_bash_charsFmt[CTX_RDRH]=${_ble_syntax_bash_charsDef[CTX_RDRH]}
_ble_syntax_bash_charsFmt[CTX_HERE1]="\\\$\`$_ble_term_nl@h"

_ble_syntax_bash_chars_simpleDef="$delimiters$expansions^!"
_ble_syntax_bash_chars_simpleFmt="$delimiters$expansions@q@h"
Expand Down Expand Up @@ -2053,11 +2055,17 @@ function ble/syntax:bash/check-dollar {
return 0
elif rex='^\$([-*@#?$!0_]|[1-9]|[a-zA-Z_][a-zA-Z_0-9]*)' && [[ $tail =~ $rex ]]; then
local rematch=$BASH_REMATCH rematch1=${BASH_REMATCH[1]}
local ret; ble/syntax/highlight/vartype "$rematch1" readvar:global
((_ble_syntax_attr[i]=CTX_PARAM,
_ble_syntax_attr[i+1]=ret,
i+=${#rematch}))
return 0
((_ble_syntax_attr[i++]=CTX_PARAM))

if ((_ble_bash<40200)) && local tail=${tail:1} &&
ble/syntax:bash/starts-with-histchars && ble/syntax:bash/check-history-expansion; then
# bash-4.1 以下では $!" や $!a 等が履歴展開の対象になる。
return 0
else
local ret; ble/syntax/highlight/vartype "$rematch1" readvar:global
((_ble_syntax_attr[i]=ret,i+=${#rematch}-1))
return 0
fi
else
# if dollar doesn't match any patterns it is treated as a normal character
((_ble_syntax_attr[i++]=ctx))
Expand Down Expand Up @@ -2374,7 +2382,7 @@ function ble/syntax:bash/check-history-expansion {
if [[ $histc1 && $tail == "$histc1"[^"$_ble_syntax_bash_histstop"]* ]]; then

# "~" 文字列中では一致可能範囲を制限する。
if ((ctx==CTX_QUOT)); then
if ((_ble_bash>=40300&&ctx==CTX_QUOT)); then
local tail=${tail%%'"'*}
[[ $tail == '!' ]] && return 1
fi
Expand Down Expand Up @@ -4625,17 +4633,25 @@ function ble/syntax:bash/ctx-heredoc-content {
((ctx=CTX_HERE1))

# \? 及び $? ${} $(()) $[] $() ``
if rex='^([^$`\'"$lf"']|\\.)+'"$lf"'?|^'"$lf" && [[ $tail =~ $rex ]]; then
((_ble_syntax_attr[i]=CTX_HERE0,
i+=${#BASH_REMATCH}))
[[ $BASH_REMATCH == *"$lf" ]] && ((ctx=CTX_HERE0))
if rex='^(\\[\$`'$lf'])|^([^'${_ble_syntax_bash_chars[CTX_HERE1]}']|\\[^\$`'$lf'])+'$lf'?|^'$lf && [[ $tail =~ $rex ]]; then
if [[ ${BASH_REMATCH[1]} ]]; then
((_ble_syntax_attr[i]=ATTR_QESC))
else
((_ble_syntax_attr[i]=CTX_HERE0))
[[ $BASH_REMATCH == *"$lf" ]] && ((ctx=CTX_HERE0))
fi
((i+=${#BASH_REMATCH}))
return 0
fi

if ble/syntax:bash/check-dollar; then
return 0
elif [[ $tail == '`'* ]] && ble/syntax:bash/check-quotes; then
return 0
elif ble/syntax:bash/starts-with-histchars; then
ble/syntax:bash/check-history-expansion ||
((_ble_syntax_attr[i]=CTX_HERE0,i++))
return 0
else
# 単独の $ や終端の \ など?
((_ble_syntax_attr[i]=CTX_HERE0,i++))
Expand Down
99 changes: 95 additions & 4 deletions note.txt
Expand Up @@ -1934,16 +1934,27 @@ bash_tips

2023-02-12

* prompt: \g{} は ble/color/setface/.spec2g を使う?
https://github.com/akinomyoga/ble.sh/issues/278

そうしたらカスタム face を指定できて、ユーザーが自分で定義する事に直接の意
義が出てくる。

* wiki: 他にも faces はあるという事を書く。

* blerc.template: update unicode versions

* README: Guix package の位置が変わっている。

* edit: bash-4.1 以下で echo "$!" を実行しようとしても履歴展開周りで変な事が
起こってコマンドを実行する事ができない。更に bash-3.0 では
* syntax: 関数名として function `xxx` 等も実は許されている。

bash-3.0: ble/history:bash/resolve-multiline: そのようなファイルやディレクトリはありません
* syntax: 5.2 以降では (()) [[]] の直後は } 等が来ても良い。

と表示される。
* ble palette
https://superuser.com/a/1512656/980046 コメント

色の排列を考え直す余地はある。現在は横幅 64 使っている。高さが 32 なのは実
は端末の 80x24 には入り切らない。

2023-02-06

Expand Down Expand Up @@ -6671,6 +6682,86 @@ bash_tips

2023-02-12

* syntax: 履歴展開 & "$!", heredoc [#D1960]

bash-4.1 以下で echo "$!" を実行しようとしても履歴展開周りで変な事が起こっ
てコマンドを実行する事ができない。更に bash-3.0 では

bash-3.0: ble/history:bash/resolve-multiline: そのようなファイルやディレクトリはありません

と表示される。

また暫くして実行してみた所違う失敗の仕方をする。どうも本当に履歴展開が起こっ
ている様だ。--norc で実行しても履歴展開が起こって変な事になってしまっている。
つまり、これは ble.sh 自体の問題ではないという事。

a ble.sh の側で履歴展開があるかどうかの判定を行って、履歴展開文字が存在しな
い時には履歴展開をそもそも試みないという可能性?

然しそれだと普通の履歴展開と "$!" が混在している場合には結局履歴展開を実
行することになるので、問題を回避できていない。それに元々の bash の振る舞
いとして履歴展開が起こる筈なのにそれを無理やり回避するのは間違っている気
がする。

b 或いは履歴展開の文法解釈を弄る。というかその様に対応するべきである。そう
すれば混乱もないだろう。

→b の方針で修正する事にする。

* fixed: というか調べてみるとどうやら 4.2 でも "echo!" 等で展開は実施される
様である。これについては対応した。

* fixed: 4.1 以下での $!... の展開

然し今回問題になっているのは 4.1 以下では $! の ! であっても履歴展開を誘
導してしまうという事である。これを文法的に正しく処理するのは難しい。とい
うか、$! に続いて何か文字列があると必ず展開されてしまうという事になる。こ
の振る舞いは困る。もう少し色々試してみる事にする。

$ echo $!a

も履歴展開されてしまう。${!} は展開されない。つまり $! に丁度一致する時に、
$! に引き続き履歴展開がある場合には履歴展開とするという事。

これに対応する為には check-dollar の中で $! に一致した時に 4.1 以下で特別
に check-history-expansion を呼び出す必要がある。所で histchar も考えると
単に '$!' だけ確認すれば良い訳では無い。

因みに check-dollar が有効な文脈は全て履歴展開も有効の様なので、
check-dollar の中で履歴展開を試みるかどうかについて追加の条件で判定を行う
必要はない。

→実装した。取り敢えず実際の bash の振る舞いと同じになる様に履歴展開の着
色がされる様になった。

* fixed: 履歴展開 in heredoc

履歴展開の着色がされていない。また、\\ \$ 等の着色もされていない。但し、
\a 等の元よりエスケープする必要のなかった物についてはエスケープとしては処
理されない。\" もエスケープとしては処理されない。\<LF> はエスケープとして
認識される。\! は unquote されないが履歴展開を抑制する効果はある。

* heredoc 内での \\ \$ \` \<LF> エスケープの着色に対応した
* heredoc 内での履歴展開の着色に対応した

* fixed: 3.0 での ble/history:bash/resolve-multiline のエラーメッセージは依
然として表示される。

どうやら bash-3.0 では resolve-multiline は有効になっていないのに、その外
側で resolve-multiline を呼び出している箇所が2箇所ある。それぞれに対応す
る (mutiline サポートなしの) 実装を提供する事にした。とは言っても
multiline サポートなしなので両方ともほぼ自明な操作である。

* fixed: histreedit は二回連続だと accept するべきなのでは? 4.1 で展開に失
敗する時何度でも失敗する。と思ったが、寧ろ 3.0 で二回連続で実行した時に実
際に実行された方が問題であった。plain Bash だと histreedit だと何回実行し
ようとしても実行できない。

代わりにエラーメッセージが表示される。というか何故エラーメッセージが表示
されていない? in ble.sh → 分かった。ble/widget/.internal-print-command
が $command を被覆している所為でちゃんとエラーメッセージの起こる履歴展開
を評価できていなかった。

* [棄却] histdb: コマンドも histdb-word と同様に数えて良いのではないか? [#D1959]

これは quote 等を除去した状態で数えるのが良い? それとも quote も含めて記録
Expand Down
8 changes: 4 additions & 4 deletions src/edit.sh
Expand Up @@ -10063,12 +10063,12 @@ function ble-decode/EPILOGUE {
}

function ble/widget/.internal-print-command {
local command=$1 opts=$2
local _ble_local_command=$1 _ble_command_opts=$2
_ble_edit_line_disabled=1 ble/widget/.insert-newline # #D1800 pair=leave-command-layout
[[ :$opts: != *:pre-flush:* ]] || ble/util/buffer.flush >&2
BASH_COMMAND=$command builtin eval -- "$command"
[[ :$_ble_command_opts: != *:pre-flush:* ]] || ble/util/buffer.flush >&2
BASH_COMMAND=$_ble_local_command builtin eval -- "$_ble_local_command"
ble/edit/leave-command-layout # #D1800 pair=.insert-newline
[[ :$opts: != *:post-flush:* ]] || ble/util/buffer.flush >&2
[[ :$_ble_command_opts: != *:post-flush:* ]] || ble/util/buffer.flush >&2
}

function ble/widget/print {
Expand Down
3 changes: 3 additions & 0 deletions src/history.sh
Expand Up @@ -837,6 +837,9 @@ if ((_ble_bash>=30100)); then
source "$TMPBASE.part"
ble/history:bash/resolve-multiline/.cleanup
}
else
function ble/history:bash/resolve-multiline/readfile { builtin history -r "$filename"; }
function ble/history:bash/resolve-multiline { ((1)); }
fi

# Note: 複数行コマンドは eval -- $'' の形に変換して
Expand Down

0 comments on commit e619e73

Please sign in to comment.