From 86f8b7f6e8c966cd9dfd25c435480bf26a496e7a Mon Sep 17 00:00:00 2001
From: JuanZoran <1430359574@qq.com>
Date: Tue, 31 Jan 2023 23:17:03 +0800
Subject: [PATCH] fix: fix float window style

---
 README.md                     |  5 +++
 lua/Trans/content.lua         | 81 ++++++++++++++++------------------
 lua/Trans/init.lua            | 22 +++++-----
 lua/Trans/node.lua            | 51 +++++++++-------------
 lua/Trans/translate.lua       | 26 ++++++-----
 lua/Trans/util/animation.lua  | 82 +++++++++++++++++------------------
 lua/Trans/util/is_Chinese.lua |  6 +++
 lua/Trans/view/float.lua      | 78 ++++++++++++++++++---------------
 lua/Trans/view/hover.lua      | 15 ++++---
 lua/Trans/window.lua          | 24 +++++-----
 10 files changed, 198 insertions(+), 192 deletions(-)
 create mode 100644 lua/Trans/util/is_Chinese.lua

diff --git a/README.md b/README.md
index ac435e0..f89962d 100644
--- a/README.md
+++ b/README.md
@@ -45,6 +45,11 @@
 ### 演示
 https://user-images.githubusercontent.com/107862700/213752097-2eee026a-ddee-4531-bf80-ba2cbc8b44ef.mp4
 
+> 视频演示的在线查询, 查询速度取决于你的网络状况  
+> 可以打开音量查看自动读音
+
+https://user-images.githubusercontent.com/107862700/215941500-3293c571-20a1-44e2-b202-77079f158ce9.mp4
+
 ### 主题
 > 如果你有更美观或者更适合的配色, 欢迎提PR  
 > 主题配色在: `lua/Trans/theme.lua`文件中,你只需要添加你主题的表就可以了
diff --git a/lua/Trans/content.lua b/lua/Trans/content.lua
index 812dbaf..911fb54 100644
--- a/lua/Trans/content.lua
+++ b/lua/Trans/content.lua
@@ -1,32 +1,16 @@
 local api = vim.api
 
-local format_meta = {
-    load_hl = function(self, content, line, col)
-        local space = self.space
-        for _, item in ipairs(self.items) do
-            item:load_hl(content, line, col)
-            col = col + #item.text + space
-        end
-    end
-}
-
 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
+        local index = self.size + 1
+        self.size = index
+        self.lines[index] = 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
+        local index = self.hl_size + 1
+        self.hl_size = index
+        self.highlights[index] = opt
     end,
 
     wipe = function(self)
