質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Vim

VimとはUnix / Linux 系のOSに標準搭載されているターミナル上で動くテキストエディタです。

Q&A

0回答

312閲覧

特定のキーを押下することで、カーソル前の文字を切り替えたい

Nojob

総合スコア2

Vim

VimとはUnix / Linux 系のOSに標準搭載されているターミナル上で動くテキストエディタです。

0グッド

1クリップ

投稿2019/08/17 17:51

実現したいこと

Vim のスクリプトに関する質問です。
現在、下記の様に、特定のキーを押すと、カーソルより一つ前の文字が切り替わるプラグインを作成しています。
(下記例では、「A」を押下することで、A->B->C->D->E->A->B->...と、切り替わります。)
イメージ説明

現状、シングルバイト->シングルバイト、マルチバイト->マルチバイトの切り替えはうまく動いているのですが、
カーソルが行末(or 行末より一つ前) にある時においてのみ、マルチバイト->シングルバイトの切り替えが
うまくいきません。(下記の様にカーソルの位置がずれてしまいます。)
イメージ説明

これをどんな場合でも、連続した切り替えを成功させる方法をご教示いただけないでしょうか。

試したこと

問題の切り分けを行った結果、行末のマルチバイト文字の後ろにカーソルがある場合、
col('.')の値が以下の例の様になることがわかりました。

例)
| = インサートモードにおけるカーソル位置

Aあ|AA の場合 col('.')=> 4
Aあ|A の場合 col('.')=> 3
Aあ| の場合 col('.')=> 2
※文字コードを utf-8 なので、日本語一文字が 3byte になっています。

該当のソースコード

Vim

1"マッピングするためのメイン関数" 2function! SwitchChar(switch_list,key) 3 "引数が辞書型以外の場合に却下" 4 if type(a:switch_list) != type([]) 5 finish "Argument requires List type!" 6 endif 7 8 let cnt_chr= GetCurrentChar() 9 if SearchList(a:switch_list, cnt_chr) < 0 10 return a:key 11 endif 12 13 call SingleSwitch(cnt_chr, a:switch_list) 14 return '' 15endfunction 16 17 18"現在の文字が切り替え対象の文字かをチェック" 19function! SearchList(switch_list, chr) 20 for item in a:switch_list 21 if item ==# a:chr 22 return match(a:switch_list, a:chr) 23 endif 24 endfor 25 return -1 26endfunction 27 28 29function! GetCurrentChar() 30 if col('.') == 1 31 return '\0' 32 endif 33 34 return matchstr(strpart(getline('.'), 0, col('.')-1), ".$") 35endfunction 36 37 38function! SingleSwitch(cnt_chr, switch_list) 39 let next_chr = a:switch_list[(match(a:switch_list, a:cnt_chr)+1) % len(a:switch_list)] 40 let cnt_chr = a:cnt_chr 41 42 call setline(line("."), 43 \ strpart(getline('.'), 0, col('.')-1 -len(cnt_chr)).next_chr.strpart(getline('.'), col('.')-1)) 44 "↓ここのカーソル位置の調整でおかしくなる" 45 call cursor(".", col('.') +(len(next_chr) - len(cnt_chr))) 46 47 return "\<BS>\<BS>" 48endfunction 49 50 51"下記の様にキーと切り替え文字のリストをマッピングして使用する" 52inoremap <buffer>A <C-R>=SwitchChar(["A","B","C","D","E"], "A")<CR> 53inoremap <buffer>. <C-R>=SwitchChar([".", "…"], ".")<CR>

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだ回答がついていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問