Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merge user setup function, module rename #9

Merged
merged 17 commits into from
Mar 5, 2025
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
refactor: rename suppress_warnings -> debug
pete3n committed Mar 5, 2025
commit 3df5de280e1a1b7347003bb2adaccd82d95b34ff
10 changes: 5 additions & 5 deletions lua/ninjection/buffer.lua
Original file line number Diff line number Diff line change
@@ -43,7 +43,7 @@ M.get_indents = function(bufnr)
lines = raw_output

if #lines == 0 then
if cfg.suppress_warnings == false then
if cfg.debug then
vim.notify(
"ninjection.buffer.get_indents() warning: No lines returned "
.. "from calling vim.api.nvim_buf_get_lines()",
@@ -128,7 +128,7 @@ M.restore_indents = function(text, indents)
---@cast raw_output string[]
lines = raw_output
if #lines == 0 then
if cfg.suppress_warnings == false then
if cfg.debug then
vim.notify(
"ninjection.buffer.restore_indents() warning: No lines " .. "returned from calling vim.split()",
vim.log.levels.WARN
@@ -335,7 +335,7 @@ M.create_child = function(p_bufnr, p_name, p_range, root_dir, text, lang)
if cfg.preserve_indents then
p_indents, err = M.get_indents(0)
if not p_indents then
if not cfg.suppress_warnings then
if cfg.debug then
vim.notify(
"ninjection.edit() warning: Unable to preserve indentation "
.. "with get_indents(): "
@@ -365,7 +365,7 @@ M.create_child = function(p_bufnr, p_name, p_range, root_dir, text, lang)
return vim.cmd("lua " .. cfg.format_cmd)
end)
if not ok then
if not cfg.suppress_warnings then
if cfg.debug then
err = tostring(raw_output)
vim.notify(
'ninjection.edit() warning: Calling vim.cmd("lua "' .. cfg.format_cmd .. ")\n" .. err,
@@ -436,7 +436,7 @@ M.set_child_cur = function(c_win, p_cursor, s_row, indents)
return vim.api.nvim_win_set_cursor(c_win, offset_cur)
end)
if not ok then
if not cfg.suppress_warnings then
if cfg.debug then
err = tostring(raw_output)
vim.notify(
"ninjection.edit() warning: Calling vim.api.nvim_win_set_cursor"
6 changes: 1 addition & 5 deletions lua/ninjection/config.lua
Original file line number Diff line number Diff line change
@@ -12,8 +12,6 @@ local vc = require("ninjection.health").validate_config

---@tag default_config
local default_config = {
---@type string
file_lang = "nix",
---@type boolean
preserve_indents = true,
---@type boolean
@@ -25,7 +23,7 @@ local default_config = {
---@type string
register = "z",
---@type boolean
suppress_warnings = false,
debug = true,
---@type EditorStyle
editor_style = "floating",
---@type table<string, string>
@@ -45,8 +43,6 @@ local default_config = {
)
]],
},
---@type string
inj_lang_query = "",
---@type table<string,string>
lsp_map = {
bash = "bashls",
9 changes: 1 addition & 8 deletions lua/ninjection/health.lua
Original file line number Diff line number Diff line change
@@ -23,7 +23,7 @@ local M = {}
---@return boolean is_valid, string? err
---
M.validate_config = function(cfg)
cfg = cfg or require("ninjection.config").values
cfg = cfg or require("ninjection.config").values or {}
---@type boolean, string?
local is_valid, err
is_valid = true
@@ -36,13 +36,6 @@ M.validate_config = function(cfg)
is_valid = false
end

-- Ensure there is a Treesitter query available for the parent file language.
if cfg.inj_lang_queries[cfg.file_lang] then
cfg.inj_lang_query = cfg.inj_lang_queries[cfg.file_lang]
else
err = "Ninjection: No injection query found for file_lang " .. cfg.file_lang
end

return is_valid, err
end

41 changes: 21 additions & 20 deletions lua/ninjection/init.lua
Original file line number Diff line number Diff line change
@@ -20,6 +20,7 @@ function ninjection.setup(user_cfg)
end
end

---@type Ninjection.Config
local cfg = require("ninjection.config").values

local ts = require("vim.treesitter")
@@ -34,7 +35,7 @@ end
---@brief
--- Identifies and selects injected text in visual mode.
---
---@return string? err
---@return nil
---
function ninjection.select()
---@type boolean, unknown, string?, integer?, NJNodeTable?
@@ -47,7 +48,7 @@ function ninjection.select()
error(tostring(raw_output), 2)
end
if type(raw_output) ~= "number" then
if not cfg.suppress_warnings then
if cfg.debug then
vim.notify(
"ninjection.select() warning: Could not get current buffer " .. "calling vim.api.nvim_get_current_buf()",
vim.log.levels.WARN
@@ -58,15 +59,15 @@ function ninjection.select()
bufnr = raw_output
---@cast bufnr integer

node_info, err = parse.get_node_table(cfg.inj_lang_query, cfg.file_lang)
node_info, err = parse.get_node_table(bufnr)
if not node_info then
if not cfg.suppress_warnings then
if cfg.debug then
vim.notify("ninjection.select() warning: could not retrieve TSNode: " .. tostring(err), vim.log.levels.WARN)
end
return nil
end
if not node_info.node then
if not cfg.suppress_warnings then
if cfg.debug then
vim.notify("ninjection.select() warning: No valid TSNode returned.", vim.log.levels.WARN)
end
return nil
@@ -76,7 +77,7 @@ function ninjection.select()
local v_range
v_range, err = parse.get_visual_range(node_info.node, bufnr)
if not v_range then
if not cfg.suppress_warnings then
if cfg.debug then
vim.notify("ninjection.select() warning: no visual range returned: " .. tostring(err), vim.log.levels.WARN)
end
return nil
@@ -115,7 +116,7 @@ end
--- and information to replace text in the parent buffer. It also appends the child
--- buffer handle to an `NJParent` object in the parent buffer.
---
---@return string? err
---@return nil
---
function ninjection.edit()
---@type boolean, unknown, string?, integer?, string?, string?
@@ -135,9 +136,9 @@ function ninjection.edit()

---@type NJNodeTable?
local inj_node_info
inj_node_info, err = parse.get_node_table(cfg.inj_lang_query, cfg.file_lang)
inj_node_info, err = parse.get_node_table(p_bufnr)
if not inj_node_info then
if not cfg.suppress_warnings then
if cfg.debug then
vim.notify(
"ninjection.edit() waring: Failed to get injected node " .. "information: " .. tostring(err),
vim.log.levels.WARN
@@ -175,7 +176,7 @@ function ninjection.edit()
return nil
end

inj_node_lang, err = parse.get_inj_lang(cfg.inj_lang_query, p_bufnr, cfg.file_lang)
inj_node_lang, err = parse.get_inj_lang(p_bufnr)
if not inj_node_lang or inj_node_lang == "" then
error(
"ninjection.edit() error: Failed to get injected node language "
@@ -198,7 +199,7 @@ function ninjection.edit()
if type(raw_output) == "table" then
p_cursor = raw_output
---@cast p_cursor integer[]
elseif not cfg.suppress_warnings then
elseif cfg.debug then
vim.notify(
"ninjection.edit() warning: No cursor position returned from " .. "vim.api.nvim_win_get_cursor(0)",
vim.log.levels.WARN
@@ -215,7 +216,7 @@ function ninjection.edit()
error(tostring(raw_output), 2)
end
if type(raw_output) ~= "string" then
if not cfg.suppress_warnings then
if cfg.debug then
vim.notify(
"ninjection.edit() warning: No name returned from " .. "vim.api.nvim_buf_get_name(0)",
vim.log.levels.WARN
@@ -273,7 +274,7 @@ function ninjection.edit()
local lsp_status
lsp_status, err = buffer.start_lsp(inj_node_lang, root_dir)
if not lsp_status then
if not cfg.suppress_warnings then
if cfg.debug then
vim.notify("ninjection.edit() warning: starting LSP " .. err, vim.log.levels.WARN)
-- Don't return early on LSP failure
end
@@ -320,7 +321,7 @@ end
--- table as an `NJParent` table in the child, and `NJChild` table indexed by the
--- child bufnr in the parent. This relationship is validated before replacing.
---
---@return string? err
---@return nil
---
function ninjection.replace()
---@type boolean, unknown, string?, integer?
@@ -350,7 +351,7 @@ function ninjection.replace()
if not ok or type(raw_output) ~= "table" then
err = tostring(raw_output)
if err:find("Key not found: ninjection") then
if not cfg.suppress_warnings then
if cfg.debug then
vim.notify(
"ninjection.replace() warning: This buffer is not a valid " .. "ninjection buffer.",
vim.log.levels.WARN
@@ -397,7 +398,7 @@ function ninjection.replace()
---@type integer[]
local this_cursor = raw_output
if not this_cursor[2] then
if not cfg.suppress_warnings then
if cfg.debug then
vim.notify(
"ninjection.replace() warning: No child cursor values returned by vim.api.nvim_win_get_cursor(0)",
vim.log.levels.WARN
@@ -418,7 +419,7 @@ function ninjection.replace()
---@type string[]
local rep_text = raw_output
if not rep_text or rep_text == "" then
if not cfg.suppress_warnings then
if cfg.debug then
vim.notify(
"ninjection.replace() warning: No replacement text returned " .. "by vim.api.nvim_buf_get_lines()",
vim.log.levels.WARN
@@ -430,7 +431,7 @@ function ninjection.replace()
if cfg.preserve_indents then
raw_output, err = buffer.restore_indents(rep_text, nj_child_b.p_indents)
if not raw_output or type(raw_output) ~= "table" then
if not cfg.suppress_warnings then
if cfg.debug then
vim.notify(
"ninjection.replace() warning: buffer.restore_indents() could not restore indents: " .. err,
vim.log.levels.WARN
@@ -469,7 +470,7 @@ function ninjection.replace()
end)
if not ok then
err = tostring(raw_output)
if not cfg.suppress_warnings then
if cfg.debug then
vim.notify(
"ninjection.replace() warning: could not remove child buffer "
.. "entry from parent buffer after deleting buffer."
@@ -503,7 +504,7 @@ function ninjection.replace()
end)
if not ok then
err = tostring(raw_output)
if not cfg.suppress_warnings then
if cfg.debug then
vim.notify(
"ninjection.replace() warning: could not restore cursor position in the parent buffer." .. err,
vim.log.levels.WARN
130 changes: 78 additions & 52 deletions lua/ninjection/parse.lua
Original file line number Diff line number Diff line change
@@ -3,34 +3,65 @@
--- The parse module contains all treesitter related functions for ninjection.
---
local M = {}
---@type Ninjection.Config
local cfg = require("ninjection.config").values
local ts = require("vim.treesitter")

---@nodoc
---@param bufnr integer Buffer handle to check filetype support.
---@return string? ft Filetype language, if supported
local function check_lang(bufnr)
---@type boolean, unknown?
local ok, raw_output = pcall(function ()
return vim.api.nvim_get_option_value("filetype", {buf = bufnr})
end)
if not ok then
error("ninjeciton.parse.get_node_table() error: " .. tostring(raw_output), 2)
end
if type(raw_output) ~= "string" then
if cfg.debug then
vim.notify("ninjeciton.parse.get_node_table() warning: no filetype detected",
vim.log.levels.WARN )
end
end
local ft = raw_output
---@cast ft string

local query = cfg.inj_lang_queries[ft]
if not query or type(query) ~= "string" or query == "" then
if cfg.debug then
vim.notify("ninjeciton.parse.get_node_table() warning: injected language " ..
"query available for filetype: " .. ft, vim.log.levels.WARN )
end
return nil
end
return ft
end

---@tag ninjection.parse.qet_query()
---@brief
--- Retrieves a parsed query from Treesitter given a language and pattern.
---
--- Parameters ~
---@param query string - Lua-literal string for Treesitter query.
---@param lang? string? - Default: `"nix"` - language grammar to parse with.
---
---@return vim.treesitter.Query? parsed_query, string? err
---@return vim.treesitter.Query? parsed_query
---The parsed Treesitter Query object
---
M.get_query = function(query, lang)
M.get_query = function(lang)
lang = lang or "nix"
---@cast lang string
---@type boolean, unknown, vim.treesitter.Query?
local ok, raw_output, parsed_query

ok, raw_output = pcall(function()
return ts.query.parse(lang, query)
return ts.query.parse(lang, cfg.inj_lang_queries[lang])
end)
if not ok then
error(tostring(raw_output), 2)
end
if not raw_output.query then
if cfg.suppress_warnings == false then
if cfg.debug then
vim.notify(
"ninjection.parse.get_query() warning: No Query result "
.. "returned from calling vim.treesitter.query.parse()",
@@ -53,7 +84,7 @@ end
---@param bufnr integer - Handle for buffer to parse.
---@param lang? string - Default: `"nix"` - language to parse with.
---
---@return TSNode? root, string? err
---@return TSNode? root
--- Root node of the TSTree for the language.
---
M.get_root = function(bufnr, lang)
@@ -67,7 +98,7 @@ M.get_root = function(bufnr, lang)
error("ninjection.parse.get_root() error: " .. tostring(raw_output), 2)
end
if not raw_output then
if cfg.suppress_warnings == false then
if cfg.debug then
vim.notify(
"ninjection.parse.get_root() warning: No parser available " .. "for: " .. lang,
vim.log.levels.WARN
@@ -81,7 +112,7 @@ M.get_root = function(bufnr, lang)
---@type TSTree?
local tree = parser:parse()[1]
if not tree then
if cfg.suppress_warnings == false then
if cfg.debug then
vim.notify(
"ninjection.parse.get.root() warning: No syntax tree found " .. "for " .. lang,
vim.log.levels.WARN
@@ -94,7 +125,7 @@ M.get_root = function(bufnr, lang)
---@type TSNode?
local root = tree:root()
if not root then
if cfg.suppress_warnings == false then
if cfg.debug then
vim.notify(
"ninjection.parse.get.root() warning: No syntax tree root " .. "found for " .. lang,
vim.log.levels.WARN
@@ -112,8 +143,7 @@ end
--- with start and ending coordinates.
---
--- Parameters ~
---@param query string - Pattern to identify an injected lang.
---@param lang? string - Default: `"nix"` language grammar to use for parsing.
---@param bufnr integer - The buffer handle to query in.
---
---@return NJNodeTable? table, string? err
--- Returns a table containing:
@@ -122,22 +152,15 @@ end
--- NOTE: Coordinates may not match the actual text locations
--- (see: `ninjection.parse.get_visual_range()` for this).
--
M.get_node_table = function(query, lang)
lang = lang or "nix"
---@type boolean, unknown, string?, integer?, integer[]?
local ok, raw_output, err, bufnr, cursor
M.get_node_table = function(bufnr)
---@type boolean, unknown, string?, integer[]?
local ok, raw_output, err, cursor

ok, raw_output = pcall(function()
return vim.api.nvim_get_current_buf()
end)
if not ok then
error("ninjection.parse.get_node_table() error: " .. tostring(raw_output), 2)
end
if type(raw_output) ~= "number" then
error("ninjection.parse.get_node_table() error: No buffer handle returned: " .. tostring(raw_output), 2)
local ft = check_lang(bufnr)
if not ft then
return nil
end
bufnr = raw_output
---@cast bufnr integer
---@cast ft string

ok, raw_output = pcall(function()
return vim.api.nvim_win_get_cursor(0) -- current window cursor position
@@ -146,7 +169,7 @@ M.get_node_table = function(query, lang)
error("ninjection.parse.get_node_table() error: " .. tostring(raw_output), 2)
end
if type(raw_output) ~= "table" then
if cfg.suppress_warnings == false then
if cfg.debug then
vim.notify(
"ninjection.parse.get_node_table() warning: Could not "
.. "determine cursor location in current window from "
@@ -166,9 +189,9 @@ M.get_node_table = function(query, lang)

--- @type vim.treesitter.Query?
local parsed_query
parsed_query, err = M.get_query(query, lang)
parsed_query, err = M.get_query(ft)
if not parsed_query then
if cfg.suppress_warnings == false then
if cfg.debug then
vim.notify(
"ninjection.parse.get_node_info() warning: get_query() " .. " returned nil: " .. tostring(err),
vim.log.levels.WARN
@@ -182,7 +205,7 @@ M.get_node_table = function(query, lang)
local root
root, err = M.get_root(bufnr)
if not root then
if cfg.suppress_warnings == false then
if cfg.debug then
vim.notify(
"ninjection.parse.get_node_table() warning: No root " .. "returned: " .. tostring(err),
vim.log.levels.WARN
@@ -220,7 +243,7 @@ M.get_node_table = function(query, lang)
end
end

if cfg.suppress_warnings == false then
if cfg.debug then
vim.notify(
"ninjection.parse.get_node_table(): No injection.content " .. "id found in node.",
vim.log.levels.WARN
@@ -235,21 +258,24 @@ end
--- Parse an injected content node for an associated language comment.
---
--- Parameters ~
---@param query string - Query to identify an injected content node.
---@param bufnr integer - Handle for the buffer to query in.
---@param file_lang? string - Default: `"nix"` - Parent file language to find
--- injections in.
---
---@return string? inj_lang , string? err - Injected language identified.
---
M.get_inj_lang = function(query, bufnr, file_lang)
---@type boolean, any|nil, string|nil, vim.treesitter.Query|nil
local ok, raw_output, err, parsed_query
file_lang = file_lang or "nix"
M.get_inj_lang = function(bufnr)
---@type boolean, unknown, string?, vim.treesitter.Query?, string?
local ok, raw_output, err, parsed_query, ft

ft = check_lang(bufnr)
if not ft then
return nil
end
---@cast ft string

parsed_query, err = M.get_query(query, file_lang)
parsed_query, err = M.get_query(ft)
if not parsed_query then
if cfg.suppress_warnings == false then
if cfg.debug then
vim.notify(
"ninjection.parse.get_inj_lang() warning: Could not parse "
.. "the Treesitter query with get_query(): "
@@ -263,9 +289,9 @@ M.get_inj_lang = function(query, bufnr, file_lang)

---@type TSNode|nil
local root
root, err = M.get_root(bufnr, file_lang)
root, err = M.get_root(bufnr, ft)
if not root then
if cfg.suppress_warnings == false then
if cfg.debug then
vim.notify(
"ninjection.parse.get_inj_lang() warning: Could not "
.. "determine the syntax tree root from get_root(): "
@@ -279,9 +305,9 @@ M.get_inj_lang = function(query, bufnr, file_lang)

---@type NJNodeTable|nil
local node_info
node_info, err = M.get_node_table(cfg.inj_lang_query, file_lang)
node_info, err = M.get_node_table(bufnr)
if not node_info then
if cfg.suppress_warnings == false then
if cfg.debug then
vim.notify(
"ninjection.parse.get_inj_lang() warning: Could not "
.. "determine injected content calling get_node_table(): "
@@ -296,7 +322,7 @@ M.get_inj_lang = function(query, bufnr, file_lang)
---@type integer|nil
local node_s_row = node_info.range.s_row
if not node_s_row then
if cfg.suppress_warnings == false then
if cfg.debug then
vim.notify(
"ninjection.parse.get_inj_lang() warning: Could not "
.. "determine injected language starting row calling get_node_table(): ",
@@ -341,7 +367,7 @@ M.get_inj_lang = function(query, bufnr, file_lang)
end
candidate_text = raw_output
if not candidate_text then
if cfg.suppress_warnings == false then
if cfg.debug then
vim.notify(
"ninjection.get_inj_lang warning: Could not retrieve "
.. "injected language text calling vim.treesitter.get_node_text()"
@@ -359,7 +385,7 @@ M.get_inj_lang = function(query, bufnr, file_lang)
---@type string|nil
local inj_lang = candidate_text:gsub("^#%s*", "")
if not inj_lang then
if cfg.suppress_warnings == false then
if cfg.debug then
vim.notify(
"ninjection.parse.get_inj.lang() warning: No language " .. "comment could be parsed.",
vim.log.levels.WARN
@@ -374,7 +400,7 @@ M.get_inj_lang = function(query, bufnr, file_lang)
return inj_lang
end

if cfg.suppress_warnings == false then
if cfg.debug then
vim.notify(
"ninjection.parse.get_inj.lang() warning: No supported "
.. "injected languages were found. Check your configuration.",
@@ -384,7 +410,7 @@ M.get_inj_lang = function(query, bufnr, file_lang)
return nil
end

if cfg.suppress_warnings == false then
if cfg.debug then
vim.notify(
"ninjection.parse.get_inj.lang() warning: No injected languages " .. "were found.",
vim.log.levels.WARN
@@ -418,12 +444,12 @@ end
---@return NJRange? vs_range, string? err - Range of text selected.
---
M.get_visual_range = function(node, bufnr)
---@type boolean, any|nil, string|nil, integer[]|nil
---@type boolean, unknown, string?, integer[]?
local ok, raw_output, err, range

range = { node:range() }
if not range or #range < 4 then
if cfg.suppress_warnings == false then
if cfg.debug then
vim.notify(
"ninjection.parse.get_visual_range() warning: No valid " .. " selection range found in range()",
vim.log.levels.WARN
@@ -442,7 +468,7 @@ M.get_visual_range = function(node, bufnr)
---@type string[]|nil
local raw_lines = raw_output
if not raw_lines or #raw_lines == 0 then
if cfg.suppress_warnings == false then
if cfg.debug then
vim.notify(
"ninjection.parse.get_visual_range() warning: Nothing "
.. "returned from calling vim.api.nvim_buf_get_lines()",
@@ -462,7 +488,7 @@ M.get_visual_range = function(node, bufnr)
---@type string|nil
local visual_text = raw_output
if not visual_text then
if cfg.suppress_warnings == false then
if cfg.debug then
vim.notify(
"ninjection.parse.get_visual_range() warning: No text "
.. "returned from vim.treesitter.get_node_text()",
@@ -487,7 +513,7 @@ M.get_visual_range = function(node, bufnr)
---@type string[]|nil
local visual_lines = raw_output
if not visual_lines or #visual_lines == 0 then
if cfg.suppress_warnings == false then
if cfg.debug then
vim.notify(
"ninjection.parse.get_visual_range(): No strings returned" .. "from vim.split()",
vim.log.levels.WARN
11 changes: 1 addition & 10 deletions lua/ninjection/types.lua
Original file line number Diff line number Diff line change
@@ -37,10 +37,6 @@
---@class Ninjection.Config
---@brief Implemented by `ninjection/config.lua` for default and user configs.
---
---@field file_lang? string - File type to search for injected languages in.
--- Must have a matching entry in `inj_lang_queries`.
--- Currently only supports nix, but could be extended.
---
---@field preserve_indents? boolean - Preserve indents from the parent buffer.
--- This option should be used in conjunction with `auto_format` because this
--- will re-apply indents that `auto_format` normally removes. If you don't remove
@@ -64,19 +60,14 @@
--- `end content'';
---
---@field register? string - Register to use to copy injected content.
---@field suppress_warnings? boolean - Suppress warnings.
--- NOTE: If ninjection is not functioning properly, ensure this is false for
--- debugging.
---@field debug? boolean - Output debug messages.
---
---@field editor_style? EditorStyle
--- Window style to use for the injected context editor.
---
---@field inj_lang_queries? table<string,string> - Contains per-language string
--- literals for Treesitter queries to Identify injected content nodes.
---
---@field inj_lang_query? string This is configured by referencing `file_lang`
--- in the table of `inj_lang_queries`. This cannot be nil.
---
---@field lsp_map? table<string,string> - LSP associated with the injected
--- languages These keys must match the language comment used to identify
--- injected languages, and the value must match the LSP configured in your