Skip to content

Commit

Permalink
prompt: support "bleopt prompt_ruler"
Browse files Browse the repository at this point in the history
  • Loading branch information
akinomyoga committed Oct 4, 2021
1 parent a3047f5 commit 05cf638
Show file tree
Hide file tree
Showing 6 changed files with 425 additions and 25 deletions.
13 changes: 13 additions & 0 deletions blerc
Expand Up @@ -179,6 +179,19 @@
#bleopt prompt_eol_mark=$'\e[94m[ble: EOF]\e[m'


## "prompt_ruler" specifies the ruler between the previous command and the
## prompt (like powerlevel10k
## "POWERLEVEL9K_PROMPT_{ADD_NEWLINE,SHOW_RULER,RULER_*}"). When the empty
## value is specified, the ruler is disabled. This is the default. When the
## value "empty-line" is specified, an empty line is inserted between the
## command and the prompt. When the other values are specified, the value is
## interpreted as an ANSI sequences, and the result is repeated to fill a line.

#bleopt prompt_ruler= # no ruler (default)
#bleopt prompt_ruler=empty-line # empty line
#bleopt prompt_ruler=$'\e[94m-' # blue line


## "exec_errexit_mark" specifies the format of the mark to show the exit status
## of the command when it is non-zero. If this setting is an empty string the
## exit status will not be shown. The value can contain ANSI escape sequences.
Expand Down
1 change: 1 addition & 0 deletions docs/ChangeLog.md
Expand Up @@ -71,6 +71,7 @@
- edit: support bash-5.2 `READLINE_ARGUMENT` `#D1638` d347fb3
- complete: support `complete [-DI]` in old versions of Bash through `_DefaultCmD_` and `_InitialWorD_` `#D1639` 925b2cd
- rlfunc: support nsearch widgets in `vi_nmap` keymap (requested by cornfeedhobo) `#D1651` 9a7c8b1
- prompt: support `bleopt prompt_ruler` `#D1666` 0000000

## Changes

Expand Down
176 changes: 176 additions & 0 deletions memo/D1665.bashrc2
@@ -0,0 +1,176 @@
# -*- mode: sh-bash -*-

type=fix3b

if [[ $type == rep-c2w-auto-fail ]]; then
source out/ble.sh --norc

getCPos() {
local v=() t=$(stty -g)
stty -echo
printf "\033[6n"
IFS='[;' read -ra v -d R
stty $t
CPos=(${v[@]:1})
}

custom_prompt() {
getCPos
if [ $CPos -eq 1 ]; then
PS1=""
else
PS1="\n"
fi
}
PROMPT_COMMAND=custom_prompt

ble-attach
fi

#------------------------------------------------------------------------------

if [[ $type == rep-c2w-auto-fail-min ]]; then
source out/ble.sh --norc
getCPos() {
local v=() t=$(stty -g)
stty -echo
printf "\033[6n"
IFS='[;' read -ra v -d R
stty $t
CPos=(${v[@]:1})
}
PROMPT_COMMAND=getCPos
fi

#------------------------------------------------------------------------------

if [[ $type == fix-exclude-blesh ]]; then
custom_prompt() {
cmd_cde=$?
window_title
if ! ble 2>/dev/null; then
getCPos
if [ $CPos -eq 1 ]; then
PS1=""
else
PS1="\n"
fi
fi
PS1+="\[$(tput setaf 1)\]┏━"
}

source out/ble.sh --norc
getCPos() {
if [[ ! ${_ble_attached-} ]]; then
#if ! ble 2>/dev/null; then
local v=() t=$(stty -g)
stty -echo
printf "\033[6n"
IFS='[;' read -ra v -d R
stty $t
CPos=(${v[@]:1})
fi
}
PROMPT_COMMAND=getCPos
fi

#------------------------------------------------------------------------------
# 修正案2

if [[ $type == fix2 ]]; then
source out/ble.sh --norc
custom_prompt() {
printf -v PS1 $'\[ \b\e[%dC %s\r\]' $((COLUMNS-2)) "$(tput xenl && echo ' ')"
PS1+='hello\$ '
}
PROMPT_COMMAND=custom_prompt
fi

if [[ $type == fix3 ]]; then
source out/ble.sh --norc

getCPos() {
local v=() t=$(stty -g)
stty -echo
printf "\033[6n"
IFS='[;' read -ra v -d R
stty $t
CPos=(${v[@]:1})
}

