refactor: add frontend.hover.load function to set buffer content

This commit is contained in:
JuanZoran 2023-03-13 21:41:17 +08:00
parent 7731c6c8cb
commit 693dd0c7aa
8 changed files with 201 additions and 345 deletions

View File

@ -109,24 +109,24 @@ local formatter = {
pos = function(res)
if not exist(res.pos) then return end
local pos_map = {
v = '动词 v',
n = '名词 n',
r = '副词 adv',
m = '数词 num',
p = '代词 pron',
a = '代词 pron',
i = '介词 prep',
u = '感叹词 int',
j = '形容词 adj',
c = '连接词 conj',
x = '否定标记 not',
t = '不定式标记 infm',
d = '限定词 determiner',
a = '代词pron ',
c = '连接词conj ',
i = '介词prep ',
j = '形容词adj ',
m = '数词num ',
n = '名词n ',
p = '代词pron ',
r = '副词adv ',
u = '感叹词int ',
v = '动词v ',
x = '否定标记not ',
t = '不定式标记infm ',
d = '限定词determiner ',
}
local pos = {}
for _, _pos in ipairs(vim.split(res.pos, '/', { plain = true })) do
pos[pos_map[_pos:sub(1, 1)]] = _pos:sub(3)
pos[pos_map[_pos:sub(1, 1)]] = ('%2s%%'):format(_pos:sub(3))
end
return pos

View File

@ -123,11 +123,13 @@ end
---@param nodes string|table|table[] string -> as line content | table -> as a node | table[] -> as node[]
---@param linenr number? line number should be set[one index] or let it be nil to append
function buffer:setline(nodes, linenr)
linenr = linenr and linenr - 1 or -1
self:set('modifiable', true)
linenr = linenr and linenr - 1 or self:line_count()
if type(nodes) == 'string' then
api.nvim_buf_set_lines(self.bufnr, linenr, linenr, false, { nodes })
elseif type(nodes) == 'table' then
else
if type(nodes[1]) == 'string' then
-- FIXME :set [nodes] type as node
---@diagnostic disable-next-line: assign-type-mismatch
@ -149,6 +151,8 @@ function buffer:setline(nodes, linenr)
end
end
end
self:set('modifiable', false)
end
---@private
@ -183,6 +187,7 @@ function buffer.new()
}, buffer)
new_buf:set('modifiable', false)
new_buf:set('filetype', 'Trans')
new_buf:set('buftype', 'nofile')
return new_buf

View File

@ -3,8 +3,20 @@ local Trans = require('Trans')
local M = {}
M.__index = M
---@class data
---@field str string
---@field mode string
---@field result table
---@field frontend table
---@field backend table
---@field from string
---@field to string
---@field is_word boolean
---Data constructor
---@param opts table
---@return data
function M.new(opts)
local mode = opts.mode
local str = opts.str
@ -39,4 +51,17 @@ function M.new(opts)
return setmetatable(data, M)
end
-- ---Get the first available result [return nil if no result]
-- ---@return table?
-- function M:get_available_result()
-- local result = self.result
-- local backend = self.backend
-- for _, name in ipairs(backend) do
-- if result[name] then
-- return result[name]
-- end
-- end
-- end
return M

View File

@ -13,19 +13,26 @@ local function init_opts(opts)
return opts
end
local function set_result(data)
local function do_query(data)
-- HACK :Rewrite this function to support multi requests
local frontend = data.frontend
local result = data.result
for _, backend in ipairs(data.backend) do
local name = backend.name
if backend.no_wait then
backend.query(data)
else
backend.query(data)
frontend:wait(data.result, name, backend.timeout)
frontend:wait(result, name, backend.timeout)
end
if type(data.result[name]) == 'table' then break end
if type(result[name]) == 'table' then
return result[name]
else
result[name] = nil
end
end
end
@ -46,20 +53,11 @@ local function process(opts)
local data = Trans.data.new(opts)
set_result(data)
local success = false
for _, v in pairs(data.result) do
if type(v) == "table" then
success = true
break
end
end
if success == false then return end
local result = do_query(data)
if not result then return end
Trans.cache[data.str] = data
data.frontend:process(data)
data.frontend:process(data, result)
end
return coroutine.wrap(process)

View File

