feat(compat): added svim, a compatibility layer for Neovim. Closes #1321

This commit is contained in:
Folke Lemaitre 2025-02-20 06:56:47 +01:00
parent 7d10a38c44
commit bc902f7032
No known key found for this signature in database
GPG key ID: 41F8B1FBACAE2040
37 changed files with 133 additions and 90 deletions

View file

@ -21,6 +21,7 @@ discard.
>lua >lua
---@class snacks.bufdelete.Opts ---@class snacks.bufdelete.Opts
---@field buf? number Buffer to delete. Defaults to the current buffer ---@field buf? number Buffer to delete. Defaults to the current buffer
---@field file? string Delete buffer by file name. If provided, `buf` is ignored
---@field force? boolean Delete the buffer even if it is modified ---@field force? boolean Delete the buffer even if it is modified
---@field filter? fun(buf: number): boolean Filter buffers to delete ---@field filter? fun(buf: number): boolean Filter buffers to delete
---@field wipe? boolean Wipe the buffer instead of deleting it (see `:h :bwipeout`) ---@field wipe? boolean Wipe the buffer instead of deleting it (see `:h :bwipeout`)

View file

@ -158,7 +158,7 @@ In case of issues, make sure to run `:checkhealth snacks`.
font_size = "Large", -- see https://www.sascha-frank.com/latex-font-size.html font_size = "Large", -- see https://www.sascha-frank.com/latex-font-size.html
-- for latex documents, the doc packages are included automatically, -- for latex documents, the doc packages are included automatically,
-- but you can add more packages here. Useful for markdown documents. -- but you can add more packages here. Useful for markdown documents.
packages = { "amsmath", "amssymb", "amsfonts", "amscd", "mathtools", "physics", "siunitx", "mhchem" }, packages = { "amsmath", "amssymb", "amsfonts", "amscd", "mathtools" },
}, },
---@type snacks.image.args ---@type snacks.image.args
mermaid = function() mermaid = function()

View file

