From bc8c673ee0db358f04beab292b6be14fe2bcf932 Mon Sep 17 00:00:00 2001
From: JuanZoran <1430359574@qq.com>
Date: Sun, 12 Mar 2023 20:09:08 +0800
Subject: [PATCH] fix: change global config to default option

---
 lua/Trans/.clocignore        |   5 +
 lua/Trans/README.md          |   1 +
 lua/Trans/core/backend.lua   |  14 +-
 lua/Trans/core/conf.lua      |  26 ++--
 lua/Trans/core/frontend.lua  |  17 +++
 lua/Trans/core/setup.lua     |  91 +++++++++--
 lua/Trans/core/util.lua      |   9 ++
 lua/Trans/frontend/hover.lua |  17 +--
 lua/Trans/init.lua           |   2 -
 lua/Trans/wrapper/window.lua | 289 ++++++++++++++++++-----------------
 10 files changed, 287 insertions(+), 184 deletions(-)
 create mode 100644 lua/Trans/.clocignore
 create mode 100644 lua/Trans/core/frontend.lua

diff --git a/lua/Trans/.clocignore b/lua/Trans/.clocignore
new file mode 100644
index 0000000..10a888a
--- /dev/null
+++ b/lua/Trans/.clocignore
@@ -0,0 +1,5 @@
+./README.md
+./util/md5.lua
+./util/base64.lua
+./util/bak_init.lua
+./test
diff --git a/lua/Trans/README.md b/lua/Trans/README.md
index a43075c..24ab2b7 100644
--- a/lua/Trans/README.md
+++ b/lua/Trans/README.md
@@ -10,3 +10,4 @@
 -   [ ] Check if str is a word
 -   [ ] init frontend window
 -   [ ] build frontend window format logic
+-   [ ] waitting animation
diff --git a/lua/Trans/core/backend.lua b/lua/Trans/core/backend.lua
index 21247b1..cdec2eb 100644
--- a/lua/Trans/core/backend.lua
+++ b/lua/Trans/core/backend.lua
@@ -1,8 +1,9 @@
 local Trans = require('Trans')
 local M = Trans.metatable('backend')
+local conf = Trans.conf
 
 --- INFO :Parse online engine keys config file
-local path = Trans.conf.dir .. '/Trans.json'
+local path = conf.dir .. '/Trans.json'
 local file = io.open(path, "r")
 
 if file then
@@ -14,19 +15,12 @@ if file then
     end
 
 
-
-    local default_opts = vim.deepcopy(Trans.conf.backend)
     for name, private_opts in pairs(result or {}) do
-        local opts = vim.tbl_extend('keep', Trans.conf.backend[name] or {}, default_opts, private_opts)
-
-        local backend = M[name]
+        local opts = vim.tbl_extend('keep', conf.backend[name] or {}, conf.backend.default, private_opts)
         for k, v in pairs(opts) do
-            if not backend[k] then
-                backend[k] = v
-            end
+            M[name][k] = v
         end
     end
 end
 
-
 return M
