🦒

vim.defer_fn でコマンドを直列実行する

に公開

はじめに

2023年6月現在、私はファイラーにoil.nvimを、バッファ内のあいまい検索にfuzzy-motion.vimを使っています。
そこで、ファイラーを開いた直後にあいまい検索ができたら便利じゃないのか?という疑問を抱き、このようなキーマップを定義しました。

vim.keymap.set("n", "<leader>e",
function ()
  vim.cmd"Oil ."
  vim.schedule(function()
    vim.cmd.FuzzyMotion()
  end)
end,
{ noremap=true, silent=true })


しかし、結果はファイラーが起動する前にあいまい検索が起動してしまい使いものになりませんでした。
vim-jpでそのことを呟くと、vim.defer_fn()で実現できますよとryoppippiさんに教えていただきました。ありがとうございます!

ドキュメントを確認したところ、第2引数へ時間を設定できるため起動タイミングをずらすことができるということでした。
そのため、vim.defer_fn()を使って書き換えたところ、

vim.keymap.set("n", "<leader>e",
function ()
  vim.cmd"Oil ."
  vim.defer_fn(function()
    vim.cmd.FuzzyMotion()
  end, 150)
end,
{ noremap=true, silent=true })


思ったとおりに動作しました。

※ 2025年5月27日追記

open({dir}, {opts}, {cb})                                               *oil.open*
    Open oil browser for a directory

    Parameters:
      {dir}  `nil|string` When nil, open the parent of the current buffer, or
             the cwd if current buffer is not a file
      {opts} `nil|oil.OpenOpts`
          {preview} `nil|oil.OpenPreviewOpts` When present, open the preview
                    window after opening oil
              {vertical}   `nil|boolean` Open the buffer in a vertical split
              {horizontal} `nil|boolean` Open the buffer in a horizontal split
              {split}      `nil|"aboveleft"|"belowright"|"topleft"|"botright"` S
                           plit modifier
      {cb}   `nil|fun()` Called after the oil buffer is ready

現在のoil.nvimではopen関数の第3引数にcallback関数を渡すことができるため、下記のように書きかえることでdefer_fnを使わずとも同様の動作をさせることができるようになっています。

 vim.keymap.set("n", "<leader>e",
 function ()
-  vim.cmd"Oil ."
-  vim.defer_fn(function()
-    vim.cmd.FuzzyMotion()
-  end, 150)
+  require("oil").open(".", nil, vim.cmd.FuzzyMotion)
 end,
 { noremap=true, silent=true })

※ 2025年5月27日追記 おわり

おわりに

vim.schedule()で直列実行がうまくいかない場合はvim.defer_fn()を使ってみてね。

Discussion