From 79348ec4c5831ebcf044155dfd547eced8f18a55 Mon Sep 17 00:00:00 2001 From: JuanZoran <1430359574@qq.com> Date: Wed, 4 Jan 2023 22:22:52 +0800 Subject: [PATCH 01/17] test: rebuild this plugin --- lua/Trans/conf.lua | 64 ++++- lua/Trans/database.lua | 14 - lua/Trans/display.lua | 601 +++++++++++++++++++++------------------- lua/Trans/highlight.lua | 26 -- lua/Trans/setup.lua | 7 +- lua/Trans/window.lua | 48 ++++ 6 files changed, 419 insertions(+), 341 deletions(-) delete mode 100644 lua/Trans/highlight.lua create mode 100644 lua/Trans/window.lua diff --git a/lua/Trans/conf.lua b/lua/Trans/conf.lua index 37acd42..493d001 100644 --- a/lua/Trans/conf.lua +++ b/lua/Trans/conf.lua @@ -1,17 +1,28 @@ return { + view = { + cursor = { + -- NOTE : + -- 可选的风格:['fixed', 'relative', .. ] + style = 'fixed', + border = 'rounded', + -- NOTE : + -- 如果style设置为'relative' + -- 则其值代表最大限制, 设置为负数则无限制 + width = 30, + height = 30, + }, + float = { + top_offset = 1, + relative_width = 0.8, + border = 'rounded', + }, + }, display = { - style = 'minimal', - max_height = 50, -- 小于0代表无限制 - max_width = 50, - -- phnoetic = true, + phnoetic = true, collins_star = true, oxford = true, + -- TODO -- history = false, - wrap = true, - border_style = 'rounded', - view = 'cursor', - offset_x = 2, - offset_y = 2, }, order = { 'title', @@ -22,7 +33,35 @@ return { 'en', }, - db_path = '$HOME/.vim/dict/ultimate.db', -- FIXME: change the path + highligh = { + TransWord = { + fg = '#7ee787', + bold = true, + }, + TransPhonetic = { + fg = '#8b949e', + }, + TransRef = { + fg = '#75beff', + bold = true, + }, + TransTag = { + fg = '#e5c07b', + }, + TransExchange = { + link = 'TransTag', + }, + TransPos = { + link = 'TransTag', + }, + TransZh = { + link = 'TransWord', + }, + TransEn = { + fg = '#bc8cff', + }, + }, + db_path = '$HOME/.vim/dict/ultimate.db', icon = { star = '⭐', @@ -30,13 +69,12 @@ return { notOxford = '' }, auto_close = true, - buf = vim.api.nvim_create_buf(false, true) - -- TODO: add online translate engine + -- TODO add online translate engine -- online_search = { -- enable = false, -- engine = {}, -- } - -- TODO: register word + -- TODO register word } diff --git a/lua/Trans/database.lua b/lua/Trans/database.lua index a0b0efd..a5b77c0 100644 --- a/lua/Trans/database.lua +++ b/lua/Trans/database.lua @@ -1,20 +1,6 @@ local M = {} -local db_path = require("Trans").conf.db_path -local dict = require("Trans").db:open(db_path) function M.query(arg) - -- TODO: return type: a result table: - local res = {} - if type(arg) == 'string' then - res = dict:select('stardict', { - where = { word = arg }, - }) - elseif type(arg) == 'table' then - res = dict:select('stardict', arg) - else - vim.notify('query argument error!') - end - return res[1] end return M diff --git a/lua/Trans/display.lua b/lua/Trans/display.lua index 41c1d93..2b41cca 100644 --- a/lua/Trans/display.lua +++ b/lua/Trans/display.lua @@ -1,309 +1,338 @@ -local M = {} - +---@diagnostic disable: unused-local +local M = {} local api = vim.api -local display = require("Trans").conf.display -local icon = require("Trans").conf.icon -local order = require("Trans").conf.order -local auto_close = require("Trans").conf.auto_close +local conf = require("Trans").conf +local display = conf.display +local icon = conf.icon +local order = conf.order +local auto_close = conf.auto_close +local view = conf.view -local hl = require("Trans.highlight").hlgroup +-- TODO : setup database +local db_path = require("Trans").conf.db_path +local dict = require("Trans").db:open(db_path) -local buf = require("Trans.conf").buf -local win = 0 -local line = 0 -local pos_info = {} +local highlight = { + word = 'TransWord', + phonetic = 'TransPhonetic', + ref = 'TransRef', + tag = 'TransTag', + exchange = 'TransExchange', + pos = 'TransPos', + zh = 'TransZh', + en = 'TransEn', +} -local handler = {} -api.nvim_buf_set_option(buf, 'filetype', 'Trans') - -local function show_win(width, height) - win = api.nvim_open_win(buf, false, { - relative = 'cursor', - col = display.offset_x, - row = display.offset_y, - title = 'Trans', - title_pos = 'center', - style = display.style, - width = (display.max_width > 0 and width > display.max_width) and display.max_width or width, - height = (display.max_width > 0 and height > display.max_height) and display.max_height or height, - border = display.border_style, - focusable = false, - zindex = 250, -- Top - }) - api.nvim_win_set_option(win, 'wrap', display.wrap) -end - --- NOTE title -handler.title = function(text, query_res) - local title = ('%s [%s] %s %s'):format( - query_res.word, - query_res.phonetic, - (display.oxford and (query_res.oxford == 1 and icon.isOxford or icon.notOxford) or ''), - ((display.collins_star and query_res.collins) and string.rep(icon.star, query_res.collins) or '') - ) - table.insert(text, title) - - pos_info.title = {} - pos_info.title.word = #query_res.word - pos_info.title.phonetic = query_res.phonetic and #query_res.phonetic or 3 - pos_info.title.line = line - line = line + 1 -end - --- NOTE tag -handler.tag = function(text, query_res) - if query_res.tag and #query_res.tag > 0 then - local tag = query_res.tag:gsub('zk', '中考'):gsub('gk', '高考'):gsub('ky', '考研'):gsub('cet4', '四级'): - gsub('cet6', '六级'):gsub('ielts', '雅思'):gsub('toefl', '托福'):gsub('gre', 'GRE') - - table.insert(text, '标签:') - table.insert(text, ' ' .. tag) - table.insert(text, '') - - pos_info.tag = line - line = line + 3 - end -end - --- NOTE pos 词性 -handler.pos = function(text, query_res) - if query_res.pos and #query_res.pos > 0 then - table.insert(text, '词性:') - - local content = 0 - for v in vim.gsplit(query_res.pos, [[/]]) do - table.insert(text, string.format(' %s', v .. '%')) - content = content + 1 - end - - table.insert(text, '') - - pos_info.pos = {} - pos_info.pos.line = line - pos_info.pos.content = content - line = line + content + 2 - end -end - --- NOTE exchange -handler.exchange = function(text, query_res) - if query_res.exchange and #query_res.exchange > 0 then - table.insert(text, '词形变化:') - - local exchange_map = { - p = '过去式', - d = '过去分词', - i = '现在分词', - r = '形容词比较级', - t = '形容词最高级', - s = '名词复数形式', - O = '词干', - ['3'] = '第三人称单数', - } - - local content = 0 - for v in vim.gsplit(query_res.exchange, [[/]]) do - table.insert(text, string.format(' %s: %s', exchange_map[v:sub(1, 1)], v:sub(3))) - content = content + 1 - -- FIXME: 中文字符与字母位宽不一致, 暂时无法对齐 - end - table.insert(text, '') - - pos_info.exchange = {} - pos_info.exchange.line = line - pos_info.exchange.content = content - line = line + content + 2 - end -end - --- NOTE 中文翻译 -handler.zh = function(text, query_res) - if query_res.translation then - table.insert(text, '中文翻译:') - - local content = 0 - for v in vim.gsplit(query_res.translation, '\n') do - table.insert(text, ' ' .. v) - content = content + 1 - end - table.insert(text, '') - - pos_info.zh = {} - pos_info.zh.line = line - pos_info.zh.content = content - line = content + line + 2 - end -end - --- NOTE 英文翻译 -handler.en = function(text, query_res) - if query_res.definition and #query_res.definition > 0 then - table.insert(text, '英文翻译:') - - local content = 0 - for v in vim.gsplit(query_res.definition, '\n') do - table.insert(text, ' ' .. v) - content = content + 1 - end - table.insert(text, '') - - pos_info.en = {} - pos_info.en.line = line - pos_info.en.content = content - line = line + content + 2 - end -end - --- @return string array -local function get_text(query_res) - local text = {} - for _, v in ipairs(order) do - handler[v](text, query_res) - end - return text -end - -local function set_text(query_res) - local text = query_res and get_text(query_res) or { '没有找到相关定义' } - - api.nvim_buf_set_lines(buf, 0, -1, false, text) - local width = 0 - for _, v in ipairs(text) do - if #v > width then - width = v:len() - end - end - return width, #text -end - -local hl_handler = {} - -hl_handler.title = function() - api.nvim_buf_add_highlight(buf, -1, hl.word, pos_info.title.line, 0, pos_info.title.word) - api.nvim_buf_add_highlight(buf, -1, hl.phonetic, pos_info.title.line, pos_info.title.word + 5, - pos_info.title.word + 5 + pos_info.title.phonetic) -end - -hl_handler.tag = function() - if pos_info.tag then - api.nvim_buf_add_highlight(buf, -1, hl.ref, pos_info.tag, 0, -1) - api.nvim_buf_add_highlight(buf, -1, hl.tag, pos_info.tag + 1, 0, -1) - end -end - -hl_handler.pos = function() - if pos_info.pos then - api.nvim_buf_add_highlight(buf, -1, hl.ref, pos_info.pos.line, 0, -1) - for i = 1, pos_info.pos.content, 1 do - api.nvim_buf_add_highlight(buf, -1, hl.pos, pos_info.pos.line + i, 0, -1) - end - end -end - -hl_handler.exchange = function() - if pos_info.exchange then - api.nvim_buf_add_highlight(buf, -1, hl.ref, pos_info.exchange.line, 0, -1) - for i = 1, pos_info.exchange.content, 1 do - api.nvim_buf_add_highlight(buf, -1, hl.exchange, pos_info.exchange.line + i, 0, -1) - end - end -end - -hl_handler.zh = function() - api.nvim_buf_add_highlight(buf, -1, hl.ref, pos_info.zh.line, 0, -1) - for i = 1, pos_info.zh.content, 1 do - api.nvim_buf_add_highlight(buf, -1, hl.zh, pos_info.zh.line + i, 0, -1) - end -end - -hl_handler.en = function() - if pos_info.en then - api.nvim_buf_add_highlight(buf, -1, hl.ref, pos_info.en.line, 0, -1) - for i = 1, pos_info.en.content, 1 do - api.nvim_buf_add_highlight(buf, -1, hl.en, pos_info.en.line + i, 0, -1) - end - end -end - - -local function set_hl() - for _, v in ipairs(order) do - hl_handler[v]() - end -end - -local function clear_tmp_info() - pos_info = {} - line = 0 -end - -local function get_visual_selection() +local function get_select() local s_start = vim.fn.getpos("'<") local s_end = vim.fn.getpos("'>") - assert(s_end[2] == s_start[2]) + if s_start[2] ~= s_start[2] then + error('TODO: multiline translate') + end local lin = vim.api.nvim_buf_get_lines(0, s_start[2] - 1, s_end[2], false)[1] local word = string.sub(lin, s_start[3], s_end[3]) return word end -function M.query(mode) - assert(buf > 0) +local function get_query_res(method) + -- NOTE : get query word local word = '' - if mode == 'n' then + if method == 'cursor' then word = vim.fn.expand('<cword>') - elseif mode == 'v' then - word = get_visual_selection() - elseif mode == 'I' then - word = vim.fn.input('请输入您要查询的单词: ') - -- vim.ui.input({prompt = '请输入您要查询的单词: '}, function (input) - -- word = input - -- end) + elseif method == 'select' then + word = get_select():match('%s+') + elseif method == 'input' then + word = vim.fn.input('请输入您要查询的单词:') -- TODO Use Telescope with fuzzy finder else - error('mode argument is invalid') + error('unknown method') end - local res = require("Trans.database").query(word) - local width, height = set_text(res) - show_win(width, height) - if res then - set_hl() - clear_tmp_info() - end - - if auto_close then - api.nvim_create_autocmd( - { 'InsertEnter', 'CursorMoved', 'BufLeave', }, { - buffer = 0, - once = true, - callback = M.close_win, - }) - end + -- TODO : dict query optimization + local res = dict:select('stardict', { + where = { word = arg }, + }) + return res[1] end -function M.query_cursor() - M.query('n') +M.TransLate = function(opts) + local res = get_query_res(opts.method) + -- TODO <++> end -function M.query_select() - M.query('v') -end -function M.query_input() - M.query('I') -end - -function M.close_win() - if win > 0 then - api.nvim_win_close(win, true) - win = 0 - end -end - --- function M.enter_win() --- if api.nvim_win_is_valid(win) then --- else --- error('current win is not valid') +-- local win = 0 +-- local line = 0 +-- local pos_info = {} +-- +-- local handler = {} +-- api.nvim_buf_set_option(buf, 'filetype', 'Trans') +-- +-- local function show_win(width, height) +-- end +-- +-- -- NOTE title +-- handler.title = function(text, query_res) +-- local title = ('%s [%s] %s %s'):format( +-- query_res.word, +-- query_res.phonetic, +-- (display.oxford and (query_res.oxford == 1 and icon.isOxford or icon.notOxford) or ''), +-- ((display.collins_star and query_res.collins) and string.rep(icon.star, query_res.collins) or '') +-- ) +-- table.insert(text, title) +-- +-- pos_info.title = {} +-- pos_info.title.word = #query_res.word +-- pos_info.title.phonetic = query_res.phonetic and #query_res.phonetic or 3 +-- pos_info.title.line = line +-- line = line + 1 +-- end +-- +-- -- NOTE tag +-- handler.tag = function(text, query_res) +-- if query_res.tag and #query_res.tag > 0 then +-- local tag = query_res.tag:gsub('zk', '中考'):gsub('gk', '高考'):gsub('ky', '考研'):gsub('cet4', '四级'): +-- gsub('cet6', '六级'):gsub('ielts', '雅思'):gsub('toefl', '托福'):gsub('gre', 'GRE') +-- +-- table.insert(text, '标签:') +-- table.insert(text, ' ' .. tag) +-- table.insert(text, '') +-- +-- pos_info.tag = line +-- line = line + 3 -- end -- end - -return M +-- +-- -- NOTE pos 词性 +-- handler.pos = function(text, query_res) +-- if query_res.pos and #query_res.pos > 0 then +-- table.insert(text, '词性:') +-- +-- local content = 0 +-- for v in vim.gsplit(query_res.pos, [[/]]) do +-- table.insert(text, string.format(' %s', v .. '%')) +-- content = content + 1 +-- end +-- +-- table.insert(text, '') +-- +-- pos_info.pos = {} +-- pos_info.pos.line = line +-- pos_info.pos.content = content +-- line = line + content + 2 +-- end +-- end +-- +-- -- NOTE exchange +-- handler.exchange = function(text, query_res) +-- if query_res.exchange and #query_res.exchange > 0 then +-- table.insert(text, '词形变化:') +-- +-- local exchange_map = { +-- p = '过去式', +-- d = '过去分词', +-- i = '现在分词', +-- r = '形容词比较级', +-- t = '形容词最高级', +-- s = '名词复数形式', +-- O = '词干', +-- ['3'] = '第三人称单数', +-- } +-- +-- local content = 0 +-- for v in vim.gsplit(query_res.exchange, [[/]]) do +-- table.insert(text, string.format(' %s: %s', exchange_map[v:sub(1, 1)], v:sub(3))) +-- content = content + 1 +-- -- FIXME: 中文字符与字母位宽不一致, 暂时无法对齐 +-- end +-- table.insert(text, '') +-- +-- pos_info.exchange = {} +-- pos_info.exchange.line = line +-- pos_info.exchange.content = content +-- line = line + content + 2 +-- end +-- end +-- +-- -- NOTE 中文翻译 +-- handler.zh = function(text, query_res) +-- if query_res.translation then +-- table.insert(text, '中文翻译:') +-- +-- local content = 0 +-- for v in vim.gsplit(query_res.translation, '\n') do +-- table.insert(text, ' ' .. v) +-- content = content + 1 +-- end +-- table.insert(text, '') +-- +-- pos_info.zh = {} +-- pos_info.zh.line = line +-- pos_info.zh.content = content +-- line = content + line + 2 +-- end +-- end +-- +-- -- NOTE 英文翻译 +-- handler.en = function(text, query_res) +-- if query_res.definition and #query_res.definition > 0 then +-- table.insert(text, '英文翻译:') +-- +-- local content = 0 +-- for v in vim.gsplit(query_res.definition, '\n') do +-- table.insert(text, ' ' .. v) +-- content = content + 1 +-- end +-- table.insert(text, '') +-- +-- pos_info.en = {} +-- pos_info.en.line = line +-- pos_info.en.content = content +-- line = line + content + 2 +-- end +-- end +-- +-- -- @return string array +-- local function get_text(query_res) +-- local text = {} +-- for _, v in ipairs(order) do +-- handler[v](text, query_res) +-- end +-- return text +-- end +-- +-- local function set_text(query_res) +-- local text = query_res and get_text(query_res) or { '没有找到相关定义' } +-- +-- api.nvim_buf_set_lines(buf, 0, -1, false, text) +-- local width = 0 +-- for _, v in ipairs(text) do +-- if #v > width then +-- width = v:len() +-- end +-- end +-- return width, #text +-- end +-- +-- local hl_handler = {} +-- +-- hl_handler.title = function() +-- api.nvim_buf_add_highlight(buf, -1, hl.word, pos_info.title.line, 0, pos_info.title.word) +-- api.nvim_buf_add_highlight(buf, -1, hl.phonetic, pos_info.title.line, pos_info.title.word + 5, +-- pos_info.title.word + 5 + pos_info.title.phonetic) +-- end +-- +-- hl_handler.tag = function() +-- if pos_info.tag then +-- api.nvim_buf_add_highlight(buf, -1, hl.ref, pos_info.tag, 0, -1) +-- api.nvim_buf_add_highlight(buf, -1, hl.tag, pos_info.tag + 1, 0, -1) +-- end +-- end +-- +-- hl_handler.pos = function() +-- if pos_info.pos then +-- api.nvim_buf_add_highlight(buf, -1, hl.ref, pos_info.pos.line, 0, -1) +-- for i = 1, pos_info.pos.content, 1 do +-- api.nvim_buf_add_highlight(buf, -1, hl.pos, pos_info.pos.line + i, 0, -1) +-- end +-- end +-- end +-- +-- hl_handler.exchange = function() +-- if pos_info.exchange then +-- api.nvim_buf_add_highlight(buf, -1, hl.ref, pos_info.exchange.line, 0, -1) +-- for i = 1, pos_info.exchange.content, 1 do +-- api.nvim_buf_add_highlight(buf, -1, hl.exchange, pos_info.exchange.line + i, 0, -1) +-- end +-- end +-- end +-- +-- hl_handler.zh = function() +-- api.nvim_buf_add_highlight(buf, -1, hl.ref, pos_info.zh.line, 0, -1) +-- for i = 1, pos_info.zh.content, 1 do +-- api.nvim_buf_add_highlight(buf, -1, hl.zh, pos_info.zh.line + i, 0, -1) +-- end +-- end +-- +-- hl_handler.en = function() +-- if pos_info.en then +-- api.nvim_buf_add_highlight(buf, -1, hl.ref, pos_info.en.line, 0, -1) +-- for i = 1, pos_info.en.content, 1 do +-- api.nvim_buf_add_highlight(buf, -1, hl.en, pos_info.en.line + i, 0, -1) +-- end +-- end +-- end +-- +-- +-- local function set_hl() +-- for _, v in ipairs(order) do +-- hl_handler[v]() +-- end +-- end +-- +-- local function clear_tmp_info() +-- pos_info = {} +-- line = 0 +-- end +-- +-- +-- function M.query(mode) +-- assert(buf > 0) +-- local word = '' +-- if mode == 'n' then +-- word = vim.fn.expand('<cword>') +-- elseif mode == 'v' then +-- word = get_visual_selection() +-- elseif mode == 'I' then +-- word = vim.fn.input('请输入您要查询的单词: ') +-- -- vim.ui.input({prompt = '请输入您要查询的单词: '}, function (input) +-- -- word = input +-- -- end) +-- else +-- error('mode argument is invalid') +-- end +-- +-- local res = require("Trans.database").query(word) +-- local width, height = set_text(res) +-- show_win(width, height) +-- if res then +-- set_hl() +-- clear_tmp_info() +-- end +-- +-- if auto_close then +-- api.nvim_create_autocmd( +-- { 'InsertEnter', 'CursorMoved', 'BufLeave', }, { +-- buffer = 0, +-- once = true, +-- callback = M.close_win, +-- }) +-- end +-- end +-- +-- function M.query_cursor() +-- M.query('n') +-- end +-- +-- function M.query_select() +-- M.query('v') +-- end +-- +-- function M.query_input() +-- M.query('I') +-- end +-- +-- function M.close_win() +-- if win > 0 then +-- api.nvim_win_close(win, true) +-- win = 0 +-- end +-- end +-- +-- -- function M.enter_win() +-- -- if api.nvim_win_is_valid(win) then +-- -- else +-- -- error('current win is not valid') +-- -- end +-- -- end +-- +-- return M diff --git a/lua/Trans/highlight.lua b/lua/Trans/highlight.lua deleted file mode 100644 index 23a4f72..0000000 --- a/lua/Trans/highlight.lua +++ /dev/null @@ -1,26 +0,0 @@ -local M = {} - -M.hlgroup = { - word = 'TransWord', - phonetic = 'TransPhonetic', - ref = 'TransRef', - tag = 'TransTag', - exchange = 'TransExchange', - pos = 'TransPos', - zh = 'TransZh', - en = 'TransEn', -} - -function M.set_hl() - local set_hl = vim.api.nvim_set_hl - set_hl(0, M.hlgroup.word, { fg = '#7ee787', bold = true }) - set_hl(0, M.hlgroup.phonetic, { fg = '#8b949e' }) - set_hl(0, M.hlgroup.ref, { fg = '#75beff', bold = true }) - set_hl(0, M.hlgroup.tag, { fg = '#e5c07b' }) - set_hl(0, M.hlgroup.pos, { link = M.hlgroup.tag }) - set_hl(0, M.hlgroup.exchange, { link = M.hlgroup.tag }) - set_hl(0, M.hlgroup.zh, { link = M.hlgroup.word }) - set_hl(0, M.hlgroup.en, { fg = '#bc8cff' }) -end - -return M diff --git a/lua/Trans/setup.lua b/lua/Trans/setup.lua index 88d1ddf..e0325b0 100644 --- a/lua/Trans/setup.lua +++ b/lua/Trans/setup.lua @@ -1,7 +1,6 @@ local db = require("Trans").db -- local conf = require("Trans").conf - vim.api.nvim_create_user_command('TranslateCursorWord', require("Trans.display").query_cursor, {}) vim.api.nvim_create_user_command('TranslateSelectWord', require("Trans.display").query_select, {}) vim.api.nvim_create_user_command('TranslateInputWord', require("Trans.display").query_input, {}) @@ -20,4 +19,8 @@ vim.api.nvim_create_autocmd('VimLeave', { -- vim.keymap.set('n', 'mm', '<cmd>TranslateCurosorWord<cr>') -- vim.keymap.set('v', 'mm', '<Esc><cmd>TranslateSelectWord<cr>') -require("Trans.highlight").set_hl() + +local highlights = require("Trans").conf.highlight +for highlight, opt in pairs(highlights) do + vim.nvim_set_hl(0, highlight, opt) +end diff --git a/lua/Trans/window.lua b/lua/Trans/window.lua new file mode 100644 index 0000000..e02eb5c --- /dev/null +++ b/lua/Trans/window.lua @@ -0,0 +1,48 @@ +-- TODO different style to display +local M = {} + +M.float_opts = function(conf) + local columns = vim.o.columns + local height = vim.o.lines - vim.o.cmdheight - conf.top_offset + local width = math.floor(columns * conf.relative_width) + + return { + relative = 'editor', + col = math.floor((columns - width) / 2), -- 两侧的宽度 + row = conf.top_offset, + title = 'Trans', + title_pos = 'center', + style = 'minimal', + width = width, + height = height, + border = conf.border, + zindex = 50, + } +end + +M.cursor_opts = function (conf) + local opts = { + relative = 'cursor', + col = 2, + row = 2, + title = 'Trans', + title_pos = 'center', + style = 'minimal', + border = conf.border, + -- TODO keymap to convert style to Float + focusable = false, + zindex = 100, + } + if conf.style == 'fixed' then + opts.width = conf.width + opts.height = conf.height + elseif conf.style == 'relative' then + opts.width = (conf.width > 0 and conf.width < conf.max_width) and conf.width or conf.max_width + opts.height = (conf.height > 0 and conf.height < conf.max_height) and conf.height or conf.max_height + else + error('unknown style!') + end + return opts +end + +return M From c51937c6cf9aaa0a50334629c15992aab8dfb9ae Mon Sep 17 00:00:00 2001 From: JuanZoran <1430359574@qq.com> Date: Wed, 4 Jan 2023 23:06:09 +0800 Subject: [PATCH 02/17] fix: fix some bugs and need to refator this project --- lua/Trans/database.lua | 6 ------ lua/Trans/init.lua | 14 ++++++-------- lua/Trans/setup.lua | 22 +++++++++++----------- 3 files changed, 17 insertions(+), 25 deletions(-) delete mode 100644 lua/Trans/database.lua diff --git a/lua/Trans/database.lua b/lua/Trans/database.lua deleted file mode 100644 index a5b77c0..0000000 --- a/lua/Trans/database.lua +++ /dev/null @@ -1,6 +0,0 @@ -local M = {} - -function M.query(arg) -end - -return M diff --git a/lua/Trans/init.lua b/lua/Trans/init.lua index 6a1a55f..909bd06 100644 --- a/lua/Trans/init.lua +++ b/lua/Trans/init.lua @@ -1,17 +1,15 @@ local M = {} - M.conf = require("Trans.conf") function M.setup(conf) conf = conf or {} - if conf.display then - conf.display = vim.tbl_extend('force', M.conf.display, conf.display) + for k, v in pairs(conf) do + if type(v) == 'table' then + M.conf[k] = vim.tbl_extend('force', M.conf[k], v) + else + M.conf[k] = v + end end - - if conf.icon then - conf.icon = vim.tbl_extend('force', M.conf.icon, conf.icon) - end - M.conf = vim.tbl_extend('force', M.conf, conf) require("Trans.setup") end diff --git a/lua/Trans/setup.lua b/lua/Trans/setup.lua index e0325b0..18d4e16 100644 --- a/lua/Trans/setup.lua +++ b/lua/Trans/setup.lua @@ -1,14 +1,17 @@ local db = require("Trans").db --- local conf = require("Trans").conf -vim.api.nvim_create_user_command('TranslateCursorWord', require("Trans.display").query_cursor, {}) -vim.api.nvim_create_user_command('TranslateSelectWord', require("Trans.display").query_select, {}) -vim.api.nvim_create_user_command('TranslateInputWord', require("Trans.display").query_input, {}) +vim.api.nvim_create_user_command('TranslateCursorWord', require("Trans.display").query_cursor, { + desc = '翻译光标下的单词', +}) +vim.api.nvim_create_user_command('TranslateSelectWord', require("Trans.display").query_select, { + desc = '翻译选中的单词', +}) +vim.api.nvim_create_user_command('TranslateInputWord', require("Trans.display").query_input, { + desc = '翻译输入的单词', +}) - -local group = vim.api.nvim_create_augroup("Trans", { clear = true }) -vim.api.nvim_create_autocmd('VimLeave', { - group = group, +vim.api.nvim_create_autocmd('VimLeavePre', { + group = vim.api.nvim_create_augroup("Trans", { clear = true }), pattern = '*', callback = function() if db:isopen() then @@ -17,9 +20,6 @@ vim.api.nvim_create_autocmd('VimLeave', { end, }) --- vim.keymap.set('n', 'mm', '<cmd>TranslateCurosorWord<cr>') --- vim.keymap.set('v', 'mm', '<Esc><cmd>TranslateSelectWord<cr>') - local highlights = require("Trans").conf.highlight for highlight, opt in pairs(highlights) do vim.nvim_set_hl(0, highlight, opt) From 409d85f615ac91712dcbcd212912ed78989d4a37 Mon Sep 17 00:00:00 2001 From: JuanZoran <1430359574@qq.com> Date: Wed, 4 Jan 2023 23:11:19 +0800 Subject: [PATCH 03/17] feat: add conf to setup view for different command --- lua/Trans/conf.lua | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lua/Trans/conf.lua b/lua/Trans/conf.lua index 493d001..fc61d66 100644 --- a/lua/Trans/conf.lua +++ b/lua/Trans/conf.lua @@ -69,7 +69,11 @@ return { notOxford = '' }, auto_close = true, - + style = { + input = 'float', + cursor = 'cursor', + select = 'cursor' + } -- TODO add online translate engine -- online_search = { -- enable = false, From 033622ed85f3b5f118abc3ab8b302888bca6e145 Mon Sep 17 00:00:00 2001 From: JuanZoran <1430359574@qq.com> Date: Thu, 5 Jan 2023 16:24:50 +0800 Subject: [PATCH 04/17] feat: improve repository framework --- lua/Trans/conf.lua | 84 --------------------- lua/Trans/conf/base.lua | 17 +++++ lua/Trans/conf/default.lua | 110 ++++++++++++++++++++++++++++ lua/Trans/conf/init.lua | 1 + lua/Trans/conf/loader.lua | 52 +++++++++++++ lua/Trans/conf/window.lua | 52 +++++++++++++ lua/Trans/content.lua | 0 lua/Trans/{display.lua => core.lua} | 11 +-- lua/Trans/database/init.lua | 29 ++++++++ lua/Trans/init.lua | 26 ++----- lua/Trans/setup.lua | 22 ++---- lua/Trans/util/debug.lua | 35 +++++++++ lua/Trans/window.lua | 48 ------------ lua/Trans/window/content.lua | 18 +++++ lua/Trans/window/display.lua | 29 ++++++++ lua/Trans/window/init.lua | 0 16 files changed, 357 insertions(+), 177 deletions(-) delete mode 100644 lua/Trans/conf.lua create mode 100644 lua/Trans/conf/base.lua create mode 100644 lua/Trans/conf/default.lua create mode 100644 lua/Trans/conf/init.lua create mode 100644 lua/Trans/conf/loader.lua create mode 100644 lua/Trans/conf/window.lua create mode 100644 lua/Trans/content.lua rename lua/Trans/{display.lua => core.lua} (97%) create mode 100644 lua/Trans/database/init.lua create mode 100644 lua/Trans/util/debug.lua delete mode 100644 lua/Trans/window.lua create mode 100644 lua/Trans/window/content.lua create mode 100644 lua/Trans/window/display.lua create mode 100644 lua/Trans/window/init.lua diff --git a/lua/Trans/conf.lua b/lua/Trans/conf.lua deleted file mode 100644 index fc61d66..0000000 --- a/lua/Trans/conf.lua +++ /dev/null @@ -1,84 +0,0 @@ -return { - view = { - cursor = { - -- NOTE : - -- 可选的风格:['fixed', 'relative', .. ] - style = 'fixed', - border = 'rounded', - -- NOTE : - -- 如果style设置为'relative' - -- 则其值代表最大限制, 设置为负数则无限制 - width = 30, - height = 30, - }, - float = { - top_offset = 1, - relative_width = 0.8, - border = 'rounded', - }, - }, - display = { - phnoetic = true, - collins_star = true, - oxford = true, - -- TODO - -- history = false, - }, - order = { - 'title', - 'tag', - 'pos', - 'exchange', - 'zh', - 'en', - }, - - highligh = { - TransWord = { - fg = '#7ee787', - bold = true, - }, - TransPhonetic = { - fg = '#8b949e', - }, - TransRef = { - fg = '#75beff', - bold = true, - }, - TransTag = { - fg = '#e5c07b', - }, - TransExchange = { - link = 'TransTag', - }, - TransPos = { - link = 'TransTag', - }, - TransZh = { - link = 'TransWord', - }, - TransEn = { - fg = '#bc8cff', - }, - }, - db_path = '$HOME/.vim/dict/ultimate.db', - - icon = { - star = '⭐', - isOxford = '✔', - notOxford = '' - }, - auto_close = true, - style = { - input = 'float', - cursor = 'cursor', - select = 'cursor' - } - -- TODO add online translate engine - -- online_search = { - -- enable = false, - -- engine = {}, - -- } - - -- TODO register word -} diff --git a/lua/Trans/conf/base.lua b/lua/Trans/conf/base.lua new file mode 100644 index 0000000..0a7f899 --- /dev/null +++ b/lua/Trans/conf/base.lua @@ -0,0 +1,17 @@ +local M = {} + +local buf_opts = { + filetype = 'Trans' +} + +local buf = vim.api.nvim_create_buf(false, true) +for k, v in pairs(buf_opts) do + vim.api.nvim_buf_set_options(buf, k, v) +end + +M.buf = buf + +M.group = vim.api.nvim_create_augroup('Trans', { clear = true }) + + +return M diff --git a/lua/Trans/conf/default.lua b/lua/Trans/conf/default.lua new file mode 100644 index 0000000..667274f --- /dev/null +++ b/lua/Trans/conf/default.lua @@ -0,0 +1,110 @@ +local M = {} + +-- INFO :加载的规则 [LuaRule] +M.replace_rules = { + 'order', + 'Trans.+', +} + +M.conf = { + style = { + window = { + input = 'float', + cursor = 'cursor', + select = 'cursor' + }, + order = { + 'title', + 'tag', + 'pos', + 'exchange', + 'zh', + 'en', + }, + conf = { + -- NOTE :可选的风格:['fixed', 'relative', .. TODO] + -- width 和 height说明: + -- 大于1: + -- 如果style为fixed , 则为固定的长宽 + -- 如果style为relative , 则为最大长宽 + -- 小于1: + -- 如果style为fixed , 则为默认 + -- 如果style为relative , 则为无限制 + -- 0 ~ 1: + -- 相对长宽 + cursor = { + style = 'fixed', + border = 'rounded', + width = 30, + height = 30, + }, + float = { + style = 'fixed', + border = 'rounded', + width = 0.8, + height = 0.9, + }, + }, + }, + ui = { + highligh = { + TransWord = { + fg = '#7ee787', + bold = true, + }, + TransPhonetic = { + fg = '#8b949e', + }, + TransRef = { + fg = '#75beff', + bold = true, + }, + TransTag = { + fg = '#e5c07b', + }, + TransExchange = { + link = 'TransTag', + }, + TransPos = { + link = 'TransTag', + }, + TransZh = { + link = 'TransWord', + }, + TransEn = { + fg = '#bc8cff', + }, + }, + icon = { + star = '⭐', + isOxford = '✔', + notOxford = '' + }, + display = { + phnoetic = true, + collins_star = true, + oxford = true, + -- TODO + -- history = false, + }, + }, + base = { + db_path = '$HOME/.vim/dict/ultimate.db', + auto_close = true, + lazy_load = false, + debug = { + enable = true, + type_check = true, + unknown_conf = true, + }, + }, + -- TODO add online translate engine + -- online_search = { + -- enable = false, + -- engine = {}, + -- } + + -- TODO register word +} + +return M diff --git a/lua/Trans/conf/init.lua b/lua/Trans/conf/init.lua new file mode 100644 index 0000000..01baf8e --- /dev/null +++ b/lua/Trans/conf/init.lua @@ -0,0 +1 @@ +return require("Trans.conf.loader").get_conf() diff --git a/lua/Trans/conf/loader.lua b/lua/Trans/conf/loader.lua new file mode 100644 index 0000000..7ccad44 --- /dev/null +++ b/lua/Trans/conf/loader.lua @@ -0,0 +1,52 @@ +---@diagnostic disable: unused-local, unused-function +local M = {} + +local replace_rules = require("Trans.conf.default").replace_rules +local conf = require("Trans.conf.default").conf +local user_conf = require("Trans").conf +local type_check = require("Trans.util.debug").type_check +local is_loaded = false + +local function need_extend(name) + type_check { + name = { name, 'string' } + } + for _, rule in ipairs(replace_rules) do + if name:match(rule) then + return false + end + end + return true +end + +-- 加载用户自定义的配置 +---@param t1 table +---@param t2 table +local function extend(t1, t2) + type_check { + t1 = { t1, 'table' }, + t2 = { t2, 'table' }, + } + for k, v in pairs(t2) do + if type(v) == 'table' and need_extend(k) then + extend(t1[k], v) + else + t1[k] = v + end + end +end + +M.get_conf = function() + if not is_loaded then + M.load_conf() + end + return conf +end + +M.load_conf = function() + -- loaded_conf = default_conf:extend(user_conf) + extend(conf, user_conf) + is_loaded = true +end + +return M diff --git a/lua/Trans/conf/window.lua b/lua/Trans/conf/window.lua new file mode 100644 index 0000000..6f49f3f --- /dev/null +++ b/lua/Trans/conf/window.lua @@ -0,0 +1,52 @@ +local M = {} +local conf = require("Trans").conf.view + +local get_float_opts = function(float_conf) + local columns = vim.o.columns + local height = vim.o.lines - vim.o.cmdheight - float_conf.top_offset + local width = math.floor(columns * float_conf.relative_width) + + return { + relative = 'editor', + col = math.floor((columns - width) / 2), -- 两侧的宽度 + row = float_conf.top_offset, + title = 'Trans', + title_pos = 'center', + style = 'minimal', + width = width, + height = height, + border = float_conf.border, + zindex = 50, + } +end + +local get_cursor_opts = function(cursor_conf) + local opts = { + relative = 'cursor', + col = 2, + row = 2, + title = 'Trans', + title_pos = 'center', + style = 'minimal', + border = cursor_conf.border, + -- TODO keymap to convert style to Float + focusable = false, + zindex = 100, + } + if cursor_conf.style == 'fixed' then + opts.width = cursor_conf.width + opts.height = cursor_conf.height + elseif cursor_conf.style == 'relative' then + opts.width = (cursor_conf.width > 0 and conf.width < conf.max_width) and conf.width or conf.max_width + opts.height = (cursor_conf.height > 0 and conf.height < conf.max_height) and conf.height or conf.max_height + else + error('unknown style!') + end + return opts +end + +M.get_float_opts = get_float_opts(conf.float) + +M.cursor_opts = get_cursor_opts(conf.cursor) + +return M diff --git a/lua/Trans/content.lua b/lua/Trans/content.lua new file mode 100644 index 0000000..e69de29 diff --git a/lua/Trans/display.lua b/lua/Trans/core.lua similarity index 97% rename from lua/Trans/display.lua rename to lua/Trans/core.lua index 2b41cca..08676d6 100644 --- a/lua/Trans/display.lua +++ b/lua/Trans/core.lua @@ -8,9 +8,6 @@ local order = conf.order local auto_close = conf.auto_close local view = conf.view --- TODO : setup database -local db_path = require("Trans").conf.db_path -local dict = require("Trans").db:open(db_path) local highlight = { word = 'TransWord', @@ -23,6 +20,7 @@ local highlight = { en = 'TransEn', } + local function get_select() local s_start = vim.fn.getpos("'<") local s_end = vim.fn.getpos("'>") @@ -46,12 +44,7 @@ local function get_query_res(method) else error('unknown method') end - - -- TODO : dict query optimization - local res = dict:select('stardict', { - where = { word = arg }, - }) - return res[1] + -- FIXME end M.TransLate = function(opts) diff --git a/lua/Trans/database/init.lua b/lua/Trans/database/init.lua new file mode 100644 index 0000000..a20baf6 --- /dev/null +++ b/lua/Trans/database/init.lua @@ -0,0 +1,29 @@ +local M = {} +local _, db = pcall(require, 'sqlite.db') +if not _ then + error('Please check out sqlite.lua') +end + +-- INFO : init database +local path = require("Trans").conf.db_path +local dict = db:open(path) + +-- INFO :Auto Close +vim.api.nvim_create_autocmd('VimLeavePre', { + group = require("Trans.conf.base").autogroup, + callback = function () + if db:isopen() then + db:close() + end + end +}) + +M.query = function (arg) + -- TODO : more opts + local res = dict:select('stardict', { + where = { word = arg }, + }) + return res[1] +end + +return M diff --git a/lua/Trans/init.lua b/lua/Trans/init.lua index 909bd06..828a1be 100644 --- a/lua/Trans/init.lua +++ b/lua/Trans/init.lua @@ -1,29 +1,13 @@ local M = {} -M.conf = require("Trans.conf") +M.conf = {} + function M.setup(conf) - conf = conf or {} - for k, v in pairs(conf) do - if type(v) == 'table' then - M.conf[k] = vim.tbl_extend('force', M.conf[k], v) - else - M.conf[k] = v - end + M.conf = conf or {} + if conf.base and not conf.base.lazy_load then + require("Trans.conf.loader").load_conf() end - M.conf = vim.tbl_extend('force', M.conf, conf) require("Trans.setup") end -local res = vim.fn.executable('sqlite3') -if res ~= 1 then - error('Please check out sqlite3') -end - -local status, db = pcall(require, 'sqlite.db') -if not status then - error('Please check out sqlite.lua') -end - -M.db = db - return M diff --git a/lua/Trans/setup.lua b/lua/Trans/setup.lua index 18d4e16..9bf3250 100644 --- a/lua/Trans/setup.lua +++ b/lua/Trans/setup.lua @@ -1,26 +1,18 @@ -local db = require("Trans").db +if vim.fn.executable('sqlite3') ~= 1 then + error('Please check out sqlite3') +end -vim.api.nvim_create_user_command('TranslateCursorWord', require("Trans.display").query_cursor, { +vim.api.nvim_create_user_command('TranslateCursorWord', require("Trans.core").query_cursor, { desc = '翻译光标下的单词', }) -vim.api.nvim_create_user_command('TranslateSelectWord', require("Trans.display").query_select, { +vim.api.nvim_create_user_command('TranslateSelectWord', require("Trans.core").query_select, { desc = '翻译选中的单词', }) -vim.api.nvim_create_user_command('TranslateInputWord', require("Trans.display").query_input, { +vim.api.nvim_create_user_command('TranslateInputWord', require("Trans.core").query_input, { desc = '翻译输入的单词', }) -vim.api.nvim_create_autocmd('VimLeavePre', { - group = vim.api.nvim_create_augroup("Trans", { clear = true }), - pattern = '*', - callback = function() - if db:isopen() then - db:close() - end - end, -}) - -local highlights = require("Trans").conf.highlight +local highlights = require("Trans.conf").ui.highligh for highlight, opt in pairs(highlights) do vim.nvim_set_hl(0, highlight, opt) end diff --git a/lua/Trans/util/debug.lua b/lua/Trans/util/debug.lua new file mode 100644 index 0000000..874954b --- /dev/null +++ b/lua/Trans/util/debug.lua @@ -0,0 +1,35 @@ +local M = {} + +-- INFO : get loaded debug conf +local base = require("Trans").conf.base +local debug = require("Trans.conf.default").conf.base.debug +if base and base.debug then + debug = vim.tbl_extend('force', debug, base) +end + +M.type_check = function (types) + if debug.enable and debug.type_check then + vim.validate(types) + end +end +-- local function dedent(lines) +-- local ind_size = math.huge +-- for i, _ in ipairs(lines) do +-- local i1, i2 = lines[i]:find("^%s*[^%s]") +-- if i1 and i2 < ind_size then +-- ind_size = i2 +-- end +-- end +-- for i, _ in ipairs(lines) do +-- lines[i] = lines[i]:sub(ind_size, -1) +-- end +-- end +-- +-- function M.dedent(s) +-- local lst = vim.split(s, "\n") +-- dedent(lst) +-- return table.concat(lst, "\n") +-- end + + +return M diff --git a/lua/Trans/window.lua b/lua/Trans/window.lua deleted file mode 100644 index e02eb5c..0000000 --- a/lua/Trans/window.lua +++ /dev/null @@ -1,48 +0,0 @@ --- TODO different style to display -local M = {} - -M.float_opts = function(conf) - local columns = vim.o.columns - local height = vim.o.lines - vim.o.cmdheight - conf.top_offset - local width = math.floor(columns * conf.relative_width) - - return { - relative = 'editor', - col = math.floor((columns - width) / 2), -- 两侧的宽度 - row = conf.top_offset, - title = 'Trans', - title_pos = 'center', - style = 'minimal', - width = width, - height = height, - border = conf.border, - zindex = 50, - } -end - -M.cursor_opts = function (conf) - local opts = { - relative = 'cursor', - col = 2, - row = 2, - title = 'Trans', - title_pos = 'center', - style = 'minimal', - border = conf.border, - -- TODO keymap to convert style to Float - focusable = false, - zindex = 100, - } - if conf.style == 'fixed' then - opts.width = conf.width - opts.height = conf.height - elseif conf.style == 'relative' then - opts.width = (conf.width > 0 and conf.width < conf.max_width) and conf.width or conf.max_width - opts.height = (conf.height > 0 and conf.height < conf.max_height) and conf.height or conf.max_height - else - error('unknown style!') - end - return opts -end - -return M diff --git a/lua/Trans/window/content.lua b/lua/Trans/window/content.lua new file mode 100644 index 0000000..1b86632 --- /dev/null +++ b/lua/Trans/window/content.lua @@ -0,0 +1,18 @@ +local M = {} + +--[[ +content = { + lines = {} ---@type string[] + highlight = {} +} +--]] +---@param contents string[] +M.set = function (win, contents) + vim.validate { + contents = { contents, 'table' }, + } + -- TODO +end + + +return M diff --git a/lua/Trans/window/display.lua b/lua/Trans/window/display.lua new file mode 100644 index 0000000..567149b --- /dev/null +++ b/lua/Trans/window/display.lua @@ -0,0 +1,29 @@ +local M = {} +local api = vim.api +local util = require("Trans.window.util") +M.buf = util.init_buf() + +--- 浮动窗口的风格 +---@param conf table 自定义配置 +M.show_float_win = function(conf) + vim.validate { + conf = { conf, 'table' }, + } + local opts = util.get_float_opts(conf) + local win = api.nvim_open_win(M.buf, true, opts) + return win +end + +M.show_cursor_win = function(conf) + vim.validate { + conf = { conf, 'table' }, + } + local opts = util.get_cursor_opts(conf) + local win = api.nvim_open_win(M.buf, true, opts) + return win +end + +-- TODO <++> more window style + + +return M diff --git a/lua/Trans/window/init.lua b/lua/Trans/window/init.lua new file mode 100644 index 0000000..e69de29 From a1488b2d9b75691a33e40232c37b4be541749d81 Mon Sep 17 00:00:00 2001 From: JuanZoran <1430359574@qq.com> Date: Thu, 5 Jan 2023 21:15:01 +0800 Subject: [PATCH 05/17] refactor: init the repo and decide to add more feature --- lua/.luarc.json | 6 ++++ lua/Trans/component/offline/Definition.lua | 7 ++++ lua/Trans/component/offline/Exchange.lua | 7 ++++ lua/Trans/component/offline/Pos.lua | 7 ++++ lua/Trans/component/offline/Tag.lua | 7 ++++ lua/Trans/component/offline/Title.lua | 7 ++++ lua/Trans/component/offline/Translation.lua | 7 ++++ lua/Trans/conf/base.lua | 2 +- lua/Trans/conf/default.lua | 34 +++++++++++-------- lua/Trans/conf/window.lua | 11 +++++- lua/Trans/core/content.lua | 19 +++++++++++ lua/Trans/{core.lua => core/init.lua} | 25 -------------- lua/Trans/core/query.lua | 37 +++++++++++++++++++++ lua/Trans/database/init.lua | 27 ++++++++++++--- lua/Trans/init.lua | 2 +- lua/Trans/{content.lua => ui/init.lua} | 0 lua/Trans/util/parser.lua | 19 +++++++++++ 17 files changed, 178 insertions(+), 46 deletions(-) create mode 100644 lua/.luarc.json create mode 100644 lua/Trans/component/offline/Definition.lua create mode 100644 lua/Trans/component/offline/Exchange.lua create mode 100644 lua/Trans/component/offline/Pos.lua create mode 100644 lua/Trans/component/offline/Tag.lua create mode 100644 lua/Trans/component/offline/Title.lua create mode 100644 lua/Trans/component/offline/Translation.lua create mode 100644 lua/Trans/core/content.lua rename lua/Trans/{core.lua => core/init.lua} (91%) create mode 100644 lua/Trans/core/query.lua rename lua/Trans/{content.lua => ui/init.lua} (100%) create mode 100644 lua/Trans/util/parser.lua diff --git a/lua/.luarc.json b/lua/.luarc.json new file mode 100644 index 0000000..43e8c9f --- /dev/null +++ b/lua/.luarc.json @@ -0,0 +1,6 @@ +{ + "$schema": "https://raw.githubusercontent.com/sumneko/vscode-lua/master/setting/schema.json", + "Lua.diagnostics.disable": [ + "unused-local" + ] +} \ No newline at end of file diff --git a/lua/Trans/component/offline/Definition.lua b/lua/Trans/component/offline/Definition.lua new file mode 100644 index 0000000..cf04e60 --- /dev/null +++ b/lua/Trans/component/offline/Definition.lua @@ -0,0 +1,7 @@ +local M = {} + +M.to_lines = function (field) + -- TODO +end + +return M diff --git a/lua/Trans/component/offline/Exchange.lua b/lua/Trans/component/offline/Exchange.lua new file mode 100644 index 0000000..cf04e60 --- /dev/null +++ b/lua/Trans/component/offline/Exchange.lua @@ -0,0 +1,7 @@ +local M = {} + +M.to_lines = function (field) + -- TODO +end + +return M diff --git a/lua/Trans/component/offline/Pos.lua b/lua/Trans/component/offline/Pos.lua new file mode 100644 index 0000000..cf04e60 --- /dev/null +++ b/lua/Trans/component/offline/Pos.lua @@ -0,0 +1,7 @@ +local M = {} + +M.to_lines = function (field) + -- TODO +end + +return M diff --git a/lua/Trans/component/offline/Tag.lua b/lua/Trans/component/offline/Tag.lua new file mode 100644 index 0000000..cf04e60 --- /dev/null +++ b/lua/Trans/component/offline/Tag.lua @@ -0,0 +1,7 @@ +local M = {} + +M.to_lines = function (field) + -- TODO +end + +return M diff --git a/lua/Trans/component/offline/Title.lua b/lua/Trans/component/offline/Title.lua new file mode 100644 index 0000000..cf04e60 --- /dev/null +++ b/lua/Trans/component/offline/Title.lua @@ -0,0 +1,7 @@ +local M = {} + +M.to_lines = function (field) + -- TODO +end + +return M diff --git a/lua/Trans/component/offline/Translation.lua b/lua/Trans/component/offline/Translation.lua new file mode 100644 index 0000000..cf04e60 --- /dev/null +++ b/lua/Trans/component/offline/Translation.lua @@ -0,0 +1,7 @@ +local M = {} + +M.to_lines = function (field) + -- TODO +end + +return M diff --git a/lua/Trans/conf/base.lua b/lua/Trans/conf/base.lua index 0a7f899..42c4d8e 100644 --- a/lua/Trans/conf/base.lua +++ b/lua/Trans/conf/base.lua @@ -6,7 +6,7 @@ local buf_opts = { local buf = vim.api.nvim_create_buf(false, true) for k, v in pairs(buf_opts) do - vim.api.nvim_buf_set_options(buf, k, v) + vim.api.nvim_buf_set_option(buf, k, v) end M.buf = buf diff --git a/lua/Trans/conf/default.lua b/lua/Trans/conf/default.lua index 667274f..7212202 100644 --- a/lua/Trans/conf/default.lua +++ b/lua/Trans/conf/default.lua @@ -1,27 +1,21 @@ local M = {} --- INFO :加载的规则 [LuaRule] -M.replace_rules = { - 'order', - 'Trans.+', -} - M.conf = { style = { - window = { + ui = { input = 'float', cursor = 'cursor', select = 'cursor' }, order = { - 'title', - 'tag', - 'pos', - 'exchange', - 'zh', - 'en', + 'Title', + 'Tag', + 'Pos', + 'Exchange', + 'Translation', + 'Definition', }, - conf = { + window = { -- NOTE :可选的风格:['fixed', 'relative', .. TODO] -- width 和 height说明: -- 大于1: @@ -44,6 +38,12 @@ M.conf = { width = 0.8, height = 0.9, }, + -- NOTE :如果你想限制某个组件的行数,可以设置 (名称与order相同) + -- Example: + -- limit = { + -- En = 1, -- 只显示第一行,(一般为最广泛的释义) + -- }, + limit = nil, }, }, ui = { @@ -107,4 +107,10 @@ M.conf = { -- TODO register word } +-- INFO :加载的规则 [LuaRule] +M.replace_rules = { + 'order', + 'Trans.+', +} + return M diff --git a/lua/Trans/conf/window.lua b/lua/Trans/conf/window.lua index 6f49f3f..04c6b49 100644 --- a/lua/Trans/conf/window.lua +++ b/lua/Trans/conf/window.lua @@ -1,7 +1,13 @@ local M = {} -local conf = require("Trans").conf.view +local conf = require("Trans.conf").style.window +local type_check = require("Trans.util.debug").type_check + +-- FIXME local get_float_opts = function(float_conf) + type_check { + float_conf = { float_conf, 'table' }, + } local columns = vim.o.columns local height = vim.o.lines - vim.o.cmdheight - float_conf.top_offset local width = math.floor(columns * float_conf.relative_width) @@ -21,6 +27,9 @@ local get_float_opts = function(float_conf) end local get_cursor_opts = function(cursor_conf) + type_check { + cursor_conf = { cursor_conf, 'table' }, + } local opts = { relative = 'cursor', col = 2, diff --git a/lua/Trans/core/content.lua b/lua/Trans/core/content.lua new file mode 100644 index 0000000..0cc6206 --- /dev/null +++ b/lua/Trans/core/content.lua @@ -0,0 +1,19 @@ +local M = {} +local type_check = require("Trans.util.debug").type_check + +local offline_dir = debug.getinfo(1, "S").source:sub(2):match('.*Trans') .. '/component/offline' + +M.to_content = function(query_res) + type_check { + query_res = { query_res, 'table' } + } + local content = {} + for file in vim.fs.dir(offline_dir) do + local res = require("Trans.component.offline." .. file:gsub('.lua', '')).to_content(query_res) + assert(res) + table.insert(content, res) + end + return content +end + +return M diff --git a/lua/Trans/core.lua b/lua/Trans/core/init.lua similarity index 91% rename from lua/Trans/core.lua rename to lua/Trans/core/init.lua index 08676d6..6e28f2d 100644 --- a/lua/Trans/core.lua +++ b/lua/Trans/core/init.lua @@ -1,4 +1,3 @@ ----@diagnostic disable: unused-local local M = {} local api = vim.api local conf = require("Trans").conf @@ -21,31 +20,7 @@ local highlight = { } -local function get_select() - local s_start = vim.fn.getpos("'<") - local s_end = vim.fn.getpos("'>") - if s_start[2] ~= s_start[2] then - error('TODO: multiline translate') - end - local lin = vim.api.nvim_buf_get_lines(0, s_start[2] - 1, s_end[2], false)[1] - local word = string.sub(lin, s_start[3], s_end[3]) - return word -end -local function get_query_res(method) - -- NOTE : get query word - local word = '' - if method == 'cursor' then - word = vim.fn.expand('<cword>') - elseif method == 'select' then - word = get_select():match('%s+') - elseif method == 'input' then - word = vim.fn.input('请输入您要查询的单词:') -- TODO Use Telescope with fuzzy finder - else - error('unknown method') - end - -- FIXME -end M.TransLate = function(opts) local res = get_query_res(opts.method) diff --git a/lua/Trans/core/query.lua b/lua/Trans/core/query.lua new file mode 100644 index 0000000..2f3f43e --- /dev/null +++ b/lua/Trans/core/query.lua @@ -0,0 +1,37 @@ +local M = {} + +local type_check = require("Trans.util.debug").type_check +local query = require("Trans.database").query + +local function get_select() + local s_start = vim.fn.getpos("'<") + local s_end = vim.fn.getpos("'>") + if s_start[2] ~= s_start[2] then + error('TODO: multiline translate') + end + local lin = vim.api.nvim_buf_get_lines(0, s_start[2] - 1, s_end[2], false)[1] + local word = string.sub(lin, s_start[3], s_end[3]) + return word +end + +M.get_query_res = function(method) + type_check { + method = { method, 'string' }, + } + + -- NOTE : get query word + local word = '' + if method == 'cursor' then + word = vim.fn.expand('<cword>') + elseif method == 'select' then + word = get_select():match('%s+') + elseif method == 'input' then + word = vim.fn.input('请输入您要查询的单词:') -- TODO Use Telescope with fuzzy finder + else + error('unknown method') + end + -- FIXME + return query(word) +end + +return M diff --git a/lua/Trans/database/init.lua b/lua/Trans/database/init.lua index a20baf6..aeab460 100644 --- a/lua/Trans/database/init.lua +++ b/lua/Trans/database/init.lua @@ -3,25 +3,44 @@ local _, db = pcall(require, 'sqlite.db') if not _ then error('Please check out sqlite.lua') end +local type_check = require("Trans.util.debug").type_check + +local query_field = { + 'word', + 'phonetic', + 'definition', + 'translation', + 'pos', + 'collins', + 'oxford', + 'tag', + 'exchange', +} -- INFO : init database -local path = require("Trans").conf.db_path +local path = require("Trans.conf").base.db_path local dict = db:open(path) -- INFO :Auto Close vim.api.nvim_create_autocmd('VimLeavePre', { group = require("Trans.conf.base").autogroup, - callback = function () + callback = function() if db:isopen() then db:close() end end }) -M.query = function (arg) +M.query = function(arg) -- TODO : more opts + type_check { + arg = { arg, 'string' }, + } local res = dict:select('stardict', { - where = { word = arg }, + where = { + word = arg, + }, + keys = query_field, }) return res[1] end diff --git a/lua/Trans/init.lua b/lua/Trans/init.lua index 828a1be..e076815 100644 --- a/lua/Trans/init.lua +++ b/lua/Trans/init.lua @@ -7,7 +7,7 @@ function M.setup(conf) if conf.base and not conf.base.lazy_load then require("Trans.conf.loader").load_conf() end - require("Trans.setup") + -- require("Trans.setup") end return M diff --git a/lua/Trans/content.lua b/lua/Trans/ui/init.lua similarity index 100% rename from lua/Trans/content.lua rename to lua/Trans/ui/init.lua diff --git a/lua/Trans/util/parser.lua b/lua/Trans/util/parser.lua new file mode 100644 index 0000000..4c4adfc --- /dev/null +++ b/lua/Trans/util/parser.lua @@ -0,0 +1,19 @@ +---@diagnostic disable: missing-return, unused-local +local M = {} +local type_check = require("Trans.util.debug").type_check + +---解析宽度 +---@param width integer +---@return integer +M.width = function (width) + -- TODO +end + +---解析宽度 +---@param height integer +---@return integer +M.height = function (height) + -- TODO +end + +return M From 2f6520940a3d0b0c675b262c0ef99a7c248f9327 Mon Sep 17 00:00:00 2001 From: JuanZoran <1430359574@qq.com> Date: Fri, 6 Jan 2023 23:05:10 +0800 Subject: [PATCH 06/17] feat: add Trans.util.test.query_youdao file ,.. and some utility function --- lua/Trans/component/offline/Definition.lua | 2 +- lua/Trans/component/offline/Exchange.lua | 2 +- lua/Trans/component/offline/Pos.lua | 2 +- lua/Trans/component/offline/Tag.lua | 2 +- lua/Trans/component/offline/Title.lua | 26 +++- lua/Trans/component/offline/Translation.lua | 2 +- lua/Trans/conf/default.lua | 17 +-- lua/Trans/util/format.lua | 124 ++++++++++++++++++++ lua/Trans/util/test/a.lua | 1 + lua/Trans/util/test/query_youdao.lua | 66 +++++++++++ 10 files changed, 225 insertions(+), 19 deletions(-) create mode 100644 lua/Trans/util/format.lua create mode 120000 lua/Trans/util/test/a.lua create mode 100644 lua/Trans/util/test/query_youdao.lua diff --git a/lua/Trans/component/offline/Definition.lua b/lua/Trans/component/offline/Definition.lua index cf04e60..94acd96 100644 --- a/lua/Trans/component/offline/Definition.lua +++ b/lua/Trans/component/offline/Definition.lua @@ -1,6 +1,6 @@ local M = {} -M.to_lines = function (field) +M.to_content = function (field) -- TODO end diff --git a/lua/Trans/component/offline/Exchange.lua b/lua/Trans/component/offline/Exchange.lua index cf04e60..94acd96 100644 --- a/lua/Trans/component/offline/Exchange.lua +++ b/lua/Trans/component/offline/Exchange.lua @@ -1,6 +1,6 @@ local M = {} -M.to_lines = function (field) +M.to_content = function (field) -- TODO end diff --git a/lua/Trans/component/offline/Pos.lua b/lua/Trans/component/offline/Pos.lua index cf04e60..94acd96 100644 --- a/lua/Trans/component/offline/Pos.lua +++ b/lua/Trans/component/offline/Pos.lua @@ -1,6 +1,6 @@ local M = {} -M.to_lines = function (field) +M.to_content = function (field) -- TODO end diff --git a/lua/Trans/component/offline/Tag.lua b/lua/Trans/component/offline/Tag.lua index cf04e60..94acd96 100644 --- a/lua/Trans/component/offline/Tag.lua +++ b/lua/Trans/component/offline/Tag.lua @@ -1,6 +1,6 @@ local M = {} -M.to_lines = function (field) +M.to_content = function (field) -- TODO end diff --git a/lua/Trans/component/offline/Title.lua b/lua/Trans/component/offline/Title.lua index cf04e60..71d3068 100644 --- a/lua/Trans/component/offline/Title.lua +++ b/lua/Trans/component/offline/Title.lua @@ -1,7 +1,31 @@ local M = {} -M.to_lines = function (field) +local display = require("Tran.conf").ui.display +-- Example: +-- local content = { +-- width = 1, +-- height = 1; +-- lines = { +-- Highlight = { +-- 'first line', +-- 'second line', +-- } +-- }, ---@table +-- } + + +-- local function format() +-- +-- end + +M.to_content = function (field) -- TODO + local line = '' + local format = '%s %s %s %s' + local content = { + height = 1, + } + return content end return M diff --git a/lua/Trans/component/offline/Translation.lua b/lua/Trans/component/offline/Translation.lua index cf04e60..94acd96 100644 --- a/lua/Trans/component/offline/Translation.lua +++ b/lua/Trans/component/offline/Translation.lua @@ -1,6 +1,6 @@ local M = {} -M.to_lines = function (field) +M.to_content = function (field) -- TODO end diff --git a/lua/Trans/conf/default.lua b/lua/Trans/conf/default.lua index 7212202..80d8694 100644 --- a/lua/Trans/conf/default.lua +++ b/lua/Trans/conf/default.lua @@ -16,24 +16,12 @@ M.conf = { 'Definition', }, window = { - -- NOTE :可选的风格:['fixed', 'relative', .. TODO] - -- width 和 height说明: - -- 大于1: - -- 如果style为fixed , 则为固定的长宽 - -- 如果style为relative , 则为最大长宽 - -- 小于1: - -- 如果style为fixed , 则为默认 - -- 如果style为relative , 则为无限制 - -- 0 ~ 1: - -- 相对长宽 cursor = { - style = 'fixed', border = 'rounded', width = 30, height = 30, }, float = { - style = 'fixed', border = 'rounded', width = 0.8, height = 0.9, @@ -43,7 +31,7 @@ M.conf = { -- limit = { -- En = 1, -- 只显示第一行,(一般为最广泛的释义) -- }, - limit = nil, + limit = nil, }, }, ui = { @@ -98,6 +86,9 @@ M.conf = { unknown_conf = true, }, }, + map = { + -- TODO + }, -- TODO add online translate engine -- online_search = { -- enable = false, diff --git a/lua/Trans/util/format.lua b/lua/Trans/util/format.lua new file mode 100644 index 0000000..7d9bf80 --- /dev/null +++ b/lua/Trans/util/format.lua @@ -0,0 +1,124 @@ +---@diagnostic disable: undefined-global +local M = {} +local type_check = require("Trans.util.debug").type_check + +-- 各种风格的基础宽度 +local style_width = { + float = require("Trans.conf.window").float.width, -- NOTE : need window parsed conf + cursor = require("Trans.conf.window").cursor.width, +} + +local m_width = nil -- 需要被格式化窗口的高度 +local m_fields = nil -- 待格式化的字段 +local m_indent = nil -- 每行的行首缩进 +local m_length = nil -- 所有字段加起来的长度(不包括缩进和间隔) + +local function get_rows() + -- TODO + return rows +end + +local function do_indent(lines) + for i, v in ipairs(lines) do + lines[i] = (' '):rep(m_indent) .. v + end +end + +local function format_to_line() + local space = math.floor((m_width - m_length) / #m_fields) + return line +end + +local function format_to_multilines() + -- TODO + type_check { + interval = { interval, 'number' }, + rows = { rows, 'number' }, + } +end + +local function get_formatted_lines() + local lines = {} + -- NOTE : 判断能否格式化成一行 + if m_length + (#m_fields * m_indent) > m_width then + lines = format_to_multilines() + else + lines[1] = format_to_line() + end + + if m_indent then + do_indent(lines) + end + return lines +end + +---将组件格式化成相应的vim支持的lines格式 +---@param style string 窗口的风格 +---@param fields string[] 需要格式化的字段 +---@param indent number 缩进的长度 +---@return string[] lines 便于vim.api.nvim_buf_set_lines +M.to_lines = function(style, fields, indent) + if not fields then + return {} + end + type_check { + style = { style, { 'string' } }, + fields = { fields, { 'table' } }, + indent = { indent, { 'number' }, true }, + } + + local length = 0 + for _, v in ipairs(fields) do + length = length + #v + end + + m_width = style_width[style] - indent + m_indent = indent + m_fields = fields + m_length = length + return get_formatted_lines() +end + +-- local function get_lines(win_width, components) +-- local lines = {} +-- local interval = win_width > 40 and 6 or 4 +-- local row = 1 +-- local width = win_width - #components[1] +-- for i in 2, #components do +-- width = width - #components[i] - interval +-- if width < 0 then +-- width = win_width - #components[i] +-- row = row + 1 +-- end +-- end +-- if row == 1 then +-- local format = '%s' .. ((' '):rep(interval) .. '%s') +-- lines[1] = string.format(format, unpack(components)) +-- else +-- table.sort(components, function (a, b) +-- return #a > #b +-- end) +-- -- FIXME +-- local res, rem = #components / (row + 1), #components % (row + 1) +-- row = math.ceil(res) +-- local rol = row - rem - 1 +-- end +-- +-- return lines +-- end +-- +-- M.format = function(style, components, indent) +-- local lines = {} +-- if #components > 1 then +-- indent = indent or 0 +-- type_check { +-- style = { style, 'string' }, +-- components = { components, 'table' }, ---@string[] +-- -- max_items = { max_items, { 'nil', 'number' } }, ---@string[] +-- } +-- local win_width = (style == 'float' and float_win_width or cursor_win_width) - indent +-- local res = get_lines(win_width, components) +-- end +-- return lines +-- end +return M diff --git a/lua/Trans/util/test/a.lua b/lua/Trans/util/test/a.lua new file mode 120000 index 0000000..9b39cbe --- /dev/null +++ b/lua/Trans/util/test/a.lua @@ -0,0 +1 @@ +query_youdao.lua \ No newline at end of file diff --git a/lua/Trans/util/test/query_youdao.lua b/lua/Trans/util/test/query_youdao.lua new file mode 100644 index 0000000..1d064f8 --- /dev/null +++ b/lua/Trans/util/test/query_youdao.lua @@ -0,0 +1,66 @@ +local M = {} +-- local type_check = require("Trans.util.debug").type_check +local salt = '96836db9-1e28-4789-b5a6-fb7bb67e1259' +local appKey = '1858465a8708c121' +local appPasswd = 'fG0sitfk16nJOlIlycnLPYZn1optxUxL' + +local curtime +local word + +local function caculate_input() + local input + local len = #word + if len > 20 then + input = word:sub(1, 10) .. len .. word:sub(-10) + else + input = word + end + return input +end + +local function caculate_sign() + -- sign=sha256(应用ID+input+salt+curtime+应用密钥); + local hash = appKey .. caculate_input() .. salt .. curtime .. appPasswd + + return vim.fn.sha256(hash) +end + +local function test() + local query = { + q = word, + from = 'auto', + to = 'zh-CHS', + -- dicts = 'ec', + signType = 'v3', + appKey = appKey, + salt = salt, + curtime = curtime, + sign = caculate_sign(), + } + return query +end + +-- curl --data {{'{"name":"bob"}'}} --header {{'Content-Type: application/json'}} {{http://example.com/users/1234}} + +local function query_word(q) + local field = ( + [[curl -s --header 'Content-Type: application/x-www-form-urlencoded' https://openapi.youdao.com/api]]) + for k, v in pairs(q) do + field = field .. ([[ -d '%s=%s']]):format(k, v) + end + -- vim.pretty_print(field) + local output = vim.fn.system(field) + local tb = vim.fn.json_decode(output) + -- print(type(output)) + -- vim.pretty_print(tb.basic) +end + +M.test = function(query) + curtime = tostring(os.time()) -- 更新一下time + word = query or 'as' + -- local json = vim.fn.json_encode(test()) + query_word(test()) + -- vim.pretty_print(vim.fn.json_encode(json)) +end + +return M From 5a424c66bb106b2d6cea77ae1793d2ca34a01169 Mon Sep 17 00:00:00 2001 From: JuanZoran <1430359574@qq.com> Date: Sun, 8 Jan 2023 15:07:12 +0800 Subject: [PATCH 07/17] feat: add format utility function and improve loader method --- go/go.mod | 3 + go/query_online.go | 50 +++++++ lua/.luarc.json | 3 +- lua/Trans/component/init.lua | 8 + lua/Trans/component/offline/Title.lua | 2 +- lua/Trans/conf/default.lua | 38 +++-- lua/Trans/conf/init.lua | 1 - lua/Trans/conf/loader.lua | 76 +++++----- lua/Trans/conf/window.lua | 2 +- lua/Trans/database/init.lua | 2 +- lua/Trans/init.lua | 8 +- lua/Trans/util/debug.lua | 2 +- lua/Trans/util/format.lua | 196 ++++++++++++++---------- lua/Trans/util/test/a.lua | 1 - lua/Trans/util/test/format.lua | 205 ++++++++++++++++++++++++++ lua/Trans/util/test/is_Chinese.lua | 15 ++ lua/Trans/util/test/test.lua | 13 ++ 17 files changed, 486 insertions(+), 139 deletions(-) create mode 100644 go/go.mod create mode 100644 go/query_online.go create mode 100644 lua/Trans/component/init.lua delete mode 100644 lua/Trans/conf/init.lua delete mode 120000 lua/Trans/util/test/a.lua create mode 100644 lua/Trans/util/test/format.lua create mode 100644 lua/Trans/util/test/is_Chinese.lua create mode 100644 lua/Trans/util/test/test.lua diff --git a/go/go.mod b/go/go.mod new file mode 100644 index 0000000..606edce --- /dev/null +++ b/go/go.mod @@ -0,0 +1,3 @@ +module query_online + +go 1.19 diff --git a/go/query_online.go b/go/query_online.go new file mode 100644 index 0000000..fc5345e --- /dev/null +++ b/go/query_online.go @@ -0,0 +1,50 @@ +package query_youcao + +import ( + "net/url" + "time" +) + +const ( + youdao = "https://openapi.youdao.com/api" + appKey = "1858465a8708c121" + appPasswd = "fG0sitfk16nJOlIlycnLPYZn1optxUxL" +) + +type data struct { + q string + from string + to string + // appKey string + salt string + sign string + signType string + curtime string +} + + +func input(word string) string { + var input string + len := len(word) + if len > 20 { + input = word[:10] + string(rune(len)) + word[len-10:] + } else { + input = word + } + return input +} + +func salt(_ string) string { + // TODO : hash salt + var salt string + + return salt +} + +func to_value(d data) url.Values { + // return value +} + +func Query(word string) { + +} diff --git a/lua/.luarc.json b/lua/.luarc.json index 43e8c9f..97534e4 100644 --- a/lua/.luarc.json +++ b/lua/.luarc.json @@ -1,6 +1,7 @@ { "$schema": "https://raw.githubusercontent.com/sumneko/vscode-lua/master/setting/schema.json", "Lua.diagnostics.disable": [ - "unused-local" + "empty-block", + "trailing-space" ] } \ No newline at end of file diff --git a/lua/Trans/component/init.lua b/lua/Trans/component/init.lua new file mode 100644 index 0000000..10247c9 --- /dev/null +++ b/lua/Trans/component/init.lua @@ -0,0 +1,8 @@ +local M = {} +local order = require('Trans.conf.loader').loaded_conf.order + +M._ = function (query_) + +end + +return M diff --git a/lua/Trans/component/offline/Title.lua b/lua/Trans/component/offline/Title.lua index 71d3068..19861b0 100644 --- a/lua/Trans/component/offline/Title.lua +++ b/lua/Trans/component/offline/Title.lua @@ -1,6 +1,6 @@ local M = {} -local display = require("Tran.conf").ui.display +local display = require("Trans.conf.loader").loaded.conf.ui.display -- Example: -- local content = { -- width = 1, diff --git a/lua/Trans/conf/default.lua b/lua/Trans/conf/default.lua index 80d8694..c182892 100644 --- a/lua/Trans/conf/default.lua +++ b/lua/Trans/conf/default.lua @@ -7,14 +7,6 @@ M.conf = { cursor = 'cursor', select = 'cursor' }, - order = { - 'Title', - 'Tag', - 'Pos', - 'Exchange', - 'Translation', - 'Definition', - }, window = { cursor = { border = 'rounded', @@ -34,8 +26,21 @@ M.conf = { limit = nil, }, }, + order = { + offline = { + 'Title', + 'Tag', + 'Pos', + 'Exchange', + 'Translation', + 'Definition', + }, + -- online = { + -- -- TODO + -- }, + }, ui = { - highligh = { + highlight = { TransWord = { fg = '#7ee787', bold = true, @@ -79,16 +84,19 @@ M.conf = { base = { db_path = '$HOME/.vim/dict/ultimate.db', auto_close = true, - lazy_load = false, debug = { enable = true, type_check = true, unknown_conf = true, }, + engine = { + -- TODO + } }, - map = { - -- TODO - }, + -- map = { + -- -- TODO + -- }, + -- TODO add online translate engine -- online_search = { -- enable = false, @@ -100,8 +108,8 @@ M.conf = { -- INFO :加载的规则 [LuaRule] M.replace_rules = { - 'order', - 'Trans.+', + 'order.*', + 'ui.highlight.*', } return M diff --git a/lua/Trans/conf/init.lua b/lua/Trans/conf/init.lua deleted file mode 100644 index 01baf8e..0000000 --- a/lua/Trans/conf/init.lua +++ /dev/null @@ -1 +0,0 @@ -return require("Trans.conf.loader").get_conf() diff --git a/lua/Trans/conf/loader.lua b/lua/Trans/conf/loader.lua index 7ccad44..67a5e08 100644 --- a/lua/Trans/conf/loader.lua +++ b/lua/Trans/conf/loader.lua @@ -1,52 +1,56 @@ ----@diagnostic disable: unused-local, unused-function +-- -@diagnostic disable: unused-local, unused-function, lowercase-global local M = {} local replace_rules = require("Trans.conf.default").replace_rules -local conf = require("Trans.conf.default").conf -local user_conf = require("Trans").conf -local type_check = require("Trans.util.debug").type_check -local is_loaded = false -local function need_extend(name) - type_check { - name = { name, 'string' } - } - for _, rule in ipairs(replace_rules) do - if name:match(rule) then - return false - end +local star_format = [[ +local def, usr = default_conf.%s, user_conf.%s +if def and usr then + for k, v in pairs(usr) do + def[k] = v + usr[k] = nil end - return true end +]] --- 加载用户自定义的配置 ----@param t1 table ----@param t2 table -local function extend(t1, t2) - type_check { - t1 = { t1, 'table' }, - t2 = { t2, 'table' }, - } - for k, v in pairs(t2) do - if type(v) == 'table' and need_extend(k) then - extend(t1[k], v) - else - t1[k] = v +local plain_format = [[ +default_conf.%s = user_conf.%s or default_conf.%s +]] + +local function pre_process() + if replace_rules then + for _, v in ipairs(replace_rules) do + local start = v:find('.*', 1, true) + local operation + if start then + -- 替换表内所有键 + v = v:sub(1, start - 1) + -- print('v is :', v) + operation = string.format(star_format, v, v) + else + operation = plain_format:format(v, v, v) + end + -- print(operation) + pcall(loadstring(operation)) end end end -M.get_conf = function() - if not is_loaded then - M.load_conf() + + +M.load_conf = function(conf) + if #M.loaded_conf == 0 then + user_conf = conf or {} + default_conf = require("Trans.conf.default").conf + pre_process() + M.loaded_conf = vim.tbl_deep_extend('force', default_conf, user_conf) + user_conf = nil + default_conf = nil + else + vim.notify('Configuration has been loaded...') end - return conf end -M.load_conf = function() - -- loaded_conf = default_conf:extend(user_conf) - extend(conf, user_conf) - is_loaded = true -end +M.loaded_conf = {} return M diff --git a/lua/Trans/conf/window.lua b/lua/Trans/conf/window.lua index 04c6b49..1bad06c 100644 --- a/lua/Trans/conf/window.lua +++ b/lua/Trans/conf/window.lua @@ -1,5 +1,5 @@ local M = {} -local conf = require("Trans.conf").style.window +local conf = require("Trans.conf.loader").loaded_conf.style.window local type_check = require("Trans.util.debug").type_check -- FIXME diff --git a/lua/Trans/database/init.lua b/lua/Trans/database/init.lua index aeab460..02b1405 100644 --- a/lua/Trans/database/init.lua +++ b/lua/Trans/database/init.lua @@ -18,7 +18,7 @@ local query_field = { } -- INFO : init database -local path = require("Trans.conf").base.db_path +local path = require("Trans.conf.loader").loaded.conf.base.db_path local dict = db:open(path) -- INFO :Auto Close diff --git a/lua/Trans/init.lua b/lua/Trans/init.lua index e076815..5b4853a 100644 --- a/lua/Trans/init.lua +++ b/lua/Trans/init.lua @@ -2,12 +2,6 @@ local M = {} M.conf = {} -function M.setup(conf) - M.conf = conf or {} - if conf.base and not conf.base.lazy_load then - require("Trans.conf.loader").load_conf() - end - -- require("Trans.setup") -end +M.setup = require('Trans.conf.loader').load_conf return M diff --git a/lua/Trans/util/debug.lua b/lua/Trans/util/debug.lua index 874954b..58cb855 100644 --- a/lua/Trans/util/debug.lua +++ b/lua/Trans/util/debug.lua @@ -1,7 +1,7 @@ local M = {} -- INFO : get loaded debug conf -local base = require("Trans").conf.base +local base = require("Trans.conf.loader").loaded_conf.base local debug = require("Trans.conf.default").conf.base.debug if base and base.debug then debug = vim.tbl_extend('force', debug, base) diff --git a/lua/Trans/util/format.lua b/lua/Trans/util/format.lua index 7d9bf80..a143705 100644 --- a/lua/Trans/util/format.lua +++ b/lua/Trans/util/format.lua @@ -2,52 +2,138 @@ local M = {} local type_check = require("Trans.util.debug").type_check +-- NOTE :中文字符及占两个字节宽,但是在lua里是3个字节长度 +-- 为了解决中文字符在lua的长度和neovim显示不一致的问题 +function string:width() + local wid = 0 + local bytes = { self:byte(1, #self) } + local index = 1 + while true do + local char = bytes[index] + if char > 0 and char <= 127 then -- 英文[1] + wid = wid + 1 + index = index + 1 + elseif char >= 224 and char <= 239 then -- 中文[3] + index = index + 3 -- 原本的宽度 + wid = wid + 2 + -- elseif char >= 194 and char <= 223 then -- TODO :2 + -- width = width + 2 + -- index = index + 2 + -- elseif char >=240 and char <= 247 then -- TODO :4 + -- width = width + 4 + -- index = index + 4 + else + error('unknown char len:' .. tostring(char)) + end + + if index > #bytes then + return wid + end + end +end + -- 各种风格的基础宽度 local style_width = { float = require("Trans.conf.window").float.width, -- NOTE : need window parsed conf cursor = require("Trans.conf.window").cursor.width, } -local m_width = nil -- 需要被格式化窗口的高度 -local m_fields = nil -- 待格式化的字段 -local m_indent = nil -- 每行的行首缩进 -local m_length = nil -- 所有字段加起来的长度(不包括缩进和间隔) +local s_to_b = true -- 从小到大排列 -local function get_rows() - -- TODO - return rows -end +local m_win_width -- 需要被格式化窗口的高度 +local m_fields -- 待格式化的字段 +local m_indent -- 每行的行首缩进 +local m_length -- 所有字段加起来的长度(不包括缩进和间隔) +local m_item_width -- 每个字段的宽度 +local m_interval -- 每个字段的间隔 -local function do_indent(lines) - for i, v in ipairs(lines) do - lines[i] = (' '):rep(m_indent) .. v +local function caculate_format() + local width = m_win_width - m_item_width[1] + local cols = 0 + for i = 2, #m_fields do + width = width - m_item_width[i] - m_interval + if width < 0 then + cols = i - 1 + break + else + cols = i + end end + + return math.ceil(#m_fields / cols), cols end local function format_to_line() - local space = math.floor((m_width - m_length) / #m_fields) + local line = m_fields[1] + local space = math.floor((m_win_width - m_length) / #m_fields) + for i = 2, #m_fields do + line = line .. (' '):rep(space) .. m_fields[i] + end return line end -local function format_to_multilines() - -- TODO - type_check { - interval = { interval, 'number' }, - rows = { rows, 'number' }, - } +local function sort_tables() + table.sort(m_item_width, function(a, b) + return a > b + end) + + table.sort(m_fields, function(a, b) + return a:width() > b:width() -- 需要按照width排序 + end) end -local function get_formatted_lines() +local function format_to_multilines() + local lines = {} + sort_tables() + + --- NOTE : 计算应该格式化成多少行和列 + local rows, cols = caculate_format() + local rest = #m_fields % cols + if rest == 0 then + rest = cols + end + + local s_width = m_item_width[1] -- 列中最宽的字符串宽度 + -- NOTE : 第一列不需要加空格 + for i = 1, rows do + local idx = s_to_b and rows - i + 1 or i + local space = (' '):rep(s_width - m_item_width[i]) + lines[idx] = m_fields[i] .. space -- NOTE 由大到小 + end + + local index = rows + 1 -- 最宽字符的下标 + local interval = (' '):rep(m_interval) -- 每个字符串间的间隙 + + for j = 2, cols do -- 以列为单位遍历 + s_width = m_item_width[index] + local stop = (j > rest and rows - 1 or rows) + for i = 1, stop do + local idx = s_to_b and stop - i + 1 or i -- 当前操作的行数 + local item = index + i - 1 -- 当前操作的字段数 + local space = (' '):rep(s_width - m_item_width[item]) -- 对齐空格 + + lines[idx] = lines[idx] .. interval .. m_fields[item] .. space -- NOTE 从大到小 + end + index = index + stop -- 更新最宽字符的下标 + end + + return lines -- TODO : evaluate the width +end + +local function formatted_lines() local lines = {} -- NOTE : 判断能否格式化成一行 - if m_length + (#m_fields * m_indent) > m_width then + if m_length + (#m_fields * m_indent) > m_win_width then lines = format_to_multilines() else lines[1] = format_to_line() end - if m_indent then - do_indent(lines) + -- NOTE :进行缩进 + if m_indent and m_indent > 0 then + for i, v in ipairs(lines) do + lines[i] = (' '):rep(m_indent) .. v + end end return lines end @@ -58,9 +144,6 @@ end ---@param indent number 缩进的长度 ---@return string[] lines 便于vim.api.nvim_buf_set_lines M.to_lines = function(style, fields, indent) - if not fields then - return {} - end type_check { style = { style, { 'string' } }, fields = { fields, { 'table' } }, @@ -68,57 +151,22 @@ M.to_lines = function(style, fields, indent) } local length = 0 - for _, v in ipairs(fields) do - length = length + #v + local width = 0 + local item_size = {} + for i, v in ipairs(fields) do + width = v:width() + items_size[i] = width + length = length + width end - m_width = style_width[style] - indent - m_indent = indent - m_fields = fields - m_length = length - return get_formatted_lines() + m_indent = indent or 0 + m_win_width = style_width[style] - m_indent + m_fields = fields + m_length = length + m_item_width = item_size + m_interval = m_win_width > 50 and 6 or 4 + + return formatted_lines() end --- local function get_lines(win_width, components) --- local lines = {} --- local interval = win_width > 40 and 6 or 4 --- local row = 1 --- local width = win_width - #components[1] --- for i in 2, #components do --- width = width - #components[i] - interval --- if width < 0 then --- width = win_width - #components[i] --- row = row + 1 --- end --- end --- if row == 1 then --- local format = '%s' .. ((' '):rep(interval) .. '%s') --- lines[1] = string.format(format, unpack(components)) --- else --- table.sort(components, function (a, b) --- return #a > #b --- end) --- -- FIXME --- local res, rem = #components / (row + 1), #components % (row + 1) --- row = math.ceil(res) --- local rol = row - rem - 1 --- end --- --- return lines --- end --- --- M.format = function(style, components, indent) --- local lines = {} --- if #components > 1 then --- indent = indent or 0 --- type_check { --- style = { style, 'string' }, --- components = { components, 'table' }, ---@string[] --- -- max_items = { max_items, { 'nil', 'number' } }, ---@string[] --- } --- local win_width = (style == 'float' and float_win_width or cursor_win_width) - indent --- local res = get_lines(win_width, components) --- end --- return lines --- end return M diff --git a/lua/Trans/util/test/a.lua b/lua/Trans/util/test/a.lua deleted file mode 120000 index 9b39cbe..0000000 --- a/lua/Trans/util/test/a.lua +++ /dev/null @@ -1 +0,0 @@ -query_youdao.lua \ No newline at end of file diff --git a/lua/Trans/util/test/format.lua b/lua/Trans/util/test/format.lua new file mode 100644 index 0000000..fe66581 --- /dev/null +++ b/lua/Trans/util/test/format.lua @@ -0,0 +1,205 @@ +local M = {} +-- local type_check = require("Trans.util.debug").type_check + + +-- NOTE :中文字符及占两个字节宽,但是在lua里是3个字节长度 +-- 为了解决中文字符在lua的长度和neovim显示不一致的问题 +function string:width() + local width = 0 + local bytes = { self:byte(1, #self) } + local index = 1 + while true do + local char = bytes[index] + if char > 0 and char <= 127 then -- 英文[1] + width = width + 1 + index = index + 1 + elseif char >= 224 and char <= 239 then -- 中文[3] + index = index + 3 -- 原本的宽度 + width = width + 2 + -- elseif char >= 194 and char <= 223 then -- TODO :2 + -- width = width + 2 + -- index = index + 2 + -- elseif char >=240 and char <= 247 then -- TODO :4 + -- width = width + 4 + -- index = index + 4 + else + error('unknown char len:' .. tostring(char)) + end + if index > #bytes then + return width + end + end +end + +-- 各种风格的基础宽度 +local style_width = { + -- float = require("Trans.conf.window").float.width, -- NOTE : need window parsed conf + cursor = 60, +} +local s_to_b = true -- 从小到大排列 + +local m_fields -- 待格式化的字段 +local m_indent -- 每行的行首缩进 +local m_length -- 所有字段加起来的长度(不包括缩进和间隔) +local m_interval -- 每个字段的间隔 +local m_win_width -- 需要被格式化窗口的高度 +local m_item_width -- 每个字段的宽度 + +local function caculate_format() + local width = m_win_width - m_item_width[1] + local cols = 0 + for i = 2, #m_fields do + width = width - m_item_width[i] - m_interval + if width < 0 then + cols = i - 1 + break + else + cols = i + end + end + + return math.ceil(#m_fields / cols), cols +end + +local function format_to_line() + local line = m_fields[1] + local space = math.floor((m_win_width - m_length) / #m_fields) + for i = 2, #m_fields do + line = line .. (' '):rep(space) .. m_fields[i] + end + return line +end + + +local function sort_tables() + table.sort(m_item_width, function (a, b) + return a > b + end) + + table.sort(m_fields, function (a, b) + return a:width() > b:width() + end) +end + + +local function format_to_multilines() + local lines = {} + sort_tables() + + --- NOTE : 计算应该格式化成多少行和列 + local rows, cols = caculate_format() + local rest = #m_fields % cols + if rest == 0 then + rest = cols + end + + local s_width = m_item_width[1] -- 列中最宽的字符串宽度 + -- NOTE : 第一列不需要加空格 + for i = 1, rows do + local idx = s_to_b and rows - i + 1 or i + local space = (' '):rep(s_width - m_item_width[i]) + lines[idx] = m_fields[i] .. space -- NOTE 由大到小 + end + + local index = rows + 1 -- 最宽字符的下标 + local interval = (' '):rep(m_interval) -- 每个字符串间的间隙 + + for j = 2, cols do -- 以列为单位遍历 + s_width = m_item_width[index] + local stop = (j > rest and rows - 1 or rows) + for i = 1, stop do + local idx = s_to_b and stop - i + 1 or i -- 当前操作的行数 + local item = index + i - 1 -- 当前操作的字段数 + local space = (' '):rep(s_width - m_item_width[item]) -- 对齐空格 + + lines[idx] = lines[idx] .. interval .. m_fields[item] .. space -- NOTE 从大到小 + end + index = index + stop -- 更新最宽字符的下标 + end + + return lines +end + + +local function get_formatted_lines() + local lines = {} + -- NOTE : 判断能否格式化成一行 + local line_size = m_length + (#m_fields * m_interval) + if line_size > m_win_width then + lines = format_to_multilines() + else + lines[1] = format_to_line() + end + + -- NOTE :进行缩进 + if m_indent > 0 then + for i, v in ipairs(lines) do + lines[i] = (' '):rep(m_indent) .. v + end + end + return lines +end + +---将组件格式化成相应的vim支持的lines格式 +---@param style string 窗口的风格 +---@param fields string[] 需要格式化的字段 +---@param indent? number 缩进的长度 +---@return string[] lines 便于vim.api.nvim_buf_set_lines +M.to_lines = function(style, fields, indent) + + local length = 0 + local width = 0 + local item_size = {} + for i, v in ipairs(fields) do + width = v:width() + item_size[i] = width + length = length + width + end + + m_indent = indent or 0 + m_win_width = style_width[style] - m_indent + m_fields = fields + m_length = length + m_item_width = item_size + m_interval = m_win_width > 50 and 6 or 4 + + return get_formatted_lines() +end + +local test = { + 'ajlkasj', + 'jklasjldajjnn测试', + 'ljlklkjjlIi戳', + '测试将安得拉蓝色', + '戳将安塞', + 'isjlkajsldj', +} + +local lines = M.to_lines('cursor', test) + +-- print('===========================================') +-- for _, v in ipairs(test) do +-- print(v .. ' width:', v:width()) +-- end +-- print('===========================================') +-- print('===========================================') +-- print('===========================================') + +-- print('type is :' .. type(lines) .. ' size is :' .. #lines[1]) + +for _, v in ipairs(lines) do + print(v) +end + +-- lines = M.to_lines('cursor', { +-- 'ajlkasj', +-- 'jklasjldajjnn测试', +-- '测试将安得拉蓝色', +-- 'cool this', +-- }, 4) + +-- for _, v in ipairs(lines) do +-- print(v) +-- end +return M + diff --git a/lua/Trans/util/test/is_Chinese.lua b/lua/Trans/util/test/is_Chinese.lua new file mode 100644 index 0000000..cf15825 --- /dev/null +++ b/lua/Trans/util/test/is_Chinese.lua @@ -0,0 +1,15 @@ +local M = {} +-- local type_check = require("Trans.util.debug").type_check + + +---@param str string +local function is_Chinese(str) + for i = 1, #str do + if not str:byte(i) >= [[\u4e00]] then + return false + end + end + return true +end + +return M diff --git a/lua/Trans/util/test/test.lua b/lua/Trans/util/test/test.lua new file mode 100644 index 0000000..5c5d03f --- /dev/null +++ b/lua/Trans/util/test/test.lua @@ -0,0 +1,13 @@ +local M = {} + +local a = { + b = 'test', +} + +local c = a +c.b = 'notest' + + + +print(a.b) +return M From eaf8a3acceba17576a4d8b5b7ff7fa67340238d5 Mon Sep 17 00:00:00 2001 From: JuanZoran <1430359574@qq.com> Date: Mon, 9 Jan 2023 01:59:04 +0800 Subject: [PATCH 08/17] feat: debug format function and add content function support --- lua/Trans/component/content.lua | 96 ++++++++++++++++++++++ lua/Trans/component/highlight.lua | 11 +++ lua/Trans/component/offline/Title.lua | 87 +++++++++++++++----- lua/Trans/component/window.lua | 12 +++ lua/Trans/conf/window.lua | 2 +- lua/Trans/database/init.lua | 2 +- lua/Trans/database/online.lua | 0 lua/Trans/test.lua | 33 ++++++++ lua/Trans/util/base64.lua | 39 +++++++++ lua/Trans/util/format.lua | 111 +++++++++++++------------- lua/Trans/util/test/format.lua | 57 +++++-------- lua/Trans/util/test/test.lua | 17 ++-- 12 files changed, 341 insertions(+), 126 deletions(-) create mode 100644 lua/Trans/component/content.lua create mode 100644 lua/Trans/component/highlight.lua create mode 100644 lua/Trans/component/window.lua create mode 100644 lua/Trans/database/online.lua create mode 100644 lua/Trans/test.lua create mode 100644 lua/Trans/util/base64.lua diff --git a/lua/Trans/component/content.lua b/lua/Trans/component/content.lua new file mode 100644 index 0000000..e86572f --- /dev/null +++ b/lua/Trans/component/content.lua @@ -0,0 +1,96 @@ +local M = {} +local type_check = require("Trans.util.debug").type_check +M.__index = M +M.lines = {} +M.highlight = {} +M.size = 0 + + +function M:new() + local content = {} + setmetatable(content, self) + return content +end + +--- NOTE :highlight 格式说明: +--- 1. 字符串 + + +function M:insert_items_to_line(items, opts) + type_check { + items = { items, 'table' }, + opts = { opts, 'table', true }, + } + self.size = self.size + 1 -- line数加一 + + local line = { + space = (' '):rep(opts.interval), + indent = opts.indent, + highlight = opts.highlight, + } + local highlight = {} + + + for i, item in ipairs(items) do + if type(item) == 'string' then + item = { item } + end + line[i] = item[1] + if item[2] then + highlight[i] = item[2] + end + end + + self.highlight[self.size] = highlight + self.lines[self.size] = line +end + +---遍历lines和高亮的迭代器 +---Usage: +--- local buffer_id +--- local lines, highlights = M:lines() +--- vim.api.nvim_buf_set_lines(buffer_id, 0, -1, false,lines) +--- for i, hl in ipairs(highlights) do +--- vim.api.nvim_buf_add_highlight(buffer_id, 0, hl.name, i, hl._start, hl._end) +--- end +---@return table line +---@return table highlight +function M:lines() + -- NOTE 返回格式化的行,如果需要高亮,则第二个参数返回高亮 + local lines = {} + local highlights = {} + for index = 1, #self.lines do + local line = '' + local highlight = {} + local l = self.lines[index] + local hl = self.highlight[index] + if l.indent then + line = (' '):rep(l.indent) + end + if l.highlight then + line = line .. table.concat(l, l.space) + highlight[1] = { name = l.highlight, _start = 1, _end = -1 } + else + line = line .. l[1] + + if hl[1] then + -- WARN :可能需要设置成字符串宽度!!! + table.insert(highlight, { name = hl[1], _start = #line - #l[1], _end = #line }) + end + + for i = 2, #l do + line = line .. l.space .. l[i] + if hl[i] then + table.insert(highlight, { name = hl[i], _start = #line - #l[i], _end = #line }) + end + end + end + + -- return line, highlights + lines[index] = line + highlights[index] = highlight + end + return lines, highlights +end + +return M diff --git a/lua/Trans/component/highlight.lua b/lua/Trans/component/highlight.lua new file mode 100644 index 0000000..6732551 --- /dev/null +++ b/lua/Trans/component/highlight.lua @@ -0,0 +1,11 @@ +local M = {} +local type_check = require("Trans.util.debug").type_check +M.__index = M + +function M:new() + +end + + +return M + diff --git a/lua/Trans/component/offline/Title.lua b/lua/Trans/component/offline/Title.lua index 19861b0..4816e0e 100644 --- a/lua/Trans/component/offline/Title.lua +++ b/lua/Trans/component/offline/Title.lua @@ -1,29 +1,78 @@ local M = {} local display = require("Trans.conf.loader").loaded.conf.ui.display --- Example: --- local content = { --- width = 1, --- height = 1; --- lines = { --- Highlight = { --- 'first line', --- 'second line', --- } --- }, ---@table +local icon = require("Trans.conf.loader").loaded.conf.ui.icon + +local m_field = {} +-- { +-- collins = 3, +-- definition = "n. an expression of greeting", +-- exchange = "s:hellos", +-- oxford = 1, +-- phonetic = "hə'ləʊ", +-- pos = "u:97/n:3", +-- tag = "zk gk", +-- translation = "n. 表示问候, 惊奇或唤起注意时的用语\nint. 喂;哈罗\nn. (Hello)人名;(法)埃洛", +-- word = "hello" -- } --- local function format() --- --- end +local content = { + lines = { + need_format = { + {}, -- line + {}, -- line + {}, -- line + {}, -- line + } + }, + highlight = { + [2] = { -- 第几行第几个组件的高亮 + [1] = 'highlightname', + }, + } +} -M.to_content = function (field) - -- TODO - local line = '' - local format = '%s %s %s %s' - local content = { - height = 1, +local function get_items() + local items = { + m_field.word, + } + if display.phonetic then + table.insert(items, '[' .. m_field.phonetic .. ']') + end + + if display.collins_star then + table.insert(items, icon.star:rep(m_field.collins)) + end + + if display.oxford then + local item + if m_field.oxford and m_field.oxford == 1 then + item = icon.isOxford + else + item = icon.notOxford + end + table.insert(items, item) + end + + return items +end + +M.content = function(field) + -- TODO + m_field = field or {} + local content = {} + + + content.lines = { + need_format = { + get_items() + }, + highlight = { + [1] = { -- 第一行 + 'Trans', + } + } } return content end diff --git a/lua/Trans/component/window.lua b/lua/Trans/component/window.lua new file mode 100644 index 0000000..bb5448f --- /dev/null +++ b/lua/Trans/component/window.lua @@ -0,0 +1,12 @@ +local M = {} +local type_check = require("Trans.util.debug").type_check + + +-- vim.pretty_print(vim.lsp.util._make_floating_popup_size) + +local v = [=[ + local test = {{ + }} +]=] +print(v) +return M diff --git a/lua/Trans/conf/window.lua b/lua/Trans/conf/window.lua index 1bad06c..c81af89 100644 --- a/lua/Trans/conf/window.lua +++ b/lua/Trans/conf/window.lua @@ -54,7 +54,7 @@ local get_cursor_opts = function(cursor_conf) return opts end -M.get_float_opts = get_float_opts(conf.float) +M.float_opts = get_float_opts(conf.float) M.cursor_opts = get_cursor_opts(conf.cursor) diff --git a/lua/Trans/database/init.lua b/lua/Trans/database/init.lua index 02b1405..82c2a39 100644 --- a/lua/Trans/database/init.lua +++ b/lua/Trans/database/init.lua @@ -18,7 +18,7 @@ local query_field = { } -- INFO : init database -local path = require("Trans.conf.loader").loaded.conf.base.db_path +local path = require("Trans.conf.loader").loaded_conf.base.db_path local dict = db:open(path) -- INFO :Auto Close diff --git a/lua/Trans/database/online.lua b/lua/Trans/database/online.lua new file mode 100644 index 0000000..e69de29 diff --git a/lua/Trans/test.lua b/lua/Trans/test.lua new file mode 100644 index 0000000..6430e03 --- /dev/null +++ b/lua/Trans/test.lua @@ -0,0 +1,33 @@ +local M = {} + +M.test = { + 'test1', + 'test1', + 'test1', + 'test1', +} + + +function M.tmp (start, stop) + if start > stop then + return + end + + local value = M.test[start] + start = start + 1 + return function () + + return start + end +end +-- function M:tmp(index) +-- end + +for v in M.tmp, 1, #M.test do + print(v) +end + +-- for i,n in square,3,0 +-- do +-- print(i,n) +-- end diff --git a/lua/Trans/util/base64.lua b/lua/Trans/util/base64.lua new file mode 100644 index 0000000..417f8e9 --- /dev/null +++ b/lua/Trans/util/base64.lua @@ -0,0 +1,39 @@ +local ffi = require('ffi') +local base64 = {} + +local b64 = ffi.new('unsigned const char[65]', + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/") + +function base64.encode(str) + local band, bor, lsh, rsh = bit.band, bit.bor, bit.lshift, bit.rshift + local len = #str + local enc_len = 4 * math.ceil(len / 3) -- (len + 2) // 3 * 4 after Lua 5.3 + + local src = ffi.new('unsigned const char[?]', len+1, str) + local enc = ffi.new('unsigned char[?]', enc_len+1) + + local i, j = 0, 0 + while i < len-2 do + enc[j] = b64[band(rsh(src[i], 2), 0x3F)] + enc[j+1] = b64[bor(lsh(band(src[i], 0x3), 4), rsh(band(src[i+1], 0xF0), 4))] + enc[j+2] = b64[bor(lsh(band(src[i+1], 0xF), 2), rsh(band(src[i+2], 0xC0), 6))] + enc[j+3] = b64[band(src[i+2], 0x3F)] + i, j = i+3, j+4 + end + + if i < len then + enc[j] = b64[band(rsh(src[i], 2), 0x3F)] + if i == len-1 then + enc[j+1] = b64[lsh(band(src[i], 0x3), 4)] + enc[j+2] = 0x3D + else + enc[j+1] = b64[bor(lsh(band(src[i], 0x3), 4), rsh(band(src[i+1], 0xF0), 4))] + enc[j+2] = b64[lsh(band(src[i+1], 0xF), 2)] + end + enc[j+3] = 0x3D + end + + return ffi.string(enc, enc_len) +end + +return base64 diff --git a/lua/Trans/util/format.lua b/lua/Trans/util/format.lua index a143705..9eb5ca5 100644 --- a/lua/Trans/util/format.lua +++ b/lua/Trans/util/format.lua @@ -5,52 +5,29 @@ local type_check = require("Trans.util.debug").type_check -- NOTE :中文字符及占两个字节宽,但是在lua里是3个字节长度 -- 为了解决中文字符在lua的长度和neovim显示不一致的问题 function string:width() - local wid = 0 - local bytes = { self:byte(1, #self) } - local index = 1 - while true do - local char = bytes[index] - if char > 0 and char <= 127 then -- 英文[1] - wid = wid + 1 - index = index + 1 - elseif char >= 224 and char <= 239 then -- 中文[3] - index = index + 3 -- 原本的宽度 - wid = wid + 2 - -- elseif char >= 194 and char <= 223 then -- TODO :2 - -- width = width + 2 - -- index = index + 2 - -- elseif char >=240 and char <= 247 then -- TODO :4 - -- width = width + 4 - -- index = index + 4 - else - error('unknown char len:' .. tostring(char)) - end - - if index > #bytes then - return wid - end - end + return vim.fn.strdisplaywidth(self) end -- 各种风格的基础宽度 local style_width = { - float = require("Trans.conf.window").float.width, -- NOTE : need window parsed conf - cursor = require("Trans.conf.window").cursor.width, + -- float = require("Trans.conf.window").float.width, -- NOTE : need window parsed conf + -- cursor = require("Trans.conf.window").cursor.width, + cursor = 50 } local s_to_b = true -- 从小到大排列 local m_win_width -- 需要被格式化窗口的高度 local m_fields -- 待格式化的字段 -local m_indent -- 每行的行首缩进 -local m_length -- 所有字段加起来的长度(不包括缩进和间隔) +local m_tot_width -- 所有字段加起来的长度(不包括缩进和间隔) local m_item_width -- 每个字段的宽度 local m_interval -- 每个字段的间隔 +local m_size -- 字段的个数 local function caculate_format() local width = m_win_width - m_item_width[1] local cols = 0 - for i = 2, #m_fields do + for i = 2, m_size do width = width - m_item_width[i] - m_interval if width < 0 then cols = i - 1 @@ -60,14 +37,20 @@ local function caculate_format() end end - return math.ceil(#m_fields / cols), cols + return math.ceil(m_size / cols), cols end local function format_to_line() local line = m_fields[1] - local space = math.floor((m_win_width - m_length) / #m_fields) - for i = 2, #m_fields do - line = line .. (' '):rep(space) .. m_fields[i] + if m_size == 1 then + --- Center Align + local space = math.floor((m_win_width - m_item_width[1]) / 2) + line = (' '):rep(space) .. line + else + local space = math.floor((m_win_width - m_tot_width) / m_size - 1) + for i = 2, m_size do + line = line .. (' '):rep(space) .. m_fields[i] + end end return line end @@ -82,37 +65,39 @@ local function sort_tables() end) end -local function format_to_multilines() +local function format_to_multilines(rows, cols) local lines = {} - sort_tables() - --- NOTE : 计算应该格式化成多少行和列 - local rows, cols = caculate_format() - local rest = #m_fields % cols + local rest = m_size % cols if rest == 0 then rest = cols end local s_width = m_item_width[1] -- 列中最宽的字符串宽度 - -- NOTE : 第一列不需要加空格 for i = 1, rows do local idx = s_to_b and rows - i + 1 or i + lines[idx] = {} + local space = (' '):rep(s_width - m_item_width[i]) - lines[idx] = m_fields[i] .. space -- NOTE 由大到小 + local item = m_fields[i] .. space + + lines[idx][1] = item + lines[idx].interval = m_interval end + local index = rows + 1 -- 最宽字符的下标 - local interval = (' '):rep(m_interval) -- 每个字符串间的间隙 for j = 2, cols do -- 以列为单位遍历 s_width = m_item_width[index] local stop = (j > rest and rows - 1 or rows) for i = 1, stop do local idx = s_to_b and stop - i + 1 or i -- 当前操作的行数 - local item = index + i - 1 -- 当前操作的字段数 - local space = (' '):rep(s_width - m_item_width[item]) -- 对齐空格 + local item_idx = index + i - 1 -- 当前操作的字段数 + local space = (' '):rep(s_width - m_item_width[item_idx]) -- 对齐空格 + local item = m_fields[item_idx] .. space - lines[idx] = lines[idx] .. interval .. m_fields[item] .. space -- NOTE 从大到小 + lines[idx][j] = item -- 插入图标 end index = index + stop -- 更新最宽字符的下标 end @@ -123,18 +108,15 @@ end local function formatted_lines() local lines = {} -- NOTE : 判断能否格式化成一行 - if m_length + (#m_fields * m_indent) > m_win_width then - lines = format_to_multilines() + if m_tot_width + (m_size * m_indent) > m_win_width then + sort_tables() + --- NOTE : 计算应该格式化成多少行和列 + local rows, cols = caculate_format() + lines = format_to_multilines(rows, cols) else lines[1] = format_to_line() end - -- NOTE :进行缩进 - if m_indent and m_indent > 0 then - for i, v in ipairs(lines) do - lines[i] = (' '):rep(m_indent) .. v - end - end return lines end @@ -155,18 +137,35 @@ M.to_lines = function(style, fields, indent) local item_size = {} for i, v in ipairs(fields) do width = v:width() - items_size[i] = width + item_size[i] = width length = length + width end - m_indent = indent or 0 m_win_width = style_width[style] - m_indent m_fields = fields - m_length = length + m_size = #m_fields + m_tot_width = length m_item_width = item_size m_interval = m_win_width > 50 and 6 or 4 return formatted_lines() end +---合并多个数组, 第一个数组将会被使用 +---@param ... string[] 需要被合并的数组 +---@return table res 合并后的数组 +M.extend_array = function(...) + local arrays = { ... } + local res = arrays[1] + local index = #res + for i = 2, #arrays do + for _, value in ipairs(arrays[i]) do + res[index] = value + index = index + 1 + end + end + return res +end + + return M diff --git a/lua/Trans/util/test/format.lua b/lua/Trans/util/test/format.lua index fe66581..62df1fe 100644 --- a/lua/Trans/util/test/format.lua +++ b/lua/Trans/util/test/format.lua @@ -5,30 +5,7 @@ local M = {} -- NOTE :中文字符及占两个字节宽,但是在lua里是3个字节长度 -- 为了解决中文字符在lua的长度和neovim显示不一致的问题 function string:width() - local width = 0 - local bytes = { self:byte(1, #self) } - local index = 1 - while true do - local char = bytes[index] - if char > 0 and char <= 127 then -- 英文[1] - width = width + 1 - index = index + 1 - elseif char >= 224 and char <= 239 then -- 中文[3] - index = index + 3 -- 原本的宽度 - width = width + 2 - -- elseif char >= 194 and char <= 223 then -- TODO :2 - -- width = width + 2 - -- index = index + 2 - -- elseif char >=240 and char <= 247 then -- TODO :4 - -- width = width + 4 - -- index = index + 4 - else - error('unknown char len:' .. tostring(char)) - end - if index > #bytes then - return width - end - end + return vim.fn.strdisplaywidth(self) end -- 各种风格的基础宽度 @@ -40,10 +17,11 @@ local s_to_b = true -- 从小到大排列 local m_fields -- 待格式化的字段 local m_indent -- 每行的行首缩进 -local m_length -- 所有字段加起来的长度(不包括缩进和间隔) +local m_tot_width -- 所有字段加起来的长度(不包括缩进和间隔) local m_interval -- 每个字段的间隔 local m_win_width -- 需要被格式化窗口的高度 local m_item_width -- 每个字段的宽度 +local m_size local function caculate_format() local width = m_win_width - m_item_width[1] @@ -63,9 +41,15 @@ end local function format_to_line() local line = m_fields[1] - local space = math.floor((m_win_width - m_length) / #m_fields) - for i = 2, #m_fields do - line = line .. (' '):rep(space) .. m_fields[i] + if m_size == 1 then + --- Center Align + local space = math.floor((m_win_width - m_item_width[1]) / 2) + line = (' '):rep(space) .. line + else + local space = math.floor((m_win_width - m_tot_width) / m_size - 1) + for i = 2, m_size do + line = line .. (' '):rep(space) .. m_fields[i] + end end return line end @@ -124,7 +108,7 @@ end local function get_formatted_lines() local lines = {} -- NOTE : 判断能否格式化成一行 - local line_size = m_length + (#m_fields * m_interval) + local line_size = m_tot_width + (#m_fields * m_interval) if line_size > m_win_width then lines = format_to_multilines() else @@ -159,20 +143,17 @@ M.to_lines = function(style, fields, indent) m_indent = indent or 0 m_win_width = style_width[style] - m_indent m_fields = fields - m_length = length + m_tot_width = length m_item_width = item_size m_interval = m_win_width > 50 and 6 or 4 + m_size = #fields return get_formatted_lines() end local test = { - 'ajlkasj', - 'jklasjldajjnn测试', - 'ljlklkjjlIi戳', - '测试将安得拉蓝色', - '戳将安塞', - 'isjlkajsldj', + 'isjlk测试dj', + '测试一下..', } local lines = M.to_lines('cursor', test) @@ -187,8 +168,8 @@ local lines = M.to_lines('cursor', test) -- print('type is :' .. type(lines) .. ' size is :' .. #lines[1]) -for _, v in ipairs(lines) do - print(v) +for _, v in ipairs(test) do + print(v:width()) end -- lines = M.to_lines('cursor', { diff --git a/lua/Trans/util/test/test.lua b/lua/Trans/util/test/test.lua index 5c5d03f..0b99fff 100644 --- a/lua/Trans/util/test/test.lua +++ b/lua/Trans/util/test/test.lua @@ -1,13 +1,8 @@ -local M = {} - -local a = { - b = 'test', +local tmp = { + '1111', + '2222', + '3333', + interval = 4, } -local c = a -c.b = 'notest' - - - -print(a.b) -return M +print(table.concat(tmp, (' '):rep(tmp.interval))) From 32cba43aa2810120cc002456e81ae54714877b48 Mon Sep 17 00:00:00 2001 From: JuanZoran <1430359574@qq.com> Date: Mon, 9 Jan 2023 15:37:58 +0800 Subject: [PATCH 09/17] feat: format code and add cmd doc --- lua/Trans/component/content.lua | 28 +++++-- lua/Trans/component/offline/Title.lua | 90 +++++++++----------- lua/Trans/conf/default.lua | 3 + lua/Trans/core/READMD.md | 96 ++++++++++++++++++++++ lua/Trans/core/query.lua | 8 +- lua/Trans/core/{init.lua => translate.lua} | 28 ++----- lua/Trans/util/format.lua | 61 +++++++++++--- lua/Trans/util/test/test.lua | 11 +-- 8 files changed, 222 insertions(+), 103 deletions(-) create mode 100644 lua/Trans/core/READMD.md rename lua/Trans/core/{init.lua => translate.lua} (94%) diff --git a/lua/Trans/component/content.lua b/lua/Trans/component/content.lua index e86572f..66f35b7 100644 --- a/lua/Trans/component/content.lua +++ b/lua/Trans/component/content.lua @@ -12,21 +12,33 @@ function M:new() return content end ---- NOTE :highlight 格式说明: ---- 1. 字符串 -function M:insert_items_to_line(items, opts) +-- NOTE : +-- local items = { +-- -- style1: string 不需要单独设置高亮的情况 +-- 'text', +-- -- style2: string[] 需要设置高亮,第二个名称为高亮组 +-- {'text2', 'highlight name'}, +-- } + +-- local opts = { +-- -- 可选的参数 +-- highlight = 'highlight name' -- string 该行的高亮 +-- indent = 4 -- integer 该行的应该在开头的缩进 +-- interval = 4 -- integer 该行组件的间隔 +-- } +function M:insert_items_to_line(items) type_check { items = { items, 'table' }, - opts = { opts, 'table', true }, } + self.size = self.size + 1 -- line数加一 local line = { - space = (' '):rep(opts.interval), - indent = opts.indent, - highlight = opts.highlight, + space = (' '):rep(items.interval), + indent = items.indent, + highlight = items.highlight, } local highlight = {} @@ -45,7 +57,7 @@ function M:insert_items_to_line(items, opts) self.lines[self.size] = line end ----遍历lines和高亮的迭代器 + ---Usage: --- local buffer_id --- local lines, highlights = M:lines() diff --git a/lua/Trans/component/offline/Title.lua b/lua/Trans/component/offline/Title.lua index 4816e0e..e8455aa 100644 --- a/lua/Trans/component/offline/Title.lua +++ b/lua/Trans/component/offline/Title.lua @@ -3,7 +3,6 @@ local M = {} local display = require("Trans.conf.loader").loaded.conf.ui.display local icon = require("Trans.conf.loader").loaded.conf.ui.icon -local m_field = {} -- { -- collins = 3, -- definition = "n. an expression of greeting", @@ -17,64 +16,53 @@ local m_field = {} -- } -local content = { - lines = { - need_format = { - {}, -- line - {}, -- line - {}, -- line - {}, -- line - } - }, - highlight = { - [2] = { -- 第几行第几个组件的高亮 - [1] = 'highlightname', - }, - } -} +-- local data = { +-- { word, 'TransWord' }, +-- -- NOTE :如果平配置设置显示,并且数据库中存在则有以下字段 +-- { phonetic, 'TransPhonetic' }, +-- collins, +-- oxford +-- -- { phonetic, 'TransPhonetic' }, +-- } -local function get_items() - local items = { - m_field.word, +---@alias stuff +---| 'data' # 所有组件的信息 +---| 'highlight?' # 整个组件的高亮 +---| 'indent?' # 每行整体的缩进 +---| 'interval?' # 每个组件的间隔 +---@alias component stuff[] + +---从查询结果中获取字符串 +---@param field table 查询的结果 +---@return component component 提取的组件信息[包含多个组件] +M.component = function(field) + local component = {} + local stuffs = {} + local data = { + {field.word, 'TransWord'}, } - if display.phonetic then - table.insert(items, '[' .. m_field.phonetic .. ']') + + if display.phonetic and field.phonetic then + table.insert(data, { + '[' .. field.phonetic .. ']', 'TransPhonetic' + }) end - if display.collins_star then - table.insert(items, icon.star:rep(m_field.collins)) + if display.collins and field.collins then + table.insert(data, { + icon.star:rep(field.collins) + }) end - if display.oxford then - local item - if m_field.oxford and m_field.oxford == 1 then - item = icon.isOxford - else - item = icon.notOxford - end - table.insert(items, item) + if display.oxford and field.oxford then + table.insert(data, { + field.oxford + }) end - return items -end - -M.content = function(field) - -- TODO - m_field = field or {} - local content = {} - - - content.lines = { - need_format = { - get_items() - }, - highlight = { - [1] = { -- 第一行 - 'Trans', - } - } - } - return content + stuffs.data = data + component[1] = stuffs + return component end return M diff --git a/lua/Trans/conf/default.lua b/lua/Trans/conf/default.lua index c182892..7cc2649 100644 --- a/lua/Trans/conf/default.lua +++ b/lua/Trans/conf/default.lua @@ -96,6 +96,9 @@ M.conf = { -- map = { -- -- TODO -- }, + -- history = { + -- -- TOOD + -- } -- TODO add online translate engine -- online_search = { diff --git a/lua/Trans/core/READMD.md b/lua/Trans/core/READMD.md new file mode 100644 index 0000000..47232dd --- /dev/null +++ b/lua/Trans/core/READMD.md @@ -0,0 +1,96 @@ +# 命令说明 + +<!--toc:start--> +- [命令说明](#命令说明) + - [Translate](#translate) + - [TranslateInput](#translateinput) + - [TranslateHistory](#translatehistory) + - [自定义](#自定义) + - [可选项说明](#可选项说明) + - [示例](#示例) +<!--toc:end--> + +## Translate +**窗口风格默认为:** `cursor` +- 动作(action): + - `vsplit` 水平分屏 + - `split` 垂直分屏 + - `float` 窗口样式又`cursor` 变为`float` + - `online_query` 使用在线引擎重新进行查询 + - `history_insert` 将此次查询的单词记录到历史记录 + - `next` 展示下一个引擎的查询结果(如果默认设置了多个引擎) + - `prev` 展示上一个查询结果 + > 如果没有设置自动保存历史的话 + + - `history` 查看历史查询的记录 + +- `online_query`: + - `local_add` 将此次查询的结果添加到本地数据库 + > **如果本地已经存在该单词,会询问是否需要覆盖掉相同的字段** + + - `local_update` 和*local_add* 类似, 但是不会询问是否覆盖 + - `diff` 对比本地查询结果和此次在线查询的区别 + +> **注意**: 动作是任何窗口通用的 +## TranslateInput +**窗口风格默认为:** `float` +- 自行得到要查询的单词 + +- TODO: + - fuzzy match + +## TranslateHistory +**窗口风格默认为:** `float` +- 查看历史查询 + +--- +## 自定义 + +### 可选项说明 +- 查询方式(method): `string` + - `input` 自行输入需要查询的单词 + - `last` 显示上一次查询的结果 + - `history` + +- 查询引擎(engine): `string | table` + - `local` 本地的数据库 + - `youcao` 有道api + - `baidu` 百度api + - `google` 谷歌api + - `bing` 必应api + - `iciba` 金山词霸api + - `xunfei` 讯飞api + +- 窗口风格(win): `string | table` + - 样式(style): + - `cursor` 在光标附近弹出 + - `float` 悬浮窗口 + - `split` 在上方或者下方分屏 + - `vsplit` 在左边或者右边分屏 + + - 高度(height): + - `value > 1` 实际高度 + - `0 <= value <= 1` 相对高度 + - `0 < value` 无限制 + + - 宽度(width): + > 和`高度(height)`相同 +### 示例 +```lua +vim.keymap.set('n', 'mi', function () + require('Trans').translate({ + method = 'input', + engine = { -- 异步查询所有的引擎, 按照列表 + 'local', + 'youdao', + 'baidu' + }, + -- view = 'cursor' + view = { + style = 'cursor', + height = 50, + width = 30, + } + }) +end, { desc = '在光标旁弹出输入的单词释义'}) +``` diff --git a/lua/Trans/core/query.lua b/lua/Trans/core/query.lua index 2f3f43e..e8f8a49 100644 --- a/lua/Trans/core/query.lua +++ b/lua/Trans/core/query.lua @@ -14,24 +14,24 @@ local function get_select() return word end + M.get_query_res = function(method) type_check { method = { method, 'string' }, } - - -- NOTE : get query word local word = '' if method == 'cursor' then word = vim.fn.expand('<cword>') elseif method == 'select' then - word = get_select():match('%s+') + word = get_select():match('%S+') elseif method == 'input' then word = vim.fn.input('请输入您要查询的单词:') -- TODO Use Telescope with fuzzy finder else error('unknown method') end - -- FIXME + return query(word) end + return M diff --git a/lua/Trans/core/init.lua b/lua/Trans/core/translate.lua similarity index 94% rename from lua/Trans/core/init.lua rename to lua/Trans/core/translate.lua index 6e28f2d..fb8cd0e 100644 --- a/lua/Trans/core/init.lua +++ b/lua/Trans/core/translate.lua @@ -1,32 +1,20 @@ local M = {} -local api = vim.api -local conf = require("Trans").conf -local display = conf.display -local icon = conf.icon -local order = conf.order -local auto_close = conf.auto_close -local view = conf.view -local highlight = { - word = 'TransWord', - phonetic = 'TransPhonetic', - ref = 'TransRef', - tag = 'TransTag', - exchange = 'TransExchange', - pos = 'TransPos', - zh = 'TransZh', - en = 'TransEn', +local opt = { + method = 'select', + view = 'cursor', } - - - -M.TransLate = function(opts) +M.Translate = function(opts) local res = get_query_res(opts.method) -- TODO <++> end +-- M.Translate_online = function () +-- -- TOOD +-- end + -- local win = 0 -- local line = 0 diff --git a/lua/Trans/util/format.lua b/lua/Trans/util/format.lua index 9eb5ca5..5f892d2 100644 --- a/lua/Trans/util/format.lua +++ b/lua/Trans/util/format.lua @@ -10,9 +10,9 @@ end -- 各种风格的基础宽度 local style_width = { - -- float = require("Trans.conf.window").float.width, -- NOTE : need window parsed conf - -- cursor = require("Trans.conf.window").cursor.width, - cursor = 50 + float = require("Trans.conf.window").float.width, -- NOTE : need window parsed conf + cursor = require("Trans.conf.window").cursor.width, + -- cursor = 50 } local s_to_b = true -- 从小到大排列 @@ -92,10 +92,10 @@ local function format_to_multilines(rows, cols) s_width = m_item_width[index] local stop = (j > rest and rows - 1 or rows) for i = 1, stop do - local idx = s_to_b and stop - i + 1 or i -- 当前操作的行数 - local item_idx = index + i - 1 -- 当前操作的字段数 - local space = (' '):rep(s_width - m_item_width[item_idx]) -- 对齐空格 - local item = m_fields[item_idx] .. space + local idx = s_to_b and stop - i + 1 or i -- 当前操作的行数 + local item_idx = index + i - 1 -- 当前操作的字段数 + local space = (' '):rep(s_width - m_item_width[item_idx]) -- 对齐空格 + local item = m_fields[item_idx] .. space lines[idx][j] = item -- 插入图标 end @@ -120,16 +120,46 @@ local function formatted_lines() return lines end +-- EXAMPLE : 接受的形式 +-- local content = { +-- { word, 'TransWord' }, +-- { phonetic, 'TransPhonetic' }, +-- collins, +-- oxford +-- -- { phonetic, 'TransPhonetic' }, +-- NOTE : +-- 可选的: +-- 1. highlight 整个content的高亮 +-- 2. indent 缩进 +-- 2. space 各个组件的及间隔 +-- } + + +-- EXAMPLE : 返回的形式 +local lines = { + { items, opts }, + { items, opts }, + { items, opts }, + -- items: string[] + -- opts { + -- highlight + -- indent + -- } +} + +local function format_stuff(stuff) + +end + +---@alias formatted_items table ---将组件格式化成相应的vim支持的lines格式 ---@param style string 窗口的风格 ----@param fields string[] 需要格式化的字段 ----@param indent number 缩进的长度 ----@return string[] lines 便于vim.api.nvim_buf_set_lines -M.to_lines = function(style, fields, indent) +---@param component table 需要格式化的字段 +---@return formatted_items[] lines +M.format = function(style, component) type_check { style = { style, { 'string' } }, - fields = { fields, { 'table' } }, - indent = { indent, { 'number' }, true }, + component = { component, { 'table' } }, } local length = 0 @@ -151,6 +181,11 @@ M.to_lines = function(style, fields, indent) return formatted_lines() end + + + + + ---合并多个数组, 第一个数组将会被使用 ---@param ... string[] 需要被合并的数组 ---@return table res 合并后的数组 diff --git a/lua/Trans/util/test/test.lua b/lua/Trans/util/test/test.lua index 0b99fff..fa4d1e9 100644 --- a/lua/Trans/util/test/test.lua +++ b/lua/Trans/util/test/test.lua @@ -1,8 +1,5 @@ -local tmp = { - '1111', - '2222', - '3333', - interval = 4, -} +local a = nil -print(table.concat(tmp, (' '):rep(tmp.interval))) + + +print((' '):rep(a)) From fef956e36df8b98c3ff485db4253d282f7e2b363 Mon Sep 17 00:00:00 2001 From: JuanZoran <1430359574@qq.com> Date: Mon, 9 Jan 2023 18:57:20 +0800 Subject: [PATCH 10/17] feat: add some bugs --- lua/.luarc.json | 5 ++ lua/Trans/api/READMD.md | 7 +++ lua/Trans/api/init.lua | 8 +++ .../{database/init.lua => api/query.lua} | 27 +++++----- lua/Trans/conf/default.lua | 3 +- lua/Trans/conf/loader.lua | 21 +++----- lua/Trans/core/READMD.md | 6 +-- lua/Trans/core/query.lua | 22 +++++++- lua/Trans/database/online.lua | 0 lua/Trans/init.lua | 6 ++- lua/Trans/test.lua | 33 ------------ lua/Trans/wrapper/translate.lua | 52 +++++++++++++++++++ 12 files changed, 125 insertions(+), 65 deletions(-) create mode 100644 lua/Trans/api/READMD.md create mode 100644 lua/Trans/api/init.lua rename lua/Trans/{database/init.lua => api/query.lua} (97%) delete mode 100644 lua/Trans/database/online.lua delete mode 100644 lua/Trans/test.lua create mode 100644 lua/Trans/wrapper/translate.lua diff --git a/lua/.luarc.json b/lua/.luarc.json index 97534e4..cb3ed2f 100644 --- a/lua/.luarc.json +++ b/lua/.luarc.json @@ -3,5 +3,10 @@ "Lua.diagnostics.disable": [ "empty-block", "trailing-space" + ], + "Lua.diagnostics.globals": [ + "vim", + "user_conf", + "default_conf" ] } \ No newline at end of file diff --git a/lua/Trans/api/READMD.md b/lua/Trans/api/READMD.md new file mode 100644 index 0000000..bdc0653 --- /dev/null +++ b/lua/Trans/api/READMD.md @@ -0,0 +1,7 @@ +# API说明 + +## 概述 +- 翻译查询 + - `` +- 字段处理 +- 窗口显示 diff --git a/lua/Trans/api/init.lua b/lua/Trans/api/init.lua new file mode 100644 index 0000000..6efad78 --- /dev/null +++ b/lua/Trans/api/init.lua @@ -0,0 +1,8 @@ +local M = {} + +local query_warpper = require 'Trans.api.query' + +M.query = query_warpper.query + + +return M diff --git a/lua/Trans/database/init.lua b/lua/Trans/api/query.lua similarity index 97% rename from lua/Trans/database/init.lua rename to lua/Trans/api/query.lua index 82c2a39..65ee90f 100644 --- a/lua/Trans/database/init.lua +++ b/lua/Trans/api/query.lua @@ -5,18 +5,6 @@ if not _ then end local type_check = require("Trans.util.debug").type_check -local query_field = { - 'word', - 'phonetic', - 'definition', - 'translation', - 'pos', - 'collins', - 'oxford', - 'tag', - 'exchange', -} - -- INFO : init database local path = require("Trans.conf.loader").loaded_conf.base.db_path local dict = db:open(path) @@ -31,6 +19,20 @@ vim.api.nvim_create_autocmd('VimLeavePre', { end }) + +local query_field = { + 'word', + 'phonetic', + 'definition', + 'translation', + 'pos', + 'collins', + 'oxford', + 'tag', + 'exchange', +} + +-- NOTE : local query M.query = function(arg) -- TODO : more opts type_check { @@ -45,4 +47,5 @@ M.query = function(arg) return res[1] end + return M diff --git a/lua/Trans/conf/default.lua b/lua/Trans/conf/default.lua index 7cc2649..2677f0b 100644 --- a/lua/Trans/conf/default.lua +++ b/lua/Trans/conf/default.lua @@ -4,7 +4,7 @@ M.conf = { style = { ui = { input = 'float', - cursor = 'cursor', + normal = 'cursor', select = 'cursor' }, window = { @@ -115,4 +115,5 @@ M.replace_rules = { 'ui.highlight.*', } + return M diff --git a/lua/Trans/conf/loader.lua b/lua/Trans/conf/loader.lua index 67a5e08..90f0803 100644 --- a/lua/Trans/conf/loader.lua +++ b/lua/Trans/conf/loader.lua @@ -13,6 +13,7 @@ if def and usr then end ]] + local plain_format = [[ default_conf.%s = user_conf.%s or default_conf.%s ]] @@ -36,21 +37,15 @@ local function pre_process() end end - - M.load_conf = function(conf) - if #M.loaded_conf == 0 then - user_conf = conf or {} - default_conf = require("Trans.conf.default").conf - pre_process() - M.loaded_conf = vim.tbl_deep_extend('force', default_conf, user_conf) - user_conf = nil - default_conf = nil - else - vim.notify('Configuration has been loaded...') - end + user_conf = conf or {} + default_conf = require("Trans.conf.default").conf + pre_process() + M.loaded_conf = vim.tbl_deep_extend('force', default_conf, user_conf) + user_conf = nil + default_conf = nil end -M.loaded_conf = {} +M.loaded_conf = nil return M diff --git a/lua/Trans/core/READMD.md b/lua/Trans/core/READMD.md index 47232dd..e86391d 100644 --- a/lua/Trans/core/READMD.md +++ b/lua/Trans/core/READMD.md @@ -79,14 +79,14 @@ ```lua vim.keymap.set('n', 'mi', function () require('Trans').translate({ - method = 'input', + method = 'input', -- 不填则自动判断mode获取查询的单词 engine = { -- 异步查询所有的引擎, 按照列表 'local', 'youdao', 'baidu' }, - -- view = 'cursor' - view = { + -- win = 'cursor' + win = { style = 'cursor', height = 50, width = 30, diff --git a/lua/Trans/core/query.lua b/lua/Trans/core/query.lua index e8f8a49..ed53437 100644 --- a/lua/Trans/core/query.lua +++ b/lua/Trans/core/query.lua @@ -15,6 +15,27 @@ local function get_select() end +local function get_word(method) + if not method then + local mode = vim.api.nvim_get_mode() + if mode == 'n' then + return vim.fn.expand('<cword>') + elseif mode == 'v' then + return get_select() + else + error('invalid mode') + end + end + + if method == 'input' then + return vim.fn.input('请输入您要查询的单词:') -- TODO Use Telescope with fuzzy finder + + -- TODO : other method + else + error('invalid method') + end +end + M.get_query_res = function(method) type_check { method = { method, 'string' }, @@ -25,7 +46,6 @@ M.get_query_res = function(method) elseif method == 'select' then word = get_select():match('%S+') elseif method == 'input' then - word = vim.fn.input('请输入您要查询的单词:') -- TODO Use Telescope with fuzzy finder else error('unknown method') end diff --git a/lua/Trans/database/online.lua b/lua/Trans/database/online.lua deleted file mode 100644 index e69de29..0000000 diff --git a/lua/Trans/init.lua b/lua/Trans/init.lua index 5b4853a..5090cb7 100644 --- a/lua/Trans/init.lua +++ b/lua/Trans/init.lua @@ -1,7 +1,9 @@ local M = {} -M.conf = {} - M.setup = require('Trans.conf.loader').load_conf +M.translate = require('Tran.wrapper.translate') + + + return M diff --git a/lua/Trans/test.lua b/lua/Trans/test.lua deleted file mode 100644 index 6430e03..0000000 --- a/lua/Trans/test.lua +++ /dev/null @@ -1,33 +0,0 @@ -local M = {} - -M.test = { - 'test1', - 'test1', - 'test1', - 'test1', -} - - -function M.tmp (start, stop) - if start > stop then - return - end - - local value = M.test[start] - start = start + 1 - return function () - - return start - end -end --- function M:tmp(index) --- end - -for v in M.tmp, 1, #M.test do - print(v) -end - --- for i,n in square,3,0 --- do --- print(i,n) --- end diff --git a/lua/Trans/wrapper/translate.lua b/lua/Trans/wrapper/translate.lua new file mode 100644 index 0000000..e1e9a8b --- /dev/null +++ b/lua/Trans/wrapper/translate.lua @@ -0,0 +1,52 @@ +local type_check = require("Trans.util.debug").type_check + +local window = require("Trans.conf.window") +-- Default conf +local core = require("Trasn.core") + +local function get_opts(opts) + local default_conf = { + method = vim.api.nvim_get_mode(), + engine = { + 'local', + -- TODO : other engine + }, + win = window.cursor_win, + } + + -- TODO :process win height and width + if type(opts.engine) == 'string' then + opts.engine = { opts.engine } + end + + if opts.win then + opts.win = window.process(opts.win) + end + return vim.tbl_extend('force', default_conf, opts) +end + +local function translate(opts) + type_check { + opts = { opts, 'table' } + } + opts = get_opts(opts or {}) + + + local field = core.query(opts) + + opts = { + field = field, + } + + local content = core.process(opts) + + opts = { + style = opts.style, + height = opts.height, + width = opts.width, + content = content, + } + core.show(opts) +end + +return translate From 67c6ffa989d0de489f8192ccfbe9b8ee9c1071d5 Mon Sep 17 00:00:00 2001 From: JuanZoran <1430359574@qq.com> Date: Mon, 9 Jan 2023 21:30:16 +0800 Subject: [PATCH 11/17] feat: add more bugs --- README.md | 2 +- lua/Trans/api/{READMD.md => README.md} | 0 lua/Trans/component/content.lua | 12 +++--- lua/Trans/component/init.lua | 8 ---- lua/Trans/component/window.lua | 12 ------ lua/Trans/conf/base.lua | 9 +---- lua/Trans/conf/default.lua | 5 ++- lua/Trans/conf/loader.lua | 14 +++++++ lua/Trans/core/{READMD.md => README.md} | 4 +- lua/Trans/core/content.lua | 19 --------- lua/Trans/core/init.lua | 7 ++++ lua/Trans/core/process.lua | 22 ++++++++++ lua/Trans/core/show_win.lua | 53 +++++++++++++++++++++++++ lua/Trans/init.lua | 4 +- lua/Trans/ui/init.lua | 0 lua/Trans/util/format.lua | 32 +++++---------- lua/Trans/window/content.lua | 18 --------- lua/Trans/window/display.lua | 29 -------------- lua/Trans/window/init.lua | 0 lua/Trans/wrapper/translate.lua | 43 +++++++++++++------- 20 files changed, 149 insertions(+), 144 deletions(-) rename lua/Trans/api/{READMD.md => README.md} (100%) delete mode 100644 lua/Trans/component/init.lua delete mode 100644 lua/Trans/component/window.lua rename lua/Trans/core/{READMD.md => README.md} (97%) delete mode 100644 lua/Trans/core/content.lua create mode 100644 lua/Trans/core/init.lua create mode 100644 lua/Trans/core/process.lua create mode 100644 lua/Trans/core/show_win.lua delete mode 100644 lua/Trans/ui/init.lua delete mode 100644 lua/Trans/window/content.lua delete mode 100644 lua/Trans/window/display.lua delete mode 100644 lua/Trans/window/init.lua diff --git a/README.md b/README.md index dbd6ee5..f294f75 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ - 支持 `normal`和 `visual`模式 > 不支持 visual-block mode -- 词库单词量: `43w` +- 本地词库单词量: `430w` ## 屏幕截图  diff --git a/lua/Trans/api/READMD.md b/lua/Trans/api/README.md similarity index 100% rename from lua/Trans/api/READMD.md rename to lua/Trans/api/README.md diff --git a/lua/Trans/component/content.lua b/lua/Trans/component/content.lua index 66f35b7..7102f78 100644 --- a/lua/Trans/component/content.lua +++ b/lua/Trans/component/content.lua @@ -12,14 +12,12 @@ function M:new() return content end - - -- NOTE : -- local items = { -- -- style1: string 不需要单独设置高亮的情况 --- 'text', +-- 'text', -- -- style2: string[] 需要设置高亮,第二个名称为高亮组 --- {'text2', 'highlight name'}, +-- {'text2', 'highlight name'}, -- } -- local opts = { @@ -28,7 +26,7 @@ end -- indent = 4 -- integer 该行的应该在开头的缩进 -- interval = 4 -- integer 该行组件的间隔 -- } -function M:insert_items_to_line(items) +function M:insert(items) type_check { items = { items, 'table' }, } @@ -57,7 +55,6 @@ function M:insert_items_to_line(items) self.lines[self.size] = line end - ---Usage: --- local buffer_id --- local lines, highlights = M:lines() @@ -93,7 +90,8 @@ function M:lines() for i = 2, #l do line = line .. l.space .. l[i] if hl[i] then - table.insert(highlight, { name = hl[i], _start = #line - #l[i], _end = #line }) + local _end = #line + table.insert(highlight, { name = hl[i], _start = _end - #l[i], _end = _end }) end end end diff --git a/lua/Trans/component/init.lua b/lua/Trans/component/init.lua deleted file mode 100644 index 10247c9..0000000 --- a/lua/Trans/component/init.lua +++ /dev/null @@ -1,8 +0,0 @@ -local M = {} -local order = require('Trans.conf.loader').loaded_conf.order - -M._ = function (query_) - -end - -return M diff --git a/lua/Trans/component/window.lua b/lua/Trans/component/window.lua deleted file mode 100644 index bb5448f..0000000 --- a/lua/Trans/component/window.lua +++ /dev/null @@ -1,12 +0,0 @@ -local M = {} -local type_check = require("Trans.util.debug").type_check - - --- vim.pretty_print(vim.lsp.util._make_floating_popup_size) - -local v = [=[ - local test = {{ - }} -]=] -print(v) -return M diff --git a/lua/Trans/conf/base.lua b/lua/Trans/conf/base.lua index 42c4d8e..c247c60 100644 --- a/lua/Trans/conf/base.lua +++ b/lua/Trans/conf/base.lua @@ -1,17 +1,12 @@ local M = {} - + local buf_opts = { - filetype = 'Trans' } local buf = vim.api.nvim_create_buf(false, true) -for k, v in pairs(buf_opts) do - vim.api.nvim_buf_set_option(buf, k, v) -end M.buf = buf -M.group = vim.api.nvim_create_augroup('Trans', { clear = true }) - +M.augroup = vim.api.nvim_create_augroup('Trans', { clear = true }) return M diff --git a/lua/Trans/conf/default.lua b/lua/Trans/conf/default.lua index 2677f0b..845e0cc 100644 --- a/lua/Trans/conf/default.lua +++ b/lua/Trans/conf/default.lua @@ -15,8 +15,8 @@ M.conf = { }, float = { border = 'rounded', - width = 0.8, - height = 0.9, + width = 0.9, + height = 0.8, }, -- NOTE :如果你想限制某个组件的行数,可以设置 (名称与order相同) -- Example: @@ -91,6 +91,7 @@ M.conf = { }, engine = { -- TODO + 'local', } }, -- map = { diff --git a/lua/Trans/conf/loader.lua b/lua/Trans/conf/loader.lua index 90f0803..ef8f53f 100644 --- a/lua/Trans/conf/loader.lua +++ b/lua/Trans/conf/loader.lua @@ -40,8 +40,22 @@ end M.load_conf = function(conf) user_conf = conf or {} default_conf = require("Trans.conf.default").conf + if user_conf.style and user_conf.window then + end + pre_process() M.loaded_conf = vim.tbl_deep_extend('force', default_conf, user_conf) + local width = M.loaded_conf.style.window.cursor.float.width + local height = M.loaded_conf.style.window.cursor.float.height + + if width > 0 and width <= 1 then + M.loaded_conf.style.window.cursor.float.width = math.floor(width * vim.o.columns) + end + + if height > 0 and height <= 1 then + M.loaded_conf.style.window.cursor.float.height = math.floor(height * (vim.o.lines - vim.o.cmdheight)) + end + user_conf = nil default_conf = nil end diff --git a/lua/Trans/core/READMD.md b/lua/Trans/core/README.md similarity index 97% rename from lua/Trans/core/READMD.md rename to lua/Trans/core/README.md index e86391d..5fa3070 100644 --- a/lua/Trans/core/READMD.md +++ b/lua/Trans/core/README.md @@ -53,7 +53,7 @@ - `history` - 查询引擎(engine): `string | table` - - `local` 本地的数据库 + - `offline` 离线的数据库 - `youcao` 有道api - `baidu` 百度api - `google` 谷歌api @@ -81,7 +81,7 @@ vim.keymap.set('n', 'mi', function () require('Trans').translate({ method = 'input', -- 不填则自动判断mode获取查询的单词 engine = { -- 异步查询所有的引擎, 按照列表 - 'local', + 'offline', 'youdao', 'baidu' }, diff --git a/lua/Trans/core/content.lua b/lua/Trans/core/content.lua deleted file mode 100644 index 0cc6206..0000000 --- a/lua/Trans/core/content.lua +++ /dev/null @@ -1,19 +0,0 @@ -local M = {} -local type_check = require("Trans.util.debug").type_check - -local offline_dir = debug.getinfo(1, "S").source:sub(2):match('.*Trans') .. '/component/offline' - -M.to_content = function(query_res) - type_check { - query_res = { query_res, 'table' } - } - local content = {} - for file in vim.fs.dir(offline_dir) do - local res = require("Trans.component.offline." .. file:gsub('.lua', '')).to_content(query_res) - assert(res) - table.insert(content, res) - end - return content -end - -return M diff --git a/lua/Trans/core/init.lua b/lua/Trans/core/init.lua new file mode 100644 index 0000000..fd633ca --- /dev/null +++ b/lua/Trans/core/init.lua @@ -0,0 +1,7 @@ +local M = {} + +M.process = require('Trans.core.process') +M.query = require('Trans.core.query') +M.show_win = require('Trans.core.show_win') + +return M diff --git a/lua/Trans/core/process.lua b/lua/Trans/core/process.lua new file mode 100644 index 0000000..f5ff007 --- /dev/null +++ b/lua/Trans/core/process.lua @@ -0,0 +1,22 @@ +local type_check = require("Trans.util.debug").type_check +local format = require("Trans.util.format") + + +-- NOTE : 将请求得到的字段进行处理 +-- local offline_dir = debug.getinfo(1, "S").source:sub(2):match('.*Trans') .. '/component/offline' +local function process (opts) + type_check { + opts = { opts, 'table' } + } + local content = require('Trans.component.content'):new() + + for _, v in ipairs(opts.order) do + local component = format.format(opts.win_style, require("Trans.component" .. opts.engine .. v)) + content:insert(component) + end + + return content:lines() +end + + +return process diff --git a/lua/Trans/core/show_win.lua b/lua/Trans/core/show_win.lua new file mode 100644 index 0000000..7c17fa3 --- /dev/null +++ b/lua/Trans/core/show_win.lua @@ -0,0 +1,53 @@ +local type_check = require("Trans.util.debug").type_check + +local buf_opts = { + filetype = 'Trans', + modifiable = false, +} + +-- local win_opts = { +-- winhl = 'Normal:TransWinNormal, FloatBorder:TransWinBorder' +-- } + +local function caculate_format(height, width) + local col = math.floor((vim.o.lines - height - vim.o.cmdheight) / 2) + local row = math.floor((vim.o.columns - width) / 2) + return row, col +end + +local function show_win(opts) + type_check { + opts = { opts, 'table' }, + win = { opts.win, 'table' }, + highlight = { opts.highlight, 'table', true }, + } + + local bufnr = vim.api.nvim_create_buf(false, true) + for k, v in pairs(buf_opts) do + vim.api.nvim_buf_set_option(bufnr, k, v) + end + + local is_float = opts.style == 'float' + local win_opts = { + relative = opts.style == 'float' and 'editor' or 'cursor', + width = opts.width, + height = opts.height, + style = 'minimal', + border = 'rounded', + title = 'Trans', + title_pos = 'center', + focusable = true, + zindex = 100, + } + if is_float then + win_opts.row, win_opts.col = caculate_format(win_opts.height, win_opts.width) + else + win_opts.row = 2 + win_opts.col = 2 + end + local winid = vim.api.nvim_open_win(bufnr, is_float, win_opts) + + return bufnr, winid +end + +return show_win diff --git a/lua/Trans/init.lua b/lua/Trans/init.lua index 5090cb7..380e4fb 100644 --- a/lua/Trans/init.lua +++ b/lua/Trans/init.lua @@ -2,8 +2,6 @@ local M = {} M.setup = require('Trans.conf.loader').load_conf -M.translate = require('Tran.wrapper.translate') - - +M.translate = require('Tran.core.translate') return M diff --git a/lua/Trans/ui/init.lua b/lua/Trans/ui/init.lua deleted file mode 100644 index e69de29..0000000 diff --git a/lua/Trans/util/format.lua b/lua/Trans/util/format.lua index 5f892d2..e3c520d 100644 --- a/lua/Trans/util/format.lua +++ b/lua/Trans/util/format.lua @@ -1,4 +1,3 @@ ----@diagnostic disable: undefined-global local M = {} local type_check = require("Trans.util.debug").type_check @@ -8,12 +7,6 @@ function string:width() return vim.fn.strdisplaywidth(self) end --- 各种风格的基础宽度 -local style_width = { - float = require("Trans.conf.window").float.width, -- NOTE : need window parsed conf - cursor = require("Trans.conf.window").cursor.width, - -- cursor = 50 -} local s_to_b = true -- 从小到大排列 @@ -136,20 +129,17 @@ end -- EXAMPLE : 返回的形式 -local lines = { - { items, opts }, - { items, opts }, - { items, opts }, - -- items: string[] - -- opts { - -- highlight - -- indent - -- } -} +-- local lines = { +-- { items, opts }, +-- { items, opts }, +-- { items, opts }, +-- -- items: string[] +-- -- opts { +-- -- highlight +-- -- indent +-- -- } +-- } -local function format_stuff(stuff) - -end ---@alias formatted_items table ---将组件格式化成相应的vim支持的lines格式 @@ -184,8 +174,6 @@ end - - ---合并多个数组, 第一个数组将会被使用 ---@param ... string[] 需要被合并的数组 ---@return table res 合并后的数组 diff --git a/lua/Trans/window/content.lua b/lua/Trans/window/content.lua deleted file mode 100644 index 1b86632..0000000 --- a/lua/Trans/window/content.lua +++ /dev/null @@ -1,18 +0,0 @@ -local M = {} - ---[[ -content = { - lines = {} ---@type string[] - highlight = {} -} ---]] ----@param contents string[] -M.set = function (win, contents) - vim.validate { - contents = { contents, 'table' }, - } - -- TODO -end - - -return M diff --git a/lua/Trans/window/display.lua b/lua/Trans/window/display.lua deleted file mode 100644 index 567149b..0000000 --- a/lua/Trans/window/display.lua +++ /dev/null @@ -1,29 +0,0 @@ -local M = {} -local api = vim.api -local util = require("Trans.window.util") -M.buf = util.init_buf() - ---- 浮动窗口的风格 ----@param conf table 自定义配置 -M.show_float_win = function(conf) - vim.validate { - conf = { conf, 'table' }, - } - local opts = util.get_float_opts(conf) - local win = api.nvim_open_win(M.buf, true, opts) - return win -end - -M.show_cursor_win = function(conf) - vim.validate { - conf = { conf, 'table' }, - } - local opts = util.get_cursor_opts(conf) - local win = api.nvim_open_win(M.buf, true, opts) - return win -end - --- TODO <++> more window style - - -return M diff --git a/lua/Trans/window/init.lua b/lua/Trans/window/init.lua deleted file mode 100644 index e69de29..0000000 diff --git a/lua/Trans/wrapper/translate.lua b/lua/Trans/wrapper/translate.lua index e1e9a8b..4cbffd3 100644 --- a/lua/Trans/wrapper/translate.lua +++ b/lua/Trans/wrapper/translate.lua @@ -1,9 +1,9 @@ local type_check = require("Trans.util.debug").type_check - -local window = require("Trans.conf.window") -- Default conf +local conf = require("Trans.conf.loader").loaded_conf local core = require("Trasn.core") + local function get_opts(opts) local default_conf = { method = vim.api.nvim_get_mode(), @@ -11,17 +11,28 @@ local function get_opts(opts) 'local', -- TODO : other engine }, - win = window.cursor_win, + win = { + style = 'cursor', + width = conf.window.cursor.width, + height = conf.window.cursor.height + }, } - -- TODO :process win height and width if type(opts.engine) == 'string' then opts.engine = { opts.engine } end if opts.win then - opts.win = window.process(opts.win) + local width, height = opts.win.width, opts.win.height + if width and width > 0 and width <= 1 then + opts.win.width = math.floor(vim.o.columns * width) + end + + if height and height > 0 and height <= 1 then + opts.win.height = math.floor(vim.o.lines * opts.win.height) + end end + return vim.tbl_extend('force', default_conf, opts) end @@ -29,24 +40,28 @@ local function translate(opts) type_check { opts = { opts, 'table' } } + + --- TODO : 异步请求 + -- NOTE : 这里只处理了本地的请求 opts = get_opts(opts or {}) - - local field = core.query(opts) - opts = { + local proc_opts = { field = field, + order = conf.order['offline'], + engine = 'offline', + win_style = opts.win.style, } - local content = core.process(opts) + local content, highlight = core.process(proc_opts) - opts = { - style = opts.style, - height = opts.height, - width = opts.width, + local win_opts = { + win = opts.win, content = content, + highlight = highlight, } - core.show(opts) + + core.show_win(win_opts) end return translate From ff36cfd549d30f2ab38a29e19518432dbe9086b7 Mon Sep 17 00:00:00 2001 From: JuanZoran <1430359574@qq.com> Date: Mon, 9 Jan 2023 23:20:56 +0800 Subject: [PATCH 12/17] feat: add more bugs --- lua/Trans/api/query.lua | 3 +- lua/Trans/component/content.lua | 2 +- lua/Trans/component/offline/Title.lua | 4 +- lua/Trans/conf/base.lua | 12 - lua/Trans/conf/default.lua | 19 +- lua/Trans/conf/loader.lua | 8 +- lua/Trans/core/backup.lua | 294 +++++++++++++++++++ lua/Trans/core/process.lua | 28 +- lua/Trans/core/query.lua | 51 ++-- lua/Trans/core/show_win.lua | 23 +- lua/Trans/core/translate.lua | 390 +++++++------------------- lua/Trans/init.lua | 9 +- lua/Trans/setup.lua | 27 +- lua/Trans/util/debug.lua | 9 +- lua/Trans/util/format.lua | 9 +- lua/Trans/util/test/test.lua | 7 +- lua/Trans/wrapper/translate.lua | 67 ----- 17 files changed, 497 insertions(+), 465 deletions(-) delete mode 100644 lua/Trans/conf/base.lua create mode 100644 lua/Trans/core/backup.lua delete mode 100644 lua/Trans/wrapper/translate.lua diff --git a/lua/Trans/api/query.lua b/lua/Trans/api/query.lua index 65ee90f..d2645af 100644 --- a/lua/Trans/api/query.lua +++ b/lua/Trans/api/query.lua @@ -11,7 +11,7 @@ local dict = db:open(path) -- INFO :Auto Close vim.api.nvim_create_autocmd('VimLeavePre', { - group = require("Trans.conf.base").autogroup, + group = require("Trans").augroup, callback = function() if db:isopen() then db:close() @@ -19,7 +19,6 @@ vim.api.nvim_create_autocmd('VimLeavePre', { end }) - local query_field = { 'word', 'phonetic', diff --git a/lua/Trans/component/content.lua b/lua/Trans/component/content.lua index 7102f78..3c6f907 100644 --- a/lua/Trans/component/content.lua +++ b/lua/Trans/component/content.lua @@ -64,7 +64,7 @@ end --- end ---@return table line ---@return table highlight -function M:lines() +function M:data() -- NOTE 返回格式化的行,如果需要高亮,则第二个参数返回高亮 local lines = {} local highlights = {} diff --git a/lua/Trans/component/offline/Title.lua b/lua/Trans/component/offline/Title.lua index e8455aa..d02eb69 100644 --- a/lua/Trans/component/offline/Title.lua +++ b/lua/Trans/component/offline/Title.lua @@ -1,7 +1,7 @@ local M = {} -local display = require("Trans.conf.loader").loaded.conf.ui.display -local icon = require("Trans.conf.loader").loaded.conf.ui.icon +local display = require("Trans.conf.loader").loaded_conf.ui.display +local icon = require("Trans.conf.loader").loaded_conf.ui.icon -- { -- collins = 3, diff --git a/lua/Trans/conf/base.lua b/lua/Trans/conf/base.lua deleted file mode 100644 index c247c60..0000000 --- a/lua/Trans/conf/base.lua +++ /dev/null @@ -1,12 +0,0 @@ -local M = {} - -local buf_opts = { -} - -local buf = vim.api.nvim_create_buf(false, true) - -M.buf = buf - -M.augroup = vim.api.nvim_create_augroup('Trans', { clear = true }) - -return M diff --git a/lua/Trans/conf/default.lua b/lua/Trans/conf/default.lua index 845e0cc..5e92c18 100644 --- a/lua/Trans/conf/default.lua +++ b/lua/Trans/conf/default.lua @@ -29,11 +29,11 @@ M.conf = { order = { offline = { 'Title', - 'Tag', - 'Pos', - 'Exchange', - 'Translation', - 'Definition', + -- 'Tag', + -- 'Pos', + -- 'Exchange', + -- 'Translation', + -- 'Definition', }, -- online = { -- -- TODO @@ -61,10 +61,10 @@ M.conf = { TransPos = { link = 'TransTag', }, - TransZh = { + TransTranslation = { link = 'TransWord', }, - TransEn = { + TransDefinition = { fg = '#bc8cff', }, }, @@ -84,11 +84,6 @@ M.conf = { base = { db_path = '$HOME/.vim/dict/ultimate.db', auto_close = true, - debug = { - enable = true, - type_check = true, - unknown_conf = true, - }, engine = { -- TODO 'local', diff --git a/lua/Trans/conf/loader.lua b/lua/Trans/conf/loader.lua index ef8f53f..3b3684f 100644 --- a/lua/Trans/conf/loader.lua +++ b/lua/Trans/conf/loader.lua @@ -45,15 +45,15 @@ M.load_conf = function(conf) pre_process() M.loaded_conf = vim.tbl_deep_extend('force', default_conf, user_conf) - local width = M.loaded_conf.style.window.cursor.float.width - local height = M.loaded_conf.style.window.cursor.float.height + local width = M.loaded_conf.style.window.float.width + local height = M.loaded_conf.style.window.float.height if width > 0 and width <= 1 then - M.loaded_conf.style.window.cursor.float.width = math.floor(width * vim.o.columns) + M.loaded_conf.style.window.float.width = math.floor(width * vim.o.columns) end if height > 0 and height <= 1 then - M.loaded_conf.style.window.cursor.float.height = math.floor(height * (vim.o.lines - vim.o.cmdheight)) + M.loaded_conf.style.window.float.height = math.floor(height * (vim.o.lines - vim.o.cmdheight)) end user_conf = nil diff --git a/lua/Trans/core/backup.lua b/lua/Trans/core/backup.lua new file mode 100644 index 0000000..fb8cd0e --- /dev/null +++ b/lua/Trans/core/backup.lua @@ -0,0 +1,294 @@ +local M = {} + + +local opt = { + method = 'select', + view = 'cursor', +} + +M.Translate = function(opts) + local res = get_query_res(opts.method) + -- TODO <++> +end + +-- M.Translate_online = function () +-- -- TOOD +-- end + + +-- local win = 0 +-- local line = 0 +-- local pos_info = {} +-- +-- local handler = {} +-- api.nvim_buf_set_option(buf, 'filetype', 'Trans') +-- +-- local function show_win(width, height) +-- end +-- +-- -- NOTE title +-- handler.title = function(text, query_res) +-- local title = ('%s [%s] %s %s'):format( +-- query_res.word, +-- query_res.phonetic, +-- (display.oxford and (query_res.oxford == 1 and icon.isOxford or icon.notOxford) or ''), +-- ((display.collins_star and query_res.collins) and string.rep(icon.star, query_res.collins) or '') +-- ) +-- table.insert(text, title) +-- +-- pos_info.title = {} +-- pos_info.title.word = #query_res.word +-- pos_info.title.phonetic = query_res.phonetic and #query_res.phonetic or 3 +-- pos_info.title.line = line +-- line = line + 1 +-- end +-- +-- -- NOTE tag +-- handler.tag = function(text, query_res) +-- if query_res.tag and #query_res.tag > 0 then +-- local tag = query_res.tag:gsub('zk', '中考'):gsub('gk', '高考'):gsub('ky', '考研'):gsub('cet4', '四级'): +-- gsub('cet6', '六级'):gsub('ielts', '雅思'):gsub('toefl', '托福'):gsub('gre', 'GRE') +-- +-- table.insert(text, '标签:') +-- table.insert(text, ' ' .. tag) +-- table.insert(text, '') +-- +-- pos_info.tag = line +-- line = line + 3 +-- end +-- end +-- +-- -- NOTE pos 词性 +-- handler.pos = function(text, query_res) +-- if query_res.pos and #query_res.pos > 0 then +-- table.insert(text, '词性:') +-- +-- local content = 0 +-- for v in vim.gsplit(query_res.pos, [[/]]) do +-- table.insert(text, string.format(' %s', v .. '%')) +-- content = content + 1 +-- end +-- +-- table.insert(text, '') +-- +-- pos_info.pos = {} +-- pos_info.pos.line = line +-- pos_info.pos.content = content +-- line = line + content + 2 +-- end +-- end +-- +-- -- NOTE exchange +-- handler.exchange = function(text, query_res) +-- if query_res.exchange and #query_res.exchange > 0 then +-- table.insert(text, '词形变化:') +-- +-- local exchange_map = { +-- p = '过去式', +-- d = '过去分词', +-- i = '现在分词', +-- r = '形容词比较级', +-- t = '形容词最高级', +-- s = '名词复数形式', +-- O = '词干', +-- ['3'] = '第三人称单数', +-- } +-- +-- local content = 0 +-- for v in vim.gsplit(query_res.exchange, [[/]]) do +-- table.insert(text, string.format(' %s: %s', exchange_map[v:sub(1, 1)], v:sub(3))) +-- content = content + 1 +-- -- FIXME: 中文字符与字母位宽不一致, 暂时无法对齐 +-- end +-- table.insert(text, '') +-- +-- pos_info.exchange = {} +-- pos_info.exchange.line = line +-- pos_info.exchange.content = content +-- line = line + content + 2 +-- end +-- end +-- +-- -- NOTE 中文翻译 +-- handler.zh = function(text, query_res) +-- if query_res.translation then +-- table.insert(text, '中文翻译:') +-- +-- local content = 0 +-- for v in vim.gsplit(query_res.translation, '\n') do +-- table.insert(text, ' ' .. v) +-- content = content + 1 +-- end +-- table.insert(text, '') +-- +-- pos_info.zh = {} +-- pos_info.zh.line = line +-- pos_info.zh.content = content +-- line = content + line + 2 +-- end +-- end +-- +-- -- NOTE 英文翻译 +-- handler.en = function(text, query_res) +-- if query_res.definition and #query_res.definition > 0 then +-- table.insert(text, '英文翻译:') +-- +-- local content = 0 +-- for v in vim.gsplit(query_res.definition, '\n') do +-- table.insert(text, ' ' .. v) +-- content = content + 1 +-- end +-- table.insert(text, '') +-- +-- pos_info.en = {} +-- pos_info.en.line = line +-- pos_info.en.content = content +-- line = line + content + 2 +-- end +-- end +-- +-- -- @return string array +-- local function get_text(query_res) +-- local text = {} +-- for _, v in ipairs(order) do +-- handler[v](text, query_res) +-- end +-- return text +-- end +-- +-- local function set_text(query_res) +-- local text = query_res and get_text(query_res) or { '没有找到相关定义' } +-- +-- api.nvim_buf_set_lines(buf, 0, -1, false, text) +-- local width = 0 +-- for _, v in ipairs(text) do +-- if #v > width then +-- width = v:len() +-- end +-- end +-- return width, #text +-- end +-- +-- local hl_handler = {} +-- +-- hl_handler.title = function() +-- api.nvim_buf_add_highlight(buf, -1, hl.word, pos_info.title.line, 0, pos_info.title.word) +-- api.nvim_buf_add_highlight(buf, -1, hl.phonetic, pos_info.title.line, pos_info.title.word + 5, +-- pos_info.title.word + 5 + pos_info.title.phonetic) +-- end +-- +-- hl_handler.tag = function() +-- if pos_info.tag then +-- api.nvim_buf_add_highlight(buf, -1, hl.ref, pos_info.tag, 0, -1) +-- api.nvim_buf_add_highlight(buf, -1, hl.tag, pos_info.tag + 1, 0, -1) +-- end +-- end +-- +-- hl_handler.pos = function() +-- if pos_info.pos then +-- api.nvim_buf_add_highlight(buf, -1, hl.ref, pos_info.pos.line, 0, -1) +-- for i = 1, pos_info.pos.content, 1 do +-- api.nvim_buf_add_highlight(buf, -1, hl.pos, pos_info.pos.line + i, 0, -1) +-- end +-- end +-- end +-- +-- hl_handler.exchange = function() +-- if pos_info.exchange then +-- api.nvim_buf_add_highlight(buf, -1, hl.ref, pos_info.exchange.line, 0, -1) +-- for i = 1, pos_info.exchange.content, 1 do +-- api.nvim_buf_add_highlight(buf, -1, hl.exchange, pos_info.exchange.line + i, 0, -1) +-- end +-- end +-- end +-- +-- hl_handler.zh = function() +-- api.nvim_buf_add_highlight(buf, -1, hl.ref, pos_info.zh.line, 0, -1) +-- for i = 1, pos_info.zh.content, 1 do +-- api.nvim_buf_add_highlight(buf, -1, hl.zh, pos_info.zh.line + i, 0, -1) +-- end +-- end +-- +-- hl_handler.en = function() +-- if pos_info.en then +-- api.nvim_buf_add_highlight(buf, -1, hl.ref, pos_info.en.line, 0, -1) +-- for i = 1, pos_info.en.content, 1 do +-- api.nvim_buf_add_highlight(buf, -1, hl.en, pos_info.en.line + i, 0, -1) +-- end +-- end +-- end +-- +-- +-- local function set_hl() +-- for _, v in ipairs(order) do +-- hl_handler[v]() +-- end +-- end +-- +-- local function clear_tmp_info() +-- pos_info = {} +-- line = 0 +-- end +-- +-- +-- function M.query(mode) +-- assert(buf > 0) +-- local word = '' +-- if mode == 'n' then +-- word = vim.fn.expand('<cword>') +-- elseif mode == 'v' then +-- word = get_visual_selection() +-- elseif mode == 'I' then +-- word = vim.fn.input('请输入您要查询的单词: ') +-- -- vim.ui.input({prompt = '请输入您要查询的单词: '}, function (input) +-- -- word = input +-- -- end) +-- else +-- error('mode argument is invalid') +-- end +-- +-- local res = require("Trans.database").query(word) +-- local width, height = set_text(res) +-- show_win(width, height) +-- if res then +-- set_hl() +-- clear_tmp_info() +-- end +-- +-- if auto_close then +-- api.nvim_create_autocmd( +-- { 'InsertEnter', 'CursorMoved', 'BufLeave', }, { +-- buffer = 0, +-- once = true, +-- callback = M.close_win, +-- }) +-- end +-- end +-- +-- function M.query_cursor() +-- M.query('n') +-- end +-- +-- function M.query_select() +-- M.query('v') +-- end +-- +-- function M.query_input() +-- M.query('I') +-- end +-- +-- function M.close_win() +-- if win > 0 then +-- api.nvim_win_close(win, true) +-- win = 0 +-- end +-- end +-- +-- -- function M.enter_win() +-- -- if api.nvim_win_is_valid(win) then +-- -- else +-- -- error('current win is not valid') +-- -- end +-- -- end +-- +-- return M diff --git a/lua/Trans/core/process.lua b/lua/Trans/core/process.lua index f5ff007..71f91fa 100644 --- a/lua/Trans/core/process.lua +++ b/lua/Trans/core/process.lua @@ -1,21 +1,35 @@ local type_check = require("Trans.util.debug").type_check -local format = require("Trans.util.format") --- NOTE : 将请求得到的字段进行处理 --- local offline_dir = debug.getinfo(1, "S").source:sub(2):match('.*Trans') .. '/component/offline' +local function format(items, interval) + +end + + local function process (opts) type_check { - opts = { opts, 'table' } + opts = { opts, 'table' }, + ['opts.field'] = { opts.field, 'table' }, + ['opts.order'] = { opts.order, 'table' }, + ['opts.win'] = { opts.win, 'table' }, + ['opts.engine'] = { opts.engine, 'table' }, } + local content = require('Trans.component.content'):new() for _, v in ipairs(opts.order) do - local component = format.format(opts.win_style, require("Trans.component" .. opts.engine .. v)) - content:insert(component) + local items = format(require("Trans.component." .. opts.engine .. '.' .. v), 4) + content:insert(items) end - return content:lines() + local lines, __highlight = content:data() + vim.api.nvim_buf_set_lines(opts.bufnr, 0, lines) + + for line, l_hl in ipairs(__highlight) do + for _, hl in ipairs(l_hl) do + vim.api.nvim_buf_add_highlight(opts.bufnr, line, hl.name, hl._start, hl._end) + end + end end diff --git a/lua/Trans/core/query.lua b/lua/Trans/core/query.lua index ed53437..dac837a 100644 --- a/lua/Trans/core/query.lua +++ b/lua/Trans/core/query.lua @@ -1,7 +1,5 @@ -local M = {} - local type_check = require("Trans.util.debug").type_check -local query = require("Trans.database").query +local query = require("Trans.api").query local function get_select() local s_start = vim.fn.getpos("'<") @@ -14,44 +12,29 @@ local function get_select() return word end - -local function get_word(method) - if not method then - local mode = vim.api.nvim_get_mode() - if mode == 'n' then - return vim.fn.expand('<cword>') - elseif mode == 'v' then - return get_select() - else - error('invalid mode') - end - end - - if method == 'input' then - return vim.fn.input('请输入您要查询的单词:') -- TODO Use Telescope with fuzzy finder - - -- TODO : other method - else - error('invalid method') - end -end - -M.get_query_res = function(method) +local query_wrapper = function(opts) type_check { - method = { method, 'string' }, + opts = { opts, 'table' }, + ['opts.method'] = { opts.method, 'string' }, } + local word = '' - if method == 'cursor' then + + if opts.method == 'input' then + word = vim.fn.input('请输入您要查询的单词:') -- TODO Use Telescope with fuzzy finder + + elseif opts.method == 'n' then word = vim.fn.expand('<cword>') - elseif method == 'select' then - word = get_select():match('%S+') - elseif method == 'input' then + + elseif opts.mehotd == 'v' then + word = get_select() + -- TODO : other method + else - error('unknown method') + error('invalid method' .. opts.method) end return query(word) end - -return M +return query_wrapper diff --git a/lua/Trans/core/show_win.lua b/lua/Trans/core/show_win.lua index 7c17fa3..be06838 100644 --- a/lua/Trans/core/show_win.lua +++ b/lua/Trans/core/show_win.lua @@ -1,10 +1,5 @@ local type_check = require("Trans.util.debug").type_check -local buf_opts = { - filetype = 'Trans', - modifiable = false, -} - -- local win_opts = { -- winhl = 'Normal:TransWinNormal, FloatBorder:TransWinBorder' -- } @@ -15,25 +10,22 @@ local function caculate_format(height, width) return row, col end + local function show_win(opts) type_check { opts = { opts, 'table' }, win = { opts.win, 'table' }, + border = { opts.border, 'string' }, highlight = { opts.highlight, 'table', true }, } - local bufnr = vim.api.nvim_create_buf(false, true) - for k, v in pairs(buf_opts) do - vim.api.nvim_buf_set_option(bufnr, k, v) - end - local is_float = opts.style == 'float' local win_opts = { relative = opts.style == 'float' and 'editor' or 'cursor', width = opts.width, height = opts.height, style = 'minimal', - border = 'rounded', + border = opts.border, title = 'Trans', title_pos = 'center', focusable = true, @@ -45,8 +37,17 @@ local function show_win(opts) win_opts.row = 2 win_opts.col = 2 end + local winid = vim.api.nvim_open_win(bufnr, is_float, win_opts) + vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, opts.lines) + + for line, l_hl in ipairs(opts.highlight) do + for i, hl in ipairs(l_hl) do + vim.api.nvim_buf_add_highlight(bufnr, line, hl.name, i, hl._start, hl._end) + end + end + return bufnr, winid end diff --git a/lua/Trans/core/translate.lua b/lua/Trans/core/translate.lua index fb8cd0e..af88e91 100644 --- a/lua/Trans/core/translate.lua +++ b/lua/Trans/core/translate.lua @@ -1,294 +1,110 @@ -local M = {} +-- Default conf +local conf = require("Trans.conf.loader").loaded_conf +local core = require("Trans.core") -local opt = { - method = 'select', - view = 'cursor', -} +local function get_opts(opts) + local default_conf = { + method = vim.api.nvim_get_mode().mode, + engine = { + 'local', + -- TODO : other engine + }, + win = { + style = 'cursor', + width = conf.style.window.cursor.width, + height = conf.style.window.cursor.height + }, + } -M.Translate = function(opts) - local res = get_query_res(opts.method) - -- TODO <++> + if type(opts.engine) == 'string' then + opts.engine = { opts.engine } + end + + if opts.win then + local width, height = opts.win.width, opts.win.height + if width and width > 0 and width <= 1 then + opts.win.width = math.floor(vim.o.columns * width) + end + + if height and height > 0 and height <= 1 then + opts.win.height = math.floor(vim.o.lines * opts.win.height) + end + end + + return vim.tbl_extend('force', default_conf, opts) end --- M.Translate_online = function () --- -- TOOD --- end +-- EXAMPLE : +-- require('Trans').translate({ +-- method = 'input', -- 不填则自动判断mode获取查询的单词 +-- engine = { -- 异步查询所有的引擎, 按照列表 +-- 'offline', +-- 'youdao', +-- 'baidu' +-- }, +-- -- win = 'cursor' +-- win = { +-- style = 'cursor', +-- height = 50, +-- width = 30, +-- } +-- }) --- local win = 0 --- local line = 0 --- local pos_info = {} --- --- local handler = {} --- api.nvim_buf_set_option(buf, 'filetype', 'Trans') --- --- local function show_win(width, height) --- end --- --- -- NOTE title --- handler.title = function(text, query_res) --- local title = ('%s [%s] %s %s'):format( --- query_res.word, --- query_res.phonetic, --- (display.oxford and (query_res.oxford == 1 and icon.isOxford or icon.notOxford) or ''), --- ((display.collins_star and query_res.collins) and string.rep(icon.star, query_res.collins) or '') --- ) --- table.insert(text, title) --- --- pos_info.title = {} --- pos_info.title.word = #query_res.word --- pos_info.title.phonetic = query_res.phonetic and #query_res.phonetic or 3 --- pos_info.title.line = line --- line = line + 1 --- end --- --- -- NOTE tag --- handler.tag = function(text, query_res) --- if query_res.tag and #query_res.tag > 0 then --- local tag = query_res.tag:gsub('zk', '中考'):gsub('gk', '高考'):gsub('ky', '考研'):gsub('cet4', '四级'): --- gsub('cet6', '六级'):gsub('ielts', '雅思'):gsub('toefl', '托福'):gsub('gre', 'GRE') --- --- table.insert(text, '标签:') --- table.insert(text, ' ' .. tag) --- table.insert(text, '') --- --- pos_info.tag = line --- line = line + 3 --- end --- end --- --- -- NOTE pos 词性 --- handler.pos = function(text, query_res) --- if query_res.pos and #query_res.pos > 0 then --- table.insert(text, '词性:') --- --- local content = 0 --- for v in vim.gsplit(query_res.pos, [[/]]) do --- table.insert(text, string.format(' %s', v .. '%')) --- content = content + 1 --- end --- --- table.insert(text, '') --- --- pos_info.pos = {} --- pos_info.pos.line = line --- pos_info.pos.content = content --- line = line + content + 2 --- end --- end --- --- -- NOTE exchange --- handler.exchange = function(text, query_res) --- if query_res.exchange and #query_res.exchange > 0 then --- table.insert(text, '词形变化:') --- --- local exchange_map = { --- p = '过去式', --- d = '过去分词', --- i = '现在分词', --- r = '形容词比较级', --- t = '形容词最高级', --- s = '名词复数形式', --- O = '词干', --- ['3'] = '第三人称单数', --- } --- --- local content = 0 --- for v in vim.gsplit(query_res.exchange, [[/]]) do --- table.insert(text, string.format(' %s: %s', exchange_map[v:sub(1, 1)], v:sub(3))) --- content = content + 1 --- -- FIXME: 中文字符与字母位宽不一致, 暂时无法对齐 --- end --- table.insert(text, '') --- --- pos_info.exchange = {} --- pos_info.exchange.line = line --- pos_info.exchange.content = content --- line = line + content + 2 --- end --- end --- --- -- NOTE 中文翻译 --- handler.zh = function(text, query_res) --- if query_res.translation then --- table.insert(text, '中文翻译:') --- --- local content = 0 --- for v in vim.gsplit(query_res.translation, '\n') do --- table.insert(text, ' ' .. v) --- content = content + 1 --- end --- table.insert(text, '') --- --- pos_info.zh = {} --- pos_info.zh.line = line --- pos_info.zh.content = content --- line = content + line + 2 --- end --- end --- --- -- NOTE 英文翻译 --- handler.en = function(text, query_res) --- if query_res.definition and #query_res.definition > 0 then --- table.insert(text, '英文翻译:') --- --- local content = 0 --- for v in vim.gsplit(query_res.definition, '\n') do --- table.insert(text, ' ' .. v) --- content = content + 1 --- end --- table.insert(text, '') --- --- pos_info.en = {} --- pos_info.en.line = line --- pos_info.en.content = content --- line = line + content + 2 --- end --- end --- --- -- @return string array --- local function get_text(query_res) --- local text = {} --- for _, v in ipairs(order) do --- handler[v](text, query_res) --- end --- return text --- end --- --- local function set_text(query_res) --- local text = query_res and get_text(query_res) or { '没有找到相关定义' } --- --- api.nvim_buf_set_lines(buf, 0, -1, false, text) --- local width = 0 --- for _, v in ipairs(text) do --- if #v > width then --- width = v:len() --- end --- end --- return width, #text --- end --- --- local hl_handler = {} --- --- hl_handler.title = function() --- api.nvim_buf_add_highlight(buf, -1, hl.word, pos_info.title.line, 0, pos_info.title.word) --- api.nvim_buf_add_highlight(buf, -1, hl.phonetic, pos_info.title.line, pos_info.title.word + 5, --- pos_info.title.word + 5 + pos_info.title.phonetic) --- end --- --- hl_handler.tag = function() --- if pos_info.tag then --- api.nvim_buf_add_highlight(buf, -1, hl.ref, pos_info.tag, 0, -1) --- api.nvim_buf_add_highlight(buf, -1, hl.tag, pos_info.tag + 1, 0, -1) --- end --- end --- --- hl_handler.pos = function() --- if pos_info.pos then --- api.nvim_buf_add_highlight(buf, -1, hl.ref, pos_info.pos.line, 0, -1) --- for i = 1, pos_info.pos.content, 1 do --- api.nvim_buf_add_highlight(buf, -1, hl.pos, pos_info.pos.line + i, 0, -1) --- end --- end --- end --- --- hl_handler.exchange = function() --- if pos_info.exchange then --- api.nvim_buf_add_highlight(buf, -1, hl.ref, pos_info.exchange.line, 0, -1) --- for i = 1, pos_info.exchange.content, 1 do --- api.nvim_buf_add_highlight(buf, -1, hl.exchange, pos_info.exchange.line + i, 0, -1) --- end --- end --- end --- --- hl_handler.zh = function() --- api.nvim_buf_add_highlight(buf, -1, hl.ref, pos_info.zh.line, 0, -1) --- for i = 1, pos_info.zh.content, 1 do --- api.nvim_buf_add_highlight(buf, -1, hl.zh, pos_info.zh.line + i, 0, -1) --- end --- end --- --- hl_handler.en = function() --- if pos_info.en then --- api.nvim_buf_add_highlight(buf, -1, hl.ref, pos_info.en.line, 0, -1) --- for i = 1, pos_info.en.content, 1 do --- api.nvim_buf_add_highlight(buf, -1, hl.en, pos_info.en.line + i, 0, -1) --- end --- end --- end --- --- --- local function set_hl() --- for _, v in ipairs(order) do --- hl_handler[v]() --- end --- end --- --- local function clear_tmp_info() --- pos_info = {} --- line = 0 --- end --- --- --- function M.query(mode) --- assert(buf > 0) --- local word = '' --- if mode == 'n' then --- word = vim.fn.expand('<cword>') --- elseif mode == 'v' then --- word = get_visual_selection() --- elseif mode == 'I' then --- word = vim.fn.input('请输入您要查询的单词: ') --- -- vim.ui.input({prompt = '请输入您要查询的单词: '}, function (input) --- -- word = input --- -- end) --- else --- error('mode argument is invalid') --- end --- --- local res = require("Trans.database").query(word) --- local width, height = set_text(res) --- show_win(width, height) --- if res then --- set_hl() --- clear_tmp_info() --- end --- --- if auto_close then --- api.nvim_create_autocmd( --- { 'InsertEnter', 'CursorMoved', 'BufLeave', }, { --- buffer = 0, --- once = true, --- callback = M.close_win, --- }) --- end --- end --- --- function M.query_cursor() --- M.query('n') --- end --- --- function M.query_select() --- M.query('v') --- end --- --- function M.query_input() --- M.query('I') --- end --- --- function M.close_win() --- if win > 0 then --- api.nvim_win_close(win, true) --- win = 0 --- end --- end --- --- -- function M.enter_win() --- -- if api.nvim_win_is_valid(win) then --- -- else --- -- error('current win is not valid') --- -- end --- -- end --- --- return M +local function create_win(opts) + local bufnr = vim.api.nvim_create_buf(false, true) + vim.api.nvim_buf_set_option(bufnr, 'filetype', 'Trans') + vim.api.nvim_buf_set_option(bufnr, 'modifiable', false) + + local is_float = opts.style == 'float' + local win_opts = { + relative = is_float and 'editor' or 'cursor', + width = opts.width, + height = opts.height, + style = 'minimal', + border = conf.style.window[opts.win.style].border, + title = 'Trans', + title_pos = 'center', + focusable = true, + zindex = 100, + } + + if is_float then + win_opts.row = math.floor((vim.o.lines - win_opts.height - vim.o.cmdheight) / 2) + win_opts.col = math.floor((vim.o.columns - win_opts.width) / 2) + else + win_opts.row = 2 + win_opts.col = 2 + end + + local winid = vim.api.nvim_open_win(bufnr, is_float, win_opts) + + return bufnr, winid +end + +local function translate(opts) + vim.validate { + opts = { opts, 'table', true } + } + + --- TODO : 异步请求 + -- NOTE : 这里只处理了本地数据库查询 + opts = get_opts(opts or {}) + local field = core.query(opts) + + local bufnr, winid = create_win(opts.win) + + local proc_opts = { + bufnr = bufnr, + winid = winid, + field = field, + order = conf.order['offline'], + engine = { 'offline' }, + win_opts = opts.win, + } + + core.process(proc_opts) +end + +return translate diff --git a/lua/Trans/init.lua b/lua/Trans/init.lua index 380e4fb..317547b 100644 --- a/lua/Trans/init.lua +++ b/lua/Trans/init.lua @@ -1,7 +1,12 @@ local M = {} -M.setup = require('Trans.conf.loader').load_conf +M.setup = function(opts) + require('Trans.conf.loader').load_conf(opts) + require("Trans.setup") + M.translate = require('Trans.core.translate') +end -M.translate = require('Tran.core.translate') +M.translate = nil +M.augroup = vim.api.nvim_create_augroup('Trans', {clear = true}) return M diff --git a/lua/Trans/setup.lua b/lua/Trans/setup.lua index 9bf3250..2e0acb8 100644 --- a/lua/Trans/setup.lua +++ b/lua/Trans/setup.lua @@ -2,17 +2,24 @@ if vim.fn.executable('sqlite3') ~= 1 then error('Please check out sqlite3') end -vim.api.nvim_create_user_command('TranslateCursorWord', require("Trans.core").query_cursor, { - desc = '翻译光标下的单词', -}) -vim.api.nvim_create_user_command('TranslateSelectWord', require("Trans.core").query_select, { - desc = '翻译选中的单词', -}) -vim.api.nvim_create_user_command('TranslateInputWord', require("Trans.core").query_input, { - desc = '翻译输入的单词', +vim.api.nvim_create_user_command('Translate', function () + require("Trans").translate() +end, { + desc = '翻译单词', }) -local highlights = require("Trans.conf").ui.highligh +vim.api.nvim_create_user_command('TranslateInput', function () + require("Trans").translate { + method = 'input', + } +end, {desc = '翻译单词'}) + +-- TODO +-- vim.api.nvim_create_user_command('TranslateHistory', require("Trans.core").query_input, { +-- desc = '翻译输入的单词', +-- }) + +local highlights = require("Trans.conf.loader").loaded_conf.ui.highlight for highlight, opt in pairs(highlights) do - vim.nvim_set_hl(0, highlight, opt) + vim.api.nvim_set_hl(0, highlight, opt) end diff --git a/lua/Trans/util/debug.lua b/lua/Trans/util/debug.lua index 58cb855..3088acd 100644 --- a/lua/Trans/util/debug.lua +++ b/lua/Trans/util/debug.lua @@ -1,17 +1,14 @@ local M = {} -- INFO : get loaded debug conf -local base = require("Trans.conf.loader").loaded_conf.base -local debug = require("Trans.conf.default").conf.base.debug -if base and base.debug then - debug = vim.tbl_extend('force', debug, base) -end +local type_check = true M.type_check = function (types) - if debug.enable and debug.type_check then + if type_check then vim.validate(types) end end + -- local function dedent(lines) -- local ind_size = math.huge -- for i, _ in ipairs(lines) do diff --git a/lua/Trans/util/format.lua b/lua/Trans/util/format.lua index e3c520d..bdc4bec 100644 --- a/lua/Trans/util/format.lua +++ b/lua/Trans/util/format.lua @@ -143,10 +143,10 @@ end ---@alias formatted_items table ---将组件格式化成相应的vim支持的lines格式 ----@param style string 窗口的风格 +---@param win_size string 窗口的宽度和高度 ---@param component table 需要格式化的字段 ---@return formatted_items[] lines -M.format = function(style, component) +M.format = function(win_width, component) type_check { style = { style, { 'string' } }, component = { component, { 'table' } }, @@ -161,19 +161,16 @@ M.format = function(style, component) length = length + width end - m_win_width = style_width[style] - m_indent + m_win_width = win_width m_fields = fields m_size = #m_fields m_tot_width = length m_item_width = item_size - m_interval = m_win_width > 50 and 6 or 4 return formatted_lines() end - - ---合并多个数组, 第一个数组将会被使用 ---@param ... string[] 需要被合并的数组 ---@return table res 合并后的数组 diff --git a/lua/Trans/util/test/test.lua b/lua/Trans/util/test/test.lua index fa4d1e9..7fa1b76 100644 --- a/lua/Trans/util/test/test.lua +++ b/lua/Trans/util/test/test.lua @@ -1,5 +1,8 @@ -local a = nil +local a = 'test' +local b = a -print((' '):rep(a)) +b = b .. 'test' + +print(a, b) diff --git a/lua/Trans/wrapper/translate.lua b/lua/Trans/wrapper/translate.lua deleted file mode 100644 index 4cbffd3..0000000 --- a/lua/Trans/wrapper/translate.lua +++ /dev/null @@ -1,67 +0,0 @@ -local type_check = require("Trans.util.debug").type_check --- Default conf -local conf = require("Trans.conf.loader").loaded_conf -local core = require("Trasn.core") - - -local function get_opts(opts) - local default_conf = { - method = vim.api.nvim_get_mode(), - engine = { - 'local', - -- TODO : other engine - }, - win = { - style = 'cursor', - width = conf.window.cursor.width, - height = conf.window.cursor.height - }, - } - - if type(opts.engine) == 'string' then - opts.engine = { opts.engine } - end - - if opts.win then - local width, height = opts.win.width, opts.win.height - if width and width > 0 and width <= 1 then - opts.win.width = math.floor(vim.o.columns * width) - end - - if height and height > 0 and height <= 1 then - opts.win.height = math.floor(vim.o.lines * opts.win.height) - end - end - - return vim.tbl_extend('force', default_conf, opts) -end - -local function translate(opts) - type_check { - opts = { opts, 'table' } - } - - --- TODO : 异步请求 - -- NOTE : 这里只处理了本地的请求 - opts = get_opts(opts or {}) - local field = core.query(opts) - - local proc_opts = { - field = field, - order = conf.order['offline'], - engine = 'offline', - win_style = opts.win.style, - } - - local content, highlight = core.process(proc_opts) - - local win_opts = { - win = opts.win, - content = content, - highlight = highlight, - } - - core.show_win(win_opts) -end - -return translate From 671e3cc7e76cad99dc43beba57dffdb7737e972a Mon Sep 17 00:00:00 2001 From: JuanZoran <1430359574@qq.com> Date: Mon, 9 Jan 2023 23:49:16 +0800 Subject: [PATCH 13/17] feat: add more bugs --- lua/Trans/component/content.lua | 1 + lua/Trans/component/items.lua | 20 ++++++++++++++++++++ lua/Trans/core/process.lua | 17 ++++++++++------- lua/Trans/util/test/test.lua | 10 +++++----- 4 files changed, 36 insertions(+), 12 deletions(-) create mode 100644 lua/Trans/component/items.lua diff --git a/lua/Trans/component/content.lua b/lua/Trans/component/content.lua index 3c6f907..86c7e3b 100644 --- a/lua/Trans/component/content.lua +++ b/lua/Trans/component/content.lua @@ -38,6 +38,7 @@ function M:insert(items) indent = items.indent, highlight = items.highlight, } + local highlight = {} diff --git a/lua/Trans/component/items.lua b/lua/Trans/component/items.lua new file mode 100644 index 0000000..d1c775e --- /dev/null +++ b/lua/Trans/component/items.lua @@ -0,0 +1,20 @@ +local M = {} +M.__index = M +M.len = 0 + +function M:new() + local items = {} + setmetatable(items, self) + return items +end + +function M:insert(item, highlight) + table.insert(self, item) + self.len = self.len + #item +end + +function M:format(win_width) + +end + +return M diff --git a/lua/Trans/core/process.lua b/lua/Trans/core/process.lua index 71f91fa..dd2ef48 100644 --- a/lua/Trans/core/process.lua +++ b/lua/Trans/core/process.lua @@ -1,25 +1,28 @@ local type_check = require("Trans.util.debug").type_check -local function format(items, interval) +local function format(component, interval) end local function process (opts) type_check { opts = { opts, 'table' }, - ['opts.field'] = { opts.field, 'table' }, - ['opts.order'] = { opts.order, 'table' }, - ['opts.win'] = { opts.win, 'table' }, - ['opts.engine'] = { opts.engine, 'table' }, + ['opts.field'] = { opts.field , 'table' }, + ['opts.order'] = { opts.order , 'table' }, + ['opts.win'] = { opts.win , 'table' }, + ['opts.engine'] = { opts.engine , 'table' }, } local content = require('Trans.component.content'):new() for _, v in ipairs(opts.order) do - local items = format(require("Trans.component." .. opts.engine .. '.' .. v), 4) - content:insert(items) + local component = require("Trans.component." .. opts.engine .. '.' .. v) + for _, items in ipairs(component) do + format(items) + content:insert(items) + end end local lines, __highlight = content:data() diff --git a/lua/Trans/util/test/test.lua b/lua/Trans/util/test/test.lua index 7fa1b76..a5bd3c3 100644 --- a/lua/Trans/util/test/test.lua +++ b/lua/Trans/util/test/test.lua @@ -1,8 +1,8 @@ -local a = 'test' +local a = { + 'test1', + 'test2', + 'test3' +} -local b = a - -b = b .. 'test' - print(a, b) From 1b95485ae68439e1833a30e32cecb731cfb66973 Mon Sep 17 00:00:00 2001 From: JuanZoran <1430359574@qq.com> Date: Tue, 10 Jan 2023 14:40:28 +0800 Subject: [PATCH 14/17] fix: try reducing some bugs --- lua/Trans/component/content.lua | 1 + lua/Trans/component/offline/Title.lua | 21 ++-- lua/Trans/conf/default.lua | 2 +- lua/Trans/core/process.lua | 132 +++++++++++++++++++++++--- lua/Trans/core/translate.lua | 16 ++-- lua/Trans/util/format.lua | 1 - lua/Trans/util/test/query_youdao.lua | 23 +++-- lua/Trans/util/test/test.lua | 12 ++- 8 files changed, 163 insertions(+), 45 deletions(-) diff --git a/lua/Trans/component/content.lua b/lua/Trans/component/content.lua index 86c7e3b..7adc86a 100644 --- a/lua/Trans/component/content.lua +++ b/lua/Trans/component/content.lua @@ -69,6 +69,7 @@ function M:data() -- NOTE 返回格式化的行,如果需要高亮,则第二个参数返回高亮 local lines = {} local highlights = {} + for index = 1, #self.lines do local line = '' local highlight = {} diff --git a/lua/Trans/component/offline/Title.lua b/lua/Trans/component/offline/Title.lua index d02eb69..c1203a8 100644 --- a/lua/Trans/component/offline/Title.lua +++ b/lua/Trans/component/offline/Title.lua @@ -37,15 +37,15 @@ local icon = require("Trans.conf.loader").loaded_conf.ui.icon ---@return component component 提取的组件信息[包含多个组件] M.component = function(field) local component = {} - local stuffs = {} local data = { - {field.word, 'TransWord'}, + { field.word, 'TransWord' }, } - if display.phonetic and field.phonetic then - table.insert(data, { - '[' .. field.phonetic .. ']', 'TransPhonetic' - }) + if display.phnoetic and field.phonetic ~= '' then + table.insert( + data, + { '[' .. field.phonetic .. ']', 'TransPhonetic' } + ) end if display.collins and field.collins then @@ -55,13 +55,12 @@ M.component = function(field) end if display.oxford and field.oxford then - table.insert(data, { - field.oxford - }) + table.insert(data, + { field.oxford == 1 and icon.isOxford or icon.notOxford, } + ) end - stuffs.data = data - component[1] = stuffs + component[1] = data return component end diff --git a/lua/Trans/conf/default.lua b/lua/Trans/conf/default.lua index 5e92c18..4518665 100644 --- a/lua/Trans/conf/default.lua +++ b/lua/Trans/conf/default.lua @@ -75,7 +75,7 @@ M.conf = { }, display = { phnoetic = true, - collins_star = true, + collins = true, oxford = true, -- TODO -- history = false, diff --git a/lua/Trans/core/process.lua b/lua/Trans/core/process.lua index dd2ef48..82df19b 100644 --- a/lua/Trans/core/process.lua +++ b/lua/Trans/core/process.lua @@ -1,39 +1,145 @@ local type_check = require("Trans.util.debug").type_check +-- NOTE :中文字符及占两个字节宽,但是在lua里是3个字节长度 +-- 为了解决中文字符在lua的长度和neovim显示不一致的问题 +local function get_width(str) + if type(str) ~= 'string' then + vim.pretty_print(str) + error('str!') + end + return vim.fn.strdisplaywidth(str) +end + +local function format(win_width, items) + table.sort(items, function(a, b) + local wa, wb = 0, 0 + if type(a) == 'string' then + wa = get_width(a) + a = { a } + else + wa = get_width(a[1]) + end + if type(b) == 'string' then + wb = get_width(b) + b = { b } + else + wb = get_width(b[1]) + end + return wa > wb + end) + + local size = #items + local width = win_width - get_width(items[1][1]) + local cols = 0 + for i = 2, size do + width = width - 4 - get_width(items[i][1]) + if width < 0 then + cols = i + break + end + end -local function format(component, interval) + if cols == 0 then + return items + else + local lines = {} + local rows = math.floor(size / cols) + local rest = size % cols + if rest == 0 then + rest = cols + end + + local max_width = get_width(items[1][1]) + for i = 1, rows do + local index = rows - i + 1 + lines[index] = { + interval = items.interval, + highlight = items.highlight, + indent = items.indent, + } + + items[i][1] = items[i][1] .. (' '):rep(max_width - get_width(items[i][1])) + lines[index][1] = items[i] + end + + local index = rows + 1 + for col = 2, cols do + max_width = get_width(items[index]) + local _end = col > rest and rows - 1 or rows + + for i = 1, _end do + local idx = _end - i + 1 -- 当前操作的行数 + local item_idx = index + i - 1 + local item = items[item_idx] + item[1] = item[1] .. (' '):rep(max_width - get_width(item[1])) + + + lines[idx][col] = item + end + index = index + _end + end + + return lines + end end -local function process (opts) +local function process(opts) type_check { - opts = { opts, 'table' }, - ['opts.field'] = { opts.field , 'table' }, - ['opts.order'] = { opts.order , 'table' }, - ['opts.win'] = { opts.win , 'table' }, - ['opts.engine'] = { opts.engine , 'table' }, + opts = { opts, 'table' }, + ['opts.field'] = { opts.field, 'table', true }, + ['opts.order'] = { opts.order, 'table' }, + ['opts.win'] = { opts.win, 'table' }, + ['opts.engine'] = { opts.engine, 'table' }, } + if opts.field == nil then + local lines = {'no tranlation'} + vim.api.nvim_buf_set_lines(opts.bufnr, 0, -1, false, lines) + return + end + + local content = require('Trans.component.content'):new() for _, v in ipairs(opts.order) do - local component = require("Trans.component." .. opts.engine .. '.' .. v) + local component = require("Trans.component." .. 'offline' --[[ opts.engine ]] .. '.' .. v).component(opts.field) + -- vim.pretty_print(component) + for _, items in ipairs(component) do - format(items) - content:insert(items) + local formatted_items, split = format(opts.win.width, items) + if split then + for _, itms in ipairs(formatted_items) do + content:insert(itms) + end + else + content:insert(formatted_items) + end end end local lines, __highlight = content:data() - vim.api.nvim_buf_set_lines(opts.bufnr, 0, lines) + vim.api.nvim_buf_set_lines(opts.bufnr, 0, -1, false, lines) + for line, l_hl in ipairs(__highlight) do for _, hl in ipairs(l_hl) do - vim.api.nvim_buf_add_highlight(opts.bufnr, line, hl.name, hl._start, hl._end) + vim.api.nvim_buf_add_highlight(opts.bufnr, -1, hl.name, line, hl._start, hl._end) end end + vim.api.nvim_buf_set_option(opts.bufnr, 'modifiable', false) + vim.api.nvim_buf_set_option(opts.bufnr, 'filetype', 'Trans') + if opts.win.style == 'cursor' then + vim.api.nvim_create_autocmd( + { 'InsertEnter', 'CursorMoved', 'BufLeave', }, { + buffer = 0, + once = true, + callback = function () + vim.api.nvim_win_close(opts.winid, true) + end, + }) + end end - return process diff --git a/lua/Trans/core/translate.lua b/lua/Trans/core/translate.lua index af88e91..b66b3c2 100644 --- a/lua/Trans/core/translate.lua +++ b/lua/Trans/core/translate.lua @@ -7,7 +7,7 @@ local function get_opts(opts) local default_conf = { method = vim.api.nvim_get_mode().mode, engine = { - 'local', + 'offline', -- TODO : other engine }, win = { @@ -52,18 +52,16 @@ end -- }) -local function create_win(opts) +local function create_win(win) local bufnr = vim.api.nvim_create_buf(false, true) - vim.api.nvim_buf_set_option(bufnr, 'filetype', 'Trans') - vim.api.nvim_buf_set_option(bufnr, 'modifiable', false) - local is_float = opts.style == 'float' + local is_float = win.style == 'float' local win_opts = { relative = is_float and 'editor' or 'cursor', - width = opts.width, - height = opts.height, + width = win.width, + height = win.height, style = 'minimal', - border = conf.style.window[opts.win.style].border, + border = conf.style.window[win.style].border, title = 'Trans', title_pos = 'center', focusable = true, @@ -98,10 +96,10 @@ local function translate(opts) local proc_opts = { bufnr = bufnr, winid = winid, + win = opts.win, field = field, order = conf.order['offline'], engine = { 'offline' }, - win_opts = opts.win, } core.process(proc_opts) diff --git a/lua/Trans/util/format.lua b/lua/Trans/util/format.lua index bdc4bec..b9c62fe 100644 --- a/lua/Trans/util/format.lua +++ b/lua/Trans/util/format.lua @@ -7,7 +7,6 @@ function string:width() return vim.fn.strdisplaywidth(self) end - local s_to_b = true -- 从小到大排列 local m_win_width -- 需要被格式化窗口的高度 diff --git a/lua/Trans/util/test/query_youdao.lua b/lua/Trans/util/test/query_youdao.lua index 1d064f8..8653e25 100644 --- a/lua/Trans/util/test/query_youdao.lua +++ b/lua/Trans/util/test/query_youdao.lua @@ -43,16 +43,21 @@ end -- curl --data {{'{"name":"bob"}'}} --header {{'Content-Type: application/json'}} {{http://example.com/users/1234}} local function query_word(q) - local field = ( - [[curl -s --header 'Content-Type: application/x-www-form-urlencoded' https://openapi.youdao.com/api]]) - for k, v in pairs(q) do - field = field .. ([[ -d '%s=%s']]):format(k, v) + local ok, curl = pcall(require, 'plenary.curl') + if ok then + -- TODO + else + local field = ( + [[curl -s --header 'Content-Type: application/x-www-form-urlencoded' https://openapi.youdao.com/api]]) + + for k, v in pairs(q) do + field = field .. ([[ -d '%s=%s']]):format(k, v) + end + + local output = vim.fn.system(field) + local tb = vim.fn.json_decode(output) + return tb end - -- vim.pretty_print(field) - local output = vim.fn.system(field) - local tb = vim.fn.json_decode(output) - -- print(type(output)) - -- vim.pretty_print(tb.basic) end M.test = function(query) diff --git a/lua/Trans/util/test/test.lua b/lua/Trans/util/test/test.lua index a5bd3c3..72af591 100644 --- a/lua/Trans/util/test/test.lua +++ b/lua/Trans/util/test/test.lua @@ -5,4 +5,14 @@ local a = { } -print(a, b) +local function test(tmp) + tmp = { + 'bbbbbb' + } +end + + +test(a) +for i, v in ipairs(a) do + print(v) +end From a57a6e47ab25a388257e50c61d38fce465f1e3e2 Mon Sep 17 00:00:00 2001 From: JuanZoran <1430359574@qq.com> Date: Tue, 10 Jan 2023 17:51:07 +0800 Subject: [PATCH 15/17] fix: fix format and process function behaviours --- lua/Trans/component/content.lua | 45 ++++- lua/Trans/component/offline/Definition.lua | 2 +- lua/Trans/component/offline/Exchange.lua | 2 +- lua/Trans/component/offline/Pos.lua | 2 +- lua/Trans/component/offline/Tag.lua | 44 ++++- lua/Trans/component/offline/Title.lua | 12 +- lua/Trans/component/offline/Translation.lua | 2 +- lua/Trans/conf/default.lua | 21 ++- lua/Trans/core/README.md | 2 +- lua/Trans/core/process.lua | 151 ++++++++-------- lua/Trans/core/query.lua | 21 ++- lua/Trans/core/translate.lua | 4 + lua/Trans/util/format.lua | 190 -------------------- lua/Trans/util/parser.lua | 19 -- 14 files changed, 193 insertions(+), 324 deletions(-) delete mode 100644 lua/Trans/util/format.lua delete mode 100644 lua/Trans/util/parser.lua diff --git a/lua/Trans/component/content.lua b/lua/Trans/component/content.lua index 7adc86a..9960e2d 100644 --- a/lua/Trans/component/content.lua +++ b/lua/Trans/component/content.lua @@ -3,7 +3,9 @@ local type_check = require("Trans.util.debug").type_check M.__index = M M.lines = {} M.highlight = {} -M.size = 0 +M.height = 0 +M.width = 0 +M.interval = ' ' function M:new() @@ -31,10 +33,9 @@ function M:insert(items) items = { items, 'table' }, } - self.size = self.size + 1 -- line数加一 + self.height = self.height + 1 -- line数加一 local line = { - space = (' '):rep(items.interval), indent = items.indent, highlight = items.highlight, } @@ -52,8 +53,8 @@ function M:insert(items) end end - self.highlight[self.size] = highlight - self.lines[self.size] = line + self.highlight[self.height] = highlight + self.lines[self.height] = line end ---Usage: @@ -78,9 +79,11 @@ function M:data() if l.indent then line = (' '):rep(l.indent) end + if l.highlight then - line = line .. table.concat(l, l.space) + line = line .. table.concat(l, self.interval) highlight[1] = { name = l.highlight, _start = 1, _end = -1 } + else line = line .. l[1] @@ -90,7 +93,7 @@ function M:data() end for i = 2, #l do - line = line .. l.space .. l[i] + line = line .. self.interval .. l[i] if hl[i] then local _end = #line table.insert(highlight, { name = hl[i], _start = _end - #l[i], _end = _end }) @@ -98,11 +101,37 @@ function M:data() end end - -- return line, highlights lines[index] = line + local len = #line + if self.width < len then + self.width = len + end highlights[index] = highlight end return lines, highlights end +function M:attach(bufnr, winid) + local height = vim.api.nvim_win_get_height(winid) + local width = vim.api.nvim_win_get_width(winid) + + vim.api.nvim_win_set_height(winid, self.height) + local lines, hls = self:data() + vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, lines) + + for line, l_hl in ipairs(hls) do + for _, hl in ipairs(l_hl) do + vim.api.nvim_buf_add_highlight(bufnr, -1, hl.name, line - 1, hl._start, hl._end) + end + end + + if self.height < height then + vim.api.nvim_win_set_height(winid, self.height) + end + + if self.width < width then + vim.api.nvim_win_set_width(winid, self.width) + end +end + return M diff --git a/lua/Trans/component/offline/Definition.lua b/lua/Trans/component/offline/Definition.lua index 94acd96..e557040 100644 --- a/lua/Trans/component/offline/Definition.lua +++ b/lua/Trans/component/offline/Definition.lua @@ -1,6 +1,6 @@ local M = {} -M.to_content = function (field) +M.component = function (field) -- TODO end diff --git a/lua/Trans/component/offline/Exchange.lua b/lua/Trans/component/offline/Exchange.lua index 94acd96..e557040 100644 --- a/lua/Trans/component/offline/Exchange.lua +++ b/lua/Trans/component/offline/Exchange.lua @@ -1,6 +1,6 @@ local M = {} -M.to_content = function (field) +M.component = function (field) -- TODO end diff --git a/lua/Trans/component/offline/Pos.lua b/lua/Trans/component/offline/Pos.lua index 94acd96..e557040 100644 --- a/lua/Trans/component/offline/Pos.lua +++ b/lua/Trans/component/offline/Pos.lua @@ -1,6 +1,6 @@ local M = {} -M.to_content = function (field) +M.component = function (field) -- TODO end diff --git a/lua/Trans/component/offline/Tag.lua b/lua/Trans/component/offline/Tag.lua index 94acd96..a95080f 100644 --- a/lua/Trans/component/offline/Tag.lua +++ b/lua/Trans/component/offline/Tag.lua @@ -1,7 +1,47 @@ local M = {} -M.to_content = function (field) - -- TODO +local tag_map = { + zk = '中考', + gk = '高考', + ky = '考研', + cet4 = '四级', + cet6 = '六级', + ielts = '雅思', + toefl = '托福', + gre = 'GRE', +} + +---从查询结果中获取字符串 +---@param field table 查询的结果 +---@return component? component 提取的组件信息[包含多个组件] +M.component = function(field) + -- TODO + if field.tag and field.tag ~= '' then + local ref = { + { '标签:', 'TransRef' }, + } + + local tags = { + needformat = true, + highlight = 'TransTag', + indent = 4, + } + + for _tag in vim.gsplit(field.tag, ' ', true) do + if _tag ~= '' then + local tag = tag_map[_tag] + + if tag then + table.insert(tags, tag) + else + error('add tag_map for [' .. _tag .. ']') + end + end + end + + return { ref, tags } + end end + return M diff --git a/lua/Trans/component/offline/Title.lua b/lua/Trans/component/offline/Title.lua index c1203a8..3613893 100644 --- a/lua/Trans/component/offline/Title.lua +++ b/lua/Trans/component/offline/Title.lua @@ -25,13 +25,13 @@ local icon = require("Trans.conf.loader").loaded_conf.ui.icon -- -- { phonetic, 'TransPhonetic' }, -- } ----@alias stuff ----| 'data' # 所有组件的信息 + +---@alias items +---| 'string[]' # 所有组件的信息 +---| 'needformat?'# 是否需要格式化 ---| 'highlight?' # 整个组件的高亮 ---| 'indent?' # 每行整体的缩进 ----| 'interval?' # 每个组件的间隔 ----@alias component stuff[] - +---@alias component items[] ---从查询结果中获取字符串 ---@param field table 查询的结果 ---@return component component 提取的组件信息[包含多个组件] @@ -41,7 +41,7 @@ M.component = function(field) { field.word, 'TransWord' }, } - if display.phnoetic and field.phonetic ~= '' then + if display.phnoetic and field.phonetic and field.phonetic ~= '' then table.insert( data, { '[' .. field.phonetic .. ']', 'TransPhonetic' } diff --git a/lua/Trans/component/offline/Translation.lua b/lua/Trans/component/offline/Translation.lua index 94acd96..e557040 100644 --- a/lua/Trans/component/offline/Translation.lua +++ b/lua/Trans/component/offline/Translation.lua @@ -1,6 +1,6 @@ local M = {} -M.to_content = function (field) +M.component = function (field) -- TODO end diff --git a/lua/Trans/conf/default.lua b/lua/Trans/conf/default.lua index 4518665..39fddc7 100644 --- a/lua/Trans/conf/default.lua +++ b/lua/Trans/conf/default.lua @@ -10,8 +10,8 @@ M.conf = { window = { cursor = { border = 'rounded', - width = 30, - height = 30, + width = 40, + height = 20, }, float = { border = 'rounded', @@ -29,11 +29,11 @@ M.conf = { order = { offline = { 'Title', - -- 'Tag', - -- 'Pos', - -- 'Exchange', - -- 'Translation', - -- 'Definition', + 'Tag', + 'Pos', + 'Exchange', + 'Translation', + 'Definition', }, -- online = { -- -- TODO @@ -67,6 +67,13 @@ M.conf = { TransDefinition = { fg = '#bc8cff', }, + TransCursorWin = { + link = 'Normal', + }, + + TransCursorBorder = { + link = 'FloatBorder', + } }, icon = { star = '⭐', diff --git a/lua/Trans/core/README.md b/lua/Trans/core/README.md index 5fa3070..fda9162 100644 --- a/lua/Trans/core/README.md +++ b/lua/Trans/core/README.md @@ -69,7 +69,7 @@ - `vsplit` 在左边或者右边分屏 - 高度(height): - - `value > 1` 实际高度 + - `value > 1` 最大高度 - `0 <= value <= 1` 相对高度 - `0 < value` 无限制 diff --git a/lua/Trans/core/process.lua b/lua/Trans/core/process.lua index 82df19b..b94a105 100644 --- a/lua/Trans/core/process.lua +++ b/lua/Trans/core/process.lua @@ -2,141 +2,136 @@ local type_check = require("Trans.util.debug").type_check -- NOTE :中文字符及占两个字节宽,但是在lua里是3个字节长度 -- 为了解决中文字符在lua的长度和neovim显示不一致的问题 -local function get_width(str) - if type(str) ~= 'string' then - vim.pretty_print(str) - error('str!') - end - return vim.fn.strdisplaywidth(str) -end +local get_width = vim.fn.strdisplaywidth local function format(win_width, items) - table.sort(items, function(a, b) - local wa, wb = 0, 0 - if type(a) == 'string' then - wa = get_width(a) - a = { a } - else - wa = get_width(a[1]) - end - if type(b) == 'string' then - wb = get_width(b) - b = { b } - else - wb = get_width(b[1]) - end - return wa > wb - end) - local size = #items - local width = win_width - get_width(items[1][1]) - local cols = 0 - for i = 2, size do - width = width - 4 - get_width(items[i][1]) - if width < 0 then - cols = i - break + local tot_width = 0 + + for i = 1, size do + if type(items[i]) == 'string' then + items[i] = { items[i] } end + tot_width = tot_width + get_width(items[i][1]) + 4 end - if cols == 0 then - return items - else + -- 判断宽度是否超过最大宽度 + if tot_width > win_width + 4 then + -- 放不下则需要分成多行 local lines = {} - local rows = math.floor(size / cols) + + -- 行内字符串按照宽度排序 + table.sort(items, function(a, b) + return get_width(a[1]) > get_width(b[1]) + end) + + local cols = 1 + win_width = win_width - get_width(items[1][1]) + while win_width > 0 and cols < size do + cols = cols + 1 + win_width = win_width - get_width(items[cols][1]) + 4 + end + cols = cols - 1 + + local rows = math.ceil(size / cols) local rest = size % cols if rest == 0 then rest = cols end - local max_width = get_width(items[1][1]) - for i = 1, rows do - local index = rows - i + 1 - lines[index] = { - interval = items.interval, + local index = 1 -- 当前操作的字符串下标 + for i = rows, 1, -1 do -- 当前操作的行号 + lines[i] = { highlight = items.highlight, indent = items.indent, } - items[i][1] = items[i][1] .. (' '):rep(max_width - get_width(items[i][1])) - lines[index][1] = items[i] + local item = items[index] + item[1] = item[1] .. (' '):rep(max_width - get_width(item[1])) + lines[i][1] = items[index] + index = index + 1 end - local index = rows + 1 + for col = 2, cols do - max_width = get_width(items[index]) + max_width = get_width(items[index][1]) local _end = col > rest and rows - 1 or rows - for i = 1, _end do - local idx = _end - i + 1 -- 当前操作的行数 - local item_idx = index + i - 1 - local item = items[item_idx] + for i = _end, 1, -1 do + local item = items[index] item[1] = item[1] .. (' '):rep(max_width - get_width(item[1])) - lines[idx][col] = item + lines[i][col] = item + index = index + 1 end - index = index + _end end - return lines + return lines, true + else + return items end end - local function process(opts) type_check { opts = { opts, 'table' }, ['opts.field'] = { opts.field, 'table', true }, ['opts.order'] = { opts.order, 'table' }, - ['opts.win'] = { opts.win, 'table' }, + ['opts.win'] = { opts.win, 'table' }, ['opts.engine'] = { opts.engine, 'table' }, } if opts.field == nil then - local lines = {'no tranlation'} + local lines = { '⚠️ 本地没有找到相关释义' } vim.api.nvim_buf_set_lines(opts.bufnr, 0, -1, false, lines) - return - end + vim.api.nvim_win_set_height(opts.winid, 1) + vim.api.nvim_win_set_width(opts.winid, get_width(lines[1])) + else + local content = require('Trans.component.content'):new() + for _, v in ipairs(opts.order) do + local component = require("Trans.component." .. 'offline' --[[ opts.engine ]] .. '.' .. v).component(opts.field) + if component then + for _, items in ipairs(component) do - local content = require('Trans.component.content'):new() + if items.needformat then + local formatted_items, split = format(opts.win.width, items) + if split then + for _, itms in ipairs(formatted_items) do + content:insert(itms) + end + else + content:insert(formatted_items) + end - for _, v in ipairs(opts.order) do - local component = require("Trans.component." .. 'offline' --[[ opts.engine ]] .. '.' .. v).component(opts.field) - -- vim.pretty_print(component) + else + content:insert(items) + end - for _, items in ipairs(component) do - local formatted_items, split = format(opts.win.width, items) - if split then - for _, itms in ipairs(formatted_items) do - content:insert(itms) end - else - content:insert(formatted_items) end + end + + content:attach(opts.bufnr, opts.winid) + end - local lines, __highlight = content:data() - vim.api.nvim_buf_set_lines(opts.bufnr, 0, -1, false, lines) - - - for line, l_hl in ipairs(__highlight) do - for _, hl in ipairs(l_hl) do - vim.api.nvim_buf_add_highlight(opts.bufnr, -1, hl.name, line, hl._start, hl._end) - end - end vim.api.nvim_buf_set_option(opts.bufnr, 'modifiable', false) vim.api.nvim_buf_set_option(opts.bufnr, 'filetype', 'Trans') + + vim.api.nvim_win_set_option(opts.winid, 'winhl', 'Normal:TransCursorWin,FloatBorder:TransCursorBorder') if opts.win.style == 'cursor' then vim.api.nvim_create_autocmd( { 'InsertEnter', 'CursorMoved', 'BufLeave', }, { buffer = 0, once = true, - callback = function () - vim.api.nvim_win_close(opts.winid, true) + callback = function() + if vim.api.nvim_win_is_valid(opts.winid) then + vim.api.nvim_win_close(opts.winid, true) + end end, }) end diff --git a/lua/Trans/core/query.lua b/lua/Trans/core/query.lua index dac837a..c973f44 100644 --- a/lua/Trans/core/query.lua +++ b/lua/Trans/core/query.lua @@ -2,14 +2,17 @@ local type_check = require("Trans.util.debug").type_check local query = require("Trans.api").query local function get_select() - local s_start = vim.fn.getpos("'<") - local s_end = vim.fn.getpos("'>") - if s_start[2] ~= s_start[2] then - error('TODO: multiline translate') + local s_start = vim.fn.getpos("v") + local s_end = vim.fn.getpos(".") + local n_lines = math.abs(s_end[2] - s_start[2]) + 1 + local lines = vim.api.nvim_buf_get_lines(0, s_start[2] - 1, s_end[2], false) + lines[1] = string.sub(lines[1], s_start[3], -1) + if n_lines == 1 then + lines[n_lines] = string.sub(lines[n_lines], 1, s_end[3] - s_start[3] + 1) + else + lines[n_lines] = string.sub(lines[n_lines], 1, s_end[3]) end - local lin = vim.api.nvim_buf_get_lines(0, s_start[2] - 1, s_end[2], false)[1] - local word = string.sub(lin, s_start[3], s_end[3]) - return word + return table.concat(lines, '\n') end local query_wrapper = function(opts) @@ -21,15 +24,15 @@ local query_wrapper = function(opts) local word = '' if opts.method == 'input' then + ---@diagnostic disable-next-line: param-type-mismatch word = vim.fn.input('请输入您要查询的单词:') -- TODO Use Telescope with fuzzy finder elseif opts.method == 'n' then word = vim.fn.expand('<cword>') - elseif opts.mehotd == 'v' then + elseif opts.method == 'v' then word = get_select() -- TODO : other method - else error('invalid method' .. opts.method) end diff --git a/lua/Trans/core/translate.lua b/lua/Trans/core/translate.lua index b66b3c2..f336240 100644 --- a/lua/Trans/core/translate.lua +++ b/lua/Trans/core/translate.lua @@ -21,6 +21,7 @@ local function get_opts(opts) opts.engine = { opts.engine } end + if opts.win then local width, height = opts.win.width, opts.win.height if width and width > 0 and width <= 1 then @@ -35,6 +36,7 @@ local function get_opts(opts) return vim.tbl_extend('force', default_conf, opts) end + -- EXAMPLE : -- require('Trans').translate({ -- method = 'input', -- 不填则自动判断mode获取查询的单词 @@ -52,6 +54,7 @@ end -- }) + local function create_win(win) local bufnr = vim.api.nvim_create_buf(false, true) @@ -81,6 +84,7 @@ local function create_win(win) return bufnr, winid end + local function translate(opts) vim.validate { opts = { opts, 'table', true } diff --git a/lua/Trans/util/format.lua b/lua/Trans/util/format.lua deleted file mode 100644 index b9c62fe..0000000 --- a/lua/Trans/util/format.lua +++ /dev/null @@ -1,190 +0,0 @@ -local M = {} -local type_check = require("Trans.util.debug").type_check - --- NOTE :中文字符及占两个字节宽,但是在lua里是3个字节长度 --- 为了解决中文字符在lua的长度和neovim显示不一致的问题 -function string:width() - return vim.fn.strdisplaywidth(self) -end - -local s_to_b = true -- 从小到大排列 - -local m_win_width -- 需要被格式化窗口的高度 -local m_fields -- 待格式化的字段 -local m_tot_width -- 所有字段加起来的长度(不包括缩进和间隔) -local m_item_width -- 每个字段的宽度 -local m_interval -- 每个字段的间隔 -local m_size -- 字段的个数 - -local function caculate_format() - local width = m_win_width - m_item_width[1] - local cols = 0 - for i = 2, m_size do - width = width - m_item_width[i] - m_interval - if width < 0 then - cols = i - 1 - break - else - cols = i - end - end - - return math.ceil(m_size / cols), cols -end - -local function format_to_line() - local line = m_fields[1] - if m_size == 1 then - --- Center Align - local space = math.floor((m_win_width - m_item_width[1]) / 2) - line = (' '):rep(space) .. line - else - local space = math.floor((m_win_width - m_tot_width) / m_size - 1) - for i = 2, m_size do - line = line .. (' '):rep(space) .. m_fields[i] - end - end - return line -end - -local function sort_tables() - table.sort(m_item_width, function(a, b) - return a > b - end) - - table.sort(m_fields, function(a, b) - return a:width() > b:width() -- 需要按照width排序 - end) -end - -local function format_to_multilines(rows, cols) - local lines = {} - - local rest = m_size % cols - if rest == 0 then - rest = cols - end - - local s_width = m_item_width[1] -- 列中最宽的字符串宽度 - for i = 1, rows do - local idx = s_to_b and rows - i + 1 or i - lines[idx] = {} - - local space = (' '):rep(s_width - m_item_width[i]) - local item = m_fields[i] .. space - - lines[idx][1] = item - lines[idx].interval = m_interval - end - - - local index = rows + 1 -- 最宽字符的下标 - - for j = 2, cols do -- 以列为单位遍历 - s_width = m_item_width[index] - local stop = (j > rest and rows - 1 or rows) - for i = 1, stop do - local idx = s_to_b and stop - i + 1 or i -- 当前操作的行数 - local item_idx = index + i - 1 -- 当前操作的字段数 - local space = (' '):rep(s_width - m_item_width[item_idx]) -- 对齐空格 - local item = m_fields[item_idx] .. space - - lines[idx][j] = item -- 插入图标 - end - index = index + stop -- 更新最宽字符的下标 - end - - return lines -- TODO : evaluate the width -end - -local function formatted_lines() - local lines = {} - -- NOTE : 判断能否格式化成一行 - if m_tot_width + (m_size * m_indent) > m_win_width then - sort_tables() - --- NOTE : 计算应该格式化成多少行和列 - local rows, cols = caculate_format() - lines = format_to_multilines(rows, cols) - else - lines[1] = format_to_line() - end - - return lines -end - --- EXAMPLE : 接受的形式 --- local content = { --- { word, 'TransWord' }, --- { phonetic, 'TransPhonetic' }, --- collins, --- oxford --- -- { phonetic, 'TransPhonetic' }, --- NOTE : --- 可选的: --- 1. highlight 整个content的高亮 --- 2. indent 缩进 --- 2. space 各个组件的及间隔 --- } - - --- EXAMPLE : 返回的形式 --- local lines = { --- { items, opts }, --- { items, opts }, --- { items, opts }, --- -- items: string[] --- -- opts { --- -- highlight --- -- indent --- -- } --- } - - ----@alias formatted_items table ----将组件格式化成相应的vim支持的lines格式 ----@param win_size string 窗口的宽度和高度 ----@param component table 需要格式化的字段 ----@return formatted_items[] lines -M.format = function(win_width, component) - type_check { - style = { style, { 'string' } }, - component = { component, { 'table' } }, - } - - local length = 0 - local width = 0 - local item_size = {} - for i, v in ipairs(fields) do - width = v:width() - item_size[i] = width - length = length + width - end - - m_win_width = win_width - m_fields = fields - m_size = #m_fields - m_tot_width = length - m_item_width = item_size - - return formatted_lines() -end - - ----合并多个数组, 第一个数组将会被使用 ----@param ... string[] 需要被合并的数组 ----@return table res 合并后的数组 -M.extend_array = function(...) - local arrays = { ... } - local res = arrays[1] - local index = #res - for i = 2, #arrays do - for _, value in ipairs(arrays[i]) do - res[index] = value - index = index + 1 - end - end - return res -end - - -return M diff --git a/lua/Trans/util/parser.lua b/lua/Trans/util/parser.lua deleted file mode 100644 index 4c4adfc..0000000 --- a/lua/Trans/util/parser.lua +++ /dev/null @@ -1,19 +0,0 @@ ----@diagnostic disable: missing-return, unused-local -local M = {} -local type_check = require("Trans.util.debug").type_check - ----解析宽度 ----@param width integer ----@return integer -M.width = function (width) - -- TODO -end - ----解析宽度 ----@param height integer ----@return integer -M.height = function (height) - -- TODO -end - -return M From 32eeae88d470102a8460922d1e963f165033cfc3 Mon Sep 17 00:00:00 2001 From: JuanZoran <1430359574@qq.com> Date: Tue, 10 Jan 2023 18:55:21 +0800 Subject: [PATCH 16/17] feat: reduce bugs --- lua/Trans/conf/window.lua | 61 ------------------------------------- lua/Trans/core/init.lua | 2 +- lua/Trans/core/show_win.lua | 54 -------------------------------- 3 files changed, 1 insertion(+), 116 deletions(-) delete mode 100644 lua/Trans/conf/window.lua delete mode 100644 lua/Trans/core/show_win.lua diff --git a/lua/Trans/conf/window.lua b/lua/Trans/conf/window.lua deleted file mode 100644 index c81af89..0000000 --- a/lua/Trans/conf/window.lua +++ /dev/null @@ -1,61 +0,0 @@ -local M = {} -local conf = require("Trans.conf.loader").loaded_conf.style.window -local type_check = require("Trans.util.debug").type_check - --- FIXME - -local get_float_opts = function(float_conf) - type_check { - float_conf = { float_conf, 'table' }, - } - local columns = vim.o.columns - local height = vim.o.lines - vim.o.cmdheight - float_conf.top_offset - local width = math.floor(columns * float_conf.relative_width) - - return { - relative = 'editor', - col = math.floor((columns - width) / 2), -- 两侧的宽度 - row = float_conf.top_offset, - title = 'Trans', - title_pos = 'center', - style = 'minimal', - width = width, - height = height, - border = float_conf.border, - zindex = 50, - } -end - -local get_cursor_opts = function(cursor_conf) - type_check { - cursor_conf = { cursor_conf, 'table' }, - } - local opts = { - relative = 'cursor', - col = 2, - row = 2, - title = 'Trans', - title_pos = 'center', - style = 'minimal', - border = cursor_conf.border, - -- TODO keymap to convert style to Float - focusable = false, - zindex = 100, - } - if cursor_conf.style == 'fixed' then - opts.width = cursor_conf.width - opts.height = cursor_conf.height - elseif cursor_conf.style == 'relative' then - opts.width = (cursor_conf.width > 0 and conf.width < conf.max_width) and conf.width or conf.max_width - opts.height = (cursor_conf.height > 0 and conf.height < conf.max_height) and conf.height or conf.max_height - else - error('unknown style!') - end - return opts -end - -M.float_opts = get_float_opts(conf.float) - -M.cursor_opts = get_cursor_opts(conf.cursor) - -return M diff --git a/lua/Trans/core/init.lua b/lua/Trans/core/init.lua index fd633ca..8a499bd 100644 --- a/lua/Trans/core/init.lua +++ b/lua/Trans/core/init.lua @@ -2,6 +2,6 @@ local M = {} M.process = require('Trans.core.process') M.query = require('Trans.core.query') -M.show_win = require('Trans.core.show_win') +-- M.show_win = require('Trans.core.show_win') return M diff --git a/lua/Trans/core/show_win.lua b/lua/Trans/core/show_win.lua deleted file mode 100644 index be06838..0000000 --- a/lua/Trans/core/show_win.lua +++ /dev/null @@ -1,54 +0,0 @@ -local type_check = require("Trans.util.debug").type_check - --- local win_opts = { --- winhl = 'Normal:TransWinNormal, FloatBorder:TransWinBorder' --- } - -local function caculate_format(height, width) - local col = math.floor((vim.o.lines - height - vim.o.cmdheight) / 2) - local row = math.floor((vim.o.columns - width) / 2) - return row, col -end - - -local function show_win(opts) - type_check { - opts = { opts, 'table' }, - win = { opts.win, 'table' }, - border = { opts.border, 'string' }, - highlight = { opts.highlight, 'table', true }, - } - - local is_float = opts.style == 'float' - local win_opts = { - relative = opts.style == 'float' and 'editor' or 'cursor', - width = opts.width, - height = opts.height, - style = 'minimal', - border = opts.border, - title = 'Trans', - title_pos = 'center', - focusable = true, - zindex = 100, - } - if is_float then - win_opts.row, win_opts.col = caculate_format(win_opts.height, win_opts.width) - else - win_opts.row = 2 - win_opts.col = 2 - end - - local winid = vim.api.nvim_open_win(bufnr, is_float, win_opts) - - vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, opts.lines) - - for line, l_hl in ipairs(opts.highlight) do - for i, hl in ipairs(l_hl) do - vim.api.nvim_buf_add_highlight(bufnr, line, hl.name, i, hl._start, hl._end) - end - end - - return bufnr, winid -end - -return show_win From 01f5882b13d370675ed69046607fe51bfd772c2c Mon Sep 17 00:00:00 2001 From: JuanZoran <1430359574@qq.com> Date: Tue, 10 Jan 2023 23:15:31 +0800 Subject: [PATCH 17/17] fix: add max_size support and definition need better format --- lua/.luarc.json | 3 +- lua/Trans/api/query.lua | 2 +- lua/Trans/component/content.lua | 26 +++++---- lua/Trans/component/highlight.lua | 11 ---- lua/Trans/component/offline/Definition.lua | 65 ++++++++++++++++++++- lua/Trans/component/offline/Exchange.lua | 42 ++++++++++++- lua/Trans/component/offline/Pos.lua | 17 +++++- lua/Trans/component/offline/Tag.lua | 13 ++--- lua/Trans/component/offline/Translation.lua | 20 ++++++- lua/Trans/conf/default.lua | 17 +++--- lua/Trans/conf/loader.lua | 13 ++--- lua/Trans/core/process.lua | 58 +++++++++++++----- lua/Trans/core/query.lua | 2 +- lua/Trans/core/translate.lua | 3 +- lua/Trans/setup.lua | 4 +- lua/Trans/util/debug.lua | 32 ---------- 16 files changed, 223 insertions(+), 105 deletions(-) delete mode 100644 lua/Trans/component/highlight.lua delete mode 100644 lua/Trans/util/debug.lua diff --git a/lua/.luarc.json b/lua/.luarc.json index cb3ed2f..8ae3698 100644 --- a/lua/.luarc.json +++ b/lua/.luarc.json @@ -8,5 +8,6 @@ "vim", "user_conf", "default_conf" - ] + ], + "Lua.workspace.checkThirdParty": false } \ No newline at end of file diff --git a/lua/Trans/api/query.lua b/lua/Trans/api/query.lua index d2645af..ad0014b 100644 --- a/lua/Trans/api/query.lua +++ b/lua/Trans/api/query.lua @@ -3,7 +3,7 @@ local _, db = pcall(require, 'sqlite.db') if not _ then error('Please check out sqlite.lua') end -local type_check = require("Trans.util.debug").type_check +local type_check = vim.validate -- INFO : init database local path = require("Trans.conf.loader").loaded_conf.base.db_path diff --git a/lua/Trans/component/content.lua b/lua/Trans/component/content.lua index 9960e2d..c04ee90 100644 --- a/lua/Trans/component/content.lua +++ b/lua/Trans/component/content.lua @@ -1,14 +1,20 @@ local M = {} -local type_check = require("Trans.util.debug").type_check +local type_check = vim.validate M.__index = M M.lines = {} M.highlight = {} M.height = 0 M.width = 0 M.interval = ' ' +M.opts = {} -function M:new() + +function M:new(opts) + if opts then + self.opts = opts + end + local content = {} setmetatable(content, self) return content @@ -111,26 +117,26 @@ function M:data() return lines, highlights end -function M:attach(bufnr, winid) - local height = vim.api.nvim_win_get_height(winid) - local width = vim.api.nvim_win_get_width(winid) - vim.api.nvim_win_set_height(winid, self.height) +function M:attach() + local height = self.opts.win.height + local width = self.opts.win.width + local lines, hls = self:data() - vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, lines) + vim.api.nvim_buf_set_lines(self.opts.bufnr, 0, -1, false, lines) for line, l_hl in ipairs(hls) do for _, hl in ipairs(l_hl) do - vim.api.nvim_buf_add_highlight(bufnr, -1, hl.name, line - 1, hl._start, hl._end) + vim.api.nvim_buf_add_highlight(self.opts.bufnr, -1, hl.name, line - 1, hl._start, hl._end) end end if self.height < height then - vim.api.nvim_win_set_height(winid, self.height) + vim.api.nvim_win_set_height(self.opts.winid, self.height) end if self.width < width then - vim.api.nvim_win_set_width(winid, self.width) + vim.api.nvim_win_set_width(self.opts.winid, self.width) end end diff --git a/lua/Trans/component/highlight.lua b/lua/Trans/component/highlight.lua deleted file mode 100644 index 6732551..0000000 --- a/lua/Trans/component/highlight.lua +++ /dev/null @@ -1,11 +0,0 @@ -local M = {} -local type_check = require("Trans.util.debug").type_check -M.__index = M - -function M:new() - -end - - -return M - diff --git a/lua/Trans/component/offline/Definition.lua b/lua/Trans/component/offline/Definition.lua index e557040..54d9f77 100644 --- a/lua/Trans/component/offline/Definition.lua +++ b/lua/Trans/component/offline/Definition.lua @@ -1,7 +1,68 @@ local M = {} -M.component = function (field) - -- TODO +M.component = function (field, max_size) + if field.definition and field.definition ~= '' then + local ref = { + { '英文注释', 'TransRef' } + } + + local definitions = { + highlight = 'TransDefinition', + needformat = true, + indent = 4, + } + local size = 0 + for defin in vim.gsplit(field.definition, '\n', true) do + if defin ~= '' then + table.insert(definitions, defin) + + size = size + 1 + if size == max_size then + break + end + end + end + + return { ref, definitions } + end end return M + +--[[n a formation of people or things one beside another +n a mark that is long relative to its width +n a formation of people or things one behind another +n a length (straight or curved) without breadth or thickness; the trace of a moving point +n text consisting of a row of words written across a page or computer screen +n a single frequency (or very narrow band) of radiation in a spectrum +n a fortified position (especially one marking the most forward position of troops) +n a course of reasoning aimed at demonstrating a truth or falsehood; the methodical process of logical reasoning +n a conductor for transmitting electrical or optical signals or electric power +n a connected series of events or actions or developments +n a spatial location defined by a real or imaginary unidimensional extent +n a slight depression in the smoothness of a surface +n a pipe used to transport liquids or gases +n the road consisting of railroad track and roadbed +n a telephone connection +n acting in conformity +n the descendants of one individual +n something (as a cord or rope) that is long and thin and flexible +n the principal activity in your life that you do to earn money +n in games or sports; a mark indicating positions or bounds of the playing area +n (often plural) a means of communication or access +n a particular kind of product or merchandise +n a commercial organization serving as a common carrier +n space for one line of print (one column wide and 1/14 inch deep) used to measure advertising +n the maximum credit that a customer is allowed +n a succession of notes forming a distinctive sequence +n persuasive but insincere talk that is usually intended to deceive or impress +n a short personal letter +n a conceptual separation or distinction +n mechanical system in a factory whereby an article is conveyed through sites at which successive operations are performed on it +v be in line with; form a line along +v cover the interior of +v make a mark or lines on a surface +v mark with lines +v fill plentifully +v reinforce with fabric +--]] diff --git a/lua/Trans/component/offline/Exchange.lua b/lua/Trans/component/offline/Exchange.lua index e557040..90cb93c 100644 --- a/lua/Trans/component/offline/Exchange.lua +++ b/lua/Trans/component/offline/Exchange.lua @@ -1,7 +1,45 @@ local M = {} -M.component = function (field) - -- TODO +local exchange_map = { + p = '过去式', + d = '过去分词', + i = '现在分词', + r = '形容词比较级', + t = '形容词最高级', + s = '名词复数形式', + f = '第三人称单数', + ['0'] = '词根', + ['1'] = '词根的变化形式', + ['3'] = '第三人称单数', +} + +M.component = function(field) + -- TODO + if field.exchange and field.exchange ~= '' then + local ref = { + { '词型变化', 'TransRef' }, + } + local exchanges = { + needformat = true, + highlight = 'TransExchange', + indent = 4, + emptyline = true, + } + + for _exchange in vim.gsplit(field.exchange, '/', true) do + local prefix = exchange_map[_exchange:sub(1, 1)] + if prefix then + local exchange = prefix .. _exchange:sub(2) + -- local exchange = exchange_map[_exchange:sub(1, 1)] .. _exchange:sub(2) + table.insert(exchanges, exchange) + + else + error('add exchange_map for [' .. _exchange .. ']') + end + end + + return { ref, exchanges } + end end return M diff --git a/lua/Trans/component/offline/Pos.lua b/lua/Trans/component/offline/Pos.lua index e557040..7d52ae5 100644 --- a/lua/Trans/component/offline/Pos.lua +++ b/lua/Trans/component/offline/Pos.lua @@ -1,7 +1,20 @@ local M = {} -M.component = function (field) - -- TODO +M.component = function(field) + -- TODO + if field.pos and field.pos ~= '' then + local ref = { + { '词性:', 'TransRef' }, + } + local pos = { + { field.pos }, + highlight = 'TransPos', + indent = 4, + emptyline = true, + } + + return { ref, pos } + end end return M diff --git a/lua/Trans/component/offline/Tag.lua b/lua/Trans/component/offline/Tag.lua index a95080f..9ccf18e 100644 --- a/lua/Trans/component/offline/Tag.lua +++ b/lua/Trans/component/offline/Tag.lua @@ -25,17 +25,16 @@ M.component = function(field) needformat = true, highlight = 'TransTag', indent = 4, + emptyline = true, } for _tag in vim.gsplit(field.tag, ' ', true) do - if _tag ~= '' then - local tag = tag_map[_tag] + local tag = tag_map[_tag] - if tag then - table.insert(tags, tag) - else - error('add tag_map for [' .. _tag .. ']') - end + if tag then + table.insert(tags, tag) + else + error('add tag_map for [' .. _tag .. ']') end end diff --git a/lua/Trans/component/offline/Translation.lua b/lua/Trans/component/offline/Translation.lua index e557040..de61ffb 100644 --- a/lua/Trans/component/offline/Translation.lua +++ b/lua/Trans/component/offline/Translation.lua @@ -1,7 +1,23 @@ local M = {} -M.component = function (field) - -- TODO +M.component = function(field) + if field.translation then + local ref = { + { '中文翻译', 'TransRef' } + } + + local translations = { + highlight = 'TransTranslation', + indent = 4, + emptyline = true, + needformat = true, + } + for trans in vim.gsplit(field.translation, '\n', true) do + table.insert(translations, trans) + end + + return { ref, translations } + end end return M diff --git a/lua/Trans/conf/default.lua b/lua/Trans/conf/default.lua index 39fddc7..57a60b9 100644 --- a/lua/Trans/conf/default.lua +++ b/lua/Trans/conf/default.lua @@ -10,8 +10,8 @@ M.conf = { window = { cursor = { border = 'rounded', - width = 40, - height = 20, + width = 50, + height = 50, }, float = { border = 'rounded', @@ -33,10 +33,10 @@ M.conf = { 'Pos', 'Exchange', 'Translation', - 'Definition', + -- { 'Definition', max_size = 4 }, }, -- online = { - -- -- TODO + -- -- TODO -- }, }, ui = { @@ -46,7 +46,7 @@ M.conf = { bold = true, }, TransPhonetic = { - fg = '#8b949e', + link = 'Linenr' }, TransRef = { fg = '#75beff', @@ -65,7 +65,8 @@ M.conf = { link = 'TransWord', }, TransDefinition = { - fg = '#bc8cff', + -- fg = '#bc8cff', + link = 'Moremsg', }, TransCursorWin = { link = 'Normal', @@ -93,14 +94,14 @@ M.conf = { auto_close = true, engine = { -- TODO - 'local', + 'offline', } }, -- map = { -- -- TODO -- }, -- history = { - -- -- TOOD + -- -- TOOD -- } -- TODO add online translate engine diff --git a/lua/Trans/conf/loader.lua b/lua/Trans/conf/loader.lua index 3b3684f..8245116 100644 --- a/lua/Trans/conf/loader.lua +++ b/lua/Trans/conf/loader.lua @@ -45,16 +45,11 @@ M.load_conf = function(conf) pre_process() M.loaded_conf = vim.tbl_deep_extend('force', default_conf, user_conf) - local width = M.loaded_conf.style.window.float.width - local height = M.loaded_conf.style.window.float.height + local win = M.loaded_conf.style.window + assert(win.float.height <= 1 and win.float.height > 0 and win.cursor.height > 1, win.cursor.width > 1) - if width > 0 and width <= 1 then - M.loaded_conf.style.window.float.width = math.floor(width * vim.o.columns) - end - - if height > 0 and height <= 1 then - M.loaded_conf.style.window.float.height = math.floor(height * (vim.o.lines - vim.o.cmdheight)) - end + win.float.width = math.floor(win.float.width * vim.o.columns) + win.float.height = math.floor(win.float.height * (vim.o.lines - vim.o.cmdheight)) user_conf = nil default_conf = nil diff --git a/lua/Trans/core/process.lua b/lua/Trans/core/process.lua index b94a105..aba65bf 100644 --- a/lua/Trans/core/process.lua +++ b/lua/Trans/core/process.lua @@ -1,4 +1,4 @@ -local type_check = require("Trans.util.debug").type_check +local type_check = vim.validate -- NOTE :中文字符及占两个字节宽,但是在lua里是3个字节长度 -- 为了解决中文字符在lua的长度和neovim显示不一致的问题 @@ -8,11 +8,15 @@ local function format(win_width, items) local size = #items local tot_width = 0 + if items.indent then + win_width = win_width - items.indent + end + for i = 1, size do if type(items[i]) == 'string' then items[i] = { items[i] } end - tot_width = tot_width + get_width(items[i][1]) + 4 + tot_width = tot_width + #items[i][1] + 4 end @@ -23,22 +27,38 @@ local function format(win_width, items) -- 行内字符串按照宽度排序 table.sort(items, function(a, b) - return get_width(a[1]) > get_width(b[1]) + return #a[1] > #b[1] end) local cols = 1 - win_width = win_width - get_width(items[1][1]) + win_width = win_width - #items[1][1] + while win_width > 0 and cols < size do cols = cols + 1 - win_width = win_width - get_width(items[cols][1]) + 4 + win_width = win_width - #items[cols][1] + 4 end - cols = cols - 1 + if cols > 1 then + cols = cols - 1 + end + + if cols == 1 then -- 只能放在一行时就对齐了 + for i = size, 1, -1 do + lines[i] = { + items[i][1], + highlight = items.highlight, + indent = items.indent, + } + end + return lines, true + end + local rows = math.ceil(size / cols) local rest = size % cols if rest == 0 then rest = cols end + local max_width = get_width(items[1][1]) local index = 1 -- 当前操作的字符串下标 for i = rows, 1, -1 do -- 当前操作的行号 @@ -48,6 +68,10 @@ local function format(win_width, items) } local item = items[index] + -- if not item then + -- error('item nil ' .. tostring(index) .. ' rows:' .. tostring(rows) .. vim.inspect(items) ) + -- end + item[1] = item[1] .. (' '):rep(max_width - get_width(item[1])) lines[i][1] = items[index] index = index + 1 @@ -69,9 +93,8 @@ local function format(win_width, items) end return lines, true - else - return items end + return items end local function process(opts) @@ -88,11 +111,16 @@ local function process(opts) vim.api.nvim_buf_set_lines(opts.bufnr, 0, -1, false, lines) vim.api.nvim_win_set_height(opts.winid, 1) vim.api.nvim_win_set_width(opts.winid, get_width(lines[1])) - else - local content = require('Trans.component.content'):new() + local content = require('Trans.component.content'):new(opts) for _, v in ipairs(opts.order) do - local component = require("Trans.component." .. 'offline' --[[ opts.engine ]] .. '.' .. v).component(opts.field) + local component + if type(v) == 'table' then + component = require("Trans.component." .. 'offline' --[[ opts.engine ]] .. '.' .. v[1]).component(opts.field + , v.max_size) + else + component = require("Trans.component." .. 'offline' --[[ opts.engine ]] .. '.' .. v).component(opts.field) + end if component then for _, items in ipairs(component) do @@ -105,23 +133,25 @@ local function process(opts) else content:insert(formatted_items) end - else content:insert(items) end + if items.emptyline then + content:insert({ '' }) + end end end end - content:attach(opts.bufnr, opts.winid) - + content:attach() end vim.api.nvim_buf_set_option(opts.bufnr, 'modifiable', false) vim.api.nvim_buf_set_option(opts.bufnr, 'filetype', 'Trans') + vim.api.nvim_win_set_option(opts.winid, 'wrap', true) vim.api.nvim_win_set_option(opts.winid, 'winhl', 'Normal:TransCursorWin,FloatBorder:TransCursorBorder') if opts.win.style == 'cursor' then vim.api.nvim_create_autocmd( diff --git a/lua/Trans/core/query.lua b/lua/Trans/core/query.lua index c973f44..5fdb0b0 100644 --- a/lua/Trans/core/query.lua +++ b/lua/Trans/core/query.lua @@ -1,4 +1,4 @@ -local type_check = require("Trans.util.debug").type_check +local type_check = vim.validate local query = require("Trans.api").query local function get_select() diff --git a/lua/Trans/core/translate.lua b/lua/Trans/core/translate.lua index f336240..4ce2295 100644 --- a/lua/Trans/core/translate.lua +++ b/lua/Trans/core/translate.lua @@ -59,6 +59,7 @@ local function create_win(win) local bufnr = vim.api.nvim_create_buf(false, true) local is_float = win.style == 'float' + local win_opts = { relative = is_float and 'editor' or 'cursor', width = win.width, @@ -79,8 +80,8 @@ local function create_win(win) win_opts.col = 2 end - local winid = vim.api.nvim_open_win(bufnr, is_float, win_opts) + local winid = vim.api.nvim_open_win(bufnr, is_float, win_opts) return bufnr, winid end diff --git a/lua/Trans/setup.lua b/lua/Trans/setup.lua index 2e0acb8..1fa8aef 100644 --- a/lua/Trans/setup.lua +++ b/lua/Trans/setup.lua @@ -5,14 +5,14 @@ end vim.api.nvim_create_user_command('Translate', function () require("Trans").translate() end, { - desc = '翻译单词', + desc = ' 单词翻译', }) vim.api.nvim_create_user_command('TranslateInput', function () require("Trans").translate { method = 'input', } -end, {desc = '翻译单词'}) +end, {desc = ' 搜索翻译'}) -- TODO -- vim.api.nvim_create_user_command('TranslateHistory', require("Trans.core").query_input, { diff --git a/lua/Trans/util/debug.lua b/lua/Trans/util/debug.lua deleted file mode 100644 index 3088acd..0000000 --- a/lua/Trans/util/debug.lua +++ /dev/null @@ -1,32 +0,0 @@ -local M = {} - --- INFO : get loaded debug conf -local type_check = true - -M.type_check = function (types) - if type_check then - vim.validate(types) - end -end - --- local function dedent(lines) --- local ind_size = math.huge --- for i, _ in ipairs(lines) do --- local i1, i2 = lines[i]:find("^%s*[^%s]") --- if i1 and i2 < ind_size then --- ind_size = i2 --- end --- end --- for i, _ in ipairs(lines) do --- lines[i] = lines[i]:sub(ind_size, -1) --- end --- end --- --- function M.dedent(s) --- local lst = vim.split(s, "\n") --- dedent(lst) --- return table.concat(lst, "\n") --- end - - -return M