🌅

Neovim用MRU保存プラグインを作った(+fzf-lua連携例の紹介)

2022/08/08に公開

luaプラグイン初挑戦です。よろしくおねがいします。

https://github.com/kawarimidoll/mru_cache.lua

機能

  • 開いたファイル(バッファに入ったファイル)を自動でキャッシュファイルに保存する
  • 保存したファイルを自動でキャッシュファイルに保存する
  • 手動でファイルパスを指定してキャッシュに追加することもできる

キャッシュされたパスを開いたり、削除したりすることはできません。あくまで追加していくだけです。

しくみ

シェルコマンドを実行するio.popensedを実行しています。
シェル芸みたいになってます。

https://github.com/kawarimidoll/mru_cache.lua/blob/53c94013076f6d20194d25c4e866ab89f6f4168a/lua/mru_cache.lua#L66-L70

保存したいファイル名が~/hello.txt、保存先が~/.cache/mru、保存最大数が10件の場合、以下のコマンドが実行されます。

sed -i -e '\|^~/hello.txt$|d' -e '10,$d' -e '1i~/hello.txt' ~/.cache/mru

  1. -e '\|^~/hello.txt$|d'でキャッシュの重複を削除
  2. -e '10,$d'で最大値を超えた行を削除(9行目までを残す)
  3. -e '1i~/hello.txt'で1行目にキャッシュを追加
  4. -iにより~/.cache/mruを直接変更

要求事項

前述の通り、sedが必要です。

つかいかた

お好みのプラグインマネージャーで読み込んでください。
setup()関数を呼ぶことで、MRU保存のautocmdが設定されます。

require('mru_cache').setup()

起動オプション

setup()には以下のオプションを渡すことができます。

  • cache_directory
    • キャッシュ先のディレクトリです。
    • type: string
    • default: '~/.cache/nvim/mru_cache'
  • max_size
    • キャッシュする件数の最大値です。
    • type: number
    • default: 100
  • ignore_filetype_list
    • キャッシュ対象から除外するfiletypeのリストです。
    • type: table of string
    • default: {}
  • ignore_regex_list
    • キャッシュ対象から除外するファイル名の正規表現のリストです。Vim scriptではなく、luaの正規表現であることに注意してください。
    • type: table of string
    • default: {}

こんな感じで設定できます。

require('mru_cache').setup({
  max_size = 1000,
  ignore_filetype_list = { "help" },
  ignore_regex_list = { "%.git/" }
})

値を省いた場合はデフォルト値が使用されます。

API

以下の関数を使用できます。

  • setup
    • プラグインのオプションの指定およびautocmdの設定を行います。
    • parameters:
      • user_opts(optional): 上述のオプションです。
  • cache_path
    • キャッシュファイルのパスを返します。
    • parameters:
      • type(required): 'mru'または'mrw'を指定します。
  • append
    • キャッシュにファイルを追加します。autocmdではなく手動で追加したいときに使います。
    • parameters:
      • path(required): キャッシュに追加したいファイルパスです。
      • type(required): 'mru'または'mrw'を指定します。

連携

以下の設定により、fzf-luaを使って保存されたファイルを選択・編集することができます。

local fzf_lua = require('fzf-lua')
local mru_cache = require('mru_cache')

local gen_mru_cmd = function(type)
  -- remove current file and cwd
  return "sed -e '\\|^" .. vim.api.nvim_buf_get_name(0) .. "$|d' -e 's|^"
      .. vim.fn.getcwd() .. "/||' " .. mru_cache.cache_path(type)
end
local gen_mru_opts = function(args)
  local opts = {
    previewer = "builtin",
    actions = fzf_lua.defaults.actions.files,
    file_icons = true,
    color_icons = true
  }
  for k, v in pairs(args) do
    opts[k] = v
  end

  opts.fn_transform = function(x)
    return fzf_lua.make_entry.file(x, opts)
  end
  return opts
end

fzf_lua.mru = function(args)
  args.prompt = 'MRU> '
  local cmd = gen_mru_cmd('mru')
  local opts = gen_mru_opts(args)
  fzf_lua.fzf_exec(cmd, opts)
end

fzf_lua.mrw = function(args)
  args.prompt = 'MRW> '
  local cmd = gen_mru_cmd('mrw')
  local opts = gen_mru_opts(args)
  fzf_lua.fzf_exec(cmd, opts)
end

そもそも、fzf-luaでMRUをバッと開きたいと思ってプラグインを作りました。
キャッシュファイルは単純にファイルパスを並べているだけなので、他のfuzzy finderでも連携できると思います。

開発時の工夫

動作確認用のinit.vimファイルを作成しました。といっても1行だけですが。
nvim -u dev/init.vimで起動すれば、純粋にプラグインの挙動にバグがないか確認できます。

https://github.com/kawarimidoll/mru_cache.lua/blob/53c94013076f6d20194d25c4e866ab89f6f4168a/dev/init.vim

公開している関数にはドキュメントを設定しているので、lua-language-serverでヒントやスニペットを出せます。べんり。
https://github.com/kawarimidoll/mru_cache.lua/blob/53c94013076f6d20194d25c4e866ab89f6f4168a/lua/mru_cache.lua#L53-L56

Discussion