diff --git a/keymap/vi.sh b/keymap/vi.sh
index 2d7a6162..22c4eabe 100644
--- a/keymap/vi.sh
+++ b/keymap/vi.sh
@@ -342,6 +342,44 @@ bleopt/declare -v keymap_vi_mode_name_select 'SELECT'
bleopt/declare -v keymap_vi_mode_name_linewise 'LINE'
bleopt/declare -v keymap_vi_mode_name_blockwise 'BLOCK'
+## @fn ble/keymap:vi/script/get-mode
+## @var[out] mode
+function ble/keymap:vi/script/get-mode {
+ mode=
+
+ local kmap=$_ble_decode_keymap
+ [[ $kmap == auto_complete ]] && kmap=vi_imap
+
+ # /[iR^R]?/
+ if [[ $_ble_keymap_vi_single_command || $kmap == vi_imap ]]; then
+ local overwrite=
+ if [[ $kmap == vi_imap ]]; then
+ overwrite=$_ble_edit_overwrite_mode
+ elif [[ $kmap == vi_[noxs]map ]]; then
+ overwrite=$_ble_keymap_vi_single_command_overwrite
+ fi
+ case $overwrite in
+ ('') mode=i ;;
+ (R) mode=R ;;
+ (*) mode=$'\x12' ;; # C-r
+ esac
+ fi
+
+ # /[nvV^VsS^S]?/
+ case $kmap:${_ble_edit_mark_active%+} in
+ (vi_xmap:vi_line) mode=$mode'v' ;;
+ (vi_xmap:vi_block)mode=$mode'V' ;;
+ (vi_xmap:*) mode=$mode$'\x16' ;; # C-v
+ (vi_smap:vi_line) mode=$mode's' ;;
+ (vi_smap:vi_block)mode=$mode'S' ;;
+ (vi_smap:*) mode=$mode$'\x13' ;; # C-s
+ (vi_[no]map:*) mode=$mode'n' ;;
+ (vi_cmap:*) mode=$mode'c' ;;
+ (vi_imap:*) ;;
+ (*:*) mode=$mode'?' ;;
+ esac
+}
+
function ble/keymap:vi/update-mode-name {
local kmap=$_ble_decode_keymap cursor=
if [[ $kmap == vi_imap ]]; then
diff --git a/memo/ChangeLog.md b/memo/ChangeLog.md
index 2d35c42f..23217b5c 100644
--- a/memo/ChangeLog.md
+++ b/memo/ChangeLog.md
@@ -17,6 +17,7 @@
- prompt: support `bleopt prompt_status_{line,align}` and `face prompt_status_line` `#D1462` cca1cbc
- prompt: fix missing height allocation for status line `#D1487` 0000000
- syntax: properly support case patterns `#D1474` `#D1475` `#D1476` 64b55b7
+- keymap/vi: add `ble/keymap:vi/script/get-mode` for user-defined mode strings `#D1488` 0000000
## Changes
diff --git a/memo/D1488.show-mode-line.v1.bashrc b/memo/D1488.show-mode-line.v1.bashrc
new file mode 100644
index 00000000..0b73c3ab
--- /dev/null
+++ b/memo/D1488.show-mode-line.v1.bashrc
@@ -0,0 +1,9 @@
+# bashrc
+
+set -o vi
+bind 'set show-mode-in-prompt on'
+bind $'set vi-cmd-mode-string \eD\eM\e7\e[9999B\r\e[K\e[1m~\e[m\e8'
+bind $'set vi-ins-mode-string \eD\eM\e7\e[9999B\r\e[K\e[1m-- INSERT --\e[m\e8'
+PS0=$'\e7\eD\eM\e[9999B\e[2K\e8'
+
+bind '"\C-l": clear-screen'
diff --git a/memo/D1488.show-mode-line.v2.bashrc b/memo/D1488.show-mode-line.v2.bashrc
new file mode 100644
index 00000000..2dc0548c
--- /dev/null
+++ b/memo/D1488.show-mode-line.v2.bashrc
@@ -0,0 +1,17 @@
+# -*- mode: sh; mode: sh-bash -*-
+
+set -o vi
+bind '"\C-l": clear-screen'
+
+# bind 'set show-mode-in-prompt on'
+# bind $'set vi-cmd-mode-string \1\eD\eM\e7\e[9999B\r\e[K\e[1m~\e[m\e8\2'
+# bind $'set vi-ins-mode-string \1\eD\eM\e7\e[9999B\r\e[K\e[1m-- INSERT --\e[m\e8\2'
+# PS0=$'\1\e7\e[9999B\e[2K\e8\2'
+
+CMD='\e[1m~\e[m'
+INSERT='\e[1m-- INSERT --\e[m'
+bind 'set show-mode-in-prompt on'
+bind $"set vi-cmd-mode-string \1\eD\eM\e7\e[9999B\r\e[K\e[1m$CMD\e[m\e8\2"
+bind $"set vi-ins-mode-string \1\eD\eM\e7\e[9999B\r\e[K\e[1m$INSERT\e[m\e8\2"
+PS0=$'\1\e7\e[9999B\e[2K\e8\2'
+#PS4=$'\1\e7\eD\eM\e[9999B\e[2K\e8\2'
diff --git a/memo/D1488.vim-mode-in-status.bash b/memo/D1488.vim-mode-in-status.bash
new file mode 100644
index 00000000..904350ca
--- /dev/null
+++ b/memo/D1488.vim-mode-in-status.bash
@@ -0,0 +1,38 @@
+#!/bin/bash
+
+function 0neGal/set-up-status-line {
+
+ # Hide the normal mode name
+ bleopt keymap_vi_mode_show=
+
+ function ble/prompt/backslash:0neGal/currentmode {
+ bleopt keymap_vi_mode_update_prompt=1
+
+ local mode; ble/keymap:vi/script/get-mode
+ case $mode in
+ (*n) ble/prompt/print $'\e[1m-- NORMAL --\e[m' ;;
+ (*v) ble/prompt/print $'\e[1m-- VISUAL --\e[m' ;;
+ (*V) ble/prompt/print $'\e[1m-- V-LINE --\e[m' ;;
+ (*) ble/prompt/print $'\e[1m-- V-BLOQ --\e[m' ;;
+ (*s) ble/prompt/print $'\e[1m-- SELECT --\e[m' ;;
+ (*S) ble/prompt/print $'\e[1m-- S-LINE --\e[m' ;;
+ (*) ble/prompt/print $'\e[1m-- S-BLOQ --\e[m' ;;
+ (i) ble/prompt/print $'\e[1m-- INSERT --\e[m' ;;
+ (R) ble/prompt/print $'\e[1m-- RPLACE --\e[m' ;;
+ () ble/prompt/print $'\e[1m-- VPLACE --\e[m' ;;
+ (*) ble/prompt/print $'\e[1m-- ?????? --\e[m' ;;
+ esac
+
+ # Change the default color of status line
+ case $mode in
+ (*n) ble-color-setface prompt_status_line bg=gray,fg=white ;;
+ (*[vVsS]) ble-color-setface prompt_status_line bg=teal,fg=white ;;
+ (*[iR]) ble-color-setface prompt_status_line bg=navy,fg=white ;;
+ (*) ble-color-setface prompt_status_line bg=240,fg=231 ;;
+ esac
+ }
+
+ bleopt prompt_status_line='\q{0neGal/currentmode}'
+
+}
+blehook/eval-after-load keymap_vi 0neGal/set-up-status-line
diff --git a/memo/D1488.vimrc b/memo/D1488.vimrc
new file mode 100644
index 00000000..a768aee1
--- /dev/null
+++ b/memo/D1488.vimrc
@@ -0,0 +1,29 @@
+" Tests for statusline mode-strings
+
+"set noshowmode " This hides the normal mode line
+set laststatus=2 " Enables the statusline
+
+" Names for each mode (used for the statusbar)
+let g:currentmode={
+ \ 'n' : '-- NORMAL --',
+ \ 'v' : '-- VISUAL --',
+ \ 'V' : '-- V-LINE --',
+ \ '' : '-- V-BLOQ --',
+ \ 'i' : '-- INSERT --',
+ \ 'ic' : '-- INSERT --',
+ \ 'ix' : '-- INSERT --',
+ \ 'R' : '-- RPLACE --',
+ \ 'Rv' : '-- VPLACE --',
+ \ 'c' : '-- PROMPT --',
+ \ '!' : '-- !SHELL --',
+ \ 't' : '-- TSHELL --',
+ \ 'r' : '-- PROMPT --',
+ \ 'r?' : '-- ACCEPT --',
+ \}
+
+" Sets the statusline
+set statusline=%{mode()}
+"%{g:currentmode[mode()]}
+
+" And unless you wanna go insane when going between modes I recommend this
+set ttimeoutlen=0 " Which eliminates the annoying delay when switching modes (This is only for normal Vim)
diff --git a/note.txt b/note.txt
index 9301f745..3f19227f 100644
--- a/note.txt
+++ b/note.txt
@@ -3746,6 +3746,53 @@ bash_tips
2021-02-22
+ * keymap/vi: vim mode strings の設定をもっと柔軟にできる様にする (motivated by 0neGal) [#D1488]
+ https://github.com/akinomyoga/ble.sh/issues/85
+
+ Note: 0neGuyDev は名前が 0neGal に変化した様だ。
+
+ * done: wiki vim のページ hook の説明で := の : が余分。
+ * done: wiki vim の設定のページで全ての項目に注意書きを書く。
+
+ 何れにしても Cygwin での IL/DL の問題 (#D1482) に取り敢えずの決着をつけてから。
+ →IL/DL の問題を解決したが未だ status line の問題 (#D1487) は残っていた。
+ その後 status line の問題も解決した。
+
+ どうやら Vim では mode() を用いて現在のモードを表現する文字列を取得する事が
+ できるらしい。然し、mode() だけでは表しきれない情報も存在する様である。取り
+ 敢えず似た関数を用意さえすれば既存の枠組みを使って mode を status ilne に表
+ 示する事ができるのではないか。
+
+ | Mode | `mode()` |
+ |:----------------------------------------------------------------------------------------------|:---------|
+ | INSERT | i |
+ | REPLACE
VREPLACE | R |
+ | NORMAL
(insert)
(replace)
(vreplace) | n |
+ | VISUAL
(insert) VISUAL
(replace) VISUAL
(vreplace) VISUAL | v |
+ | VISUAL LINE
(insert) VISUAL LINE
(replace) VISUAL LINE
(vreplace) VISUAL LINE | V |
+ | VISUAL BLOCK
(insert) VISUAL BLOCK
(replace) VISUAL BLOCK
(vreplace) VISUAL BLOCK | ^V |
+ | SELECT
(insert) SELECT
(replace) SELECT
(vreplace) SELECT | s |
+ | SELECT LINE
(insert) SELECT LINE
(replace) SELECT LINE
(vreplace) SELECT LINE | S |
+ | SELECT BLOCK
(insert) SELECT BLOCK
(replace) SELECT BLOCK
(vreplace) SELECT BLOCK | ^S |
+
+ これらは基本的にはそのモードに入る為に使うコマンドが使われる。
+ 然し、normal の n や select の s は名前から来ている。
+
+ これに倣えば。拡張するとしたら VREPLACE は gR になるだろうか。
+ insert, replace, vreplace は それぞれ i^O R^O gR^O になる。
+ でもどうせ組み合わせるのであれば、実の所 ^O は必要ないのではないか。
+
+ つまり、/(i|R|gR)?(n|v|V|^V|s|S|^S)?/ - ε (4x8-1=32-1=31種) という事になる。
+
+ うーん。サンプルを見ると Rv というのが存在しているが実際に試してみると R に
+ なっている。何故だろうか。後、やはり gR というのは都合が悪い気がする。
+ vreplace の文字はまた別に考えたい。小文字の r を考えたがどうやら既に PROMPT
+ というのの為に使われている様だ。だとすると ^R という事になるだろうか。うー
+ ん。取り敢えず ^R という事にする。そもそも制御文字を使うとうのが良い事なの
+ か微妙だが。RSTUV で何れも近い値というのも比較的良い事の気がする。
+
+ * テストに用いた vimrc を移動する。
+
* edit: prompt_status_line の表示が崩れる [#D1487]
| prompt_status_line を試しに組み合わせて見たら表示がおかしくなっている。うー
diff --git a/src/canvas.sh b/src/canvas.sh
index 82352879..8e7f0035 100644
--- a/src/canvas.sh
+++ b/src/canvas.sh
@@ -615,8 +615,9 @@ function ble/canvas/put-clear-lines.draw {
## ANSI制御シーケンスではなく現在の端末のシーケンスとして
## 制御機能SGRを解釈します。
##
-## g0
-## 背景色・既定属性として用いる属性値を指定します。
+## g0 face0
+## 背景色・既定属性として用いる属性値または描画設定を指定します。
+## 両方指定された場合は g0 を優先させます。
##
## @var[in,out] DRAW_BUFF[]
## ble/canvas/trace.draw の出力先の配列です。
@@ -961,6 +962,10 @@ function ble/canvas/trace/.impl {
local opt_g0= opt_sgr0=$_ble_term_sgr0
if rex=':g0=([^:]+):'; [[ :$opts: =~ $rex ]]; then
opt_g0=${BASH_REMATCH[1]}
+ elif rex=':face0=([^:]+):'; [[ :$opts: =~ $rex ]]; then
+ ble/color/face2g "${BASH_REMATCH[1]}"; opt_g0=$ret
+ fi
+ if [[ $opt_g0 ]]; then
ble/color/g2sgr "$opt_g0"; opt_sgr0=$ret
ble/canvas/put.draw "$opt_sgr0"
fi
diff --git a/src/edit.sh b/src/edit.sh
index 1a3d16d8..71010b5b 100644
--- a/src/edit.sh
+++ b/src/edit.sh
@@ -1021,11 +1021,9 @@ function ble/prompt/update {
# bleopt prompt_status_line
if [[ $bleopt_prompt_status_line ]]; then
- ble/color/face2g prompt_status_line; local g0=$ret
-
local ps=$bleopt_prompt_status_line
local cols=$COLUMNS; ((_ble_term_xenl||cols--))
- local trace_opts=confine:relative:measure-bbox:noscrc:g0=$g0
+ local trace_opts=confine:relative:measure-bbox:noscrc:face0=prompt_status_line
local trace_hash esc x y g lc lg
local x1=${_ble_prompt_status_bbox[0]}
@@ -1038,6 +1036,7 @@ function ble/prompt/update {
local -a DRAW_BUFF=()
# background color
+ ble/color/face2g prompt_status_line; local g0=$ret
if ((g0)); then
ble/color/g2sgr "$g0"; local sgr=$ret
if ((_ble_term_bce)); then