@ -67,7 +67,7 @@ function M:destroy()
end
---Init hover window
---@param opts table @window options: width, height
---@param opts table? @window options: width, height
---@return unknown
function M:init_window(opts)
opts = opts or {}
@ -130,11 +130,17 @@ function M:wait(tbl, name, timeout)
-- TODO : End waitting animation
end
---Process data and display it in hover window
---@param data table @data to be processed
function M:process(data)
vim.pretty_print(data.result)
print('TODO: process data')
function M:process(_, result)
if not self.window then self:init_window() end
local node = Trans.util.node
local it, t, f = node.item, node.text, node.format
self.buffer:setline(it('hello', 'MoreMsg'))
-- for _, field in ipairs(self.opts.order) do
-- self:load(result, field)
-- end
end
---Check if hover window and buffer are valid
@ -143,204 +149,8 @@ function M:is_available()
return self.buffer:is_valid() and self.window:is_valid()
end
return M
-- local error_msg = conf.icon.notfound .. ' 没有找到相关的翻译'
-- local buffer = require('Trans.buffer')()
-- local node = require('Trans.node')
-- local it, t, f = node.item, node.text, node.format
-- local function handle_result(result)
-- local icon = conf.icon
-- local notfound = icon.notfound
-- local indent = ' '
-- local word = result.title.word
-- if hover.auto_play then
-- string.play(word:isEn() and word or result.definition)
-- end
-- local addtitle = function(title)
-- buffer:addline {
-- it('', 'TransTitleRound'),
-- it(title, 'TransTitle'),
-- it('', 'TransTitleRound'),
-- }
-- end
-- local process = {
-- title = function(title)
-- local oxford = title.oxford
-- local collins = title.collins
-- local phonetic = title.phonetic
-- if not phonetic and not collins and not oxford then
-- buffer:addline(it(word, 'TransWord'))
-- else
-- buffer:addline(f {
-- width = hover.width,
-- text = t {
-- it(word, 'TransWord'),
-- t {
-- it('['),
-- it((phonetic and phonetic ~= '') and phonetic or notfound, 'TransPhonetic'),
-- it(']')
-- },
-- it(collins and icon.star:rep(collins) or notfound, 'TransCollins'),
-- it(oxford == 1 and icon.yes or icon.no)
-- },
-- })
-- end
-- end,
-- tag = function(tag)
-- addtitle('标签')
-- local tag_map = {
-- zk = '中考',
-- gk = '高考',
-- ky = '考研',
-- cet4 = '四级',
-- cet6 = '六级',
-- ielts = '雅思',
-- toefl = '托福',
-- gre = 'gre ',
-- }
-- local tags = {}
-- local size = 0
-- local interval = ' '
-- for _tag in vim.gsplit(tag, ' ', true) do
-- size = size + 1
-- tags[size] = tag_map[_tag]
-- end
-- for i = 1, size, 3 do
-- buffer:addline(
-- it(
-- indent .. tags[i] ..
-- (tags[i + 1] and interval .. tags[i + 1] ..
-- (tags[i + 2] and interval .. tags[i + 2] or '') or ''),
-- 'TransTag'
-- )
-- )
-- end
-- buffer:addline('')
-- end,
-- pos = function(pos)
-- addtitle('词性')
-- local pos_map = {
-- a = '代词pron ',
-- c = '连接词conj ',
-- i = '介词prep ',
-- j = '形容词adj ',
-- m = '数词num ',
-- n = '名词n ',
-- p = '代词pron ',
-- r = '副词adv ',
-- u = '感叹词int ',
-- v = '动词v ',
-- x = '否定标记not ',
-- t = '不定式标记infm ',
-- d = '限定词determiner ',
-- }
-- local s = '%s %2s%%'
-- for _pos in vim.gsplit(pos, '/', true) do
-- buffer:addline(
-- it(indent .. s:format(pos_map[_pos:sub(1, 1)], _pos:sub(3)), 'TransPos')
-- )
-- end
-- buffer:addline('')
-- end,
-- exchange = function(exchange)
-- addtitle('词形变化')
-- local exchange_map = {
-- ['p'] = '过去式 ',
-- ['d'] = '过去分词 ',
-- ['i'] = '现在分词 ',
-- ['r'] = '比较级 ',
-- ['t'] = '最高级 ',
-- ['s'] = '复数 ',
-- ['0'] = '原型 ',
-- ['1'] = '类别 ',
-- ['3'] = '第三人称单数',
-- ['f'] = '第三人称单数',
-- }
-- local interval = ' '
-- for exc in vim.gsplit(exchange, '/', true) do
-- buffer:addline(
-- it(indent .. exchange_map[exc:sub(1, 1)] .. interval .. exc:sub(3), 'TransExchange')
-- )
-- end
-- buffer:addline('')
-- end,
-- translation = function(translation)
-- addtitle('中文翻译')
-- for trs in vim.gsplit(translation, '\n', true) do
-- buffer:addline(
-- it(indent .. trs, 'TransTranslation')
-- )
-- end
-- buffer:addline('')
-- end,
-- definition = function(definition)
-- addtitle('英文注释')
-- for def in vim.gsplit(definition, '\n', true) do
-- def = def:gsub('^%s+', '', 1) -- TODO :判断是否需要分割空格
-- buffer:addline(
-- it(indent .. def, 'TransDefinition')
-- )
-- end
-- buffer:addline('')
-- end,
-- }
-- buffer:set('modifiable', true)
-- for _, field in ipairs(conf.order) do
-- local value = result[field]
-- if value and value ~= '' then
-- process[field](value)
-- end
-- end
-- buffer:set('modifiable', false)
-- end
-- local function open_window(opts)
-- opts = opts or {}
-- local col = opts.col or 1
-- local row = opts.row or 1
-- local width = opts.width or hover.width
-- local height = opts.height or hover.height
-- local relative = opts.relative or 'cursor'
-- return require('Trans.window') {
-- col = col,
-- row = row,
-- buf = buffer,
-- relative = relative,
-- width = width,
-- height = height,
-- title = hover.title,
-- border = hover.border,
-- animation = hover.animation,
-- ns = require('Trans').ns,
-- }
-- end
-- local function handle_keymap(win, word)
-- local keymap = hover.keymap
-- local cur_buf = api.nvim_get_current_buf()
@ -438,102 +248,3 @@ return M
-- })
-- end
-- end
-- local function online_query(win, word)
-- local lists = {
-- remove = table.remove
-- }
-- local engines = conf.engines
-- local size = #engines
-- local icon = conf.icon
-- local error_line = it(error_msg, 'TransFailed')
-- if size == 0 then
-- buffer:addline(error_line)
-- return
-- end
-- for i = 1, size do
-- lists[i] = require('Trans.query.' .. engines[i])(word)
-- end
-- local cell = icon.cell
-- local timeout = hover.timeout
-- local spinner = require('Trans.style.spinner')[hover.spinner]
-- local range = #spinner
-- local interval = math.floor(timeout / (win.width - spinner[1]:width()))
-- local win_width = win.width
-- local s = '%s %s'
-- local width, height = hover.width, hover.height
-- local function waitting_result(this, times)
-- for i = size, 1, -1 do
-- local res = lists[i][1]
-- if res then
-- buffer:wipe()
-- win:set_width(width)
-- handle_result(res)
-- height = math.min(height, buffer:height(width))
-- win:expand {
-- field = 'height',
-- target = height,
-- }
-- this.run = false
-- return
-- elseif res == false then
-- lists:remove(i)
-- size = size - 1
-- end
-- end
-- if size == 0 or times == win_width then
-- buffer:addline(error_line, 1)
-- this.run = false
-- else
-- buffer:addline(it(s:format(spinner[times % range + 1], cell:rep(times)), 'MoreMsg'), 1)
-- end
-- end
-- buffer:set('modifiable', true)
-- local run = require('Trans.util.display') {
-- times = win_width,
-- interval = interval,
-- frame = waitting_result,
-- }
-- run(function()
-- buffer:set('modifiable', false)
-- end)
-- end
-- ---处理不同hover模式的窗口
-- ---@param word string 待查询的单词
-- return function(word)
-- buffer:init()
-- local result = require('Trans.query.offline')(word)
-- if result then
-- handle_result(result)
-- local width = hover.width
-- local win, run = open_window {
-- width = width,
-- height = math.min(buffer:height(width), hover.height)
-- }
-- run(function()
-- win:set('wrap', true)
-- handle_keymap(win, word)
-- end)
-- else
-- local win, run = open_window {
-- width = error_msg:width(),
-- height = 1,
-- }
-- run(function()
-- win:set('wrap', true)
-- handle_keymap(win, word)
-- online_query(win, word)
-- end)
-- end
-- end

