Vimでコマンドライン履歴を遡りやすくする

by

本記事はVim 駅伝7/24の記事です。

Vimのコマンドラインで、履歴を遡りたい時、:wとか:qaとかが出てきて煩わしく感じることがあります。

正直、これくらいシンプルなExコマンドであれば履歴に残しておく意味すら薄いので、履歴に残さない(or 履歴から消す)といいでしょう。

履歴に残さないのはそこそこ面倒なので、消す方法を実装しました。

やってることはとてもシンプル。

この場合、CmdlineLeaveが使えない点には注意です。 CmdlineLeaveはコマンドラインモード終了前のイベントなので、このタイミングでは履歴が更新されていません。

Vim script

augroup histclean
  autocmd!
  autocmd ModeChanged c:* call s:HistClean()
augroup END

function! s:HistClean() abort
  let cmd = histget(":", -1)
  if cmd == "x" || cmd == "xa" || cmd =~# "^w\\?q\\?a\\?!\\?$"
    call histdel(":", -1)
  endif
endfunction

Lua (Neovim)

vim.api.nvim_create_autocmd("ModeChanged", {
  pattern = "c:*",
  group = utils.augroup,
  callback = function()
    local cmd = vim.fn.histget(":", -1)
    if cmd == "x" or cmd == "xa" or cmd:match("^w?q?a?!?$") then
      vim.fn.histdel(":", -1)
    end
  end,
})

おまけ

面倒と言いましたマッピングを駆使すれば履歴を残さずに特定のコマンドを実行することもできます。 Exprマッピングを使っているので、コマンドが < などを含む場合はもう少し丁寧にやってください。

vim.keymap.set("c", "<cr>", function()
  if vim.fn.getcmdtype() ~= ":" then
    return "<cr>"
  end
  local cmd = vim.fn.getcmdline()
  if cmd == "x" or cmd == "xa" or cmd:match("^w?q?a?!?$") then
    return "<c-u><bs><cmd>" .. cmd .. "<cr>"
  end
  return "<cr>"
end, {expr = true})