summaryrefslogtreecommitdiff
path: root/plugin
diff options
context:
space:
mode:
authorChristian Segundo2023-10-08 01:59:18 +0200
committerChristian Segundo2023-10-08 01:59:18 +0200
commita4644e03b1aa7daf0f2d4c0474d04c3b3aabebbd (patch)
tree90ab0f6151a8bd1efae60111c5a204cb9435102d /plugin
parentb816ee2793da722f5aa27f9f5a2fd077a6dfc091 (diff)
downloadpromqlfmt-a4644e03b1aa7daf0f2d4c0474d04c3b3aabebbd.tar.gz
first commit
Diffstat (limited to 'plugin')
-rw-r--r--plugin/promql.lua130
1 files changed, 130 insertions, 0 deletions
diff --git a/plugin/promql.lua b/plugin/promql.lua
new file mode 100644
index 0000000..e44d1c3
--- /dev/null
+++ b/plugin/promql.lua
@@ -0,0 +1,130 @@
+-- How it started
+--vim.api.nvim_create_user_command(
+-- "Promqlfmt",
+-- '<line1>,<line2>!promtool promql format --experimental "$(cat /dev/stdin)"',
+-- { nargs = 0, range = "%" }
+--)
+
+-- How it's going
+if vim.g.promqlfmt == 1 then
+ return
+end
+
+vim.g.promqlfmt = 1
+
+--- Format a PromQL query using promtool
+--- @param query string @query to format
+--- @param padding number|nil @number of spaces to add to each line, default 0
+--- @param padchar string|nil @character for padding, default " "
+--- @return string[]|nil @formatted query, one element per line or nil
+local promql_format = function(query, padding, padchar)
+ padding = padding or 0
+ padchar = padchar or " "
+
+ local success, result = pcall(function()
+ return vim
+ .system(
+ { "promtool", "promql", "format", "--experimental", query },
+ { text = true }
+ )
+ :wait()
+ end)
+
+ if success and result and result.code == 0 then
+ local lines = vim.fn.split(result.stdout, "\n")
+ if padding == 0 then
+ return lines
+ end
+
+ for i, line in ipairs(lines or {}) do
+ lines[i] = (padchar):rep(padding) .. line
+ end
+ return lines
+ else
+ print("woops error occurred while formatting query")
+ print(vim.inspect(result))
+ end
+end
+
+--- Get the last column of a line, ie the position of the last character
+--- @param bufnr number
+--- @param linenr number
+local last_col_line = function(bufnr, linenr)
+ local line = vim.api.nvim_buf_get_lines(bufnr, linenr, linenr + 1, true)[1]
+ return #line
+end
+
+--- Get the selected text in a buffer
+--- @param bufnr number|nil
+--- @return table
+local buf_get_selected_text = function(bufnr)
+ local r = {
+ text = "",
+ start_line = nil,
+ start_row = nil,
+ end_line = nil,
+ end_row = nil,
+ }
+ local region = vim.region(bufnr or 0, "'<", "'>", vim.fn.visualmode(), true)
+ local maxcol = vim.v.maxcol
+ for line, cols in vim.spairs(region) do
+ if r.start_line == nil then
+ r.start_line = line
+ r.start_row = cols[1]
+ end
+
+ local endcol = cols[2] == maxcol and -1 or cols[2]
+ local chunk =
+ vim.api.nvim_buf_get_text(0, line, cols[1], line, endcol, {})[1]
+ r.text = ("%s%s\n"):format(r.text, chunk)
+
+ r.end_line = line
+ r.end_row = endcol
+ end
+
+ r.end_row = r.end_row > last_col_line(0, r.end_line) and -1 or r.end_row
+ return r
+end
+
+vim.api.nvim_create_user_command("Promqlfmt", function(opts)
+ -- it was not called from a visual selection
+ if opts.range == 0 then
+ -- get all lines
+ local buf_text = vim.api.nvim_buf_get_lines(0, 0, -1, true)
+ -- format query
+ local text_formatted = promql_format(table.concat(buf_text, "\n"))
+ if text_formatted == nil then
+ return
+ end
+ -- replace all text with the formatted version
+ vim.api.nvim_buf_set_lines(0, 0, -1, true, text_formatted)
+ return
+ end
+
+ local s = buf_get_selected_text()
+ -- use the position of the first non-whitespace character of the first line
+ -- as padding
+ local padding = string.find(
+ vim.api.nvim_buf_get_lines(0, s.start_line, s.start_line + 1, true)[1],
+ "%S"
+ ) - 1
+ local text_formatted = promql_format(s.text, padding)
+
+ if text_formatted == nil then
+ return
+ end
+
+ -- remove padding from first line
+ if s.start_row ~= 0 then
+ text_formatted[1] = text_formatted[1]:sub(padding + 1)
+ end
+
+ vim.api.nvim_buf_set_text(
+ 0,
+ s.start_line,
+ s.start_row,
+ s.end_line,
+ s.end_row,
+ text_formatted
+ )
+end, { nargs = 0, range = "%" })