From b1954a147a21ad934e826de7ce3332e92abf0913 Mon Sep 17 00:00:00 2001 From: "RingOfStorms (Joshua Bell)" Date: Mon, 31 Jul 2023 01:51:47 -0500 Subject: [PATCH] sqlformat refactor --- lua/keymaps.lua | 3 +- lua/plugins/null-ls.lua | 122 +------------------------------------- lua/tools/sqlx-format.lua | 119 +++++++++++++++++++++++++++++++++++++ 3 files changed, 123 insertions(+), 121 deletions(-) create mode 100644 lua/tools/sqlx-format.lua diff --git a/lua/keymaps.lua b/lua/keymaps.lua index 9252121..a282601 100644 --- a/lua/keymaps.lua +++ b/lua/keymaps.lua @@ -38,11 +38,12 @@ require("util").keymaps({ -- reformat LSP ["lf"] = { function() - vim.cmd "SqlMagic" + -- vim.cmd "SqlxFormat" vim.lsp.buf.format() end, desc = "Reformat file", }, + ["lsf"] = { "SqlxFormat", desc = "Format sqlx queries in rust raw string literals." }, ["ld"] = { function() vim.diagnostic.open_float() diff --git a/lua/plugins/null-ls.lua b/lua/plugins/null-ls.lua index 2d7b0d9..5706b9c 100644 --- a/lua/plugins/null-ls.lua +++ b/lua/plugins/null-ls.lua @@ -14,124 +14,6 @@ function prereqs() end end --- https://github.com/darold/pgFormatter - -local rust_sqlx_f = function() - return vim.treesitter.query.parse( - "rust", - [[ -; query macro -(macro_invocation - (scoped_identifier - path: (identifier) @_path (#eq? @_path "sqlx") - name: (identifier) @_name (#any-of? @_name "query" "query_scalar")) - - (token_tree - . (raw_string_literal) @sql (#offset! @sql 1 0 -1 0)) - ) - -; query_as macro -(macro_invocation - (scoped_identifier - path: (identifier) @_path (#eq? @_path "sqlx") - name: (identifier) @_name (#eq? @_name "query_as")) - - (token_tree - (_) . (raw_string_literal) @sql (#offset! @sql 1 0 -1 0)) - - ) - -; query and query_as function -(call_expression - (scoped_identifier - path: (identifier) @_path (#eq? @_path "sqlx") - name: (identifier) @_name (#contains? @_name "query")) - - (arguments - (raw_string_literal) @sql (#offset! @sql 1 0 -1 0)) - ) - ]] - ) -end - -local get_root = function(bufnr) - local parser = vim.treesitter.get_parser(bufnr, "rust", {}) - local tree = parser:parse()[1] - return tree:root() -end - -local format_dat_sql = function(bufnr) - local rust_sqlx = rust_sqlx_f() - bufnr = bufnr or vim.api.nvim_get_current_buf() - - if vim.bo[bufnr].filetype ~= "rust" then - vim.notify "can only be used in rust" - return - end - - local root = get_root(bufnr) - - local changes = {} - for id, node in rust_sqlx:iter_captures(root, bufnr, 0, -1) do - local name = rust_sqlx.captures[id] - if name == "sql" then - -- range: { row_start [1], col_start [2], row_end [3], col_end } - local range = { node:range() } - local indentation = string.rep(" ", range[2]) - - local node_text = vim.treesitter.get_node_text(node, bufnr) - if node_text:match('r#"\n(.*\n)+?%s*"#$') == nil then - -- text is invalid because it does not have newlines in raw string literal - goto continue - end - - local text = node_text:sub(4, -3) -- get just the inside of the raw string literal - -- TODO get current spaces for indentation and run pg_format with that indendation amount - local formatted = vim.fn.system({ "pg_format", "-L" }, text) - local lines = {} - for line in formatted:gmatch("[^\r\n]+") do - lines[#lines + 1] = line - end - - for idx, line in ipairs(lines) do - lines[idx] = indentation .. line - end - - -- Fix indentation of end of raw string literal as well - local last_line = vim.api.nvim_buf_get_lines(bufnr, range[3], range[3] + 1, true)[1]:match("^%s*(.*)") - -- print("LAST LINE", last_line) - lines[#lines + 1] = indentation .. last_line - - table.insert(changes, 1, { - start = range[1] + 1, - final = range[3] + 1, - formatted = lines, - }) - - -- changes[#changes + 1] = { - -- col = 0, - -- row = range[1] + 2, - -- end_col = -1, - -- end_row = range[3] + 1, - -- text = table.concat(lines, '\n'), - -- } - - ::continue:: - end - end - - -- return changes - - print("Change", vim.inspect(changes)) - 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, {}) - return { { "jose-elias-alvarez/null-ls.nvim", @@ -189,9 +71,9 @@ return { null_ls.builtins.formatting.prettier, -- typescript/javascript null_ls.builtins.formatting.stylua, -- lua --null_ls.builtins.formatting.rustfmt, -- rust - rust_formatter_genemichaels, -- order matters, we run genemichaels first then rustfmt + rust_formatter_genemichaels, -- order matters, run genemichaels first then rustfmt rust_formatter_rustfmt, - rust_formatter_sqlx, + -- rust_formatter_sqlx, -- see tools/sqlx-format.lua null_ls.builtins.formatting.black, -- python -- null_ls.builtins.code_actions.proselint, -- TODO looks interesting null_ls.builtins.code_actions.cspell.with({ diff --git a/lua/tools/sqlx-format.lua b/lua/tools/sqlx-format.lua new file mode 100644 index 0000000..8504832 --- /dev/null +++ b/lua/tools/sqlx-format.lua @@ -0,0 +1,119 @@ +--PREREQ: https://github.com/darold/pgFormatter + +-- Based on this video: https://www.youtube.com/watch?v=v3o9YaHBM4Q + +local rust_sqlx_f = function() + return vim.treesitter.query.parse( + "rust", + [[ +; query macro +(macro_invocation + (scoped_identifier + path: (identifier) @_path (#eq? @_path "sqlx") + name: (identifier) @_name (#any-of? @_name "query" "query_scalar")) + + (token_tree + . (raw_string_literal) @sql (#offset! @sql 1 0 -1 0)) + ) + +; query_as macro +(macro_invocation + (scoped_identifier + path: (identifier) @_path (#eq? @_path "sqlx") + name: (identifier) @_name (#eq? @_name "query_as")) + + (token_tree + (_) . (raw_string_literal) @sql (#offset! @sql 1 0 -1 0)) + ) + +; query and query_as function +(call_expression + (scoped_identifier + path: (identifier) @_path (#eq? @_path "sqlx") + name: (identifier) @_name (#contains? @_name "query")) + + (arguments + (raw_string_literal) @sql (#offset! @sql 1 0 -1 0)) + ) + ]] + ) +end + +local get_root = function(bufnr) + local parser = vim.treesitter.get_parser(bufnr, "rust", {}) + local tree = parser:parse()[1] + return tree:root() +end + +local format_dat_sql = function(bufnr) + local rust_sqlx = rust_sqlx_f() + bufnr = bufnr or vim.api.nvim_get_current_buf() + + if vim.bo[bufnr].filetype ~= "rust" then + vim.notify "can only be used in rust" + return + end + + local root = get_root(bufnr) + + local changes = {} + for id, node in rust_sqlx:iter_captures(root, bufnr, 0, -1) do + local name = rust_sqlx.captures[id] + if name == "sql" then + -- range: { row_start [1], col_start [2], row_end [3], col_end } + local range = { node:range() } + local indentation = string.rep(" ", range[2]) + + local node_text = vim.treesitter.get_node_text(node, bufnr) + if node_text:match('r#"\n(.*\n)+?%s*"#$') == nil then + -- text is invalid because it does not have newlines in raw string literal + goto continue + end + + local text = node_text:sub(4, -3) -- get just the inside of the raw string literal + -- TODO get current spaces for indentation and run pg_format with that indendation amount + local formatted = vim.fn.system({ "pg_format", "-L" }, text) + local lines = {} + for line in formatted:gmatch("[^\r\n]+") do + lines[#lines + 1] = line + end + + for idx, line in ipairs(lines) do + lines[idx] = indentation .. line + end + + -- Fix indentation of end of raw string literal as well + local last_line = vim.api.nvim_buf_get_lines(bufnr, range[3], range[3] + 1, true)[1]:match("^%s*(.*)") + -- print("LAST LINE", last_line) + lines[#lines + 1] = indentation .. last_line + + table.insert(changes, 1, { + start = range[1] + 1, + final = range[3] + 1, + formatted = lines, + }) + + -- Some left overs from me attempting to get this to work inside of a null_ls formatter + -- changes[#changes + 1] = { + -- col = 0, + -- row = range[1] + 2, + -- end_col = -1, + -- end_row = range[3] + 1, + -- text = table.concat(lines, '\n'), + -- } + + ::continue:: + end + end + + -- return changes + + -- print("Change", vim.inspect(changes)) + 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("SqlxFormat", function() + format_dat_sql() +end, {})