Location via proxy:   
[Report a bug]   [Manage cookies]                
  • 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/' },
      })
      

      比如,在使用一些启动屏插件(dashboard.nvim)时,会在启动时显示近期打开过的文件, 如果前面打开过一些非文本类文件,比如图片类的,这类文件可以从浏览历史中去除掉。

      require('mru').setup({
        ignore_path_regexs = { '/.git/', '.mp3$', '.png$' },
      })
      
    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,
      },
    }
    

  • Neovim 录制按键及屏幕

    2025-04-12
    Eric Wong

    以前偶尔也会录制一些动图,使用的是 LICEcap,这也是一个开源项目,但是不能录制成视频。 在网上搜到不少的录视频的软件,比较火热的是班迪录屏,但是我还是倾向于免费开源方案。

    开源实现

    Neovim 增加了一个 vim.on_key,这个函数在按键按下后会触发。借助这个函数及 Neovim 的悬浮窗口, 实现了一个按键弹窗提示的效果插件 record-key.nvim

    record-screen.nvim 是一个 Neovim 屏幕录制的插件, 借助 ffmpeg 这个命令和 Neovim 的异步机制。

    安装配置

    使用 nvim-plug 插件管理器:

    require('plug').add({
      {
        'wsdjeg/record-key.nvim',
        cmds = { 'RecordKeyToggle' },
        config_before = function()
          vim.keymap.set(
            'n',
            '<leader>rk',
            '<cmd>RecordKeyToggle<cr>',
            { silent = true }
          )
        end,
      },
      {
        'wsdjeg/record-screen.nvim',
        depends = {
          { 'wsdjeg/job.nvim' },
          { 'wsdjeg/notify.nvim' },
        },
        config = function()
          vim.keymap.set(
            'n',
            '<F8>',
            '<cmd>lua require("record-screen").start()<cr>',
            { silent = true }
          )
          vim.keymap.set(
            'n',
            '<F9>',
            '<cmd>lua require("record-screen").stop()<cr>',
            { silent = true }
          )
        end,
      },
    })
    

  • Neovim 自动切换至项目根目录

    2025-03-22
    Eric Wong

    在使用 Neovim 打开某个文件时,我希望 Neovim 自动把当前目录切换到该文件所在的项目根目录。 其实,能实现这一功能的有不少的插件,我最早使用的是 vim-rooter,但是后来因为切换到了 Neovim, 因此使用 Lua 重写了该功能,这个功能早期是 SpaceVim 的内置的, 在 SpaceVim 项目停止维护后独立成单独的插件:rooter.nvim

    安装 rooter.nvim

    可以使用任意插件管理器进行安装,比如 nvim-plug

    require('plug').add({
      {
        'wsdjeg/rooter.nvim',
        config = function()
          require('rooter').setup({})
        end,
      },
    })
    

    插件配置

    以下是默认的配置:

    require('rooter').setup({
      root_patterns = { '.git/' },
      outermost = true,
      enable_cache = true,
      project_non_root = '',  -- this can be '', 'home' or 'current'
      enable_logger = true,   -- enable runtime log via logger.nvim
    })
    
    • project_non_root: 配置打开非项目文件时的行为
    • outermost: 若设为 true,那么通过 root_patterns 检索到的多个目录时,取最外层目录。

    Telescope 拓展

    rooter.nvim 自带 telescope.nvim 拓展,可以使用 :Telescope project 列出过往打开过的项目。

    telescope project

    插件运行日志

    在插件运行过程中产生的日志信息,可以使用 logger.nvim 进行查看。 如果有这一需求,那么在安装 rooter.nvim 时,需要添加相应的依赖插件。

    require('plug').add({
      {
        'wsdjeg/rooter.nvim',
        config = function()
          require('rooter').setup({})
        end,
        depends = {
          {
            'wsdjeg/logger.nvim',
          },
        },
      },
    })
    

    设置 callback 函数

    通过 reg_callback 可以设置 callback 函数,该函数会在项目切换时被调用。

    local function update_ctags_option()
      local project_root = vim.fn.getcwd()
      local dir = require('util').unify_path(require('tags').cache_dir) 
            .. require('util').path_to_fname(project_root)
      table.insert(tags, dir .. '/tags')
      vim.o.tags = table.concat(tags, ',')
    end
    require('rooter').reg_callback(update_gtags_option)
    

  • Neovim 日志插件 logger.nvim

    2025-03-16
    Eric Wong

    logger.nvim 提供了一个基础的日志框架,不同的插件可以共用一个日志系统。

    安装

    和安装其他插件一样,可以使用nvim-plug安装:

    require('plug').add({
      'wsdjeg/logger.nvim',
      config = function()
        require('logger').setup({
          -- the level only can be:
          -- 0 : log debug, info, warn, error messages
          -- 1 : log info, warn, error messages
          -- 2 : log warn, error messages
          -- 3 : log error messages
          level = 0,
        })
      end,
    })
    

    在插件中使用

    比如新建了一个插件 fyz.nvim,此时可以添加一个文件 lua/fyz/log.lua:

    local M = {}
    local logger
    function M.info(msg)
      if not logger then
        pcall(function()
          logger = require('logger').derive('fyz')
          logger.info('hello world')
        end)
      else
        logger.info('hello world')
      end
    end
    
    return M
    

    在自己的插件中就可以使用:

    local log = require('fyz.log')
    
    log.info('this is log from fyz.nvim')
    

    可以使用 logger.viewRuntimeLog() 查看所有的日志输出,其中就会有如下一行:

    [     fyz ] [23:22:50:576] [ Info  ] this is log from fyz.nvim
    
    

  • Neovim 任务管理插件 tasks.nvim

    2025-03-01
    Eric Wong

    起因

    关于任务(Tasks)管理,实际上早在 2020 年的时候就已经给 SpaceVim 增加了 Tasks 支持,参考的是 Vscode Tasks Manager 的实现。 最早的版本使用 Vim Script 实现的,大约在 2023 年的时候增加了 Lua 实现版本, 不过这些都是在 SpaceVim 内置的插件。

    现在,SpaceVim 已经不再维护,而这些常用的功能,我也会陆续剥离出来单独形成插件,这篇文章主要介绍 tasks.nvim

    安装及配置 tasks.nvim

    可以使用任意插件管理器进行安装,这里以 nvim-plug 为例:

    require('plug').add({
      {
        'wsdjeg/tasks.nvim',
        depends = {
          {
            'wsdjeg/code-runner.nvim',
          },
        },
        config = function()
          require('tasks').setup({
            global_tasks = '~/.tasks.toml',
            local_tasks = '.tasks.toml',
            provider = { 'npm' },
          })
        end,
      },
    })
    

    常用命令

    tasks.nvim 提供了三个常用命令:

    • :TasksEdit:用于打开 tasks 配置文件,默认打开的是项目配置文件,加上感叹号(:TasksEdit!)则打开全局配置文件。
    • :TasksList:使用分屏列出所有 tasks
    • :TasksSelect:选择某个 task 并执行

    当然,如果你也安装了 telescope.nvim 那么,可以使用 :Telescope tasks 模糊搜索可用的 tasks.


  • Neovim 代码执行插件 code-runner.nvim

    2025-02-28
    Eric Wong

    Vscode 有一个非常出名的插件,叫做 Code Runner,我曾经也给 SpaceVim 添加了这么一个功能。

    现在将这一功能剥离出来形成一个单独独立的 neovim 插件:code-runner.nvim

    安装及配置

    可以使用任意插件管理器进行安装,这里以 nvim-plug 为例:

    require('plug').add({
      {
        'wsdjeg/code-runner.nvim',
        config = function()
          require('code-runner').setup({
            runners = {
              lua = { exe = 'lua', opt = { '-' }, usestdin = true },
            },
            enter_win = false,
          })
        end,
      },
    })