fix: 取消了回调的设计, 修复了部分bug

将回调的接口换成了run的函数接口, 修复了在线查询, 自动命令, 窗口显示的bug
This commit is contained in:
JuanZoran 2023-02-03 15:27:00 +08:00
parent 8b8879b2cd
commit 6f75ba057b
9 changed files with 284 additions and 333 deletions

View File

@ -12,7 +12,7 @@ wget https://github.com/skywind3000/ECDICT-ultimate/releases/download/1.0.0/ecdi
unzip /tmp/dict.zip -d "$HOME/.vim/dict" && rm -rf /tmp/dict.zip
uNames=`uname -s`
uNames=$(uname -s)
osName=${uNames: 0: 4}
if [ "$osName" != "Linux" ];then
cd ./tts/ && npm install

View File

@ -42,6 +42,11 @@ local buffer = {
end
end,
wipe = function(self)
api.nvim_buf_set_lines(self.bufnr, 0, -1, false, {})
self.size = 0
end,
del = function(self, _start, _end)
if not _start then
fn.deletebufline(self.bufnr, '$')
@ -91,14 +96,10 @@ local buffer = {
return api.nvim_buf_get_lines(self.bufnr, i, j, false)
end,
height = function(self, opts)
local width = opts.width
local wrap = opts.wrap or false
height = function(self, width)
local size = self.size
if width then
local lines = self:lines()
local size = #lines
if wrap then
local height = 0
for i = 1, size do
height = height + math.max(1, (math.ceil(lines[i]:width() / width)))

View File

@ -2,12 +2,21 @@ local M = {}
local api = vim.api
local fn = vim.fn
local title = fn.has('nvim-0.9') == 1 and {
local win_title = fn.has('nvim-0.9') == 1 and {
{ '', 'TransTitleRound' },
{ ' Trans', 'TransTitle' },
{ '', 'TransTitleRound' },
} or nil
-- local title = {
-- "████████╗██████╗ █████╗ ███╗ ██╗███████╗",
-- "╚══██╔══╝██╔══██╗██╔══██╗████╗ ██║██╔════╝",
-- " ██║ ██████╔╝███████║██╔██╗ ██║███████╗",
-- " ██║ ██╔══██╗██╔══██║██║╚██╗██║╚════██║",
-- " ██║ ██║ ██║██║ ██║██║ ╚████║███████║",
-- " ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═══╝╚══════╝",
--}
string.width = api.nvim_strwidth
string.isEn = function(self)
@ -41,7 +50,7 @@ M.conf = {
width = 37,
height = 27,
border = 'rounded',
title = title,
title = win_title,
keymap = {
pageup = '[[',
pagedown = ']]',
@ -71,7 +80,7 @@ M.conf = {
width = 0.8,
height = 0.8,
border = 'rounded',
title = title,
title = win_title,
keymap = {
quit = 'q',
},

View File

@ -59,12 +59,12 @@ return {
format = function(opts)
local text = opts.text
local size = text.size
local width = opts.width
local spin = opts.spin or ' '
local size = text.size
local text_width = text[1]:width()
local space = math.max(math.floor((width - text_width) / (size - 1)), 0)
local wid = text[1]:width()
local space = math.max(math.floor((width - wid) / (size - 1)), 0)
if space > 0 then
text.step = spin:rep(space)
end

View File

@ -1,24 +1,20 @@
local youdao = require("Trans").conf.engine.youdao
local appKey = youdao.appKey
local appPasswd = youdao.appPasswd
local uri = 'https://openapi.youdao.com/api'
local salt = tostring(math.random(bit.rshift(1, 5)))
local ok, curl = pcall(require, 'plenary.curl')
if not ok then
error('plenary not found')
end
local salt = tostring(math.random(bit.lshift(1, 15)))
local appid = youdao.appid
local appPasswd = youdao.appPasswd
local post = require('Trans.util.curl').POST
local function get_field(word)
-- local to = isEn and 'zh-'
local len = #word
local curtime = tostring(os.time())
local input = len > 20 and
word:sub(1, 10) .. len .. word:sub(-10) or word
-- sign=sha256(应用ID+input+salt+curtime+应用密钥)
local hash = appKey .. input .. salt .. curtime .. appPasswd
local hash = appid .. input .. salt .. curtime .. appPasswd
local sign = vim.fn.sha256(hash)
return {
@ -26,7 +22,7 @@ local function get_field(word)
from = 'auto',
to = 'zh-CHS',
signType = 'v3',
appKey = appKey,
appKey = appid,
salt = salt,
curtime = curtime,
sign = sign,
@ -35,14 +31,15 @@ end
return function(word)
-- return result
local field = get_field(word)
local output = curl.post(uri, {
body = field,
})
if output.exit == 0 and output.status == 200 then
local result = vim.fn.json_decode(output.body)
if result and result.errorCode == 0 then
--- TODO :
end
end
-- local field = get_field(word)
-- local output = post(uri, {
-- body = field,
-- })
-- if output.exit == 0 and output.status == 200 then
-- local result = vim.fn.json_decode(output.body)
-- if result and result.errorCode == 0 then
-- --- TODO :
-- end
-- end
end

View File

@ -1,27 +1,15 @@
return function(opts)
local callback = opts.callback or function()
end
opts.run = true
local target = opts.times
if opts.sync then
if target then
for i = 1, target do
if opts.run then
opts:frame(i)
opts.run = target ~= 0
---@type function[]
local tasks = {}
local function do_task()
for _, task in ipairs(tasks) do
task()
end
end
else
while opts.run do
opts:frame()
end
end
callback()
else
local frame
if target then
local times = 0
@ -30,8 +18,9 @@ return function(opts)
times = times + 1
opts:frame(times)
vim.defer_fn(frame, opts.interval)
else
callback()
do_task()
end
end
@ -41,11 +30,19 @@ return function(opts)
opts:frame()
vim.defer_fn(frame, opts.interval)
else
callback()
do_task()
end
end
end
frame()
---任务句柄, 如果任务结束了则立即执行, 否则立即执行
---@param task function
return function(task)
if opts.run then
tasks[#tasks + 1] = task
else
task()
end
end
return opts
end

View File

@ -1,11 +1,11 @@
local api = vim.api
local conf = require('Trans').conf
local m_window
local m_result
local m_content
local buffer = require('Trans.buffer')()
local node = require("Trans.node")
local t = node.text
local it = node.item
local f = node.format
local engine_map = {
@ -16,45 +16,45 @@ local engine_map = {
}
local function set_tag_hl(name, status)
local hl = conf.float.tag[status]
m_window:set_hl(name, {
fg = '#000000',
bg = hl,
})
-- local hl = conf.float.tag[status]
-- m_window:set_hl(name, {
-- fg = '#000000',
-- bg = hl,
-- })
m_window:set_hl(name .. 'round', {
fg = hl,
})
-- m_window:set_hl(name .. 'round', {
-- fg = hl,
-- })
end
local function set_title()
local title = m_window:new_content()
local github = ' https://github.com/JuanZoran/Trans.nvim'
-- local title = m_window:new_content()
-- local github = ' https://github.com/JuanZoran/Trans.nvim'
title:addline(
title:center(it(github, '@text.uri'))
)
-- title:addline(
-- title:center(it(github, '@text.uri'))
-- )
local f = '%s(%d)'
-- local f = '%s(%d)'
local tags = {}
local load_tag = function(engine, index)
set_tag_hl(engine, 'wait')
local round = engine .. 'round'
table.insert(tags, t(
it('', round),
it(f:format(engine_map[engine], index), engine),
it('', round)
))
end
load_tag('offline', 1)
title:addline(unpack(tags))
title:newline('')
-- local tags = {}
-- local load_tag = function(engine, index)
-- set_tag_hl(engine, 'wait')
-- local round = engine .. 'round'
-- table.insert(tags, t(
-- it('', round),
-- it(f:format(engine_map[engine], index), engine),
-- it('', round)
-- ))
-- end
-- load_tag('offline', 1)
-- title:addline(unpack(tags))
-- title:newline('')
end
local action = {
quit = function()
m_window:try_close()
-- m_window:try_close()
end,
}
@ -64,54 +64,56 @@ end
local function process()
-- TODO :
local icon = conf.icon
m_content:addline(m_content:format {
nodes = {
it(m_result.word, 'TransWord'),
t(
it('['),
it(exist(m_result.phonetic) and m_result.phonetic or icon.notfound, 'TransPhonetic'),
it(']')
),
it(m_result.collins and icon.star:rep(m_result.collins) or icon.notfound, 'TransCollins'),
it(m_result.oxford == 1 and icon.yes or icon.no)
},
width = math.floor(m_window.width * 0.5)
})
m_content:addline(it('该窗口还属于实验性功能 .... '))
-- local icon = conf.icon
-- m_content:addline(m_content:format {
-- nodes = {
-- it(m_result.word, 'TransWord'),
-- t(
-- it('['),
-- it(exist(m_result.phonetic) and m_result.phonetic or icon.notfound, 'TransPhonetic'),
-- it(']')
-- ),
-- it(m_result.collins and icon.star:rep(m_result.collins) or icon.notfound, 'TransCollins'),
-- it(m_result.oxford == 1 and icon.yes or icon.no)
-- },
-- width = math.floor(m_window.width * 0.5)
-- })
-- m_content:addline(it('该窗口还属于实验性功能 .... '))
end
return function(word)
-- TODO :online query
local float = conf.float
vim.notify('[注意]: float窗口目前还待开发, 如果需要input查询功能, 请将窗口改成hover',
vim.log.WARN)
local opt = {
relative = 'editor',
width = float.width,
height = float.height,
border = float.border,
title = float.title,
animation = float.animation,
row = bit.rshift((vim.o.lines - float.height), 1),
col = bit.rshift((vim.o.columns - float.width), 1),
zindex = 20,
}
m_window = require('Trans.window')(true, opt)
set_title()
m_content = m_window:new_content()
m_result = require('Trans.query.offline')(word)
if m_result then
set_tag_hl('offline', 'success')
process()
else
set_tag_hl('offline', 'fail')
end
-- local float = conf.float
vim.notify([[
[]:
float窗口目前还待开发
input查询功能, hover]])
-- local opt = {
-- relative = 'editor',
-- width = float.width,
-- height = float.height,
-- border = float.border,
-- title = float.title,
-- animation = float.animation,
-- row = bit.rshift((vim.o.lines - float.height), 1),
-- col = bit.rshift((vim.o.columns - float.width), 1),
-- zindex = 20,
-- }
-- m_window = require('Trans.window')(true, opt)
-- set_title()
-- m_content = m_window:new_content()
-- m_result = require('Trans.query.offline')(word)
-- if m_result then
-- set_tag_hl('offline', 'success')
-- process()
-- else
-- set_tag_hl('offline', 'fail')
-- end
m_window:open()
m_window:bufset('bufhidden', 'wipe')
-- m_window:open()
-- m_window:bufset('bufhidden', 'wipe')
for act, key in pairs(float.keymap) do
m_window:map(key, action[act])
end
-- for act, key in pairs(float.keymap) do
-- m_window:map(key, action[act])
-- end
end

View File

@ -14,6 +14,12 @@ local function handle_result(result)
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'),
@ -24,13 +30,12 @@ local function handle_result(result)
local process = {
title = function(title)
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
buffer:addline(it(result.word, 'TransWord'))
buffer:addline(it(word, 'TransWord'))
else
buffer:addline(f {
@ -138,10 +143,6 @@ local function handle_result(result)
end,
translation = function(translation)
if hover.auto_play then
result.title.word:play()
end
addtitle('中文翻译')
for trs in vim.gsplit(translation, '\n', true) do
@ -179,17 +180,16 @@ 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'
local task = opts.task
local win = require('Trans.window') {
return require('Trans.window') {
col = col,
row = row,
task = task,
buf = buffer,
relative = relative,
width = width,
@ -197,11 +197,10 @@ local function open_window(opts)
title = hover.title,
border = hover.border,
animation = hover.animation,
zindex = 100,
zindex = 80,
enter = false,
ns = require('Trans').ns,
}
return win
end
local function handle_keymap(win, word)
@ -210,13 +209,13 @@ local function handle_keymap(win, word)
local del = vim.keymap.del
local function try_del_keymap()
for _, key in pairs(keymap) do
pcall(del, 'n', key, { buffer = cur_buf })
pcall(del, 'n', key)
end
end
local lock = false
local cmd_id
local next = win.id
local next
local action = {
pageup = function()
buffer:normal('gg')
@ -228,7 +227,7 @@ local function handle_keymap(win, word)
pin = function()
if lock then
error('too many window')
error('请先关闭窗口')
else
lock = true
end
@ -237,19 +236,22 @@ local function handle_keymap(win, word)
local height = win.height
local col = vim.o.columns - width - 3
local buf = buffer.bufnr
win:try_close()
win.tasks:add(function()
win = open_window {
local run = win:try_close()
run(function()
local w, r = open_window {
width = width,
height = height,
relative = 'editor',
col = col,
task = function(self)
self:set('wrap', true)
end,
}
del('n', keymap.pin, { buffer = cur_buf })
next = w.winid
win = w
r(function()
w:set('wrap', true)
end)
del('n', keymap.pin)
api.nvim_create_autocmd('BufWipeOut', {
callback = function(opt)
if opt.buf == buf or opt.buf == cur_buf then
@ -263,8 +265,8 @@ local function handle_keymap(win, word)
close = function()
pcall(api.nvim_del_autocmd, cmd_id)
win:try_close()
win.tasts:add(function()
local run = win:try_close()
run(function()
buffer:delete()
end)
try_del_keymap()
@ -276,7 +278,7 @@ local function handle_keymap(win, word)
api.nvim_set_current_win(next)
next = prev
else
del('n', keymap.toggle_entry, { buffer = cur_buf })
del('n', keymap.toggle_entry)
end
end,
@ -286,31 +288,21 @@ local function handle_keymap(win, word)
end
end,
}
local set = vim.keymap.set
local opts = { buffer = cur_buf, silent = true }
for act, key in pairs(hover.keymap) do
set('n', key, action[act], opts)
set('n', key, action[act])
end
if hover.auto_close_events then
cmd_id = api.nvim_create_autocmd(
hover.auto_close_events, {
buffer = 0,
callback = function(opt)
win:try_close()
win.tasks:add(function()
buffer:delete()
try_del_keymap()
end)
api.nvim_del_autocmd(opt.id)
end,
callback = action.close,
})
end
end
local function online_query(win, word)
-- FIXME :
local lists = {
remove = table.remove
}
@ -318,116 +310,93 @@ local function online_query(win, word)
local size = #engines
local icon = conf.icon
local error_line = it(error_msg, 'TransFailed')
if size == 0 then
buffer:addline(error_line)
else
for i = 1, size do
lists[size] = require('Trans.query.' .. engines[i])(word)
end
local win_width = win.width
local cell = icon.cell
local timeout = hover.timeout
local spinner = require('Trans.ui.spinner')[hover.spinner]
local range = #spinner
local timeout = hover.timeout
local interval = math.floor(timeout / (win.width - spinner[1]:width()))
local win_width = win.width
local s = '%s %s'
local width = hover.width
local height = hover.height
buffer:set('modifiable', true)
require('Trans.util.display') {
times = win_width,
interval = interval,
frame = function(self, times)
for i, v in ipairs(lists) do
local res = v[1]
local function waitting_result(self, times)
for i = 1, size do
local res = lists[i][1]
if res then
vim.pretty_print(res)
buffer:del(1)
buffer:wipe()
win:set_width(width)
handle_result(res)
local actual_height = buffer:height {
width = width,
wrap = true,
}
local actual_height = buffer:height(width)
height = math.min(height, actual_height)
win:expand {
field = 'height',
target = height,
}
win.tasks:add(function(this)
this:set('wrap', true)
handle_keymap(this, word)
end)
self.run = false
return
elseif res == false then
lists:remove(i)
size = size - 1
end
end
local line
if size == 0 or times == win_width then
line = error_line
buffer:addline(error_line, 1)
self.run = false
win:set('wrap', true)
handle_keymap(win, word)
else
line = it(s:format(spinner[times % range + 1], cell:rep(times)), 'MoreMsg')
buffer:addline(it(s:format(spinner[times % range + 1], cell:rep(times)), 'MoreMsg'), 1)
end
end
buffer:addline(line, 1)
end,
callback = function()
buffer:set('modifiable', false)
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
end
---处理不同hover模式的窗口
---@param word string 待查询的单词
return function(word)
buffer:init()
local result = require('Trans.query.offline')(word)
local opts
if result then
handle_result(result)
local width = hover.width
local height = math.min(buffer:height {
local win, run = open_window {
width = width,
wrap = true,
}, hover.height)
opts = {
width = width,
height = height,
task = function(self)
self:set('wrap', true)
handle_keymap(self, word)
end
height = math.min(buffer:height(width), hover.height)
}
run(function()
win:set('wrap', true)
handle_keymap(win, word)
end)
else
opts = {
local win, run = open_window {
width = error_msg:width(),
height = 1,
task = function(win)
online_query(win, word)
end
}
end
open_window(opts)
run(function()
win:set('wrap', true)
handle_keymap(win, word)
online_query(win, word)
end)
end
end

View File

@ -30,71 +30,52 @@ local window = {
expand = function(self, opts)
self:lock()
local wrap = self:option('wrap')
self:set('wrap', false)
local field = opts.field
local target = opts.target
local interval = opts.interval or self.animation.interval
local callback = function()
self:set('wrap', wrap)
local tasks = self.tasks
for i = 1, #tasks do
tasks[i](self)
tasks[i] = nil
end
self:unlock()
end
local cur = self[field]
local times = math.abs(target - cur)
if times ~= 0 then
local frame
local wrap = self:option('wrap')
self:set('wrap', false)
local interval = opts.interval or self.animation.interval
local method = 'set_' .. field
if target > cur then
frame = function(_, cur_times)
self[method](self, cur + cur_times)
end
elseif target < cur then
frame = function(_, cur_times)
local frame = target > cur and function(_, cur_times)
self[method](self, cur + cur_times)
end or function(_, cur_times)
self[method](self, cur - cur_times)
end
end
display {
local run = display {
times = times,
frame = frame,
interval = interval,
callback = callback,
}
else
callback()
end
run(function()
self:set('wrap', wrap)
self:unlock()
end)
return run
end,
try_close = function(self)
if self:is_valid() then
local winid = self.winid
self.tasks:add(function()
api.nvim_win_close(winid, true)
end)
local animation = self.animation
local field = ({
slid = 'width',
fold = 'height',
})[animation.close]
})[self.animation.close]
if field then
--- 播放动画
self:expand {
local run = self:expand {
field = field,
target = 1,
debug = true,
}
end
run(function()
api.nvim_win_close(winid, true)
end)
return run
end
end,
@ -125,6 +106,10 @@ local window = {
}
window.__index = window
---window的构造函数
---@param opts table
---@return table
---@return function
return function(opts)
assert(type(opts) == 'table')
local buf = opts.buf
@ -139,7 +124,6 @@ return function(opts)
local enter = opts.enter
local ns = opts.ns
local animation = opts.animation
local task = opts.task
local open = animation.open
@ -173,26 +157,18 @@ return function(opts)
local win = setmetatable({
buf = buf,
ns = ns,
tasks = {
add = table.insert,
},
height = win_opt.height,
width = win_opt.width,
animation = animation,
winid = api.nvim_open_win(buf.bufnr, enter, win_opt),
}, window)
if task then
win.tasks:add(task)
end
win:expand {
field = field,
target = opts[field],
}
api.nvim_win_set_hl_ns(win.winid, win.ns)
win:set_hl('Normal', { link = 'TransWin' })
win:set_hl('FloatBorder', { link = 'TransBorder' })
return win
return win, win:expand {
field = field,
target = opts[field],
}
end