View File

@ -0,0 +1,121 @@
local node = require('Trans').util.node
local it, t, f = node.item, node.text, node.format
local function conjunction(text)
return {
it('', 'TransTitleRound'),
it(text, 'TransTitle'),
it('', 'TransTitleRound'),
}
end
local interval = (' '):rep(4)
local strategy = {
title = function(hover, title)
if type(title) == 'string' then
hover.buffer:setline(it(title, 'TransTitle'))
return
end
local icon = hover.opts.icon
local word = title.word
local oxford = title.oxford
local collins = title.collins
local phonetic = title.phonetic
if not phonetic and not collins and not oxford then
hover.buffer:setline(it(word, 'TransWord'))
else
hover.buffer:setline(f {
width = hover.width,
text = t {
it(word, 'TransWord'),
t {
it('['),
it((phonetic and phonetic ~= '') and phonetic or icon.notfound, 'TransPhonetic'),
it(']')
},
it(collins and icon.star:rep(collins) or icon.notfound, 'TransCollins'),
it(oxford == 1 and icon.yes or icon.no)
},
})
end
end,
tag = function(hover, tag)
local buffer = hover.buffer
buffer:setline(conjunction('标签'))
local size = #tag
for i = 1, size, 3 do
buffer:setline(
it(
interval .. tag[i] ..
(tag[i + 1] and interval .. tag[i + 1] ..
(tag[i + 2] and interval .. tag[i + 2] or '') or ''),
'TransTag'
)
)
end
buffer:setline('')
end,
exchange = function(hover, exchange)
local buffer = hover.buffer
buffer:setline(conjunction('词形变化'))
for description, value in pairs(exchange) do
buffer:setline(
it(interval .. description .. interval .. value, 'TransExchange')
)
end
buffer:setline('')
end,
pos = function(hover, pos)
local buffer = hover.buffer
buffer:setline(conjunction('词性'))
for description, value in pairs(pos) do
buffer:setline(
it(interval .. description .. interval .. value, 'TransPos')
)
end
buffer:setline('')
end,
translation = function(hover, translation)
local buffer = hover.buffer
buffer:setline(conjunction('中文翻译'))
for _, value in ipairs(translation) do
buffer:setline(
it(interval .. value, 'TransTranslation')
)
end
buffer:setline('')
end,
definition = function(hover, definition)
local buffer = hover.buffer
buffer:setline(conjunction('英文注释'))
for _, value in ipairs(definition) do
buffer:setline(
it(interval .. value, 'TransDefinition')
)
end
buffer:setline('')
end,
}
return function(hover, result, field)
strategy[field](hover, result[field])
end

