Eric's Blog 时光荏苒,岁月如梭

Neovim 近期文件浏览历史记录

2025-04-13
Eric Wong

起因

Neovim 和 Vim 一样,支持使用 v:oldfiles 获取最近浏览的文件名称列表。但是 Neovim 这一变量在 Windows 系统下面存在文件名称格式不一致的问题。 比如,一些使用 v:oldfiles 的插件,如 telescope.nvim、dashboard.nvim 等,其列表内会出现一些重复的文件。

D:/hello.txt
D:\hello.txt
d:/hello.txt
d:\hello.txt

mru.nvim 的特点

为了避免上述原因,我做了一个插件 mru.nvim

  1. Windows 系统下统一的文件名格式,上述四种文件名称统一显示为 D:/hello.txt

  2. 可以预设置多个正则表达式,当文件名称匹配上时,阻止其被加入文件浏览历史记录。

    require('mru').setup({
      ignore_path_regexs = { '/.git/', '/nvim/runtime/doc/' },
    })
    
  3. 提供了 telescope.nvim 拓展,可以使用 :Telescope mru 打开。

安装与配置

使用 nvim-plug 插件管理器进行安装:

require('plug').add({
  {
    'wsdjeg/mru.nvim',
    config = function()
      require('mru').setup({
        enable_cache = true,
        mru_cache_file = vim.fn.stdpath('data') .. '/nvim-mru.json',
        events = { 'BufEnter', 'BufWritePost' }, -- events to update mru file list
        ignore_path_regexs = { '/.git/' },
        enable_logger = true, -- require wsdjeg/logger.nvim
      })
    end,
  },
})

LeaderF 拓展

当然,如果并未使用 telescope,也可以自行拓展,使用 require('mru').get() 获取历史记录文件名称列表。以 leaderf 为例:

function! s:nmru(...) abort
  return v:lua.require('mru').get()
endfunction

function! s:nmru_acp(line, args) abort
  exe 'e' a:line
endfunction
" function() wrapper
if v:version > 703 || v:version == 703 && has('patch1170')
  function! s:_SID() abort
    return matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze__SID$')
  endfunction
  let s:_s = '<SNR>' . s:_SID() . '_'
  function! s:_function(fstr, ...) abort
    if a:0 > 1
      return function(substitute(a:fstr, 's:', s:_s, 'g'))
    else
      return function(a:fstr)
    endif
  endfunction
else
  function! s:_SID() abort
    return matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze__SID$')
  endfunction
  let s:_s = '<SNR>' . s:_SID() . '_'
  function! s:_function(fstr) abort
    return function(substitute(a:fstr, 's:', s:_s, 'g'))
  endfunction
endif
let g:Lf_Extensions = {
    \ 'nmru': {
    \       'source': string(s:_function('s:nmru', 1))[10:-3],
    \       'accept': string(s:_function('s:nmru_acp', 1))[10:-3],
    \       'supports_name_only': 1,
    \       'supports_multi': 0,
    \ },
    \}

以上为 VimL 写的 LeaderF 拓展,尝试了使用 Lua 来写,可读性更简单,但是似乎不起作用:

local function mru()
  return require('mru').get()
end

local function mru_acp(line, args)
  vim.cmd('e ' .. line)
end
vim.g.Lf_Extensions = {
  nvimmru = {
    source = mru,
    accept = mru_acp,
    supports_name_only = true,
    supports_multi = false,
  },
}

版权声明:本文为原创文章,遵循 署名-非商业性使用-禁止演绎 4.0 国际 (CC BY-NC-ND 4.0)版权协议,转载请附上原文出处链接和本声明。


延生阅读

分享到:

评论

目前只支持使用邮件参与评论。