以下の内容はhttps://fs0414.hatenablog.com/entry/2025/11/29/203057より取得しました。


NeoVimでのfile path取得コマンドから、URI Schemeを削除する変換処理

汐れいらさんの No oneがよすぎてずっと聴いてます。
糸しいひと, うぶ, 笑ってベイビー あたりが特に。
fujitani soraです

No one ‑「Album」by 汐れいら | Spotify


エディタで相対path or 絶対pathを簡単にcopyできる手段があると何かと便利です。
例えばAI Agentに特定のファイルを渡すときとか。

また、環境依存の話として、自分はNeoVimのoil.nvimというテキスト編集可能なfilerを利用しています。

github.com

テキスト編集可能であるということは、NeoVimのbufferとして開いているということであり、そこではVimのコマンドが実行可能です。
vim.api.nvim_create_user_command によるkeymap登録で、copy_path関数に文字列リテラルのパラメータを渡します。
パラメータで分岐させて、一つの関数で統一的にpathの取得と変換を行います。

local function copy_path(opts, target)
  local expr = '%'
  if target == 'full path' then
    expr = '%:p'
  elseif target == 'file name' then
    expr = '%:t'
  elseif target == 'relative path' then
    -- Get path relative to the directory where nvim was started
    local current_file = vim.fn.expand('%:p')

    local nvim_start_dir = vim.fn.getcwd()
    local relative_path = vim.fn.fnamemodify(current_file, ':s?' .. vim.fn.escape(nvim_start_dir, '\\') .. '/??')
    local path = relative_path .. get_range_str(opts)
    vim.fn.setreg('*', path)
    vim.notify('Copied ' .. target .. ': ' .. path)
    return
  end

  local path = vim.fn.expand(expr) .. get_range_str(opts)
  vim.fn.setreg('*', path)
  vim.notify('Copied ' .. target .. ': ' .. path)
end

vim.api.nvim_create_user_command('Cfp', function(opts)
  copy_path(opts, 'full path')
end, { range = true, desc = 'Copy the full path of the current file to the clipboard' })

vim.api.nvim_create_user_command('Crp', function(opts)
  copy_path(opts, 'relative path')
end, { range = true, desc = 'Copy the relative path of the current file to the clipboard' })

vim.api.nvim_create_user_command('Cfn', function(opts)
  copy_path(opts, 'file name')
end, { range = true, desc = 'Copy the file name of the current file to the clipboard' })

この時に起こる問題として、通常のfile path copyは正しいが、oil.nvimによって開いたbufferでのcopyで、取得pathにツール依存のURI schemeが含まれてしまう問題がありました。

lua/keymap.lua

:Crp

# => lua/keymap.lua

oil.nvimで開いた lua/

:Crp

# => oil://lua/

これは不要であり、文字列を渡される側にとってのノイズになります。
解決手段として、oil://というツールに依存せずにディレクトリ文頭のURL schemeを削除する変換処理を入れてあげます。

local function copy_path(opts, target)
  local expr = '%'
  if target == 'full path' then
    expr = '%:p'
  elseif target == 'file name' then
    expr = '%:t'
  elseif target == 'relative path' then
    -- Get path relative to the directory where nvim was started
    local current_file = vim.fn.expand('%:p')

    -- Remove any URI scheme (e.g., oil://, neo-tree://, etc.)
    if current_file:match('^%w+://') then
      current_file = current_file:gsub('^%w+://', '')
    end

    local nvim_start_dir = vim.fn.getcwd()
    local relative_path = vim.fn.fnamemodify(current_file, ':s?' .. vim.fn.escape(nvim_start_dir, '\\') .. '/??')
    local path = relative_path .. get_range_str(opts)
    vim.fn.setreg('*', path)
    vim.notify('Copied ' .. target .. ': ' .. path)
    return
  end

  local path = vim.fn.expand(expr)

  -- Remove any URI scheme (e.g., oil://, neo-tree://, etc.)
  if path:match('^%w+://') then
    path = path:gsub('^%w+://', '')
  end

  path = path .. get_range_str(opts)
  vim.fn.setreg('*', path)
  vim.notify('Copied ' .. target .. ': ' .. path)
end

vim.api.nvim_create_user_command('Cfp', function(opts)
  copy_path(opts, 'full path')
end, { range = true, desc = 'Copy the full path of the current file to the clipboard' })

vim.api.nvim_create_user_command('Crp', function(opts)
  copy_path(opts, 'relative path')
end, { range = true, desc = 'Copy the relative path of the current file to the clipboard' })

vim.api.nvim_create_user_command('Cfn', function(opts)
  copy_path(opts, 'file name')
end, { range = true, desc = 'Copy the file name of the current file to the clipboard' })

patchはこんな感じ

この変換によって、実行bufferに依存せずにpath copyが可能になりました。

oil.nvimで開いた lua/

:Crp

# => lua/

ちなみに、範囲選択して:Crp などを実行すると行範囲の取得も行われます。
かなり便利

:Crp

lua/keymap.lua#L76-L78



以上の内容はhttps://fs0414.hatenablog.com/entry/2025/11/29/203057より取得しました。
このページはhttp://font.textar.tv/のウェブフォントを使用してます

不具合報告/要望等はこちらへお願いします。
モバイルやる夫Viewer Ver0.14