refactor: rewrite TransNode and use main_loop in process instead of buffer function

This commit is contained in:
JuanZoran
2023-03-23 09:52:44 +08:00
parent 8e9ccfc8f7
commit 84e06a268e
8 changed files with 135 additions and 262 deletions

View File

@ -1,166 +0,0 @@
--- INFO : Generated by newbing
-- 基类node
local Node = {}
Node.__index = Node
-- 构造函数
function Node:new(row, col, width, height)
local obj = {
row = row,
col = col,
width = width,
height = height,
}
setmetatable(obj, self)
return obj
end
-- 渲染方法(空实现)
function Node:render()
end
-- 更新方法(空实现)
function Node:update()
end
-- 子类box node
local BoxNode = setmetatable({}, Node)
BoxNode.__index = BoxNode
-- 构造函数
function BoxNode:new(row, col, width, height, border_style)
local obj = Node.new(self, row, col, width, height)
obj.border_style = border_style or "single"
return obj
end
-- 渲染方法(画边框)
function BoxNode:render()
local top_left_char =
self.border_style == "single" and "" or self.border_style == "double" and ""
local top_right_char =
self.border_style == "single" and "" or self.border_style == "double" and ""
local bottom_left_char =
self.border_style == "single" and "" or self.border_style == "double" and ""
local bottom_right_char =
self.border_style == "single" and "" or self.border_style == "double" and ""
local horizontal_char =
self.border_style == "single" and "-" or self.border_style == "double" and "="
local vertical_char =
self.border_style == "single" and "|" or self.border_style == "double" and "|"
-- draw top line
vim.api.nvim_buf_set_text(
vim.api.nvim_get_current_buf(),
self.row,
self.col,
self.row,
math.min(self.col + self.width - 1),
{ top_left_char .. horizontal_char:rep(self.width - 2) .. top_right_char }
)
-- draw bottom line
vim.api.nvim_buf_set_text(
vim.api.nvim_get_current_buf(),
math.min(self.row + self.height - 1),
math.max(self.col),
math.min(self.row + self.height - 1),
math.min(self.col + self.width - 1),
{ bottom_left_char .. horizontal_char:rep(self.width - 2) .. bottom_right_char }
)
-- draw left line
for i = self.row + 1, self.row + self.height - 2 do
vim.api.nvim_buf_set_text(
vim.api.nvim_get_current_buf(),
i,
math.max(self.col),
i,
math.max(self.col + 1),
{ vertical_char }
)
end
-- draw right line
for i = self.row + 1, self.row + self.height - 2 do
vim.api.nvim_buf_set_text(
vim.api.nvim_get_current_buf(),
i,
math.min(self.col + self.width - 1),
i,
math.min(self.col + self.width),
{ vertical_char }
)
end
end
-- 更新方法(暂无)
-- 子类text node
local TextNode = setmetatable({}, Node)
TextNode.__index = TextNode
-- 构造函数
function TextNode:new(row, col, width, height, text_content)
local obj = Node.new(self, row, col, width, height)
obj.text_content = text_content or ""
return obj
end
-- 渲染方法(写入文本内容)
function TextNode:render()
-- split text content by newline character
local lines = vim.split(obj.text_content, "\n")
-- write each line to buffer text within the node boundaries
for i, line in ipairs(lines) do
if i <= self.height then
vim.api.nvim_buf_set_text(
vim.api.nvim_get_current_buf(),
math.min(self.row + i - 1), math.max(self.col),
math.min(self.row + i - 1),
math.min(self.col + self.width - 1),
{ line:sub(1, self.width) }
)
end
end
end
-- 更新方法(暂无)
-- 子类extmark node
local ExtmarkNode = setmetatable({}, Node)
ExtmarkNode.__index = ExtmarkNode
-- 构造函数
function ExtmarkNode:new(row, col, width, height, hl_group)
local obj = Node.new(self, row, col, width, height)
obj.hl_group = hl_group or "Normal"
return obj
end
-- 渲染方法创建一个extmark
function ExtmarkNode:render()
-- create a namespace for extmarks
local ns = vim.api.nvim_create_namespace("nodes")
-- create an extmark with the given highlight group and position
vim.api.nvim_buf_set_extmark(
vim.api.nvim_get_current_buf(),
ns,
self.row,
self.col,
{ hl_group = self.hl_group, end_line = self.row + self.height - 1, end_col = self.col + self.width - 1 }
)
end
-- 更新方法(暂无)
-- 返回所有的节点类
return {
Node = Node,
BoxNode = BoxNode,
TextNode = TextNode,
ExtmarkNode = ExtmarkNode,
}

View File

@ -1,3 +1,11 @@
local util = require('Trans').util
---@class TransNode
---@field [1] string text to be rendered
---@field render fun(self: TransNode, buffer: TransBuffer, line: number, col: number) render the node
---@class TransItem : TransNode
local item_meta = {
render = function(self, buffer, line, col)
if self[2] then
@ -6,71 +14,85 @@ local item_meta = {
end,
}
---@class TransText : TransNode
---@field step string
---@field nodes TransNode[]
local text_meta = {
---@param self TransText
---@param buffer TransBuffer
---@param line integer
---@param col integer
render = function(self, buffer, line, col)
local items = self.items
local step = self.step or ""
local len = #step
local nodes = self.nodes
local step = self.step
local len = step and #step or 0
for i = 1, self.size do
local item = items[i]
item:render(buffer, line, col)
col = col + #item[1] + len
for _, node in ipairs(nodes) do
node:render(buffer, line, col)
col = col + #node[1] + len
end
end,
}
item_meta.__index = item_meta
text_meta.__index = function(self, key)
return text_meta[key] or (key == 1 and table.concat(self.strs, self.step) or nil)
text_meta.__index = text_meta
---Basic item node
---@param tuple {[1]: string, [2]: string?}
---@return TransItem
local function item(tuple)
return setmetatable(tuple, item_meta)
end
local function item(text, highlight)
return setmetatable({
[1] = text,
[2] = highlight,
}, item_meta)
end
local function text(items)
local strs = {}
local size = #items
assert(size > 1)
for i = 1, size do
strs[i] = items[i][1]
end
---@param nodes {[number]: TransNode, step: string?}
---@return table
local function text(nodes)
return setmetatable({
strs = strs,
size = size,
items = items,
[1] = table.concat(util.list_fields(nodes, 1), nodes.step),
step = nodes.step,
nodes = nodes,
}, text_meta)
end
local function format(opts)
local str = opts.text
local size = str.size
local width = opts.width
local spin = opts.spin or " "
local wid = str[1]:width()
local space = math.max(math.floor((width - wid) / (size - 1)), 0)
if space > 0 then
str.step = spin:rep(space)
---@param args {[number]: TransNode, width: integer, spin: string?}
local function format(args)
local width = args.width
local spin = args.spin or " "
local size = #args
local wid = 0
for i = 1, size do
wid = wid + args[i][1]:width()
end
return str
local space = math.max(math.floor((width - wid) / (size - 1)), 0)
args.step = spin:rep(space)
args.width = nil
args.spin = nil
---@diagnostic disable-next-line: param-type-mismatch
return text(args)
end
---@type table<string, function>
---@class TransUtil
---@field node TransNodes
---@class TransNodes
return {
item = item,
text = text,
format = format,
conjunction = function(str)
return {
item("", "TransTitleRound"),
item(str, "TransTitle"),
item("", "TransTitleRound"),
item { "", "TransTitleRound" },
item { str, "TransTitle" },
item { "", "TransTitleRound" },
}
end,
}