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