if [[ ${BLE_VERSION-} ]]; then
ble/function#advice after ble/widget/clear-screen '_ble_edit_lineno=0'
_check_clear_command() {
local rex_eval_prefix='((eval|command|env|sudo)[[:space:]]+)?'
local rex_clear_command='(tput[[:space:]]+)?(clear|reset)'
local rex=$'(^|[\n;&|(])[[:space:]]*'$rex_eval_prefix$rex_clear_command'([ \t\n;&|)]|$)'
[[ $BASH_COMMAND =~ $rex ]] && _ble_edit_lineno=0
}
blehook POSTEXEC+=_check_clear_command
fi

custom_prompt() {
if
if [[ $_ble_attached ]]; then
((_ble_edit_lineno==0))
else
getCPos; [ $CPos -eq 1 ]
fi
then
PS1=""
else
PS1="\n"
fi
PS1+='hello\$ '
}
PROMPT_COMMAND=custom_prompt
fi

if [[ $type == fix3b ]]; then
source out/ble.sh --norc

getCPos() {
local v=() t=$(stty -g)
stty -echo
printf "\033[6n"
IFS='[;' read -ra v -d R
stty $t
CPos=(${v[@]:1})
}

if [[ ${BLE_VERSION-} ]]; then
CPos=(1 1)
blehook POSTEXEC+=getCPos
fi

custom_prompt() {
if [[ ! ${_ble_attached-} ]]; then
getCPos
fi
if [ $CPos -eq 1 ]; then
PS1=""
else
PS1="\n"
fi
PS1+='hello\$ '
}
PROMPT_COMMAND=custom_prompt
fi

#------------------------------------------------------------------------------
# minimal reproducer for absorbed characters

if [[ $type == rep-absorb-chars ]]; then
getCPos() {
local v=() t=$(stty -g)
stty -echo
printf "\033[6n"
IFS='[;' read -ra v -d R
stty $t
CPos=(${v[@]:1})
}
#PROMPT_COMMAND=getCPos

something_slow() { sleep 2; }
something_slow
fi
22 changes: 22 additions & 0 deletions memo/D1665.bashrc3
@@ -0,0 +1,22 @@
# -*- mode: sh; mode: sh-bash -*-

# urxvt で C-l した直後に bash が 1-2 秒程 100% になって反応しなくなる
# 問題。

source out/ble.sh --norc
#PS1=$'\[\e[38;5;1m\]┏━[\e[38;5;7m\]\w\[\e[38;5;1m\]]\n\[\e[38;5;1m\]┗━━ \[\e[38;5;8m\]■ \[\e[38;5;7m\]'
#PS1=$'\[\e[38;5;1m\]┏━[\[\e[38;5;7m\]\w\[\e[38;5;1m\]]\n\[\e[38;5;1m\]┗━━ \[\e[38;5;8m\]■ \[\e[38;5;7m\]'
#PS1=$'┏━[\w]\n┗━━ ■ ' # ok
#PS1=$'\e[38;5;1m@\e[38;5;7m@\e[38;5;1m]@\e[38;5;1m@\e[38;5;8m@\e[38;5;7m'
#PS1=$'\e[38;5;1m@\e[38;5;1m@\e[38;5;1m@\e[38;5;1m@\e[38;5;1m@\e[38;5;1m' # NG
#PS1=$'\e[31m@\e[31m@\e[31m@\e[31m@\e[31m@\e[31m' # NG
#PS1=$'\e[31m\e[31m\e[31m\e[31m\e[31m\e[31mA ' # NG
#PS1=$'\e[1m\e[1m\e[1m\e[1m\e[1m\e[1mA ' # OK

# これで再現する??? と思ったら再現しなくなった。改めて urxvt を起動し
# 直して試したら再現しなくなってしまった。何らかの urxvt の設定と関係
# があるのだろうか。例えば C-l をすると何か大量のデータを送ってくる等?
# 然し、そうだとすると PS1 に関係なく発生しそうだし、着色の SGR を出力
# する時にだけ問題が発生するというのも変である。

PS1=$'\e[31mA ' # NG
152 changes: 143 additions & 9 deletions note.txt
Expand Up @@ -1827,15 +1827,6 @@ bash_tips
そもそも desc の内容自体その場に表示するのではなくて preview 的な小さな窓の中に
選択した時にだけ表示するという形式でも良いのではないかという気がする。

