🦔

自作Vimプラグイン用に作ったヘルプファイルフォーマッタ

2024/04/29に公開

最近いくつかVimプラグインを作りました。

https://zenn.dev/kawarimidoll/articles/f71236b43de0e2

https://zenn.dev/kawarimidoll/articles/f80e2194303564

https://zenn.dev/vim_jp/articles/358848a5144b63

https://zenn.dev/vim_jp/articles/af5c0bc86cfb45

プラグインにはヘルプファイルを添付しています。
単なるテキストファイルなのですが、Vimで適切に表示するため、いくつかルールがあります。

  • 見出しは左揃え
  • 本文は字下げ
  • ヘルプタグは*tag*の形式で右揃え
  • 適当な文字数で折り返し
  • などなど

特に日本語では良い感じに右揃えしたり改行するのが面倒です。gqというマッピングで整形することはできるのですが、これをいちいち手動でやるのは億劫…ということで、ファイル全体に適用するフォーマッタを自作しました。

function Doc_fmt() abort
  " ファイルタイプ設定を更新
  if &filetype != 'help'
    setfiletype help
  endif

  let save_cursor = getcurpos()

  " 行末空白、ファイル末空行を削除
  silent %s/\s\+$\|\n\+\%$//e

  " 見出しタグ位置を調整
  silent %s/\v^(.*\S)\s*(\*\S+\*)$/\=submatch(1) .. repeat(' ', max([1, 78-len(submatch(1) .. submatch(2))])) .. submatch(2)/e

  " インデント
  let newline_pat = '^\S.*[*]$'
  let skip_pat = '[-~=<>]$\|' .. newline_pat
  let skip_hls = ['helpExample']
  let blanks = 4
  let i = 7
  while i < line('$')
    call cursor(i, 1)
    let line = getline(i)
    if !empty(line) && line !~ skip_pat && index(skip_hls, synIDattr(synID(line('.'), col('.'), 0), 'name'))
      if line =~ '^\s*-'
        let blanks = 6
        call setline(i, substitute(' ' .. line, '^\s*', repeat(' ', blanks), ''))
        let blanks = 8
      else
        call setline(i, substitute(' ' .. line, '^\s*', repeat(' ', blanks), ''))
        normal! gql
      endif
    else
      let blanks = 4
      if line =~ newline_pat && line !~ '^\s*$'
        call append(i, '')
      endif
    endif
    let i += 1
  endwhile

  " 見出しタグ位置を調整
  silent %s/\v^\s*(\*\S+\*)$/\=repeat(' ', max([1, 78-len(submatch(1))])) .. submatch(1)/e

  " 連続空行を削除
  silent %s/^\n\zs\n\+//e

  call setpos('.', save_cursor)
endfunction

この関数を読み込み、ヘルプファイルを開いて:call Doc_fmt()すれば良い感じにフォーマットされます。

見出しタグ位置を調整の部分の78は1行の文字数を、インデントの部分の各数値はインデントの深さを、それぞれ指定しています。自分用のため即値になっていますが、これらは自由に調整可能です。
自作のプラグインではこれをhelpファイルと同じディレクトリに保存しておき、ヘルプ編集時にサッと読み込んでフォーマットできるようにしています。参考になれば幸いです。

Discussion