View File

@ -6,8 +6,7 @@ local function metatable(folder_name, origin)
return setmetatable(origin or {}, {
__index = function(tbl, key)
local status, result = pcall(require, ('Trans.%s.%s'):format(folder_name, key))
if not status then error('fail to load: ' .. key .. '\n' .. result) end
if not status then return end
tbl[key] = result
return result
@ -18,7 +17,6 @@ end
local M = metatable('core')
M.metatable = metatable
M.style = metatable("style")

View File

@ -1,23 +1,20 @@
local api = vim.api
local add_hl = api.nvim_buf_add_highlight
local item_meta = {
render = function(self, bufnr, line, col)
render = function(self, buffer, line, col)
if self[2] then
add_hl(bufnr, self.ns or -1, self[2], line, col, col + #self[1])
buffer:add_highlight(line, self[2], col, col + #self[1])
end
end,
}
local text_meta = {
render = function(self, bufnr, line, col)
render = function(self, buffer, line, col)
local items = self.items
local step = self.step or ''
local len = #step
for i = 1, self.size do
local item = items[i]
item:render(bufnr, line, col)
item:render(buffer, line, col)
col = col + #item[1] + len
end
end
@ -28,6 +25,7 @@ text_meta.__index = function(self, key)
return text_meta[key] or (key == 1 and table.concat(self.strs, self.step) or nil)
end
return {
item = function(text, highlight)
return setmetatable({