You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
zk-nvim/lua/zk/util.lua

95 lines
3.0 KiB
Lua

local M = {}
---Finds the root directory of the notebook of the given path
--
---@param notebook_path string
---@return string? root
function M.notebook_root(notebook_path)
return require("zk.root_pattern_util").root_pattern(".zk")(notebook_path)
end
---Try to resolve a notebook path by checking the following locations in that order
---1. current buffer path
---2. current working directory
---3. `$ZK_NOTEBOOK_DIR` environment variable
---
---Note that the path will not necessarily be the notebook root.
--
---@param bufnr number?
---@return string? path inside a notebook
function M.resolve_notebook_path(bufnr)
local path = vim.api.nvim_buf_get_name(bufnr)
local cwd = vim.fn.getcwd(0)
-- if the buffer has no name (i.e. it is empty), set the current working directory as it's path
if path == "" then
path = cwd
end
if not M.notebook_root(path) then
if not M.notebook_root(cwd) then
-- if neither the buffer nor the cwd belong to a notebook, use $ZK_NOTEBOOK_DIR as fallback if available
if vim.env.ZK_NOTEBOOK_DIR then
path = vim.env.ZK_NOTEBOOK_DIR
end
else
-- the buffer doesn't belong to a notebook, but the cwd does!
path = cwd
end
end
-- at this point, the buffer either belongs to a notebook, or everything else failed
return path
end
---Makes an LSP location object from the last selection in the current buffer.
--
---@return table LSP location object
---@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#location
function M.get_lsp_location_from_selection()
local params = vim.lsp.util.make_given_range_params()
params.uri = params.textDocument.uri
params.textDocument = nil
return params
end
---Gets the text in the given range of the current buffer.
---Needed until https://github.com/neovim/neovim/pull/13896 is merged.
--
---@param range table contains {start} and {end} tables with {line} and {character} values
---@return string? text in range
function M.get_text_in_range(range)
local A = range["start"]
local B = range["end"]
local lines = vim.api.nvim_buf_get_lines(0, A.line, B.line + 1, true)
if vim.tbl_isempty(lines) then
return nil
end
lines[#lines] = string.sub(lines[#lines], 1, B.character)
lines[1] = string.sub(lines[1], A.character + 1)
return table.concat(lines, "\n")
end
---Gets the most recently selected text of the current buffer.
---That is the text between the '<,'> marks.
---Note that these marks are only updated *after* leaving the visual mode.
--
---@return string? selected text
function M.get_selected_text()
-- code adjusted from `vim.lsp.util.make_given_range_params`
-- we don't want to use character encoding offsets here
local A = vim.api.nvim_buf_get_mark(0, "<")
local B = vim.api.nvim_buf_get_mark(0, ">")
-- convert to 0-index
A[1] = A[1] - 1
B[1] = B[1] - 1
if vim.o.selection ~= "exclusive" then
B[2] = B[2] + 1
end
return M.get_text_in_range({
start = { line = A[1], character = A[2] },
["end"] = { line = B[1], character = B[2] },
})
end
return M