feat: add sql injections

This commit is contained in:
Kristofers Solo 2025-07-30 22:00:42 +03:00
parent 18671923c6
commit 40dda1c8f3
Signed by: kristoferssolo
GPG Key ID: 8687F2D3EEE6F0ED
7 changed files with 39 additions and 120 deletions

View File

@ -1,102 +0,0 @@
local run_formatter = function(text)
local split = vim.split(text, "\n")
local result = table.concat(vim.list_slice(split, 2, #split - 1), "\n")
local j = require("plenary.job"):new({
command = "sqruff",
args = { "format", "-" },
writer = { result },
})
return j:sync()
end
local literals = {
rust = { "string_literal", "raw_string_literal" },
python = { "string_content" },
}
local function generate_query(lang, nodes)
local node_string = table.concat(nodes, ")\n\t\t(")
local query = string.format(
[[
([
(%s)
] @sql
(#match? @sql "(SELECT|select|INSERT|insert|UPDATE|update|DELETE|delete).+(FROM|from|INTO|into|VALUES|values|SET|set).*(WHERE|where|GROUP BY|group by)?")
(#offset! @sql 1 0 -1 0))
]],
node_string
)
return lang, query
end
local queries = {}
for lang, nodes in pairs(literals) do
local language, query_string = generate_query(lang, nodes)
queries[lang] = {
language = language,
query = query_string,
}
end
local get_root = function(bufnr, lang)
local parser = vim.treesitter.get_parser(bufnr, lang, {})
local tree = parser:parse()[1]
return tree:root()
end
local format_dat_sql = function(bufnr)
bufnr = bufnr or vim.api.nvim_get_current_buf()
local changes = {}
for _, query in pairs(queries) do
local root = get_root(bufnr, query.language)
-- if vim.bo[bufnr].filetype ~= query.language then
-- vim.notify("can only be used in {}", query.language)
-- return
-- end
local embedded_sql = vim.treesitter.query.parse(query.language, query.query)
for id, node in embedded_sql:iter_captures(root, bufnr, 0, -1) do
local name = embedded_sql.captures[id]
if name == "sql" then
-- { start row, start col, end row, end col }
local range = { node:range() }
local indentation = string.rep(" ", range[2])
-- Run the formatter, based on the node text
local formatted = run_formatter(vim.treesitter.get_node_text(node, bufnr))
-- Add some indentation (can be anything you like!)
for idx, line in ipairs(formatted) do
formatted[idx] = indentation .. line
end
-- Keep track of changes
-- But insert them in reverse order of the file,
-- so that when we make modifications, we don't have
-- any out of date line numbers
table.insert(changes, 1, {
start = range[1] + 1,
final = range[3],
formatted = formatted,
})
end
end
end
for _, change in ipairs(changes) do
vim.api.nvim_buf_set_lines(bufnr, change.start, change.final, false, change.formatted)
end
end
vim.api.nvim_create_user_command("SqlMagic", function()
format_dat_sql()
end, {})
local group = vim.api.nvim_create_augroup("rust-sql-magic", { clear = true })
vim.api.nvim_create_autocmd("BufWritePre", {
group = group,
pattern = "*.rs",
callback = function()
format_dat_sql()
end,
})

View File

@ -1,7 +1,9 @@
;extends
([
(string_content)
(string)
] @injection.content
(#match? @injection.content "(SELECT|select|INSERT|insert|UPDATE|update|DELETE|delete).+(FROM|from|INTO|into|VALUES|values|SET|set).*(WHERE|where|GROUP BY|group by)?")
(#offset! @injection.content 0 1 0 -1)
(#set! injection.language "sql"))
(#match? @injection.content "(SELECT|select|INSERT|insert|UPDATE|update|DELETE|delete).+(FROM|from|INTO|into|VALUES|values|SET|set).*(WHERE|where|GROUP BY|group by|ORDER BY|order by)?")
(#offset! @injection.content 0 3 0 -3)
(#set! injection.language "sql")
(#set! injection.include-children)
)

View File

@ -4,9 +4,11 @@
(string_literal)
(raw_string_literal)
] @injection.content
(#match? @injection.content "(SELECT|select|INSERT|insert|UPDATE|update|DELETE|delete).+(FROM|from|INTO|into|VALUES|values|SET|set).*(WHERE|where|GROUP BY|group by)?")
(#offset! @injection.content 0 1 0 -1)
(#set! injection.language "sql"))
(#match? @injection.content "(SELECT|select|INSERT|insert|UPDATE|update|DELETE|delete).+(FROM|from|INTO|into|VALUES|values|SET|set).*(WHERE|where|GROUP BY|group by|ORDER BY|order by)?")
(#offset! @injection.content 0 3 0 -2)
(#set! injection.language "sql")
(#set! injection.include-children)
)
;; Inject HTML into view! macro blocks for leptos
(

View File

@ -6,7 +6,7 @@ if not (vim.uv or vim.loop).fs_stat(lazypath) then
if vim.v.shell_error ~= 0 then
vim.api.nvim_echo({
{ "Failed to clone lazy.nvim:\n", "ErrorMsg" },
{ out, "WarningMsg" },
{ out, "WarningMsg" },
{ "\nPress any key to exit..." },
}, true, {})
vim.fn.getchar()

View File

@ -1,4 +1,7 @@
local js = { "biome", "biome-check" }
local html = { "djlint", "rustywind" }
local makrdown = { "cbfmt", "markdownlint", "markdown-toc" }
return {
"stevearc/conform.nvim",
event = { "BufWritePre" },
@ -16,20 +19,21 @@ return {
opts = {
formatters_by_ft = {
["_"] = { "trim_whitespace" },
["*"] = { "injected" },
bash = { "shfmt" },
c = { "clang-format" },
cmake = { "cmake_format" },
cpp = { "clang-format" },
css = { "prettier" },
go = { "goimports", "gofmt" },
html = { "djlint", "rustywind" },
htmldjango = { "djlint", "rustywind" },
html = html,
htmldjango = html,
http = { "kulala-fmt" },
javascript = js,
javascriptreact = js,
json = { "jq" },
lua = { "stylua" },
markdown = { "cbfmt", "markdownlint", "markdown-toc" },
markdown = makrdown,
python = { "ruff_format", "ruff_fix", "ruff_organize_imports", "docformatter" },
rest = { "kulala" },
rust = { "rustfmt", "leptosfmt", "yew-fmt" },
@ -39,9 +43,19 @@ return {
typescript = js,
typescriptreact = js,
typst = { "typstyle" },
vimwiki = { "cbfmt", "markdownlint", "markdown-toc" },
vimwiki = makrdown,
yaml = { "yamlfmt" },
},
formatters = {
sqruff = {
prepend_args = function(_self, _ctx)
return {
"--config",
vim.fn.expand("~/.config/sqruff/config.cfg"),
}
end,
},
},
format_on_save = {
timeout_ms = 500,
lsp_format = "fallback",

View File

@ -4,16 +4,16 @@ return {
opts = {
events = { "InsertLeave", "BufWritePost", "BufReadPost", "InsertEnter" },
linters_by_ft = {
["*"] = { "codespell", "typos" },
cmake = { "cmakelint" },
htmldjango = { "djlint" },
javascript = js,
javascriptreact = js,
lua = { "selene" },
python = { "mypy" },
sql = { "sqruff" },
typescript = js,
typescriptreact = js,
python = { "mypy" },
htmldjango = { "djlint" },
sql = { "sqruff" },
lua = { "selene" },
cmake = { "cmakelint" },
["*"] = { "codespell", "typos" },
},
},
config = function(_, opts)

View File

@ -41,6 +41,9 @@ return {
},
},
},
semanticHighlighting = {
strings = { enable = false },
},
},
},
},