diff --git a/.gitignore b/.gitignore index a0863a7..70eae03 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ lua/Trans/util/ -lua/Trans/core/ +lua/Trans/test/ +note/ +go/ diff --git a/README.md b/README.md index 3599452..1b5f88c 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ - [高亮组](#高亮组) - [声明](#声明) - [感谢](#感谢) - - [TODO](#todo) + - [待办 (画大饼)](#待办-画大饼) @@ -194,7 +194,7 @@ vim.keymap.set('n', 'mi', 'TranslateInput') - [sqlite.lua](https://github.com/kharji/sqlite.lua) 数据库访问 - [T.vim](https://github.com/sicong-li/T.vim) 灵感来源 -## TODO +## 待办 (画大饼) - ~~移动光标自动关闭窗口~~ - 多风格样式 - 历史查询结果保存 diff --git a/go/go.mod b/go/go.mod deleted file mode 100644 index 606edce..0000000 --- a/go/go.mod +++ /dev/null @@ -1,3 +0,0 @@ -module query_online - -go 1.19 diff --git a/go/query_online.go b/go/query_online.go deleted file mode 100644 index fc5345e..0000000 --- a/go/query_online.go +++ /dev/null @@ -1,50 +0,0 @@ -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/install.sh b/install.sh index a939dce..a9adb84 100755 --- a/install.sh +++ b/install.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -e if [[ -d "$HOME/.vim" ]]; then diff --git a/lua/Trans/content.lua b/lua/Trans/content.lua new file mode 100644 index 0000000..ba2f31f --- /dev/null +++ b/lua/Trans/content.lua @@ -0,0 +1,167 @@ +local api = vim.api +local content = { + newline = function(self, value) + if not self.modifiable then + error('content can not add newline now') + end + self.size = self.size + 1 + self.lines[self.size] = value + end, + + newhl = function(self, opt) + if not self.modifiable then + error('content can not add newline now') + end + self.hl_size = self.hl_size + 1 + self.highlights[self.hl_size] = opt + end, + + center_line = function(self, text, highlight) + vim.validate { + text = { text, 's' } + } + + local space = math.floor((self.window.width - text:width()) / 2) + local interval = (' '):rep(space) + self:newline(interval .. text) + if highlight then + self:newhl { + name = highlight, + line = self.size - 1, + _start = space, + _end = space + #text, + } + end + end, + + wipe = function(self) + local clear = require('table.clear') + clear(self.lines) + clear(self.highlights) + self.size = 0 + end, + + attach = function(self) + if self.size == 0 then + return + end + + self.window:bufset('modifiable', true) + local window = self.window + local offset = self.offset + + api.nvim_buf_set_lines(window.bufnr, offset, offset + 1, true, self.lines) + + for _, hl in ipairs(self.highlights) do + api.nvim_buf_add_highlight(window.bufnr, window.hl, hl.name, offset + hl.line, hl._start, hl._end) + end + self.window:bufset('modifiable', false) + end, + + actual_height = function(self) + if self.window:option('wrap') then + local height = 0 + local width = self.window.width + local lines = self.lines + for i = 1, self.size do + height = height + math.max(1, (math.ceil(lines[i]:width() / width))) + end + return height + else + return self.size + end + end, + + addline = function(self, newline, highlight) + self:newline(newline) + if highlight then + self:newhl { + name = highlight, + line = self.size - 1, + _start = 0, + _end = -1, + } + end + end, + + items_wrap = function(self) + local items = {} + local size = 0 + local width = 0 + + return { + add_item = function(item, highlight) + size = size + 1 + items[size] = { item, highlight } + width = width + item:width() + end, + + load = function() + assert(size > 1, 'no item need be loaded') + local space = math.floor((self.window.width - width) / (size - 1)) + assert(space > 0, 'try to expand window width') + local interval = (' '):rep(space) + local line = '' + + local function load_item(idx) + local item = items[idx] + if item[2] then + self:newhl { + name = item[2], + line = self.size, -- NOTE : 此时还没插入新行, size ==> 行号(zero index) + _start = #line, + _end = #line + #item[1], + } + end + line = line .. item[1] + end + + load_item(1) + for i = 2, size do + line = line .. interval + load_item(i) + end + + self:newline(line) + end + } + end, + + line_wrap = function(self) + self:newline('') + local index = self.size + return function(text, highlight) + if highlight then + local _start = #self.lines[index] + local _end = _start + #text + self:newhl { + name = highlight, + line = index - 1, + _start = _start, + _end = _end, + } + end + + self.lines[index] = self.lines[index] .. text + end + end +} + + +---content的构造函数 +---@param window table 链接的窗口 +---@return table 构造好的content +return function(window, offset) + vim.validate { + window = { window, 't' }, + } + return setmetatable({ + modifiable = true, + offset = offset or 0, + window = window, + size = 0, + hl_size = 0, + lines = {}, + highlights = {}, + }, { __index = content }) +end diff --git a/lua/Trans/init.lua b/lua/Trans/init.lua index a7232a1..389b50f 100644 --- a/lua/Trans/init.lua +++ b/lua/Trans/init.lua @@ -20,8 +20,14 @@ M.conf = { -- TODO : pageup = '[[', pagedown = ']]', + pin = '_', + close = '+', }, - animation = 13, + animation = { + open = 'slid', + close = 'slid', + interval = 12, + } }, float = { width = 0.8, @@ -35,7 +41,11 @@ M.conf = { keymap = { quit = 'q', }, - animation = 9, + animation = { + open = 'slid', + close = 'slid', + interval = 8, + } }, order = { -- offline = { diff --git a/lua/Trans/view/hover.lua b/lua/Trans/view/hover.lua index 04a7db1..d94b3a7 100644 --- a/lua/Trans/view/hover.lua +++ b/lua/Trans/view/hover.lua @@ -1,12 +1,14 @@ +local api = vim.api local conf = require('Trans').conf local icon = conf.icon -local m_window = require('Trans.window') +local m_window local m_result +local m_content local m_indent = ' ' local title = function(str) - local wrapper = m_window.text_wrap() + local wrapper = m_content:line_wrap() -- wrapper('', 'TransTitleRound') wrapper('', 'TransTitleRound') wrapper(str, 'TransTitle') @@ -61,7 +63,7 @@ end local process = { title = function() - local line = m_window.line_wrap() + local line = m_content:items_wrap() line.add_item( m_result.word, 'TransWord' @@ -94,12 +96,13 @@ local process = { end for i = 1, size, 3 do - m_window.addline( + m_content:addline( m_indent .. tags[i] .. interval .. (tags[i + 1] or '') .. interval .. (tags[i + 2] or ''), 'TransTag' ) end - m_window.addline('') + + m_content:addline('') end end, @@ -108,13 +111,13 @@ local process = { title('词性') for pos in vim.gsplit(m_result.pos, '/', true) do - m_window.addline( + m_content:addline( m_indent .. pos_map[pos:sub(1, 1)] .. pos:sub(3) .. '%', 'TransPos' ) end - m_window.addline('') + m_content:addline('') end end, @@ -124,13 +127,13 @@ local process = { local interval = ' ' for exc in vim.gsplit(m_result.exchange, '/', true) do - m_window.addline( + m_content:addline( m_indent .. exchange_map[exc:sub(1, 1)] .. interval .. exc:sub(3), 'TransExchange' ) end - m_window.addline('') + m_content:addline('') end end, @@ -138,13 +141,13 @@ local process = { title('中文翻译') for trs in vim.gsplit(m_result.translation, '\n', true) do - m_window.addline( + m_content:addline( m_indent .. trs, 'TransTranslation' ) end - m_window.addline('') + m_content:addline('') end, definition = function() @@ -153,18 +156,18 @@ local process = { for def in vim.gsplit(m_result.definition, '\n', true) do def = def:gsub('^%s+', '', 1) -- TODO :判断是否需要分割空格 - m_window.addline( + m_content:addline( m_indent .. def, 'TransDefinition' ) end - m_window.addline('') + m_content:addline('') end end, failed = function() - m_window.addline( + m_content:addline( icon.notfound .. m_indent .. '没有找到相关的翻译', 'TransFailed' ) @@ -172,12 +175,71 @@ local process = { } +local cmd_id + +local try_del_keymap = function() + for _, key in pairs(conf.hover.keymap) do + pcall(vim.keymap.del, 'n', key, { buffer = true }) + end +end + + +local pin = false local action = { pageup = function() - m_window.normal('gg') + m_window:normal('gg') end, + pagedown = function() - m_window.normal('G') + m_window:normal('G') + end, + + pin = function() + if pin then + error('too many window') + end + if cmd_id > 0 then + api.nvim_del_autocmd(cmd_id) + cmd_id = -1 + end + + m_window:set('wrap', false) + + m_window:try_close(function() + m_window:reopen(false, { + relative = 'editor', + row = 1, + col = vim.o.columns - m_window.width - 3, + }, function() + m_window:set('wrap', true) + end) + + m_window:bufset('bufhidden', 'wipe') + vim.keymap.del('n', conf.hover.keymap.pin, { buffer = true }) + + local buf = m_window.bufnr + pin = true + + api.nvim_create_autocmd('BufWipeOut', { + callback = function(opt) + if opt.buf == buf then + pin = false + api.nvim_del_autocmd(opt.id) + end + end + }) + end) + end, + + close = function() + if cmd_id > 0 then + api.nvim_del_autocmd(cmd_id) + cmd_id = -1 + end + + m_window:set('wrap', false) + m_window:try_close() + try_del_keymap() end, } @@ -190,7 +252,7 @@ return function(word) -- 目前只处理了本地数据库的查询 m_result = require('Trans.query.offline')(word) local hover = conf.hover - local opt = { + local opt = { relative = 'cursor', width = hover.width, height = hover.height, @@ -200,8 +262,9 @@ return function(word) row = 2, } - - m_window.init(false, opt) + m_window = require("Trans.window")(false, opt) + m_window.animation = hover.animation + m_content = m_window.content if m_result then for _, field in ipairs(conf.order) do @@ -211,25 +274,24 @@ return function(word) process.failed() end - m_window.draw() + m_window:draw(true) + m_window:open(function() + m_window:set('wrap', true) + end) + -- Auto Close - vim.api.nvim_create_autocmd( - { --[[ 'InsertEnter', ]] 'CursorMoved', 'BufLeave', }, { + cmd_id = api.nvim_create_autocmd( + { 'InsertEnter', 'CursorMoved', 'BufLeave', }, { buffer = 0, once = true, callback = function() - m_window.try_close(hover.animation) -- NOTE :maybe can be passed by uesr + m_window:set('wrap', false) + m_window:try_close() + try_del_keymap() end, }) - m_window.set('wrap', true) - m_window.adjust() - for act, key in pairs(hover.keymap) do - vim.keymap.set('n', key, function() - if m_window.is_open() then - action[act]() - end - end) + vim.keymap.set('n', key, action[act], { buffer = true, silent = true }) end end diff --git a/lua/Trans/window.lua b/lua/Trans/window.lua index 5900289..6abc068 100644 --- a/lua/Trans/window.lua +++ b/lua/Trans/window.lua @@ -1,29 +1,232 @@ local api = vim.api ---- =================== Window Attributes ================================ -local M = { - height = 0, -- 窗口的当前的高度 - size = 0, -- 窗口的行数 - width = 0, -- 窗口的当前的宽度 - lines = {}, - highlights = {}, - winid = -1, -- 窗口的handle - bufnr = -1, -- 窗口对应的buffer的handle - hl = api.nvim_create_namespace('TransWinHl'), -} --- M.<++> --> <++> +---@diagnostic disable-next-line: duplicate-set-field function string:width() ---@diagnostic disable-next-line: param-type-mismatch return vim.fn.strwidth(self) end ---- =================== Load Window Options ================================ -M.init = function(entry, opts) +local busy = false +local function check_busy() + while busy do + vim.wait(50) + end +end + +---@type window +local window = { + ---设置窗口的选项 + ---@param self table 需要设置的window + ---@param option string 待设置的选项名 + ---@param value any 选项的值 + set = function(self, option, value) + api.nvim_win_set_option(self.winid, option, value) + end, + + ---设置窗口的高度 + ---@param self table 窗口类 + ---@param height integer 设置的高度 + set_height = function(self, height) + api.nvim_win_set_height(self.winid, height) + self.height = height + end, + + ---设置窗口的宽度 + ---@param self table 窗口对象 + ---@param width integer 设置的宽度 + set_width = function(self, width) + api.nvim_win_set_width(self.winid, width) + self.width = width + end, + + ---设置窗口对应的buffer + ---@param self table 同set类似 + ---@param option string + ---@param value any + bufset = function(self, option, value) + api.nvim_buf_set_option(self.bufnr, option, value) + end, + + ---查看**窗口**的选项 + ---@param self table 窗口对象 + ---@param name string 选项名 + ---@return any 对应的值 + ---@nodiscard + option = function(self, name) + return api.nvim_win_get_option(self.winid, name) + end, + + ---设置当前窗口内的键映射, **需要光标在该窗口内** + ---@param self table 窗口对象 + ---@param key string 映射的键位 + ---@param operation any 执行的操作 + map = function(self, key, operation) + vim.keymap.set('n', key, operation, { + buffer = self.bufnr, + silent = true, + }) + end, + + ---查看窗口是否是打开状态 + ---@param self table window对象 + ---@return boolean + ---@nodiscard + is_open = function(self) + return self.winid > 0 and api.nvim_win_is_valid(self.winid) + end, + + normal = function(self, key) + api.nvim_buf_call(self.bufnr, function() + vim.cmd([[normal! ]] .. key) + end) + end, + + ---**第一次**绘制窗口的内容 + ---@param self table 窗口的对象 + ---@param adjust boolean 是否需要调整窗口的高度和宽度 (只有窗口只有一行时才会调整宽度) + draw = function(self, adjust) + -- TODO : + if self.title then + self.title:attach() + end + self.content:attach() + + if adjust then + local height = self.content:actual_height() + self.title:actual_height() + if self.height > height then + self:set_height(height) + end + + if self.content.size == 1 and self.title.size == 0 then + self:set_width(self.content.lines[1]:width()) + end + end + end, + + open = function(self, callback) + local animation = self.animation + if animation.open then + check_busy() + + local handler + local function wrap(name, target) + local count = 0 + return function() + if count < self[target] then + busy = true + count = count + 1 + api['nvim_win_set_' .. target](self.winid, count) + vim.defer_fn(handler[name], animation.interval) + + else + busy = false + if type(callback) == 'function' then + callback() + end + end + end + end + + handler = { + slid = wrap('slid', 'width'), + fold = wrap('fold', 'height'), + } + + handler[animation.open]() + end + end, + + ---**重新绘制内容**(标题不变) + ---@param self table 窗口对象 + redraw = function(self) + self.content:attach() + end, + + + ---安全的关闭窗口 + try_close = function(self, callback) + if self:is_open() then + check_busy() + self.config = api.nvim_win_get_config(self.winid) + local animation = self.animation + if animation.close then + + local handler + local function wrap(name, target) + local count = self[target] + return function() + if count > 1 then + busy = true + count = count - 1 + api['nvim_win_set_' .. target](self.winid, count) + vim.defer_fn(handler[name], animation.interval) + + else + vim.defer_fn(function() + api.nvim_win_close(self.winid, true) + self.winid = -1 + busy = false + + if type(callback) == 'function' then + callback() + end + + end, animation.interval + 2) + end + end + end + + handler = { + slid = wrap('slid', 'width'), + fold = wrap('fold', 'height'), + } + + handler[animation.close]() + + else + api.nvim_win_close(self.winid, true) + self.winid = -1 + end + end + end, + + reopen = function (self, entry, opt, callback) + check_busy() + self.config.win = nil + if opt then + for k, v in pairs(opt) do + self.config[k] = v + end + end + + self.winid = api.nvim_open_win(self.bufnr, entry, self.config) + self:open(callback) + end +} + +---@class window +---@field title table 窗口不变的title对象,载入后不可修改 +---@field winid integer 窗口的handle +---@field bufnr integer 窗口对应buffer的handle +---@field content table 窗口内容的对象, 和title一样是content类 +---@field width integer 窗口当前的宽度 +---@field height integer 窗口当前的高度 +---@field hl integer 窗口highlight的namespace + + + +---窗口对象的构造器 +---@param entry boolean 光标初始化时是否应该进入窗口 +---@param option table 需要设置的选项 +---@return window +---@nodiscard +return function(entry, option) vim.validate { entry = { entry, 'b' }, - opts = { opts, 't' } + option = { option, 't' }, } + local opt = { relative = nil, width = nil, @@ -37,253 +240,44 @@ M.init = function(entry, opts) zindex = 100, style = 'minimal', } - - for k, v in pairs(opts) do + for k, v in pairs(option) do opt[k] = v end - M.height = opt.height - M.width = opt.width - M.bufnr = api.nvim_create_buf(false, true) - M.winid = api.nvim_open_win(M.bufnr, entry, opt) - M.set('winhl', 'Normal:TransWin,FloatBorder:TransBorder') - M.bufset('bufhidden', 'wipe') - M.bufset('filetype', 'Trans') - M.wipe() -end + local bufnr = api.nvim_create_buf(false, true) + local winid = api.nvim_open_win(bufnr, entry, opt) - -M.draw = function() - -- TODO : - M.bufset('modifiable', true) - api.nvim_buf_set_lines(M.bufnr, 0, -1, false, M.lines) - for _, hl in ipairs(M.highlights) do - api.nvim_buf_add_highlight(M.bufnr, M.hl, hl.name, hl.line, hl._start, hl._end) - end - - M.bufset('modifiable', false) - -- vim.pretty_print(M.highlights) -end - ----清空window的数据 -M.wipe = function() - M.size = 0 - local clear = require('table.clear') - clear(M.lines) - clear(M.highlights) -end - -M.is_open = function() - return M.winid > 0 and api.nvim_win_is_valid(M.winid) -end - - ----安全的关闭窗口 ----@param interval integer 窗口关闭动画的间隔 -M.try_close = function(interval) - if M.is_open() then - local function narrow() - if M.height > 1 then - M.height = M.height - 1 - api.nvim_win_set_height(M.winid, M.height) - vim.defer_fn(narrow, interval) - else - -- Wait animation done - vim.defer_fn(function() - api.nvim_win_close(M.winid, true) - M.winid = -1 - end, interval + 2) - end - end - - narrow() - end -end - - -M.cur_height = function() - if api.nvim_win_get_option(M.winid, 'wrap') then - local height = 0 - local width = M.width - local lines = M.lines - - for i = 1, M.size do - height = height + math.max(1, (math.ceil(lines[i]:width() / width))) - end - return height - - else - return M.size - end -end - - -M.adjust = function() - local cur_height = M.cur_height() - if M.height > cur_height then - api.nvim_win_set_height(M.winid, cur_height) - M.height = cur_height - end - - if M.size == 1 then - api.nvim_win_set_width(M.winid, M.lines[1]:width()) - end -end - - ----- ============ Utility functions ============ ----设置窗口选项 ----@param option string 需要设置的窗口 ----@param value any 需要设置的值 -M.set = function(option, value) - api.nvim_win_set_option(M.winid, option, value) -end - ----设置窗口对应buffer的选项 ----@param option string 需要设置的窗口 ----@param value any 需要设置的值 -M.bufset = function(option, value) - api.nvim_buf_set_option(M.bufnr, option, value) -end - - -M.normal = function(key) - api.nvim_buf_call(M.bufnr, function() - vim.cmd([[normal! ]] .. key) - end) -end - ----设置该窗口的本地的键映射(都为normal模式) ----@param key string 映射的键 ----@param operation any 执行的操作 -M.map = function(key, operation) - -- api.nvim_buf_set_keymap(M.bufnr, 'n', key, operation, { silent = true, noremap = true, }) - vim.keymap.set('n', key, operation, { - silent = true, - buffer = M.bufnr, - }) -end - - ---- =================== Window lines ================================ -local function insert_line(text) - vim.validate { - text = { text, 's' }, - } - - M.size = M.size + 1 - M.lines[M.size] = text -end - - ----向窗口中添加新行 ----@param newline string 待添加的新行 ----@param opt? table|string 可选的行属性: highlight, TODO : -M.addline = function(newline, opt) - insert_line(newline) - - if type(opt) == 'string' then - table.insert(M.highlights, { - name = opt, - line = M.size - 1, -- NOTE : 高亮的行号是以0为第一行 - _start = 0, - _end = -1, - }) - -- elseif type(opt) == 'table' then - -- -- TODO : - -- error('TODO') - end -end - ----添加一行新的内容并居中 ----@param text string 需要居中的文本 ----@param highlight? string 可选的高亮组 -M.center = function(text, highlight) - vim.validate { - text = { text, 's' } - } - local space = math.floor((M.width - text:width()) / 2) - local interval = (' '):rep(space) - insert_line(interval .. text) - if highlight then - table.insert(M.highlights, { - name = highlight, - line = M.size - 1, - _start = space, - _end = space + #text, - }) - end -end - - ----返回一个行的包装器: 具有 [add_item] [load] 方法 ----能够添加item, 调用load格式化并载入window.lines -M.line_wrap = function() - local items = {} - local width = 0 -- 所有item的总width - local size = 0 -- item数目 - return { - add_item = function(item, highlight) - size = size + 1 - items[size] = { item, highlight } - width = width + item:width() - end, - - load = function() - assert(size > 1, 'no item need be loaded') - local space = math.floor((M.width - width) / (size - 1)) - assert(space > 0, 'try to expand window width') - local interval = (' '):rep(space) - local value = '' - local function load_item(idx) - local item = items[idx] - if item[2] then - table.insert(M.highlights, { - name = item[2], - line = M.size, -- NOTE : 此时还没插入新行, size ==> 行号(zero index) - _start = #value, - _end = #value + #item[1], - }) + local win = setmetatable({ + winid = winid, + bufnr = bufnr, + title = nil, + content = nil, + width = opt.width, + height = opt.height, + hl = api.nvim_create_namespace('TransWinHl'), + }, + { __index = function(tbl, key) + if key == 'content' then + if tbl.title then + tbl.content = require('Trans.content')(tbl, tbl.title.size) + tbl.title.modifiable = false + else + tbl.content = require('Trans.content')(tbl) end - value = value .. item[1] + return tbl.content + + elseif key == 'title' then + tbl.title = require('Trans.content')(tbl, 0) + return tbl.title + + else + return window[key] end + end }) - load_item(1) - for i = 2, size do - value = value .. interval - load_item(i) - end + win:set('winhl', 'Normal:TransWin,FloatBorder:TransBorder') + win:bufset('filetype', 'Trans') - insert_line(value) - end - } + ---@diagnostic disable-next-line: return-type-mismatch + return win end - - - -M.text_wrap = function() - insert_line('') - local l = M.size - - return function(text, highlight) - if highlight then - local _start = #M.lines[l] - local _end = _start + #text - table.insert(M.highlights, { - name = highlight, - line = M.size - 1, - _start = _start, - _end = _end, - }) - end - - M.lines[l] = M.lines[l] .. text - end -end - - - ---- =================== Window Highlights ================================ ---- TODO : add helpful function for highlights - -return M diff --git a/note/api.md b/note/api.md deleted file mode 100644 index 3b4d0ef..0000000 --- a/note/api.md +++ /dev/null @@ -1,132 +0,0 @@ -# API说明 - - -- [API说明](#api说明) - - [数据结构](#数据结构) - - [翻译](#翻译) - - [窗口](#窗口) - - [翻译结果](#翻译结果) - - [内容单位](#内容单位) -- [窗口绘制逻辑](#窗口绘制逻辑) - - [hover](#hover) - - [float](#float) - - -## 数据结构 - -### 翻译 -- `word` -待翻译的字符串: string -- `sentence` -是否为句子: boolean -- `result` -翻译查询的结果: table - > 见: [翻译结果](#翻译结果) -- `engine` - -### 窗口 -- `style` -风格: string -- `height` -高度: integer -- `width` -宽度: integer -- `border` -边框样式: string -- `winhl` -窗口的高亮: string - -### 翻译结果 -**无特殊说明, 所有字段均为`string`类型** - -- `word` -查询的字符串 -- `phonetic` -音标 -- `collins` -柯林斯星级: integer -- `oxford` -是否为牛津词汇: integer (1为是) -- `tag` -标签 -- `pos` -词性 -- `exchange` -词态变化 -- `translation` -中文翻译 -- `definition` -英文注释 - - -### 内容单位 -- `field` 字段 - > 是展示的最小单位 - - **属性** - - `1` - 存储的文本: string - - `2` (optional) - 对应的高亮: string - - `_start` - 起始行: integer - - `_end` - 结束行: integer - > **注意:** `_start` 和`_end` 字段只有已经被展示到窗口后才会被设置 - - **方法** - - 无 - -- `line` 行 - > 窗口展示的每一行, 一个行有多个`field` - - **属性** - - `text` - 当前保存的字符串: string - - `hls` - 行内的高亮: table - - `index` - 行号[0为起始下标] - - `fields` - 行内保存的`field` - - `status` - 行内是否需要更新: boolean - > **注意:** `num` 只有已经被展示到窗口后才会被设置 - - **方法** - - `update` - 更新`text`和`hls` - - `data` - 获取行的text - - `insert` - 添加新`field` - - `add_highlight` - 添加高亮 - > 参数: bufnr - -- `content` 内容 - > 窗口展示的单位, 一个内容内有多个`line` - - **方法** - - `data` - 返回lines和highlights - - `insert` - 插入新的行 - - `attach` - 将内容展示到buffer - > 参数: bufnr - -# 窗口绘制逻辑 - -- 获取所有组件 -## hover -- 按照order顺序加载 -- 按组件间距为4计算组件个数能否在一行以内放下 - - 放不下则按照组件间距为4 计算组件个数并对齐 - - 放得下则重新计算组间距 - -获得组件行内容, 设置到行内 -获取组件高亮, 设置高亮 - -## float -由定义好的逻辑,绘制整个窗口 diff --git a/note/engine.md b/note/engine.md deleted file mode 100644 index 4999dc9..0000000 --- a/note/engine.md +++ /dev/null @@ -1,129 +0,0 @@ -# 字段说明 - - -- [字段说明](#字段说明) - - [本地](#本地) - - [有道](#有道) - - [中英](#中英) - - [百度](#百度) - - [返回结果](#返回结果) - - [彩云小译](#彩云小译) - - [必应](#必应) - - [腾讯翻译君](#腾讯翻译君) - - [阿里翻译](#阿里翻译) - - [火山翻译](#火山翻译) - - [金山词霸](#金山词霸) - - -## 本地 -- `word` -查询的字符串 -- `phonetic` -音标 -- `collins` -柯林斯星级: integer -- `oxford` -是否为牛津词汇: integer (1为是) -- `tag` -标签 -- `pos` -词性 -- `exchange` -词态变化 -- `translation` -中文翻译 -- `definition` -英文注释 - -## 有道 -### 中英 - -basic JSONObject 简明释义 -phonetic text 词典音标 -usPhonetic text 美式音标 -ukPhonetic text 英式音标 -ukSpeech text 英式发音 -usSpeech text 美式发音 -explains text 基本释义 -text text 短语 -explain String Array 词义解释列表 -wordFormats Object Array 单词形式变化列表 -name String 形式名称,例如:复数 -web JSONArray 网络释义 -phrase String 词组 -meaning String 含义 -synonyms JSONObject 近义词 -pos String 词性 -words String Array 近义词列表 -trans String 释义 -antonyms ObjectArray 反义词 -relatedWords JSONArray 相关词 -wordNet JSONObject 汉语词典网络释义 -phonetic String 发音 -meanings ObjectArray 释义 -meaning String 释义 -example array 示例 -dict String 词典deeplink -webDict String 词典网页deeplink -sentenceSample text 例句 -sentence text 例句 -sentenceBold text 将查询内容加粗的例句 -translation text 例句翻译 -wfs text 单词形式变化 -exam_type text 考试类型 - -## 百度 -from string 源语言 返回用户指定的语言,或者自动检测出的语种(源语言设为auto时) -to string 目标语言 返回用户指定的目标语言 -trans_result array 翻译结果 返回翻译结果,包括src和dst字段 -trans_result.*.src string 原文 接入举例中的“apple” -trans_result.*dst string 译文 接入举例中的“苹果” -error_code integer 错误码 仅当出现错误时显示 -以下字段仅开通了词典、tts用户可见 -src_tts string 原文tts链接 mp3格式,暂时无法指定发音 -dst_tts string 译文tts链接 mp3格式,暂时无法指定发音 -dict string 中英词典资源 返回中文或英文词典资源,包含音标;简明释义等内容 - -### 返回结果 -- 英-> 中 -```json -{ - "from": "en", - "to": "zh", - "trans_result": [ - { - "src": "apple", - "dst": "苹果" - } - ] -} -``` -- 中->英 -```json -{ - "from": "zh", - "to": "en", - "trans_result": [ - { - "src": "中国", - "dst": "China" - } - ] -} -``` -## 彩云小译 -句子翻译 -> sh xiaoyi.sh en2zh "You know some birds are not meant to be caged, their feathers are just too bright." -> 你知道有些鸟不应该被关在笼子里,它们的羽毛太亮了。 - -## 必应 - -## 腾讯翻译君 - -## 阿里翻译 - -## 火山翻译 - -## 金山词霸 - -## Dictionary diff --git a/note/logic.md b/note/logic.md deleted file mode 100644 index fda9162..0000000 --- a/note/logic.md +++ /dev/null @@ -1,96 +0,0 @@ -# 命令说明 - - -- [命令说明](#命令说明) - - [Translate](#translate) - - [TranslateInput](#translateinput) - - [TranslateHistory](#translatehistory) - - [自定义](#自定义) - - [可选项说明](#可选项说明) - - [示例](#示例) - - -## 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` - - `offline` 离线的数据库 - - `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', -- 不填则自动判断mode获取查询的单词 - engine = { -- 异步查询所有的引擎, 按照列表 - 'offline', - 'youdao', - 'baidu' - }, - -- win = 'cursor' - win = { - style = 'cursor', - height = 50, - width = 30, - } - }) -end, { desc = '在光标旁弹出输入的单词释义'}) -```