@@ -46,17 +30,19 @@ local content = {
         end
 
         offset = offset or 0
-        self.window:bufset('modifiable', true)
-        local window = self.window
+        local win = self.window
+        win:bufset('modifiable', true)
         --- NOTE : 使用-1 则需要按顺序设置
-        api.nvim_buf_set_lines(window.bufnr, offset, -1, true, self.lines)
+        api.nvim_buf_set_lines(win.bufnr, offset, -1, true, self.lines)
 
         local hl
+        local highlights = self.highlights
+        local method = api.nvim_buf_add_highlight
         for i = 1, self.hl_size do
-            hl = self.highlights[i]
-            api.nvim_buf_add_highlight(window.bufnr, window.hl, hl.name, offset + hl.line, hl._start, hl._end)
+            hl = highlights[i]
+            method(win.bufnr, win.hl, hl.name, offset + hl.line, hl._start, hl._end)
         end
-        self.window:bufset('modifiable', false)
+        win:bufset('modifiable', false)
     end,
 
     actual_height = function(self, wrap)
@@ -80,45 +66,53 @@ local content = {
         local nodes = opt.nodes
         local size = #nodes
         assert(size > 1, 'check items size')
-        local width = 0
+        local tot_width = 0
         local strs = {}
-        for i, node in ipairs(nodes) do
-            local str = node.text
+        local str
+        for i = 1, size do
+            str = nodes[i].text
             strs[i] = str
-            width = width + str:width()
+            tot_width = tot_width + str:width()
         end
 
-        local space = math.floor(((win_width - width) / (size - 1)))
+        local space = math.floor(((win_width - tot_width) / (size - 1)))
         if opt.strict and space < 0 then
             return false
         end
 
         local interval = (' '):rep(space)
-        return setmetatable({
+        return {
             text = table.concat(strs, interval),
-            items = nodes,
-            space = space,
-        }, { __index = format_meta })
+            load_hl = function(_, content, line, col)
+                for _, item in ipairs(nodes) do
+                    item:load_hl(content, line, col)
+                    col = col + #item.text + space
+                end
+            end
+        }
     end,
 
     center = function(self, item)
-        local space = bit.rshift(self.window.width - item.text:width(), 1)
-        item.text = (' '):rep(space) .. item.text
+        local text = item.text
+        local space = bit.rshift(self.window.width - text:width(), 1)
+        item.text = (' '):rep(space) .. text
         local load_hl = item.load_hl
         item.load_hl = function(this, content, line, col)
             load_hl(this, content, line, col + space)
         end
-
         return item
     end,
 
     addline = function(self, ...)
         local strs = {}
         local col = 0
+        local str
+        local line = self.size -- line is zero index
+
         for i, node in ipairs { ... } do
-            local str = node.text
+            str = node.text
             strs[i] = str
-            node:load_hl(self, self.size, col)
+            node:load_hl(self, line, col)
             col = col + #str
         end
         self:newline(table.concat(strs))
@@ -135,11 +129,10 @@ return function(window)
         window = { window, 't' },
     }
     return setmetatable({
-        modifiable = true,
         window = window,
         size = 0,
         hl_size = 0,
         lines = {},
         highlights = {},
     }, content)
-end
+end
\ No newline at end of file
diff --git a/lua/Trans/init.lua b/lua/Trans/init.lua
index 7ba4caa..8f981ad 100644
--- a/lua/Trans/init.lua
+++ b/lua/Trans/init.lua
@@ -61,9 +61,6 @@ M.conf = {
             fail = '#e46876',
             success = '#10b981',
         },
-        engine = {
-            '本地',
-        }
     },
     order = { -- only work on hover mode
         'title',
@@ -78,8 +75,8 @@ M.conf = {
         notfound = ' ',
         yes = '✔',
         no = '',
-    -- --- char: ■ | □ | ▇ | ▏ ▎ ▍ ▌ ▋ ▊ ▉ █
-    -- --- ◖■■■■■■■◗▫◻ ▆ ▆ ▇⃞ ▉⃞
+        -- --- char: ■ | □ | ▇ | ▏ ▎ ▍ ▌ ▋ ▊ ▉ █
+        -- --- ◖■■■■■■■◗▫◻ ▆ ▆ ▇⃞ ▉⃞
         cell = '■',
         -- star = '⭐',
         -- notfound = '❔',
@@ -117,17 +114,22 @@ M.setup = function(opts)
     if opts then
         M.conf = vim.tbl_deep_extend('force', M.conf, opts)
     end
+    local conf = M.conf
 
-    local float = M.conf.float
-
+    local float = conf.float
     if 0 < float.height and float.height <= 1 then
         float.height = math.floor((vim.o.lines - vim.o.cmdheight - 1) * float.height)
     end
-
     if 0 < float.width and float.width <= 1 then
         float.width = math.floor(vim.o.columns * float.width)
     end
 
+    local engines = {}
+    for k, _ in pairs(conf.engine) do
+        table.insert(engines, k)
+    end
+    conf.engines = engines
+
     times = times + 1
     if times == 1 then
         M.translate = require('Trans.translate')
@@ -136,7 +138,7 @@ M.setup = function(opts)
             error('Please check out sqlite3')
         end
 
-        vim.api.nvim_create_user_command('Translate', function ()
+        vim.api.nvim_create_user_command('Translate', function()
             M.translate()
         end, { desc = '  单词翻译', })
 
@@ -145,7 +147,7 @@ M.setup = function(opts)
         end, { desc = '  搜索翻译' })
 
 
-        local hls = require('Trans.ui.theme')[M.conf.theme]
+        local hls = require('Trans.ui.theme')[conf.theme]
         for hl, opt in pairs(hls) do
             vim.api.nvim_set_hl(0, hl, opt)
         end
diff --git a/lua/Trans/node.lua b/lua/Trans/node.lua
index 0eada96..7c8b48c 100644
--- a/lua/Trans/node.lua
+++ b/lua/Trans/node.lua
@@ -1,50 +1,39 @@
 -- NOTE : 设置content的node
-local item_meta = {
-    load_hl = function(self, content, line, col)
-        if self.hl then
-            content:newhl {
-                name = self.hl,
-                line = line,
-                _start = col,
-                _end = col + #self.text,
-            }
-        end
+local item_load = function(self, content, line, col)
+    if self.hl then
+        content:newhl {
+            name = self.hl,
+            line = line,
+            _start = col,
+            _end = col + #self.text,
+        }
     end
-}
-
-local text_meta = {
-    load_hl = function(self, content, line, col)
-        for _, item in ipairs(self.items) do
-            item:load_hl(content, line, col)
-            col = col + #item.text
-        end
-    end,
-}
-
-item_meta.__index = item_meta
-text_meta.__index = text_meta
-
+end
 
 return {
     item = function(text, hl)
-        return setmetatable({
+        return {
             text = text,
             hl = hl,
-        }, item_meta)
+            load_hl = item_load,
+        }
     end,
 
-
     text = function(...)
         local items = { ... }
         local strs = {}
-
         for i, item in ipairs(items) do
             strs[i] = item.text
         end
 
-        return setmetatable({
+        return {
             text = table.concat(strs),
-            items = items,
-        }, text_meta)
+            load_hl = function(_, content, line, col)
+                for _, item in ipairs(items) do
+                    item:load_hl(content, line, col)
+                    col = col + #item.text
+                end
+            end
+        }
     end,
 }
diff --git a/lua/Trans/translate.lua b/lua/Trans/translate.lua
index d37ba38..9794528 100644
--- a/lua/Trans/translate.lua
+++ b/lua/Trans/translate.lua
@@ -17,33 +17,37 @@ local function get_select()
 end
 
 local function get_word(mode)
+    local word
     if mode == 'n' then
-        return vim.fn.expand('<cword>')
+        word = vim.fn.expand('<cword>')
     elseif mode == 'v' then
         vim.api.nvim_input('<ESC>')
-        return get_select()
+        word = get_select()
     elseif mode == 'i' then
         -- TODO Use Telescope with fuzzy finder
-        ---@diagnostic disable-next-line: param-type-mismatch
-        return vim.fn.input('请输入您要查询的单词: ')
+        vim.ui.input({ prompt = '请输入需要查询的单词: ' }, function(input)
+            word = input
+        end)
     else
         error('invalid mode: ' .. mode)
     end
+
+    return word
 end
 
-
-local function translate(mode, view)
+return function(mode, view)
     vim.validate {
         mode = { mode, 's', true },
         view = { view, 's', true }
     }
 
-    ---@diagnostic disable-next-line: undefined-field
     mode = mode or vim.api.nvim_get_mode().mode
     view = view or require('Trans').conf.view[mode]
     assert(mode and view)
-    local word = get_word(mode):gsub('^%s+', '', 1)
-    require('Trans.view.' .. view)(word)
+    local word = get_word(mode)
+    if word == nil or word == '' then
+        return
+    else
+        require('Trans.view.' .. view)(word:gsub('^%s+', '', 1))
+    end
 end
-
-return translate
diff --git a/lua/Trans/util/animation.lua b/lua/Trans/util/animation.lua
index 81f7f77..684f71a 100644
--- a/lua/Trans/util/animation.lua
+++ b/lua/Trans/util/animation.lua
@@ -1,57 +1,55 @@
-local animation = {
-    display = function(self)
-        local callback = self.callback or function ()
+local display = function(self)
+    local callback = self.callback or function()
 
+    end
+
+    if self.sync then
+        local times = self.times
+        if times then
+            for i = 1, self.times do
+                if self.run then
+                    self:frame(i)
+                end
+            end
+        else
+            while self.run do
+                self:frame()
+            end
+            callback()
         end
 
-        if self.sync then
-            local times = self.times
-            if times then
-                for i = 1, self.times do
-                    if self.run then
-                        self:frame(i)
-                    end
+    else
+        local frame
+        if self.times then
+            local target = self.times
+            local times = 0
+            frame = function()
+                if self.run and times < target then
+                    times = times + 1
+                    self:frame(times)
+                    vim.defer_fn(frame, self.interval)
+                else
+                    callback()
                 end
-            else
-                while self.run do
-                    self:frame()
-                end
-                callback()
             end
 
         else
-            local frame
-            if self.times then
-                local target = self.times
-                local times = 0
-                frame = function()
-                    if self.run and times < target then
-                        times = times + 1
-                        self:frame(times)
-                        vim.defer_fn(frame, self.interval)
-                    else
-                        callback()
-                    end
-                end
-
-            else
-                frame = function()
-                    if self.run then
-                        self:frame()
-                        vim.defer_fn(frame, self.interval)
-                    else
-                        callback()
-                    end
+            frame = function()
+                if self.run then
+                    self:frame()
+                    vim.defer_fn(frame, self.interval)
+                else
+                    callback()
                 end
             end
-            frame()
         end
-    end,
-}
+        frame()
+    end
+end
 
-animation.__index = animation
 
 return function(opts)
     opts.run = true
-    return setmetatable(opts, animation)
+    opts.display = display
+    return opts
 end
diff --git a/lua/Trans/util/is_Chinese.lua b/lua/Trans/util/is_Chinese.lua
new file mode 100644
index 0000000..09ec9e5
--- /dev/null
+++ b/lua/Trans/util/is_Chinese.lua
@@ -0,0 +1,6 @@
+---判断单词是否含有中文
+---@param word string 需要判断的单词
+---@return boolean 判断结果
+return function (word)
+    return false
+end
diff --git a/lua/Trans/view/float.lua b/lua/Trans/view/float.lua
index 9c36e1b..0123b9c 100644
--- a/lua/Trans/view/float.lua
+++ b/lua/Trans/view/float.lua
@@ -3,17 +3,18 @@ local m_window
 local m_result
 local m_content
 
-local engine_map = {
-    ['本地'] = 'offline',
-    ['百度'] = 'baidu',
-    ['有道'] = 'youdao',
-}
-
 local node = require("Trans.node")
 local t = node.text
 local it = node.item
 
 
+local engine_map = {
+    baidu   = '百度',
+    youdao  = '有道',
+    iciba   = 'iciba',
+    offline = '本地',
+}
+
 local function set_tag_hl(name, status)
     local hl = conf.float.tag[status]
     m_window:set_hl(name, {
@@ -27,29 +28,28 @@ local function set_tag_hl(name, status)
 end
 
 local function set_title()
-    local title = m_window.contents[1]
+    local title = m_window:new_content()
     local github = '  https://github.com/JuanZoran/Trans.nvim'
 
     title:addline(
         title:center(it(github, '@text.uri'))
     )
 
-    local format = '%s(%d)'
-    for i, engine_ch in ipairs(conf.float.engine) do
-        local engine_us = engine_map[engine_ch]
-        set_tag_hl(engine_us, 'wait')
+    local f = '%s(%d)'
 
-        local round = engine_us .. 'round'
-        title:addline(
-            t(
-                it('', round),
-                it(format:format(engine_ch, i), engine_us),
-                it('', round)
-            )
-        )
-
-        title:newline('')
+    local tags = {}
+    local load_tag = function(engine, index)
+        set_tag_hl(engine, 'wait')
+        local round = engine .. 'round'
+        table.insert(tags, t(
+            it('', round),
+            it(f:format(engine_map[engine], index), engine),
+            it('', round)
+        ))
     end
+    load_tag('offline', 1)
+    title:addline(unpack(tags))
+    title:newline('')
 end
 
 local action = {
@@ -58,22 +58,34 @@ local action = {
     end,
 }
 
+local exist = function (str)
+    return str and str ~= ''
+end
 
 local function process()
     -- TODO :
+    local icon = conf.icon
+    m_content:addline(m_content:format {
+        nodes = {
+            it(m_result.word, 'TransWord'),
+            t(
+                it('['),
+                it(exist(m_result.phonetic) and m_result.phonetic or icon.notfound, 'TransPhonetic'),
+                it(']')
+            ),
+            it(m_result.collins and icon.star:rep(m_result.collins) or icon.notfound, 'TransCollins'),
+            it(m_result.oxford == 1 and icon.yes or icon.no)
+        },
+        width = math.floor(m_window.width * 0.5)
+    })
+    m_content:addline(it('该窗口还属于实验性功能 .... '))
 end
 
 return function(word)
     -- TODO :online query
     local float = conf.float
-    local engine_ch = '本地'
-    local engine_us = engine_map[engine_ch]
-
     vim.notify('[注意]: float窗口目前还待开发, 如果需要input查询功能, 请将窗口改成hover',
         vim.log.WARN)
-
-    m_result = require('Trans.query.' .. engine_us)(word)
-
     local opt = {
         relative  = 'editor',
         width     = float.width,
@@ -83,19 +95,17 @@ return function(word)
         animation = float.animation,
         row       = bit.rshift((vim.o.lines - float.height), 1),
         col       = bit.rshift((vim.o.columns - float.width), 1),
-        zindex    = 50,
+        zindex    = 20,
     }
-
     m_window = require('Trans.window')(true, opt)
-
     set_title()
-    m_content = m_window.contents[2]
-
+    m_content = m_window:new_content()
+    m_result = require('Trans.query.offline')(word)
     if m_result then
-        set_tag_hl(engine_us, 'success')
+        set_tag_hl('offline', 'success')
         process()
     else
-        set_tag_hl(engine_us, 'fail')
+        set_tag_hl('offline', 'fail')
     end
 
     m_window:open()
diff --git a/lua/Trans/view/hover.lua b/lua/Trans/view/hover.lua
index ff6d76b..1d18494 100644
--- a/lua/Trans/view/hover.lua
+++ b/lua/Trans/view/hover.lua
@@ -282,22 +282,23 @@ end
 local function online_query(word)
     -- TODO :Progress Bar
     local lists = {}
-    local size = 0
+    local engines = conf.engines
+    local size = #engines
     local icon = conf.icon
-    for k, _ in pairs(conf.engine) do
-        size = size + 1
-        lists[size] = require('Trans.query.' .. k)(word)
-    end
-
     local error_msg = icon.notfound .. '    没有找到相关的翻译'
-
     m_window:set_height(1)
     local width = m_window.width
     m_window:set_width(error_msg:width())
+
     if size == 0 then
         m_content:addline(it(error_msg, 'TransFailed'))
         m_window:open()
         return
+    else
+        m_window:open()
+        for i = 1, size do
+            lists[size] = require('Trans.query.' .. engines[i])(word)
+        end
     end
 
     local cell = icon.cell
diff --git a/lua/Trans/window.lua b/lua/Trans/window.lua
index 6d19f32..f3b3869 100644
--- a/lua/Trans/window.lua
+++ b/lua/Trans/window.lua
@@ -2,10 +2,7 @@ local api = vim.api
 local new_content = require('Trans.content')
 local new_animation = require('Trans.util.animation')
 
-function string:width()
-    ---@diagnostic disable-next-line: param-type-mismatch
-    return vim.fn.strwidth(self)
-end
+string.width = vim.fn.strwidth
 
 local busy = false
 local function lock()
@@ -57,7 +54,7 @@ local window = {
 
     ---@nodiscard
     is_open = function(self)
-        return self.winid > 0 and api.nvim_win_is_valid(self.winid)
+        return api.nvim_win_is_valid(self.winid)
     end,
 
     normal = function(self, key)
@@ -96,12 +93,13 @@ local window = {
                 slid = 'width',
             })[animation]
 
-            local method = 'nvim_win_set_' .. field
+            local method = api['nvim_win_set_' .. field]
+            local winid = self.winid
             new_animation({
                 interval = interval,
                 times = self[field],
                 frame = function(_, times)
-                    api[method](self.winid, times)
+                    method(winid, times)
                 end,
                 callback = callback,
             }):display()
@@ -141,11 +139,12 @@ local window = {
                 })[animation]
 
                 local target = self[field]
-                local method = 'nvim_win_set_' .. field
+                local method = api['nvim_win_set_' .. field]
+                local winid = self.winid
                 new_animation({
                     times = target,
                     frame = function(_, times)
-                        api[method](self.winid, target - times)
+                        method(winid, target - times)
                     end,
                     callback = callback,
                     interval = interval,
@@ -172,13 +171,13 @@ local window = {
         self:open(opt)
     end,
 
-    set_hl = function(self, name, hl)
-        api.nvim_set_hl(self.hl, name, hl)
+    set_hl = function(self, name, opts)
+        api.nvim_set_hl(self.hl, name, opts)
     end,
 
     new_content = function(self)
         local index = self.size + 1
-        self.size = index + 1
+        self.size = index
         self.contents[index] = new_content(self)
 
         return self.contents[index]
@@ -246,7 +245,6 @@ return function(entry, option)
     api.nvim_win_set_hl_ns(win.winid, win.hl)
     win:set_hl('Normal', { link = 'TransWin' })
     win:set_hl('FloatBorder', { link = 'TransBorder' })
-    win:set_hl('NormalFloat', { link = 'TransBorder' })
     ---@diagnostic disable-next-line: return-type-mismatch
     return win
 end