Vim: ファイル形式に応じた位置マーカーの統一管理関数 by Claude

2025年7月18日

背景

  • Web連載用のTeX原稿では現在位置を -here マーカーで管理している。
  • 他のファイルでは \HERE マーカーを使用している。
  • ファイル中に散在するマーカーを現在のカーソル位置に集約したい。

問題

  • 既存のマーカーを削除して現在位置に挿入する際、上の行を削除すると行番号がずれる。
  • ファイル形式に応じて異なるマーカー(-here または \HERE)を使い分けたい。
  • 位置を保持しながら確実にマーカーを統一したい。

解法

  • 一時的なマーカーを使用して位置ずれを防ぐ。
  • ファイル名の正規表現マッチングでマーカー種別を自動判定する。
  • key 変数を使用してコードを統一化する。

" Web連載用: -here を現在位置に集約する
function! InsertAndUnifyHere()
  " ファイル名を取得してマーカーを決定
  let filename = expand('%:t')
  
  if filename =~ '^\d\d\d\.tex$'
    " ファイル名が 000.tex から 999.tex の形式の場合
    let key = '-here'
  else
    " それ以外の場合
    let key = '\HERE'
  endif
  
  " 共通処理
  let temp_marker = key . '-marker'
  let message = key . ' を集約しました'
  
  " 現在行に一時的なマーカーを挿入
  let lnum = line('.')
  call append(lnum - 1, temp_marker)
  
  " 既存のマーカー行を削除
  execute 'silent! g/^' . escape(key, '\') . '$/d'
  
  " 一時マーカーを本来のマーカーに置換
  execute 'silent! %s/^' . escape(temp_marker, '\') . '$/' . escape(key, '\') . '/'
  
  " 置換されたマーカー行にカーソルを移動
  call search('^' . escape(key, '\') . '$', 'w')
  
  " メッセージ表示
  redraw
  echo message
endfunction

" キーマップ
nnoremap <Leader>h :call InsertAndUnifyHere()<CR>

結果

  • 001.tex999.tex ファイルでは -here マーカーが使用される
  • その他のファイルでは \HERE マーカーが使用される
  • 既存のマーカーがすべて削除され、現在のカーソル位置に統一される
  • 一時マーカー方式により位置ずれが完全に防がれる

参考

  • :help expand() - ファイル名の取得
  • :help escape() - 正規表現でのエスケープ処理
  • :help search() - パターン検索と移動

このメモの作成経緯

(2025年7月18日)