1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

改行時に\begin{hoge}を認識して\end{hoge}を補完する

Last updated at Posted at 2020-05-08

この記事の目標

vim を使って Latex のコードを書く方へ,少しだけ便利な設定を共有します.
\begin{hoge} の文章で改行をしたときに \end{hoge} を補完するように vimrc に設定を追記します.
movie.gif

環境・前提事項

私の VIM は バージョン 8.2.200 です.プラグインは使っていません.
最新バージョンでしか使えない機能など,特別なものは含まれていないと思います.
ただし "\begin{hoge}\begin{fuga}" と一行に複数回 "\begin{}" を登場させる方には,
意図通りの動作にならない可能性が高いです.
VIMのバージョンが7の場合,意図通りに動きませんでした.
バージョン7と8では count(...) 関数の使い方が異なるようです.
下記をご利用の際にはバージョンを8以上にしてください.(2021/04/13追記)

実践

vimrc に以下の内容を追記します.

function! s:AutoEndComp()
 let l:line_char=getline('.')
 if count(l:line_char,"\\begin{")
  let l:len=stridx(l:line_char,"}")-(stridx(l:line_char,"\\begin{")+7)
  let l:obj_name=strpart(l:line_char,stridx(l:line_char,"\\begin{")+7,l:len)
  let l:command="\<CR>\\end{"..l:obj_name.."}\<Esc>O "
  call feedkeys(l:command,'n')
 else
  call feedkeys("\<CR>",'n')
 endif
endfunction
inoremap <CR> <C-\><C-O>:call <SID>AutoEndComp()<CR>

解説

改行すると関数 AutoEndComp() が呼び出されます.この関数の大まかなアルゴリズムは以下の通りです.
まず,関数 getline() によりカーソルがある行を抜き出し,文字列変数 line_char に格納します.変数の前にある「l:」はローカル変数であることを明示する接頭辞です.この接頭辞はこちらのページ

接頭辞を関数内で省略した場合は「l:」になる.

と解説されている通り,省略することもできます.

次に関数 count() により文字列変数 line_char に文字列 "\begin{" がいくつ含まれるかを調べます.
ひとつも含まれていない場合は else 節が実行され,通常の改行となります.
ひとつでも含まれている場合は else 前の部分が実行され,以下の処理となります.

  1. \begin{hoge} の "hoge" の部分の文字数をカウントします.そのために関数 stridx(str, "extr") を使っています.この関数は,文字列変数 str における文字列 "extr" が始まる位置を返します.この関数をうまいこと使い "hoge" の文字数を変数 len に格納します.
  2. "hoge" の部分の具体的な名前を調べます.そのために関数 strpart(str, "extr", len) を使います.この関数は,文字列変数 str の中で文字列 "extr" が始まる位置から文字数 len だけ文字列を抽出します.抽出した文字列を文字列変数 obj_name に格納します.
  3. \end{hoge} を補完するために関数 feedkeys() を使用します.第一引数に改行したときの振る舞いを与えます.ここでは見栄えを優先して,文字列変数 command を導入しています.let により文字列を結合する際には,let str=char1..char2のように,ピリオドを二つ使います.

気がついた点,不備などありましたら,ぜひご指摘ください.


(5月9日追記)文字列を結合する方法について
訂正前: let str=char1.char2のように,ピリオドを使います
訂正後: let str=char1..char2のように,ピリオドを二つ使います
文字列の結合はこちらのページで解説されている通り,
ピリオド二つの利用が推奨されていました.
実践 に示したソースコードの該当箇所も書き換えました.
@htsign 様にご指摘いただきました.改めて感謝します.

1
1
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?