@ -58,7 +58,7 @@ colorscheme and integrate edit with the current neovim instance.
nerdFontsVersion = "3", nerdFontsVersion = "3",
}, },
}, },
theme_path = vim.fs.normalize(vim.fn.stdpath("cache") .. "/lazygit-theme.yml"), theme_path = svim.fs.normalize(vim.fn.stdpath("cache") .. "/lazygit-theme.yml"),
-- Theme for lazygit -- Theme for lazygit
theme = { theme = {
[241] = { fg = "Special" }, [241] = { fg = "Special" },

View file

@ -93,6 +93,7 @@ Table of Contents *snacks-picker-table-of-contents*
- vscode |snacks-picker-layouts-vscode| - vscode |snacks-picker-layouts-vscode|
10. snacks.picker.actions |snacks-picker-snacks.picker.actions| 10. snacks.picker.actions |snacks-picker-snacks.picker.actions|
- Snacks.picker.actions.bufdelete()|snacks-picker-snacks.picker.actions-snacks.picker.actions.bufdelete()| - Snacks.picker.actions.bufdelete()|snacks-picker-snacks.picker.actions-snacks.picker.actions.bufdelete()|
- Snacks.picker.actions.cancel()|snacks-picker-snacks.picker.actions-snacks.picker.actions.cancel()|
- Snacks.picker.actions.cd()|snacks-picker-snacks.picker.actions-snacks.picker.actions.cd()| - Snacks.picker.actions.cd()|snacks-picker-snacks.picker.actions-snacks.picker.actions.cd()|
- Snacks.picker.actions.close()|snacks-picker-snacks.picker.actions-snacks.picker.actions.close()| - Snacks.picker.actions.close()|snacks-picker-snacks.picker.actions-snacks.picker.actions.close()|
- Snacks.picker.actions.cmd()|snacks-picker-snacks.picker.actions-snacks.picker.actions.cmd()| - Snacks.picker.actions.cmd()|snacks-picker-snacks.picker.actions-snacks.picker.actions.cmd()|
@ -387,11 +388,11 @@ below.
["/"] = "toggle_focus", ["/"] = "toggle_focus",
["<C-Down>"] = { "history_forward", mode = { "i", "n" } }, ["<C-Down>"] = { "history_forward", mode = { "i", "n" } },
["<C-Up>"] = { "history_back", mode = { "i", "n" } }, ["<C-Up>"] = { "history_back", mode = { "i", "n" } },
["<C-c>"] = { "close", mode = "i" }, ["<C-c>"] = { "cancel", mode = "i" },
["<C-w>"] = { "<c-s-w>", mode = { "i" }, expr = true, desc = "delete word" }, ["<C-w>"] = { "<c-s-w>", mode = { "i" }, expr = true, desc = "delete word" },
["<CR>"] = { "confirm", mode = { "n", "i" } }, ["<CR>"] = { "confirm", mode = { "n", "i" } },
["<Down>"] = { "list_down", mode = { "i", "n" } }, ["<Down>"] = { "list_down", mode = { "i", "n" } },
["<Esc>"] = "close", ["<Esc>"] = "cancel",
["<S-CR>"] = { { "pick_win", "jump" }, mode = { "n", "i" } }, ["<S-CR>"] = { { "pick_win", "jump" }, mode = { "n", "i" } },
["<S-Tab>"] = { "select_and_prev", mode = { "i", "n" } }, ["<S-Tab>"] = { "select_and_prev", mode = { "i", "n" } },
["<Tab>"] = { "select_and_next", mode = { "i", "n" } }, ["<Tab>"] = { "select_and_next", mode = { "i", "n" } },
@ -439,7 +440,7 @@ below.
["<2-LeftMouse>"] = "confirm", ["<2-LeftMouse>"] = "confirm",
["<CR>"] = "confirm", ["<CR>"] = "confirm",
["<Down>"] = "list_down", ["<Down>"] = "list_down",
["<Esc>"] = "close", ["<Esc>"] = "cancel",
["<S-CR>"] = { { "pick_win", "jump" } }, ["<S-CR>"] = { { "pick_win", "jump" } },
["<S-Tab>"] = { "select_and_prev", mode = { "n", "x" } }, ["<S-Tab>"] = { "select_and_prev", mode = { "n", "x" } },
["<Tab>"] = { "select_and_next", mode = { "n", "x" } }, ["<Tab>"] = { "select_and_next", mode = { "n", "x" } },
@ -487,7 +488,7 @@ below.
-- preview window -- preview window
preview = { preview = {
keys = { keys = {
["<Esc>"] = "close", ["<Esc>"] = "cancel",
["q"] = "close", ["q"] = "close",
["i"] = "focus_input", ["i"] = "focus_input",
["<ScrollWheelDown>"] = "list_scroll_wheel_down", ["<ScrollWheelDown>"] = "list_scroll_wheel_down",
@ -797,23 +798,6 @@ TROUBLE *snacks-picker-examples-trouble*
---@field notify? boolean ---@field notify? boolean
< <
>lua
---@alias snacks.Picker.ref (fun():snacks.Picker?)|{value?: snacks.Picker}
<
>lua
---@class snacks.picker.Last
---@field cursor number
---@field topline number
---@field opts? snacks.picker.Config
---@field selected snacks.picker.Item[]
---@field filter snacks.picker.Filter
<
>lua
---@alias snacks.picker.history.Record {pattern: string, search: string, live?: boolean}
<
>lua >lua
---@alias snacks.picker.Extmark vim.api.keyset.set_extmark|{col:number, row?:number, field?:string} ---@alias snacks.picker.Extmark vim.api.keyset.set_extmark|{col:number, row?:number, field?:string}
---@alias snacks.picker.Text {[1]:string, [2]:string?, virtual?:boolean, field?:string} ---@alias snacks.picker.Text {[1]:string, [2]:string?, virtual?:boolean, field?:string}
@ -892,6 +876,23 @@ that shows a preview based on the item data.
---@field preview? snacks.win.Config|{} preview window config ---@field preview? snacks.win.Config|{} preview window config
< <
>lua
---@alias snacks.Picker.ref (fun():snacks.Picker?)|{value?: snacks.Picker}
<
>lua
---@class snacks.picker.Last
---@field cursor number
---@field topline number
---@field opts? snacks.picker.Config
---@field selected snacks.picker.Item[]
---@field filter snacks.picker.Filter
<
>lua
---@alias snacks.picker.history.Record {pattern: string, search: string, live?: boolean}
<
============================================================================== ==============================================================================
7. Module *snacks-picker-module* 7. Module *snacks-picker-module*
@ -2630,6 +2631,13 @@ SNACKS.PICKER.ACTIONS.BUFDELETE()*snacks-picker-snacks.picker.actions-snacks.pic
< <
SNACKS.PICKER.ACTIONS.CANCEL()*snacks-picker-snacks.picker.actions-snacks.picker.actions.cancel()*
>lua
Snacks.picker.actions.cancel(picker)
<
SNACKS.PICKER.ACTIONS.CD()*snacks-picker-snacks.picker.actions-snacks.picker.actions.cd()* SNACKS.PICKER.ACTIONS.CD()*snacks-picker-snacks.picker.actions-snacks.picker.actions.cd()*
>lua >lua

View file

@ -107,10 +107,11 @@ Lets LSP clients know that a file has been renamed
`Snacks.rename.rename_file()` *Snacks.rename.rename_file()* `Snacks.rename.rename_file()` *Snacks.rename.rename_file()*
Prompt for the new filename, do the rename, and trigger LSP handlers Renames the provided file, or the current buffers file. Prompt for the new
filename if `to` is not provided. do the rename, and trigger LSP handlers
>lua >lua
---@param opts? {file?: string, on_rename?: fun(new:string, old:string)} ---@param opts? {from?: string, to?:string, on_rename?: fun(to:string, from:string, ok:boolean)}
Snacks.rename.rename_file(opts) Snacks.rename.rename_file(opts)
< <

View file

@ -44,7 +44,7 @@ and integrate edit with the current neovim instance.
nerdFontsVersion = "3", nerdFontsVersion = "3",
}, },
}, },
theme_path = vim.fs.normalize(vim.fn.stdpath("cache") .. "/lazygit-theme.yml"), theme_path = svim.fs.normalize(vim.fn.stdpath("cache") .. "/lazygit-theme.yml"),
-- Theme for lazygit -- Theme for lazygit
theme = { theme = {
[241] = { fg = "Special" }, [241] = { fg = "Special" },

32
lua/snacks/compat.lua Normal file
View file

@ -0,0 +1,32 @@
---@generic T
---@param t T
---@return T
local function wrap(t)
return setmetatable({}, { __index = t })
end
local M = wrap(vim)
M.meta = {
desc = "Neovim compatibility layer",
hide = true,
}
local is_win = jit.os:find("Windows")
M.islist = vim.islist or vim.tbl_islist
M.uv = vim.uv or vim.loop
if vim.fn.has("nvim-0.11") == 0 then
M.fs = wrap(vim.fs)
---@param path (string) Path to normalize
---@param opts? vim.fs.normalize.Opts
---@return (string) : Normalized path
function M.normalize(path, opts)
local ret = svim.fs.normalize(path, opts)
return is_win and ret:gsub("^%a:", string.upper) or ret
end
end
return M

View file

@ -792,14 +792,14 @@ function M.oldfiles(opts)
local filter = {} ---@type {path:string, want:boolean}[] local filter = {} ---@type {path:string, want:boolean}[]
for path, want in pairs(opts.filter or {}) do for path, want in pairs(opts.filter or {}) do
table.insert(filter, { path = vim.fs.normalize(path), want = want }) table.insert(filter, { path = svim.fs.normalize(path), want = want })
end end
local done = {} ---@type table<string, boolean> local done = {} ---@type table<string, boolean>
local i = 1 local i = 1
local oldfiles = vim.v.oldfiles local oldfiles = vim.v.oldfiles
return function() return function()
while oldfiles[i] do while oldfiles[i] do
local file = vim.fs.normalize(oldfiles[i], { _fast = true, expand_env = false }) local file = svim.fs.normalize(oldfiles[i], { _fast = true, expand_env = false })
local want = not done[file] local want = not done[file]
if want then if want then
done[file] = true done[file] = true
@ -850,7 +850,7 @@ function M.sections.recent_files(opts)
return function() return function()
opts = opts or {} opts = opts or {}
local limit = opts.limit or 5 local limit = opts.limit or 5
local root = opts.cwd and vim.fs.normalize(opts.cwd == true and vim.fn.getcwd() or opts.cwd) or "" local root = opts.cwd and svim.fs.normalize(opts.cwd == true and vim.fn.getcwd() or opts.cwd) or ""
local ret = {} ---@type snacks.dashboard.Section local ret = {} ---@type snacks.dashboard.Section
for file in M.oldfiles({ filter = { [root] = true } }) do for file in M.oldfiles({ filter = { [root] = true } }) do
if not opts.filter or opts.filter(file) then if not opts.filter or opts.filter(file) then

View file

@ -160,7 +160,7 @@ function M.actions.explorer_add(picker)
if not value or value:find("^%s$") then if not value or value:find("^%s$") then
return return
end end
local path = vim.fs.normalize(picker:dir() .. "/" .. value) local path = svim.fs.normalize(picker:dir() .. "/" .. value)
local is_file = value:sub(-1) ~= "/" local is_file = value:sub(-1) ~= "/"
local dir = is_file and vim.fs.dirname(path) or path local dir = is_file and vim.fs.dirname(path) or path
if is_file and uv.fs_stat(path) then if is_file and uv.fs_stat(path) then
@ -237,7 +237,7 @@ function M.actions.explorer_copy(picker, item)
return return
end end
local dir = vim.fs.dirname(item.file) local dir = vim.fs.dirname(item.file)
local to = vim.fs.normalize(dir .. "/" .. value) local to = svim.fs.normalize(dir .. "/" .. value)
if uv.fs_stat(to) then if uv.fs_stat(to) then
Snacks.notify.warn("File already exists:\n- `" .. to .. "`") Snacks.notify.warn("File already exists:\n- `" .. to .. "`")
return return

View file

@ -22,7 +22,7 @@ function M.update(cwd)
for _, diag in ipairs(diags) do for _, diag in ipairs(diags) do
local path = diag.bufnr and vim.api.nvim_buf_get_name(diag.bufnr) local path = diag.bufnr and vim.api.nvim_buf_get_name(diag.bufnr)
path = path and path ~= "" and vim.fs.normalize(path) or nil path = path and path ~= "" and svim.fs.normalize(path) or nil
if path then if path then
add(path, diag) add(path, diag)
add(cwd, diag) add(cwd, diag)

View file

@ -80,7 +80,7 @@ function M.reveal(opts)
local Actions = require("snacks.explorer.actions") local Actions = require("snacks.explorer.actions")
local Tree = require("snacks.explorer.tree") local Tree = require("snacks.explorer.tree")
opts = opts or {} opts = opts or {}
local file = vim.fs.normalize(opts.file or vim.api.nvim_buf_get_name(opts.buf or 0)) local file = svim.fs.normalize(opts.file or vim.api.nvim_buf_get_name(opts.buf or 0))
local explorer = Snacks.picker.get({ source = "explorer" })[1] or M.open() local explorer = Snacks.picker.get({ source = "explorer" })[1] or M.open()
local cwd = explorer:cwd() local cwd = explorer:cwd()
if not Tree:in_cwd(cwd, file) then if not Tree:in_cwd(cwd, file) then

View file

@ -24,7 +24,7 @@
local uv = vim.uv or vim.loop local uv = vim.uv or vim.loop
local function norm(path) local function norm(path)
return vim.fs.normalize(path) return svim.fs.normalize(path)
end end
local function assert_dir(path) local function assert_dir(path)

View file

@ -29,7 +29,7 @@ end
function M.get_root(path) function M.get_root(path)
path = path or 0 path = path or 0
path = type(path) == "number" and vim.api.nvim_buf_get_name(path) or path --[[@as string]] path = type(path) == "number" and vim.api.nvim_buf_get_name(path) or path --[[@as string]]
path = vim.fs.normalize(path) path = svim.fs.normalize(path)
path = path == "" and (vim.uv or vim.loop).cwd() or path path = path == "" and (vim.uv or vim.loop).cwd() or path
local todo = { path } ---@type string[] local todo = { path } ---@type string[]
@ -40,13 +40,13 @@ function M.get_root(path)
-- check cache first -- check cache first
for _, dir in ipairs(todo) do for _, dir in ipairs(todo) do
if git_cache[dir] then if git_cache[dir] then
return vim.fs.normalize(dir) or nil return svim.fs.normalize(dir) or nil
end end
end end
for _, dir in ipairs(todo) do for _, dir in ipairs(todo) do
if is_git_root(dir) then if is_git_root(dir) then
return vim.fs.normalize(dir) or nil return svim.fs.normalize(dir) or nil
end end
end end

View file

@ -149,7 +149,7 @@ end
function M._open(opts) function M._open(opts)
opts = Snacks.config.get("gitbrowse", defaults, opts) opts = Snacks.config.get("gitbrowse", defaults, opts)
local file = vim.api.nvim_buf_get_name(0) ---@type string? local file = vim.api.nvim_buf_get_name(0) ---@type string?
file = file and (uv.fs_stat(file) or {}).type == "file" and vim.fs.normalize(file) or nil file = file and (uv.fs_stat(file) or {}).type == "file" and svim.fs.normalize(file) or nil
local cwd = file and vim.fn.fnamemodify(file, ":h") or vim.fn.getcwd() local cwd = file and vim.fn.fnamemodify(file, ":h") or vim.fn.getcwd()
---@type snacks.gitbrowse.Fields ---@type snacks.gitbrowse.Fields

View file

@ -420,7 +420,7 @@ function M.norm(src)
src = vim.uri_to_fname(src) src = vim.uri_to_fname(src)
end end
if not M.is_uri(src) then if not M.is_uri(src) then
src = vim.fs.normalize(vim.fn.fnamemodify(src, ":p")) src = svim.fs.normalize(vim.fn.fnamemodify(src, ":p"))
end end
return src return src
end end

View file

@ -107,7 +107,7 @@ end
---@param src string ---@param src string
function M.resolve(buf, src) function M.resolve(buf, src)
src = M.url_decode(src) src = M.url_decode(src)
local file = vim.fs.normalize(vim.api.nvim_buf_get_name(buf)) local file = svim.fs.normalize(vim.api.nvim_buf_get_name(buf))
local s = Snacks.image.config.resolve and Snacks.image.config.resolve(file, src) or nil local s = Snacks.image.config.resolve and Snacks.image.config.resolve(file, src) or nil
if s then if s then
return s return s
@ -130,7 +130,7 @@ function M.resolve(buf, src)
break break
end end
end end
src = vim.fs.normalize(src) src = svim.fs.normalize(src)
end end
return src return src
end end

View file

@ -7,7 +7,7 @@ local dims = {} ---@type table<string, snacks.image.Size>
---@param file string ---@param file string
---@return snacks.image.Size ---@return snacks.image.Size
function M.dim(file) function M.dim(file)
file = vim.fs.normalize(file) file = svim.fs.normalize(file)
if dims[file] then if dims[file] then
return dims[file] return dims[file]
end end

View file

@ -10,6 +10,7 @@ setmetatable(M, {
}) })
_G.Snacks = M _G.Snacks = M
_G.svim = vim.fn.has("nvim-0.11") and vim or require("snacks.compat")
---@class snacks.Config.base ---@class snacks.Config.base
---@field example? string ---@field example? string

View file

@ -40,7 +40,7 @@ local defaults = {
nerdFontsVersion = "3", nerdFontsVersion = "3",
}, },
}, },
theme_path = vim.fs.normalize(vim.fn.stdpath("cache") .. "/lazygit-theme.yml"), theme_path = svim.fs.normalize(vim.fn.stdpath("cache") .. "/lazygit-theme.yml"),
-- Theme for lazygit -- Theme for lazygit
-- stylua: ignore -- stylua: ignore
theme = { theme = {
@ -89,7 +89,7 @@ local function env(opts)
-- add the default config file if it's not already there -- add the default config file if it's not already there
if #config_files == 0 then if #config_files == 0 then
config_files[1] = vim.fs.normalize(config_dir .. "/config.yml") config_files[1] = svim.fs.normalize(config_dir .. "/config.yml")
end end
-- add the theme file if it's not already there -- add the theme file if it's not already there

View file

@ -26,7 +26,7 @@ M.meta = {
M.root = vim.fn.fnamemodify(debug.getinfo(1, "S").source:sub(2), ":h:h") M.root = vim.fn.fnamemodify(debug.getinfo(1, "S").source:sub(2), ":h:h")
function M.file(name) function M.file(name)
return vim.fs.normalize(("%s/%s"):format(M.root, name)) return svim.fs.normalize(("%s/%s"):format(M.root, name))
end end
--- Get the metadata for all snacks plugins --- Get the metadata for all snacks plugins

View file

@ -80,7 +80,7 @@ function M.get(opts)
if opts.cwd == true or opts.cwd == "" then if opts.cwd == true or opts.cwd == "" then
opts.cwd = nil opts.cwd = nil
elseif opts.cwd then elseif opts.cwd then
opts.cwd = vim.fs.normalize(vim.fn.fnamemodify(opts.cwd, ":p")) opts.cwd = svim.fs.normalize(vim.fn.fnamemodify(opts.cwd, ":p"))
end end
for _, t in ipairs(todo) do for _, t in ipairs(todo) do
if t.config then if t.config then

View file

@ -39,13 +39,13 @@ function M:init(opts)
self.paths = {} self.paths = {}
local cwd = self.opts and self.opts.cwd local cwd = self.opts and self.opts.cwd
self.cwd = type(cwd) == "string" and cwd or opts.cwd or uv.cwd() or "." self.cwd = type(cwd) == "string" and cwd or opts.cwd or uv.cwd() or "."
self.cwd = vim.fs.normalize(self.cwd --[[@as string]], { _fast = true }) self.cwd = svim.fs.normalize(self.cwd --[[@as string]], { _fast = true })
if not self.all and self.opts then if not self.all and self.opts then
self.buf = self.opts.buf == true and 0 or self.opts.buf --[[@as number?]] self.buf = self.opts.buf == true and 0 or self.opts.buf --[[@as number?]]
self.buf = self.buf == 0 and M.current_buf or self.buf self.buf = self.buf == 0 and M.current_buf or self.buf
self.file = self.buf and vim.fs.normalize(vim.api.nvim_buf_get_name(self.buf), { _fast = true }) or nil self.file = self.buf and svim.fs.normalize(vim.api.nvim_buf_get_name(self.buf), { _fast = true }) or nil
for path, want in pairs(self.opts.paths or {}) do for path, want in pairs(self.opts.paths or {}) do
table.insert(self.paths, { path = vim.fs.normalize(path), want = want }) table.insert(self.paths, { path = svim.fs.normalize(path), want = want })
end end
end end
return self return self
@ -58,7 +58,7 @@ end
---@param cwd string ---@param cwd string
function M:set_cwd(cwd) function M:set_cwd(cwd)
self.cwd = cwd self.cwd = cwd
self.cwd = vim.fs.normalize(self.cwd --[[@as string]], { _fast = true }) self.cwd = svim.fs.normalize(self.cwd --[[@as string]], { _fast = true })
end end
---@param opts? {trim?:boolean} ---@param opts? {trim?:boolean}

View file

@ -85,7 +85,7 @@ function M:run(picker)
self.task:abort() self.task:abort()
picker.list:clear() picker.list:clear()
self.cwd = vim.fs.normalize(picker.opts.cwd or (vim.uv or vim.loop).cwd() or ".") self.cwd = svim.fs.normalize(picker.opts.cwd or (vim.uv or vim.loop).cwd() or ".")
self.sorting = not self:empty() or picker.opts.matcher.sort_empty self.sorting = not self:empty() or picker.opts.matcher.sort_empty
-- PERF: fast path for empty pattern -- PERF: fast path for empty pattern

View file

@ -6,11 +6,11 @@ local uv = vim.uv or vim.loop
function M.diagnostics(opts, ctx) function M.diagnostics(opts, ctx)
local items = {} ---@type snacks.picker.finder.Item[] local items = {} ---@type snacks.picker.finder.Item[]
local current_buf = vim.api.nvim_get_current_buf() local current_buf = vim.api.nvim_get_current_buf()
local cwd = vim.fs.normalize(uv.cwd() or ".") local cwd = svim.fs.normalize(uv.cwd() or ".")
for _, diag in ipairs(vim.diagnostic.get(ctx.filter.buf, { severity = opts.severity })) do for _, diag in ipairs(vim.diagnostic.get(ctx.filter.buf, { severity = opts.severity })) do
local buf = diag.bufnr local buf = diag.bufnr
if buf and vim.api.nvim_buf_is_valid(buf) then if buf and vim.api.nvim_buf_is_valid(buf) then
local file = vim.fs.normalize(vim.api.nvim_buf_get_name(buf), { _fast = true }) local file = svim.fs.normalize(vim.api.nvim_buf_get_name(buf), { _fast = true })
local severity = diag.severity local severity = diag.severity
severity = type(severity) == "number" and vim.diagnostic.severity[severity] or severity severity = type(severity) == "number" and vim.diagnostic.severity[severity] or severity
---@cast severity string? ---@cast severity string?

View file

@ -19,7 +19,7 @@ local uv = vim.uv or vim.loop
---@field status? string ---@field status? string
local function norm(path) local function norm(path)
return vim.fs.normalize(path) return svim.fs.normalize(path)
end end
---@class snacks.picker.explorer.State ---@class snacks.picker.explorer.State
@ -40,7 +40,7 @@ function State.new(picker)
Tree:refresh(picker:cwd()) Tree:refresh(picker:cwd())
local buf = vim.api.nvim_win_get_buf(picker.main) local buf = vim.api.nvim_win_get_buf(picker.main)
local buf_file = vim.fs.normalize(vim.api.nvim_buf_get_name(buf)) local buf_file = svim.fs.normalize(vim.api.nvim_buf_get_name(buf))
if uv.fs_stat(buf_file) then if uv.fs_stat(buf_file) then
Tree:open(buf_file) Tree:open(buf_file)
end end
@ -66,7 +66,7 @@ function State.new(picker)
picker.list.win:on("DirChanged", function(_, ev) picker.list.win:on("DirChanged", function(_, ev)
local p = ref() local p = ref()
if p then if p then
p:set_cwd(vim.fs.normalize(ev.file)) p:set_cwd(svim.fs.normalize(ev.file))
p:find() p:find()
end end
end) end)

View file

@ -133,7 +133,7 @@ local function get_cmd(opts, filter)
vim.list_extend(dirs, Snacks.picker.util.rtp()) vim.list_extend(dirs, Snacks.picker.util.rtp())
end end
if #dirs > 0 then if #dirs > 0 then
dirs = vim.tbl_map(vim.fs.normalize, dirs) ---@type string[] dirs = vim.tbl_map(svim.fs.normalize, dirs) ---@type string[]
if is_fd and not pattern then if is_fd and not pattern then
args[#args + 1] = "." args[#args + 1] = "."
end end
@ -154,7 +154,7 @@ end
---@type snacks.picker.finder ---@type snacks.picker.finder
function M.files(opts, ctx) function M.files(opts, ctx)
local cwd = not (opts.rtp or (opts.dirs and #opts.dirs > 0)) local cwd = not (opts.rtp or (opts.dirs and #opts.dirs > 0))
and vim.fs.normalize(opts and opts.cwd or uv.cwd() or ".") and svim.fs.normalize(opts and opts.cwd or uv.cwd() or ".")
or nil or nil
local cmd, args = get_cmd(opts, ctx.filter) local cmd, args = get_cmd(opts, ctx.filter)
if not cmd then if not cmd then

View file

@ -27,7 +27,7 @@ function M.files(opts, ctx)
opts.cwd = Snacks.git.get_root() or uv.cwd() or "." opts.cwd = Snacks.git.get_root() or uv.cwd() or "."
ctx.picker:set_cwd(opts.cwd) ctx.picker:set_cwd(opts.cwd)
end end
local cwd = vim.fs.normalize(opts.cwd) or nil local cwd = svim.fs.normalize(opts.cwd) or nil
return require("snacks.picker.source.proc").proc({ return require("snacks.picker.source.proc").proc({
opts, opts,
{ {
@ -59,7 +59,7 @@ function M.grep(opts, ctx)
opts.cwd = Snacks.git.get_root() or uv.cwd() or "." opts.cwd = Snacks.git.get_root() or uv.cwd() or "."
ctx.picker:set_cwd(opts.cwd) ctx.picker:set_cwd(opts.cwd)
end end
local cwd = vim.fs.normalize(opts.cwd) or nil local cwd = svim.fs.normalize(opts.cwd) or nil
return require("snacks.picker.source.proc").proc({ return require("snacks.picker.source.proc").proc({
opts, opts,
{ {
@ -121,9 +121,9 @@ function M.log(opts, ctx)
end end
local Proc = require("snacks.picker.source.proc") local Proc = require("snacks.picker.source.proc")
file = file and vim.fs.normalize(file) or nil file = file and svim.fs.normalize(file) or nil
local cwd = vim.fs.normalize(file and vim.fn.fnamemodify(file, ":h") or opts and opts.cwd or uv.cwd() or ".") or nil local cwd = svim.fs.normalize(file and vim.fn.fnamemodify(file, ":h") or opts and opts.cwd or uv.cwd() or ".") or nil
cwd = Snacks.git.get_root(cwd) or cwd cwd = Snacks.git.get_root(cwd) or cwd
local renames = { file } ---@type string[] local renames = { file } ---@type string[]
@ -180,7 +180,7 @@ function M.status(opts, ctx)
table.insert(args, "--ignored=matching") table.insert(args, "--ignored=matching")
end end
local cwd = vim.fs.normalize(opts and opts.cwd or uv.cwd() or ".") or nil local cwd = svim.fs.normalize(opts and opts.cwd or uv.cwd() or ".") or nil
cwd = Snacks.git.get_root(cwd) cwd = Snacks.git.get_root(cwd)
local prev ---@type snacks.picker.finder.Item? local prev ---@type snacks.picker.finder.Item?
return require("snacks.picker.source.proc").proc({ return require("snacks.picker.source.proc").proc({
@ -266,7 +266,7 @@ end
---@type snacks.picker.finder ---@type snacks.picker.finder
function M.branches(opts, ctx) function M.branches(opts, ctx)
local args = git_args(opts.args, "--no-pager", "branch", "--no-color", "-vvl") local args = git_args(opts.args, "--no-pager", "branch", "--no-color", "-vvl")
local cwd = vim.fs.normalize(opts and opts.cwd or uv.cwd() or ".") or nil local cwd = svim.fs.normalize(opts and opts.cwd or uv.cwd() or ".") or nil
cwd = Snacks.git.get_root(cwd) cwd = Snacks.git.get_root(cwd)
local patterns = { local patterns = {
@ -310,7 +310,7 @@ end
---@type snacks.picker.finder ---@type snacks.picker.finder
function M.stash(opts, ctx) function M.stash(opts, ctx)
local args = git_args(opts.args, "--no-pager", "stash", "list") local args = git_args(opts.args, "--no-pager", "stash", "list")
local cwd = vim.fs.normalize(opts and opts.cwd or uv.cwd() or ".") or nil local cwd = svim.fs.normalize(opts and opts.cwd or uv.cwd() or ".") or nil
cwd = Snacks.git.get_root(cwd) cwd = Snacks.git.get_root(cwd)
return require("snacks.picker.source.proc").proc({ return require("snacks.picker.source.proc").proc({

View file

@ -88,7 +88,7 @@ local function get_cmd(opts, filter)
-- dirs -- dirs
if #paths > 0 then if #paths > 0 then
paths = vim.tbl_map(vim.fs.normalize, paths) ---@type string[] paths = vim.tbl_map(svim.fs.normalize, paths) ---@type string[]
vim.list_extend(args, paths) vim.list_extend(args, paths)
end end
@ -102,7 +102,7 @@ function M.grep(opts, ctx)
return function() end return function() end
end end
local absolute = (opts.dirs and #opts.dirs > 0) or opts.buffers or opts.rtp local absolute = (opts.dirs and #opts.dirs > 0) or opts.buffers or opts.rtp
local cwd = not absolute and vim.fs.normalize(opts and opts.cwd or uv.cwd() or ".") or nil local cwd = not absolute and svim.fs.normalize(opts and opts.cwd or uv.cwd() or ".") or nil
local cmd, args = get_cmd(opts, ctx.filter) local cmd, args = get_cmd(opts, ctx.filter)
if opts.debug.grep then if opts.debug.grep then
Snacks.notify.info("grep: " .. cmd .. " " .. table.concat(args, " ")) Snacks.notify.info("grep: " .. cmd .. " " .. table.concat(args, " "))

View file

@ -84,7 +84,7 @@ function M.find(opts, ctx)
if type(cmd) == "table" and #cmd > 0 then if type(cmd) == "table" and #cmd > 0 then
---@type string[] ---@type string[]
cmd = vim.deepcopy(cmd) cmd = vim.deepcopy(cmd)
cmd[1] = vim.fs.normalize(cmd[1]) cmd[1] = svim.fs.normalize(cmd[1])
if cmd[1]:find("/") then if cmd[1]:find("/") then
installed = vim.fn.filereadable(cmd[1]) == 1 installed = vim.fn.filereadable(cmd[1]) == 1
bin = cmd[1] bin = cmd[1]

View file

@ -180,7 +180,7 @@ function M.get_locations(method, opts, filter)
local win = filter.current_win local win = filter.current_win
local buf = filter.current_buf local buf = filter.current_buf
local fname = vim.api.nvim_buf_get_name(buf) local fname = vim.api.nvim_buf_get_name(buf)
fname = vim.fs.normalize(fname) fname = svim.fs.normalize(fname)
local cursor = vim.api.nvim_win_get_cursor(win) local cursor = vim.api.nvim_win_get_cursor(win)
local bufmap = M.bufmap() local bufmap = M.bufmap()
@ -203,7 +203,7 @@ function M.get_locations(method, opts, filter)
if not opts.include_current then if not opts.include_current then
---@param item vim.quickfix.entry ---@param item vim.quickfix.entry
items = vim.tbl_filter(function(item) items = vim.tbl_filter(function(item)
if vim.fs.normalize(item.filename) ~= fname then if svim.fs.normalize(item.filename) ~= fname then
return true return true
end end
if not item.lnum then if not item.lnum then

View file

@ -54,7 +54,7 @@ function M.proc(opts, ctx)
local spawn_opts = { local spawn_opts = {
args = opts.args, args = opts.args,
stdio = { nil, stdout, nil }, stdio = { nil, stdout, nil },
cwd = opts.cwd and vim.fs.normalize(opts.cwd) or nil, cwd = opts.cwd and svim.fs.normalize(opts.cwd) or nil,
env = opts.env, env = opts.env,
hide = true, hide = true,
} }
@ -174,7 +174,7 @@ function M.debug(opts)
end end
Snacks.notify.info( Snacks.notify.info(
("- **cwd**: `%s`\n```sh\n%s\n```"):format( ("- **cwd**: `%s`\n```sh\n%s\n```"):format(
vim.fn.fnamemodify(vim.fs.normalize(opts.cwd or uv.cwd() or "."), ":~"), vim.fn.fnamemodify(svim.fs.normalize(opts.cwd or uv.cwd() or "."), ":~"),
table.concat(lines, "\n") table.concat(lines, "\n")
), ),
{ id = "snacks.picker.proc." .. id, title = "Snacks Proc" } { id = "snacks.picker.proc." .. id, title = "Snacks Proc" }

View file

@ -14,7 +14,7 @@ local function oldfiles(filter, extra)
for f = i + 1, #files do for f = i + 1, #files do
i = f i = f
local file = files[f] local file = files[f]
file = vim.fs.normalize(file, { _fast = true, expand_env = false }) file = svim.fs.normalize(file, { _fast = true, expand_env = false })
local want = not done[file] and filter:match({ file = file, text = "" }) local want = not done[file] and filter:match({ file = file, text = "" })
done[file] = true done[file] = true
if want and uv.fs_stat(file) then if want and uv.fs_stat(file) then
@ -29,7 +29,7 @@ end
---@param opts snacks.picker.recent.Config ---@param opts snacks.picker.recent.Config
---@type snacks.picker.finder ---@type snacks.picker.finder
function M.files(opts, ctx) function M.files(opts, ctx)
local current_file = vim.fs.normalize(vim.api.nvim_buf_get_name(0), { _fast = true }) local current_file = svim.fs.normalize(vim.api.nvim_buf_get_name(0), { _fast = true })
---@type number[] ---@type number[]
local bufs = vim.tbl_filter(function(b) local bufs = vim.tbl_filter(function(b)
return vim.api.nvim_buf_get_name(b) ~= "" and vim.bo[b].buftype == "" and vim.bo[b].buflisted return vim.api.nvim_buf_get_name(b) ~= "" and vim.bo[b].buftype == "" and vim.bo[b].buflisted
@ -76,7 +76,7 @@ function M.projects(opts, ctx)
vim.list_extend(args, { "-g", "{" .. table.concat(opts.patterns or {}, ",") .. "}" }) vim.list_extend(args, { "-g", "{" .. table.concat(opts.patterns or {}, ",") .. "}" })
local dev = type(opts.dev) == "string" and { opts.dev } or opts.dev or {} local dev = type(opts.dev) == "string" and { opts.dev } or opts.dev or {}
---@cast dev string[] ---@cast dev string[]
vim.list_extend(args, vim.tbl_map(vim.fs.normalize, dev)) vim.list_extend(args, vim.tbl_map(svim.fs.normalize, dev))
local fd = require("snacks.picker.source.files").get_fd() local fd = require("snacks.picker.source.files").get_fd()
if not fd then if not fd then
Snacks.notify.warn("`fd` or `fdfind` is required for projects") Snacks.notify.warn("`fd` or `fdfind` is required for projects")

View file

@ -10,7 +10,7 @@ function M.path(item)
return return
end end
item._path = item._path item._path = item._path
or vim.fs.normalize(item.cwd and item.cwd .. "/" .. item.file or item.file, { _fast = true, expand_env = false }) or svim.fs.normalize(item.cwd and item.cwd .. "/" .. item.file or item.file, { _fast = true, expand_env = false })
return item._path return item._path
end end
@ -18,9 +18,9 @@ end
---@param len? number ---@param len? number
---@param opts? {cwd?: string} ---@param opts? {cwd?: string}
function M.truncpath(path, len, opts) function M.truncpath(path, len, opts)
local cwd = vim.fs.normalize(opts and opts.cwd or vim.fn.getcwd(), { _fast = true, expand_env = false }) local cwd = svim.fs.normalize(opts and opts.cwd or vim.fn.getcwd(), { _fast = true, expand_env = false })
local home = vim.fs.normalize("~") local home = svim.fs.normalize("~")
path = vim.fs.normalize(path, { _fast = true, expand_env = false }) path = svim.fs.normalize(path, { _fast = true, expand_env = false })
if path:find(cwd .. "/", 1, true) == 1 and #path > #cwd then if path:find(cwd .. "/", 1, true) == 1 and #path > #cwd then
path = path:sub(#cwd + 2) path = path:sub(#cwd + 2)
@ -440,15 +440,15 @@ end
function M.dir(item) function M.dir(item)
local path = type(item) == "table" and M.path(item) or item local path = type(item) == "table" and M.path(item) or item
---@cast path string ---@cast path string
path = vim.fs.normalize(path) path = svim.fs.normalize(path)
return vim.fn.isdirectory(path) == 1 and path or vim.fs.dirname(path) return vim.fn.isdirectory(path) == 1 and path or vim.fs.dirname(path)
end end
---@param paths string[] ---@param paths string[]
---@param dir string ---@param dir string
function M.copy(paths, dir) function M.copy(paths, dir)
dir = vim.fs.normalize(dir) dir = svim.fs.normalize(dir)
paths = vim.tbl_map(vim.fs.normalize, paths) ---@type string[] paths = vim.tbl_map(svim.fs.normalize, paths) ---@type string[]
for _, path in ipairs(paths) do for _, path in ipairs(paths) do
local name = vim.fn.fnamemodify(path, ":t") local name = vim.fn.fnamemodify(path, ":t")
local to = dir .. "/" .. name local to = dir .. "/" .. name
@ -539,7 +539,7 @@ function M.get_bins()
local path = vim.split(os.getenv("PATH") or "", is_win and ";" or ":", { plain = true }) local path = vim.split(os.getenv("PATH") or "", is_win and ";" or ":", { plain = true })
local bins = {} ---@type table<string, string> local bins = {} ---@type table<string, string>
for _, p in ipairs(path) do for _, p in ipairs(path) do
p = vim.fs.normalize(p) p = svim.fs.normalize(p)
for file, t in vim.fs.dir(p) do for file, t in vim.fs.dir(p) do
if t ~= "directory" then if t ~= "directory" then
local fpath = p .. "/" .. file local fpath = p .. "/" .. file

View file

@ -35,8 +35,8 @@ function M.realpath(path)
if path_cache[path] then if path_cache[path] then
return path_cache[path] return path_cache[path]
end end
path = vim.fs.normalize(path, { expand_env = false }) path = svim.fs.normalize(path, { expand_env = false })
path_cache[path] = vim.fs.normalize(vim.uv.fs_realpath(path) or path, { expand_env = false, _fast = true }) path_cache[path] = svim.fs.normalize(vim.uv.fs_realpath(path) or path, { expand_env = false, _fast = true })
return path_cache[path] return path_cache[path]
end end

View file

@ -44,7 +44,7 @@ function M.rename_file(opts)
if not value or value == "" or value == extra then if not value or value == "" or value == extra then
return return
end end
to = vim.fs.normalize(root .. "/" .. value) to = svim.fs.normalize(root .. "/" .. value)
rename() rename()
end) end)
end end

View file

@ -101,7 +101,7 @@ function M.list()
local decoded = Snacks.util.file_decode(file) local decoded = Snacks.util.file_decode(file)
local count, icon, name, cwd, branch, ft = decoded:match("^(%d*)|([^|]*)|([^|]*)|([^|]*)|([^|]*)%.([^|]*)$") local count, icon, name, cwd, branch, ft = decoded:match("^(%d*)|([^|]*)|([^|]*)|([^|]*)|([^|]*)%.([^|]*)$")
if count and icon and name and cwd and branch and ft then if count and icon and name and cwd and branch and ft then
file = vim.fs.normalize(root .. "/" .. file) file = svim.fs.normalize(root .. "/" .. file)
table.insert(ret, { table.insert(ret, {
file = file, file = file,
stat = uv.fs_stat(file), stat = uv.fs_stat(file),
@ -182,7 +182,7 @@ function M.open(opts)
opts.filekey.count and tostring(vim.v.count1) or "", opts.filekey.count and tostring(vim.v.count1) or "",
opts.icon or "", opts.icon or "",
opts.name:gsub("|", " "), opts.name:gsub("|", " "),
opts.filekey.cwd and vim.fs.normalize(assert(uv.cwd())) or "", opts.filekey.cwd and svim.fs.normalize(assert(uv.cwd())) or "",
branch, branch,
} }
@ -190,7 +190,7 @@ function M.open(opts)
local fname = Snacks.util.file_encode(table.concat(filekey, "|") .. "." .. ft) local fname = Snacks.util.file_encode(table.concat(filekey, "|") .. "." .. ft)
file = opts.root .. "/" .. fname file = opts.root .. "/" .. fname
end end
file = vim.fs.normalize(file) file = svim.fs.normalize(file)
local icon, icon_hl = unpack(type(opts.icon) == "table" and opts.icon or { opts.icon, nil }) local icon, icon_hl = unpack(type(opts.icon) == "table" and opts.icon or { opts.icon, nil })
---@cast icon string ---@cast icon string

View file

@ -1,4 +1,4 @@
;; extends ;; extends
((identifier) @namespace.builtin ((identifier) @namespace.builtin
(#eq? @namespace.builtin "Snacks")) (#any-of? @namespace.builtin "Snacks" "svim"))