diff --git a/lua/Trans/core/conf.lua b/lua/Trans/core/conf.lua
index 983fe13..018bd04 100644
--- a/lua/Trans/core/conf.lua
+++ b/lua/Trans/core/conf.lua
@@ -10,21 +10,27 @@ end
 return {
     dir      = os.getenv('HOME') .. '/.vim/dict',
     strategy = {
-        frontend = 'hover',
-        backend = '*',
+        default = {
+            frontend = 'hover',
+            backend = '*',
+        },
     },
     backend  = {
-        timeout = 2000,
+        default = {
+            timeout = 2000,
+        },
     },
     frontend = {
-        auto_play = true,
-        border = 'rounded',
-        animation = {
-            open = 'slid', -- 'fold', 'slid'
-            close = 'slid',
-            interval = 12,
+        default = {
+            auto_play = true,
+            border = 'rounded',
+            animation = {
+                open = 'slid', -- 'fold', 'slid'
+                close = 'slid',
+                interval = 12,
+            },
+            title = title, -- need nvim-0.9
         },
-        title = title, -- need nvim-0.9
         hover = {
             width = 37,
             height = 27,
diff --git a/lua/Trans/core/frontend.lua b/lua/Trans/core/frontend.lua
new file mode 100644
index 0000000..4c88885
--- /dev/null
+++ b/lua/Trans/core/frontend.lua
@@ -0,0 +1,17 @@
+local Trans = require('Trans')
+local M = Trans.metatable('frontend')
+
+
+-- local default_opts = vim.deepcopy(Trans.conf.frontend)
+-- for name, private_opts in pairs(result or {}) do
+--     local opts = vim.tbl_extend('keep', Trans.conf.backend[name] or {}, default_opts, private_opts)
+
+--     local backend = M[name]
+--     for k, v in pairs(opts) do
+--         if not backend[k] then
+--             backend[k] = v
+--         end
+--     end
+-- end
+
+return M
diff --git a/lua/Trans/core/setup.lua b/lua/Trans/core/setup.lua
index 011dafb..fdcecd2 100644
--- a/lua/Trans/core/setup.lua
+++ b/lua/Trans/core/setup.lua
@@ -13,27 +13,24 @@ local function set_strategy_opts(conf)
         return backend
     end
 
-    local global_strategy = conf.strategy
-    global_strategy.backend = parse_backend(global_strategy.backend)
+    local default_strategy = conf.strategy.default
+    default_strategy.backend = parse_backend(default_strategy.backend)
+
+
 
 
     local meta = {
         __index = function(tbl, key)
-            tbl[key] = global_strategy[key]
+            tbl[key] = default_strategy[key]
             return tbl[key]
         end
     }
 
-
+    local strategy = conf.strategy
     for _, mode in ipairs(all_modes) do
-        if not global_strategy[mode] then
-            global_strategy[mode] = setmetatable({}, meta)
-        else
-            if mode.backend then
-                mode.backend = parse_backend(mode.backend)
-            end
-
-            setmetatable(mode, meta)
+        strategy[mode] = setmetatable(strategy[mode] or {}, meta)
+        if type(strategy[mode].backend) == 'string' then
+            strategy[mode].backend = parse_backend(strategy[mode].backend)
         end
     end
 end
@@ -102,4 +99,74 @@ return function(opts)
     set_frontend_opts(conf)
     define_keymaps(conf)
     define_highlights(conf)
+
 end
+
+-- {
+--   backend = {
+--     default = {
+--       timeout = 2000
+--     }
+--   },
+--   dir = "/home/zoran/.vim/dict",
+--   frontend = {
+--     default = {
+--       animation = {
+--         close = "slid",
+--         interval = 12,
+--         open = "slid"
+--       },
+--       auto_play = true,
+--       border = "rounded",
+--       title = { { "", "TransTitleRound" }, { " Trans", "TransTitle" }, { "", "TransTitleRound" } }
+--     },
+--     hover = {
+--       auto_close_events = { "InsertEnter", "CursorMoved", "BufLeave" },
+--       height = 27,
+--       keymap = {
+--         close = "<leader>]",
+--         pagedown = "]]",
+--         pageup = "[[",
+--         pin = "<leader>[",
+--         play = "_",
+--         toggle_entry = "<leader>;"
+--       },
+--       order = { "title", "tag", "pos", "exchange", "translation", "definition" },
+--       spinner = "dots",
+--       width = 37,
+--       <metatable> = {
+--         __index = <function 1>
+--       }
+--     }
+--   },
+--   strategy = {
+--     default = {
+--       backend = <1>{ "offline", "baidu" },
+--       frontend = "hover"
+--     },
+--     input = {
+--       backend = <table 1>,
+--       <metatable> = <2>{
+--         __index = <function 2>
+--       }
+--     },
+--     normal = {
+--       backend = <table 1>,
+--       <metatable> = <table 2>
+--     },
+--     visual = {
+--       backend = <table 1>,
+--       <metatable> = <table 2>
+--     }
+--   },
+--   style = {
+--     icon = {
+--       cell = "■",
+--       no = "",
+--       notfound = " ",
+--       star = "",
+--       yes = "✔"
+--     },
+--     theme = "default"
+--   }
+-- }
diff --git a/lua/Trans/core/util.lua b/lua/Trans/core/util.lua
index 8e87543..b82a1c7 100644
--- a/lua/Trans/core/util.lua
+++ b/lua/Trans/core/util.lua
@@ -48,6 +48,15 @@ function M.get_str(mode)
     end
 end
 
+
+function M.pause(ms)
+    local co = coroutine.running()
+    vim.defer_fn(function()
+        coroutine.resume(co)
+    end, ms)
+    coroutine.yield()
+end
+
 function M.is_English(str)
     local char = { str:byte(1, -1) }
     for i = 1, #str do
diff --git a/lua/Trans/frontend/hover.lua b/lua/Trans/frontend/hover.lua
index 39358c2..0c8c282 100644
--- a/lua/Trans/frontend/hover.lua
+++ b/lua/Trans/frontend/hover.lua
@@ -1,7 +1,8 @@
-local M = {}
+local M     = {}
 
-local api = vim.api
-local conf = require('Trans').conf
+local Trans = require('Trans')
+local api   = vim.api
+local conf  = Trans.conf
 
 
 function M.init()
@@ -9,20 +10,12 @@ function M.init()
 end
 
 function M.wait(tbl, name, timeout)
-    local thread = coroutine.running()
-    local function pause(ms)
-        vim.defer_fn(function()
-            coroutine.resume(thread)
-        end, ms)
-        coroutine.yield()
-    end
-
     local error_message = 'Faild'
     local interval = math.floor(timeout / #error_message)
     for i = 1, #error_message do
         if tbl[name] ~= nil then break end
         print('waitting' .. ('.'):rep(i))
-        pause(interval)
+        Trans.util.pause(interval)
     end
 
     -- TODO : End waitting animation
diff --git a/lua/Trans/init.lua b/lua/Trans/init.lua
index 13bb071..ce74727 100644
--- a/lua/Trans/init.lua
+++ b/lua/Trans/init.lua
@@ -19,8 +19,6 @@ local M = metatable('core')
 M.metatable = metatable
 M.style     = metatable("style")
 M.wrapper   = metatable("wrapper")
-M.frontend  = metatable("frontend")
-
 
 M.cache = {}
 return M
diff --git a/lua/Trans/wrapper/window.lua b/lua/Trans/wrapper/window.lua
index 72dccf0..c68765d 100644
--- a/lua/Trans/wrapper/window.lua
+++ b/lua/Trans/wrapper/window.lua
@@ -1,13 +1,14 @@
 local api = vim.api
-local display = require('Trans.util.display')
+local Trans = require("Trans")
+
 
 ---@class win
+---@field win_opts table window config [**when open**]
 ---@field winid integer window handle
----@field width integer
----@field height integer
 ---@field ns integer namespace for highlight
 ---@field animation table window animation
----@field buf buf buffer for attached
+---@field enter boolean cursor should [enter] window when open
+---@field buffer buffer attached buffer object
 local window = {}
 
 ---Change window attached buffer
@@ -41,91 +42,98 @@ end
 ---@param height integer
 function window:set_height(height)
     api.nvim_win_set_height(self.winid, height)
-    self.height = height
 end
 
 ---@param width integer
 function window:set_width(width)
     api.nvim_win_set_width(self.winid, width)
-    self.width = width
+end
+
+---Get  window width
+function window:width()
+    return api.nvim_win_get_width(self.winid)
+end
+
+---Get window height
+function window:height()
+    return api.nvim_win_get_height(self.winid)
 end
 
 ---Expand window [width | height] value
 ---@param opts table
 ---|'field'string [width | height]
 ---|'target'integer
----@return function
-function window:expand(opts)
-    self:lock()
-    local field  = opts.field
-    local target = opts.target
-    local cur    = self[field]
-    local times  = math.abs(target - cur)
+function window:smooth_expand(opts)
+    local field = opts.field -- width | height
+    local from  = self[field](self)
+    local to    = opts.target
 
-    local wrap = self:option('wrap')
-    self:set('wrap', false)
-    local interval = opts.interval or self.animation.interval
+    if from == to then return end
+
+
+    local pause  = Trans.util.pause
     local method = api['nvim_win_set_' .. field]
 
-    local winid = self.winid
-    local frame = target > cur and function(_, cur_times)
-        method(winid, cur + cur_times)
-    end or function(_, cur_times)
-        method(winid, cur - cur_times)
+
+    local wrap = self:option('wrap')
+
+    local interval = self.animation.interval
+    for i = from + 1, to, (from < to and 1 or -1) do
+        self:set('wrap', false)
+        method(self.winid, i)
+        pause(interval)
     end
 
-    local run = display {
-        times    = times,
-        frame    = frame,
-        interval = interval,
-    }
-
-    run(function()
-        self:set('wrap', wrap)
-        self[field] = target
-        self:unlock()
-    end)
-    return run
+    self:set('wrap', wrap)
 end
 
 ---Close window
----@return function run run until close done
 function window:try_close()
-    local field = ({
-        slid = 'width',
-        fold = 'height',
-    })[self.animation.close]
+    local close_animation = self.animation.close
+    if close_animation then
+        local field = ({
+            slid = 'width',
+            fold = 'height',
+        })[close_animation]
 
-    --- 播放动画
-    local run = self:expand {
-        field = field,
-        target = 1,
-    }
-    run(function()
-        api.nvim_win_close(self.winid, true)
-    end)
-    return run
-end
-
----lock window [open | close] operation
-function window:lock()
-    while self.busy do
-        vim.wait(50)
+        self:smooth_expand({
+            field = field,
+            target = 1,
+        })
     end
-    self.busy = true
+
+    api.nvim_win_close(self.winid, true)
 end
 
-function window:unlock()
-    self.busy = false
-end
-
----设置窗口本地的高亮组
----@param name string 高亮组的名称
----@param opts table 高亮选项
+---set window local highlight group
+---@param name string
+---@param opts table
 function window:set_hl(name, opts)
     api.nvim_set_hl(self.ns, name, opts)
 end
 
+function window:open()
+    assert(self.winid == nil, 'window already opened')
+    local win_opts = self.win_opts
+    local open_animation = self.animation.open
+    if open_animation then
+        local field = ({
+            slid = 'width',
+            fold = 'height',
+        })[open_animation]
+
+        local to = win_opts[field]
+        win_opts[field] = 1
+        self.winid = api.nvim_open_win(self.buffer.bufnr, self.enter, win_opts)
+        self:smooth_expand({
+            field = field,
+            target = to,
+        })
+    else
+        self.winid = api.nvim_open_win(self.buffer.bufnr, self.enter, win_opts)
+    end
+end
+
 ---buffer:addline() helper function
 ---@param node table
 ---@return table node formatted node
@@ -138,86 +146,91 @@ function window:center(node)
     return node
 end
 
----@private
 window.__index = window
 
----@class win_opts
----@field buf buf buffer for attached
----@field height integer
----@field width integer
----@field col integer
----@field row integer
----@field border string
----@field title string | nil | table
----@field relative string
----@field ns integer namespace for highlight
----@field zindex? integer
----@field enter? boolean cursor should [enter] window
----@field animation table window animation
-
----window constructor
----@param opts win_opts
----@return table
----@return function
-return function(opts)
-    assert(type(opts) == 'table')
-    local ns        = opts.ns
-    local buf       = opts.buf
-    local col       = opts.col
-    local row       = opts.row
-    local title     = opts.title
-    local width     = opts.width
-    local enter     = opts.enter or false
-    local height    = opts.height
-    local border    = opts.border
-    local zindex    = opts.zindex
-    local relative  = opts.relative
-    local animation = opts.animation
-
-    local open = animation.open
-
-    local field = ({
-        slid = 'width',
-        fold = 'height',
-    })[open]
-
-    local win_opt = {
-        title_pos = nil,
-        focusable = false,
+local default_opts = {
+    ns       = api.nvim_create_namespace('TransHoverWin'),
+    enter    = false,
+    win_opts = {
         style     = 'minimal',
-        zindex    = zindex,
-        width     = width,
-        height    = height,
-        col       = col,
-        row       = row,
-        border    = border,
-        title     = title,
-        relative  = relative,
-    }
+        border    = 'rounded',
+        focusable = false,
+        noautocmd = true,
+    },
+}
 
-    if field then
-        win_opt[field] = 1
-    end
+return function(opts)
+    opts = vim.tbl_deep_extend('keep', opts, default_opts)
 
-    if win_opt.title then
-        win_opt.title_pos = 'center'
-    end
-
-    local win = setmetatable({
-        buf       = buf,
-        ns        = ns,
-        height    = win_opt.height,
-        width     = win_opt.width,
-        animation = animation,
-        winid     = api.nvim_open_win(buf.bufnr, enter, win_opt),
-    }, window)
-
-    api.nvim_win_set_hl_ns(win.winid, win.ns)
-    win:set_hl('Normal', { link = 'TransWin' })
-    win:set_hl('FloatBorder', { link = 'TransBorder' })
-
-    return win, win:expand {
-        field = field,
-        target = opts[field],
-    }
+    local win = setmetatable(opts, window)
+    win:open()
+    return win
 end
+
+--@class win_opts
+--@field buf buf buffer for attached
+--@field height integer
+--@field width integer
+--@field col integer
+--@field row integer
+--@field border string
+--@field title string | nil | table
+--@field relative string
+--@field ns integer namespace for highlight
+--@field zindex? integer
+--@field enter? boolean cursor should [enter] window
+--@field animation table window animation
+
+-- local ns        = opts.ns
+-- local buf       = opts.buf
+-- local col       = opts.col
+-- local row       = opts.row
+-- local title     = opts.title
+-- local width     = opts.width
+-- local height    = opts.height
+-- local border    = opts.border
+-- local zindex    = opts.zindex
+-- local relative  = opts.relative
+-- local animation = opts.animation
+
+-- local open      = animation.open
+
+-- local field     = ({
+--     slid = 'width',
+--     fold = 'height',
+-- })[open]
+
+-- local win_opt   = {
+--     focusable = false,
+--     style     = 'minimal',
+--     zindex    = zindex,
+--     width     = width,
+--     height    = height,
+--     col       = col,
+--     row       = row,
+--     border    = border,
+--     title     = title,
+--     relative  = relative,
+-- }
+
+-- if field then
+--     win_opt[field] = 1
+-- end
+
+-- if win_opt.title then
+--     win_opt.title_pos = 'center'
+-- end
+
+-- local win = setmetatable({
+--     buf       = buf,
+--     ns        = ns,
+--     height    = win_opt.height,
+--     width     = win_opt.width,
+--     animation = animation,
+--     winid     = api.nvim_open_win(buf.bufnr, enter, win_opt),
+-- }, window)
+
+-- return win, win:expand {
+--     field = field,
+--     target = opts[field],
+-- }