diff --git a/lua/Trans/core/backend.lua b/lua/Trans/core/backend.lua index 1074539..fec610c 100644 --- a/lua/Trans/core/backend.lua +++ b/lua/Trans/core/backend.lua @@ -71,7 +71,6 @@ if file then end -- WARNING : [Breaking change] 'Trans.json' should use json object instead of array - ---@class Trans ---@field backend TransBackendCore return setmetatable(M, { diff --git a/lua/Trans/core/data.lua b/lua/Trans/core/data.lua index 512913a..dcc939d 100644 --- a/lua/Trans/core/data.lua +++ b/lua/Trans/core/data.lua @@ -1,55 +1,39 @@ local Trans = require 'Trans' - ----@class TransData +---@class TransData: TransDataOption +---@field mode string @The mode of the str ---@field from string @Source language type ---@field to string @Target language type ----@field is_word boolean @Is the str a word ---@field str string @The original string ----@field mode string @The mode of the str ---@field result table @The result of the translation ---@field frontend TransFrontend +---@field is_word? boolean @Is the str a word ---@field trace table debug message ---@field backends TransBackend[] local M = {} M.__index = M ---TransData constructor ----@param opts table +---@param opts TransDataOption ---@return TransData function M.new(opts) - local mode = opts.mode - local str = opts.str - + ---@cast opts TransData + local mode = opts.mode + opts.result = {} + opts.trace = {} local strategy = Trans.conf.strategy[mode] - local data = setmetatable({ - str = str, - mode = mode, - result = {}, - trace = {}, - }, M) - data.frontend = Trans.frontend[strategy.frontend].new() - data.backends = {} + ---@cast opts TransData + setmetatable(opts, M) - -- FIXME : - -- for i, name in ipairs(strategy.backend) do - -- data.backends[i] = Trans.backend[name] - -- end - if Trans.util.is_english(str) then - data.from = 'en' - data.to = 'zh' - else - data.from = 'zh' - data.to = 'en' - end - - data.is_word = Trans.util.is_word(str) + -- NOTE : whether should we use the default strategy + opts.frontend = Trans.frontend[strategy.frontend].new() + opts.backends = {} - return data + return opts end ---@class TransResult @@ -69,12 +53,8 @@ end ---@return string? backend.name function M:get_available_result() local result = self.result - - if result['offline'] then return result['offline'], 'offline' end - for _, backend in ipairs(self.backends) do if result[backend.name] then - ---@diagnostic disable-next-line: return-type-mismatch return result[backend.name], backend.name end end diff --git a/lua/Trans/core/debug.lua b/lua/Trans/core/debug.lua new file mode 100644 index 0000000..9ad53d8 --- /dev/null +++ b/lua/Trans/core/debug.lua @@ -0,0 +1,8 @@ +---@class Trans +---@field debug fun(message: string, level: number?) + +return function (message, level) + level = level or vim.log.levels.INFO + -- TODO : custom messaage filter + vim.notify(message, level) +end diff --git a/lua/Trans/core/frontend.lua b/lua/Trans/core/frontend.lua index 67f0a09..ecaefb2 100644 --- a/lua/Trans/core/frontend.lua +++ b/lua/Trans/core/frontend.lua @@ -6,9 +6,9 @@ local default_frontend = { query = 'fallback', border = 'rounded', title = vim.fn.has 'nvim-0.9' == 1 and { - { '', 'TransTitleRound' }, + { '', 'TransTitleRound' }, { ' Trans', 'TransTitle' }, - { '', 'TransTitleRound' }, + { '', 'TransTitleRound' }, } or nil, -- need nvim-0.9+ ---@type {open: string | boolean, close: string | boolean, interval: integer} Window Animation animation = { @@ -16,26 +16,38 @@ local default_frontend = { close = 'slid', interval = 12, }, - timeout = 2000, -- only for online backend query + timeout = 2000, -- only for online backend query } if Trans.conf.frontend.default then default_frontend = vim.tbl_extend('force', default_frontend, Trans.conf.frontend.default) end +local function empty_method(method) + return function() error('Method [' .. method .. '] not implemented') end +end + ---@class TransFrontend ---@field opts? TransFrontendOpts options which user can set ---@field get_active_instance fun():TransFrontend? ----@field process fun(self: TransFrontend, data: TransData) @render backend result ---@field wait fun(self: TransFrontend): fun(backend: TransBackend): boolean Update wait status ---@field execute fun(action: string) @Execute action for frontend instance ----@field fallback fun() @Fallback method when no result ---@field setup? fun() @Setup method for frontend [optional] **NOTE: This method will be called when frontend is first used** +local M = { + ---@type fun() @Fallback method when no result + fallback = empty_method 'fallback', + ---@type fun(self: TransFrontend, data: TransData) @render backend result + process = empty_method 'process', +} + + + + ---@class Trans ---@field frontend TransFrontend -return setmetatable({}, { +return setmetatable(M, { __index = function(self, name) ---@type TransFrontend local frontend = require('Trans.frontend.' .. name) diff --git a/lua/Trans/core/init.lua b/lua/Trans/core/init.lua new file mode 100644 index 0000000..fe169f8 --- /dev/null +++ b/lua/Trans/core/init.lua @@ -0,0 +1,7 @@ +-- Return Core module +local M = {} + + + + +return M diff --git a/lua/Trans/core/translate.lua b/lua/Trans/core/translate.lua index 244426a..93fcab4 100644 --- a/lua/Trans/core/translate.lua +++ b/lua/Trans/core/translate.lua @@ -1,22 +1,43 @@ local Trans = require 'Trans' --- HACK : Core process logic local function process(opts) opts = opts or {} opts.mode = opts.mode or vim.fn.mode() local str = Trans.util.get_str(opts.mode) opts.str = str - if not str or str == '' then return end + + if not str or str == '' then + Trans.debug 'No string to translate' + return + end + + + if opts.from == nil and opts.to == nil then + -- INFO : Default support [zh -> en] or [en -> zh] + if Trans.util.is_english(str) then + opts.from = 'en' + opts.to = 'zh' + else + opts.from = 'zh' + opts.to = 'en' + end + end + assert(opts.from and opts.to, 'opts.from and opts.to must be set at the same time') + + opts.is_word = opts.is_word or Trans.util.is_word(str) -- Find in cache if Trans.cache[str] then local data = Trans.cache[str] - data.frontend:process(data) - return + return data.frontend:process(data) end + + + + -- Create new data local data = Trans.data.new(opts) if Trans.strategy[data.frontend.opts.query](data) then Trans.cache[data.str] = data @@ -26,9 +47,18 @@ local function process(opts) end end ----@class Trans ----@field translate fun(opts: { frontend: string?, mode: string?}?) Translate string core function -return function(opts) - coroutine.wrap(process)(opts) -end +---@class TransDataOption +---@field mode string? +---@field frontend string? +---@field from string? @Source language type +---@field to string? @Target language type +---@field is_word? boolean @Is the str a word + + + +--- NOTE : Use coroutine to stop and resume the process (for animation) + +---@class Trans +---@field translate fun(opts: TransDataOption?) Translate string core function +return function(...) coroutine.wrap(process)(...) end diff --git a/lua/Trans/core/util.lua b/lua/Trans/core/util.lua index 4d50638..8c934b4 100644 --- a/lua/Trans/core/util.lua +++ b/lua/Trans/core/util.lua @@ -38,21 +38,21 @@ end ---Get selected text ---@return string function M.get_lines() - local _start = vim.fn.getpos 'v' - local _end = vim.fn.getpos '.' + local _start = vim.fn.getpos 'v' + local _end = vim.fn.getpos '.' - if _start[2] > _end[2] then - _start, _end = _end, _start - end + if _start[2] > _end[2] then + _start, _end = _end, _start + end - local s_row, e_row = _start[2], _end[2] + local s_row, e_row = _start[2], _end[2] - if s_row == e_row then - return vim.fn.getline(s_row) - else - local lines = vim.fn.getline(s_row, e_row) - return table.concat(lines, " ") - end + if s_row == e_row then + return vim.fn.getline(s_row) + else + local lines = vim.fn.getline(s_row, e_row) + return table.concat(lines, ' ') + end end ---Get Text which need to be translated @@ -224,6 +224,13 @@ function M.list_fields(list, field) return ret end +-- function M.checker(method, ...) +-- -- TODO :Use function programming to simplify the code +-- local params = { ... } + +-- end + + ---@class Trans ---@field util TransUtil return M