* canvas: Void Linux で文字幅計算がずれる (reported by Barbarossa93)
https://github.com/akinomyoga/ble.sh/issues/135

と思ったがそもそもキャッシュしていない様に見える。という事は何を意味するの
か。うーん。prompt 計算のキャッシュが残っているという事だろうか。そんな気が
する。試してみる事にする。→プロンプトの trace_hash に char_width_mode も入
れて置く事にした。char_width_mode=west にしても前の設定が残っている問題は解
決した。

2021-09-02

* 改めて確認した所また Windows Terminal で動かなくなっている
Expand Down Expand Up @@ -5397,6 +5388,149 @@ bash_tips

2021-09-27

* edit: powerlevel10k の prompt_add_newline を実装する (motivated by Barbarossa93) [#D1666]
https://github.com/akinomyoga/ble.sh/issues/135#issuecomment-927284636

prompt_ruler='empty-line'
prompt_ruler='-'
prompt_ruler=$'\e[38;5;242m-'
prompt_ruler='---='

等に対応する。これは実はそんなに難しくないかもしれない。対応した。

対応する powerlevel10k に於ける設定名は以下の通り

POWERLEVEL9K_PROMPT_ADD_NEWLINE=true/false
POWERLEVEL9K_SHOW_RULER=true/false
POWERLEVEL9K_RULER_CHAR=-
POWERLEVEL9K_RULER_FOREGROUND=242

ble.sh では prompt_ruler に ANSI seq を指定できる様にしたので色も一つの変数
で済む。

* [外部 bashrc] Void Linux で文字幅計算がずれる (reported by Barbarossa93) [#D1665]
https://github.com/akinomyoga/ble.sh/issues/135

と思ったがそもそもキャッシュしていない様に見える。という事は何を意味するの
か。うーん。prompt 計算のキャッシュが残っているという事だろうか。そんな気が
する。試してみる事にする。→プロンプトの trace_hash に char_width_mode も入
れて置く事にした。char_width_mode=west にしても前の設定が残っている問題は解
決した。

* 2021-09-26 これは結局 Barbarossa93 の設定に含まれる getCPos で printf
DSR(6) & read CPR していたのが原因だった。この為に ble.sh の遅延処理して
いる CPR の処理と getCPos の CPR の処理が入れ替わって双方で誤った結果を生
み出しているというのが原因であった。

更に、もう一つの報告された問題である入力した文字列が失われるという問題に
ついても、この getCPos が CPR 待ちで読み取っているが為に起こっている問題
であった。この問題は ble.sh をロードしなくても、単に bashrc で時間がかか
るだけで再現するという事が分かった。

* 2021-09-26 PROMPT_COMMAND の中でこの様な事をしても大丈夫な様に対策する?

そもそも技術的に可能なのか分からない。

a PROMPT_COMMAND の呼び出し前の段階でユーザー入力があるかどうかを確認して、
もしユーザー入力があるのであれば一旦その時点で抜けるという事が必要にな
る気がする。然し、現時点で既にその様な実装になっている様な気もする。こ
れは全然対策になっていない。

つまり、textarea#render に入る直前までに返答が返ってくれば処理もできる
が、そうでなければ PROMPT_COMMAND の中で stdin を読み取ろうとした時に、
返答が来るまで待って其処で CPR が読み取られてしまうという事になる。

うーん。やはりこれに対する対策は原理的に困難である様な気がする。

b 或いは、terminal-test.buff を sync (timeout 付き) で処理する可能性もある。

然し、端末が CPR に対応していない時に固まってしまう。

timeout を入れたとしてもその分遅延が生じる事になる。ble.sh では初期化の
遅延を可能な限り減らそうとしているので 50ms でも待つ等という事はしたく
ない。それに timeout した時に、それよりもずっと後になって返答が返って来
た時にまた問題が生じるかもしれないので、timeout はもっと長く設定しなけ
ればならない気がする。もしくは、timeout してしまったら何らかのエラーと
して処理を中断するというのが普通のシェルプログラムの動作として望ましい
が、対話セッションの時にはセッションを抜けるという訳にも行かない。

もし本当に位置を特定したいのであれば、やはり ble.sh の様に非同期で処理
する事が必要で、その為には line editor の event loop に登録するしかない。
ble.sh ではその為の枠組を用意しているので、本当にそういった処理を実施し
たいのであれば、ble.sh の枠組みを経由でカーソル位置を取得してもらうしか
ない。readline に至っては robust な方法はない様な気がする。一応、
readline の動作は高速なので変な遅延が生じる可能性は少ないし、そもそも
readline が返答を必要とする様な要求を出さないので問題が起こる事は余りな
いのだろう。

結局技術的に考えても困難であるし、これの対策はしない事にする。

対策しないとするとどれだけの範囲で問題が生じるか調べておく必要がある。

https://github.com/search?q=filename%3Abashrc+getcpos
https://github.com/Barbarossa93/Muspelheim/blob/c9ea8ffd83ab5c85da47b5c36f39b3ec97b96230/.config/bash/bashrc

検索すると以上の様に報告者の bashrc しか見つからないので、この getCPos を
bashrc の中で使うという手法は報告者独自のものであると推察される。なので、
そんなに多くの設定で使われている物という訳でもないのだろうという気がする。
うーん。以下で検索すると PROOMPT_COMMAND で CPR を取得するのは実は沢山存
在している様だ。

https://github.com/search?q=filename%3Abashrc+PROMPT_COMMAND+%22%5B6n%22
https://github.com/ScoreUnder/scripts-and-dotfiles/blob/f69f2f11739342a7c46fb38a9be2f5a5c803a438/dotfiles/.bashrc.m4
https://github.com/safocl/safocl_profiles/blob/31ce40e9ff4619d1099c4f95c1f717e8a9b389fb/.bashrc

* [再現不可] urxvt: C-l をした直後に何故か反応が遅くなる

C-l の直後以外では問題はない様に見える。うーん。もしかすると C-l の直後以外
ではプロンプトの更新がされていない? 単にプロンプトの計算に時間がかかってい
るという事?

以下の PS1 で再現する

PS1=$'\[\e[38;5;1m\]┏━[\e[38;5;7m\]\w\[\e[38;5;1m\]]\n\[\e[38;5;1m\]┗━━ \[\e[38;5;8m\]■ \[\e[38;5;7m\]'

というか更に以下の PS1 でも再現する

PS1=$'\e[31mA '

うーん。これは結局再現する事はできなかった。改めて urxvt で提供された
bashrc を実行してみたがそれでも駄目だった。何か urxvt か或いは別の設定が
壊れていたのかもしれない。

* 2021-09-26 workaround を提示したら思っている動作と異なるとの報告が来た。
改めて見てみると、元のコードでしたのは「一番左にいなかったら改行を追加す
る」ではなくて「一番上にいなかったら改行を追加する」という物だった。

少し考えてみたがよく分からない。困難の気がする。powerlevel10k にその機能
があるというので p10k を 6n で検索してみたが、特にその様な文字列は含まれ
ていない様だ。或いは、powerlevel10k はまた異なる手法を用いているのかもし
れない。どうやら

POWERLEVEL9K_PROMPT_ADD_NEWLINE

というのが該当する設定の様である。うーん。これを使っている所を調べると

[[ $P9K_TTY == old ]] && { unset _p9k__empty_line_i; _p9k__display_v[2]=print }

というのを設定している。P9K_TTY は preexec で old に設定されている。

if [[ $_p9k__preexec_cmd == [[:space:]]#(clear([[:space:]]##-(|x)(|T[a-zA-Z0-9-_\'\"]#))#|reset)[[:space:]]# &&
$_p9k__status == 0 ]]; then
P9K_TTY=new
elif [[ $P9K_TTY == new && $_p9k__fully_initialized == 1 ]] && ! zle; then
P9K_TTY=old
fi

if [[ $1 == (clear-screen|z4h-clear-screen-*-top) ]]; then
P9K_TTY=new
_p9k__expanded=0
_p9k_reset_prompt
fi

うーん。これを見ると powerlevel10k は単に直前のコマンドを見ている様だ。具
体的に座標を抽出している訳ではない様だ。これなら実装できなくもないが…。

* canvas: 文字幅判定の為の CPR は internal 状態で実行したい [#D1664]

CPR が画面に出力されてしまうのは stty echo の時に DSR(6) が出力されるから。
Expand Down

0 comments on commit 05cf638

Please sign in to comment.