feat: probably first prototype
parent
606f654a54
commit
25d824714e
151
lua/tsql.lua
151
lua/tsql.lua
|
@ -1,55 +1,114 @@
|
|||
---@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 = {}
|
||||
|
||||
M.ts_query = {}
|
||||
---@class TSQuery
|
||||
M.TSQuery = {}
|
||||
---@class mod_sink_by
|
||||
M.sink_by = {}
|
||||
---@module 'tsql.format'
|
||||
---@alias Format fun(self, nodes: QNode[])
|
||||
|
||||
---@class mod_format
|
||||
---@alias Format fun(nodes: QNode[]): string
|
||||
M.format = {}
|
||||
---@class Tsql
|
||||
M.Tsql = {}
|
||||
|
||||
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 = require('tsql.buf_select')
|
||||
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
|
||||
|
||||
function M.ts_query.from_scm(treesitter_query)
|
||||
-- TODO: implement
|
||||
return M.TSQuery
|
||||
end
|
||||
M.ts_query = token_select.ts_query
|
||||
M.TSQuery = token_select.TSQuery
|
||||
|
||||
function M.TSQuery:find_locs(files)
|
||||
-- TODO: implement
|
||||
return {}
|
||||
end
|
||||
|
||||
function M.sink_by.highlight()
|
||||
-- TODO: implement
|
||||
end
|
||||
|
||||
---@type Format
|
||||
function M.format.display()
|
||||
-- TODO: implement
|
||||
end
|
||||
|
||||
---@type Format
|
||||
function M.format.dump()
|
||||
-- TODO: implement
|
||||
end
|
||||
|
||||
---@param format Format
|
||||
function M.sink_by.print(format)
|
||||
-- TODO: implement
|
||||
end
|
||||
|
||||
---@param format Format
|
||||
function M.sink_by.nvim_yank_buf(format)
|
||||
-- TODO: implement
|
||||
end
|
||||
---@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
|
||||
|
@ -62,13 +121,21 @@ end
|
|||
---@param codeql TSQuery
|
||||
---@param sink Sink
|
||||
function M.t(buf_match, codeql, sink)
|
||||
-- TODO: implement
|
||||
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()
|
||||
-- TODO: implement
|
||||
self.sink:sink(
|
||||
self.codeql:find_nodes(
|
||||
self.buf_match:filter_on(M.nvim_get_qbufs())
|
||||
)
|
||||
)
|
||||
end
|
||||
|
||||
return M
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
---@module 'buf_select'
|
||||
---@class mod_buf_select
|
||||
---@alias MatchPredicate fun(nodes: QNode[]): boolean
|
||||
local M = {}
|
||||
|
||||
---@alias MatchPredicate fun(nodes: QBuf): boolean
|
||||
|
||||
---@class QBuf
|
||||
---@field bufnr number representing the vim runtime's bufnr, 0 is current buf
|
||||
---@field path string the absolute path to the buffer. This uses
|
||||
|
@ -71,7 +72,7 @@ M.buf_match = {}
|
|||
---@field not_ fun(self): BufMatch
|
||||
---@field or_ fun(self, q: BufMatch): BufMatch
|
||||
---@field then_ fun(self, q: BufMatch): BufMatch
|
||||
---@field filter_on fun(self, q: QNode[]): QNode[]
|
||||
---@field filter_on fun(self, q: QBuf[]): QBuf[]
|
||||
M.BufMatch = {}
|
||||
|
||||
function M.buf_match.is_loaded()
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
local M = {}
|
||||
|
||||
---@class Sink
|
||||
M.Sink = {}
|
||||
|
||||
function M.print()
|
||||
|
|
|
@ -1,24 +1,59 @@
|
|||
---@module 'tsql.token_select'
|
||||
---@class mod_token_select
|
||||
local M = {}
|
||||
|
||||
---@class FileLoc
|
||||
---@field
|
||||
M.FileLoc = {
|
||||
}
|
||||
|
||||
---@class QNode
|
||||
M.QNode = {}
|
||||
|
||||
---@class mod_ts_query
|
||||
M.ts_query = {}
|
||||
---@class TSQuery
|
||||
---@field find_nodes fun(self: TSQuery, bufs: QBuf[]): TSNode[]
|
||||
---@field query string the passthru for treesitter language parser
|
||||
M.TSQuery = {}
|
||||
|
||||
---@param treesitter_q string Treesitter DSL for query
|
||||
---TODO: some examples of `treesitter_q` here
|
||||
---
|
||||
---@class FileLoc
|
||||
---@field row_0 number 0-index row location
|
||||
---@field col_0 number 0-index col location
|
||||
M.FileLoc = {}
|
||||
M.FileLoc.__index = M.FileLoc
|
||||
|
||||
---@class QNode
|
||||
---@field start FileLoc
|
||||
---@field end_ex_col FileLoc
|
||||
---@field buf QBuf
|
||||
M.QNode = {}
|
||||
M.QNode.__index = M.QNode
|
||||
|
||||
---@param treesitter_query string the passthru for treesitter language
|
||||
---parser
|
||||
---@return TSQuery
|
||||
function M.from_ts_scm(treesitter_q)
|
||||
|
||||
function M.ts_query.from_scm(treesitter_query)
|
||||
return {
|
||||
query = treesitter_query
|
||||
}
|
||||
end
|
||||
|
||||
---@param files QBuf[]
|
||||
---@return QNode[]
|
||||
function M.TSQuery:find_nodes(files)
|
||||
local result = {}
|
||||
for _, file in ipairs(files) do
|
||||
local parser = vim.treesitter.get_parser(file.bufnr, file.filetype)
|
||||
local tree = parser:parse()[1]
|
||||
local root = tree:root()
|
||||
---@type Query
|
||||
local query = vim.treesitter.parse_query(file.lang, self.query)
|
||||
for _, match, _ in query:iter_matches(root, file.bufnr, 0, -1) do
|
||||
for id, node in pairs(match) do
|
||||
local start_row, start_col, end_row, end_col = node:range(false)
|
||||
local start = { row_0 = start_row, col_0 = start_col }
|
||||
-- NOTE: Will need to validate that this is correct to be exclusive
|
||||
-- :lua local parser = vim.treesitter.get_parser(0, 'lua'); local tree = parser:parse()[1]; local query = vim.treesitter.parse_query('lua', '(identifier) @name'); for id, node in query:iter_captures(tree:root(), 0) do local name = query.captures[id]; if name == 'name' and vim.treesitter.get_node_text(node, 0) == 'TSQuery' then local sr, sc, er, ec = node:range(); print(string.format("TSQuery Start: (%d, %d), End: (%d, %d)", sr, sc, er, ec)); end; end
|
||||
local end_ex_col = { row_0 = end_row, col_0 = end_col }
|
||||
local qnode = { buf = file, start = start, end_ex_col = end_ex_col }
|
||||
setmetatable(qnode, M.QNode)
|
||||
table.insert(result, qnode)
|
||||
end
|
||||
end
|
||||
end
|
||||
return result
|
||||
end
|
||||
|
||||
return M
|
||||
|
||||
|
|
Loading…
Reference in New Issue