tsql.nvim/lua/tsql.lua

142 lines
3.5 KiB
Lua

---@type mod_buf_select
local buf_select = require('tsql.buf_select')
---@type mod_token_select
local token_select = require('tsql.token_select')
---@module 'tsql'
local M = {}
---@class mod_sink_by
M.sink_by = {}
---@class mod_format
---@alias Format fun(nodes: QNode[]): string
M.format = {}
M.nvim_ns = vim.api.nvim_create_namespace("tsql")
M.nvim_hl_group = "Search"
---@class Sink
---@field sink fun(self, nodes: QNode[])
M.Sink = {}
M.Sink.__index = M.Sink
---@return Sink
function M.sink_by.highlight()
return setmetatable({
---@type fun(nodes: QNode[])
sink = function(nodes)
for _, node in ipairs(nodes) do
vim.highlight.range(
node.buf.bufnr,
M.nvim_ns,
M.nvim_hl_group,
{ node.start.row_0, node.start.col_0 },
{ node.end_ex_col.row_0, node.end_ex_col.col_0 },
{}
)
end
end
}, M.Sink)
end
---@type Format
---Something that can be represented in string in a concise/DSL format.
---In the context of QNode, it should just be the text content. If it's multiline,
---just join by newline
---
---`vim.api.nvim_buf_get_text(
--- bufnr: number,
--- start_row: number,
--- start_col: number,
--- end_row: number,
--- end_col_exclusive: number,
--- opt: {}
---) -> string[]` return value is array of lines, empty array for unloaded buffer
function M.format.display(nodes)
local texts = {}
for _, node in ipairs(nodes) do
local text = vim.api.nvim_buf_get_text(node.buf.bufnr, node.start.row_0, node.start.col_0, node.end_ex_col.row_0,
node.end_ex_col.col_0)
table.insert(texts, table.concat(text, '\n'))
end
return table.concat(texts, '\n\n')
end
---@type Format
---Something like a JSON if natively possible, or RON for Rust for clarity
---Basically return a string that is pretty-printed that represents
---a Lua table onto string
function M.format.dump(nodes)
return vim.inspect(nodes, { newline = '\n', indent = ' ' })
end
---@param format Format
---@return Sink
function M.sink_by.print(format)
return setmetatable({
---@type fun(nodes: QNode[])
sink = function(nodes)
print(format(nodes))
end
}, M.Sink)
end
---@param format Format
---@return Sink
function M.sink_by.nvim_yank_buf(format)
return setmetatable({
---@type fun(nodes: QNode[])
sink = function(nodes)
local text = format(nodes)
vim.fn.setreg('"', text)
end
}, M.Sink)
end
---NOTE: re-export with implementation
M.buf_match = buf_select.buf_match
M.BufMatch = buf_select.BufMatch
M.QBuf = buf_select.QBuf
M.nvim_get_qbufs = buf_select.nvim_get_qbufs
M.ts_query = token_select.ts_query
M.TSQuery = token_select.TSQuery
---@class Tsql
---@field buf_match BufMatch
---@field codeql TSQuery
---@field sink Sink
M.Tsql = {}
M.Tsql.__index = M.Tsql
---@return Tsql
---@param external_dsl string
function M.s(external_dsl)
-- TODO: implement
end
---@return Tsql
---@param buf_match BufMatch
---@param codeql TSQuery
---@param sink Sink
function M.t(buf_match, codeql, sink)
return setmetatable({
buf_match = buf_match,
codeql = codeql,
sink = sink
}, M.Tsql)
end
---NOTE: This is now exiting the functional core and entering
--- imperative shell
function M.Tsql:do_nvim()
self.sink:sink(
self.codeql:find_nodes(
self.buf_match:filter_on(M.nvim_get_qbufs())
)
)
end
return M