From 0d4eec6f2ec2f8e05f43210940f542d74e1bfbfc Mon Sep 17 00:00:00 2001
From: JuanZoran <1430359574@qq.com>
Date: Thu, 16 Mar 2023 17:17:30 +0800
Subject: [PATCH] feat: begin to render youdao Translation window

---
 lua/Trans/backend/youdao.lua         |  33 ++------
 lua/Trans/core/util.lua              |   1 -
 lua/Trans/frontend/hover/load.lua    | 115 ++++-----------------------
 lua/Trans/frontend/hover/offline.lua |  90 +++++++++++++++++++++
 lua/Trans/frontend/hover/youdao.lua  |   8 ++
 lua/Trans/util/node.lua              |  81 +++++++++++--------
 6 files changed, 169 insertions(+), 159 deletions(-)
 create mode 100644 lua/Trans/frontend/hover/offline.lua
 create mode 100644 lua/Trans/frontend/hover/youdao.lua

diff --git a/lua/Trans/backend/youdao.lua b/lua/Trans/backend/youdao.lua
index 6fd34eb..e444706 100644
--- a/lua/Trans/backend/youdao.lua
+++ b/lua/Trans/backend/youdao.lua
@@ -51,26 +51,6 @@ function M.get_content(data)
     }
 end
 
--- {
---   dict = {
---     url = "yddict://m.youdao.com/dict?le=eng&q=shows+your+registers+on+%22+in+NORMAL+or+%3CC-r%3E+in+INSERT+mode"
---   },
---   errorCode = "0",
---   isWord = false,
---   l = "en2zh-CHS",
---   mTerminalDict = {
---     url = "https://m.youdao.com/m/result?lang=en&word=shows+your+registers+on+%22+in+NORMAL+or+%3CC-r%3E+in+INSERT+mode"
---   },
---   query = 'shows your registers on " in NORMAL or <C-r> in INSERT mode',
---   requestId = "9dddf583-1233-48a5-a9ca-f1d0324a5349",
---   speakUrl = "https://openapi.youdao.com/ttsapi?q=shows+your+registers+on+%22+in+NORMAL+or+%3CC-r%3E+in+INSERT+mode&langType=en-USA&sign=8A0B3742F4E9FA92D4B65F028E1A6008&salt=1678931340864&voice=4&format=mp3&appKey=1858465a8708c121&ttsVoiceStrict=false",
---   tSpeakUrl = "https://openapi.youdao.com/ttsapi?q=%E5%9C%A8%E6%AD%A3%E5%B8%B8%E6%88%96%3CC-r%3E%E6%8F%92%E5%85%A5%E6%A8%A1%E5%BC%8F%E4%B8%8B%E6%98%BE%E7%A4%BA%E4%BD%A0%E7%9A%84%E5%AF%84%E5%AD%98%E5%99%A8&langType=zh-CHS&sign=456E436DBEC35447D36157200FC5ACA7&salt=1678931340864&voice=4&format=mp3&appKey=1858465a8708c121&ttsVoiceStrict=false",
---   translation = { "在正常或<C-r>插入模式下显示你的寄存器" },
---   webdict = {
---     url = "http://mobile.youdao.com/dict?le=eng&q=shows+your+registers+on+%22+in+NORMAL+or+%3CC-r%3E+in+INSERT+mode"
---   }
--- }
-
 -- {
 --   basic = {
 --     explains = { "normal", "regular", "normality" },
@@ -148,7 +128,7 @@ end
 function M.query(data)
     local handle = function(res)
         local status, body = pcall(vim.json.decode, res.body)
-        vim.print(body)
+        -- vim.print(body)
         if not status or not body or body.errorCode ~= "0" then
             data.result.youdao = false
             data[#data + 1] = res
@@ -163,13 +143,9 @@ function M.query(data)
             return
         end
 
-        if true then
-            data.result.youdao = false
-            return
-        end
-
-        data.result.youdao = {
+        local tmp = {
             title                                                 = {
+                word     = body.query,
                 phonetic = body.basic.phonetic,
             },
             web                                                   = body.web,
@@ -180,6 +156,9 @@ function M.query(data)
             sentenceSample                                        = body.sentenceSample,
             [data.from == 'en' and 'translation' or 'definition'] = body.translation,
         }
+
+
+        data.result.youdao = tmp
     end
 
     require('Trans').curl.get(M.uri, {
diff --git a/lua/Trans/core/util.lua b/lua/Trans/core/util.lua
index bb5df38..14c42f5 100644
--- a/lua/Trans/core/util.lua
+++ b/lua/Trans/core/util.lua
@@ -144,7 +144,6 @@ function M.main_loop(func)
 end
 
 
-
 ---@class Trans
 ---@field util TransUtil
 return M
diff --git a/lua/Trans/frontend/hover/load.lua b/lua/Trans/frontend/hover/load.lua
index 92812e8..adb75c9 100644
--- a/lua/Trans/frontend/hover/load.lua
+++ b/lua/Trans/frontend/hover/load.lua
@@ -1,16 +1,13 @@
 local node = require('Trans').util.node
-local it, t, f = node.item, node.text, node.format
+local it, conjunction = node.item, node.conjunction
 local interval = (' '):rep(4)
 
-local function conjunction(text)
-    return {
-        it('', 'TransTitleRound'),
-        it(text, 'TransTitle'),
-        it('', 'TransTitleRound'),
-    }
-end
 
----@type table<string, fun(hover:TransHover, result: TransResult)>
+---@alias TransHoverFormatter fun(hover:TransHover, result: TransResult)
+---@alias TransHoverRenderer table<string, TransHoverFormatter>
+
+
+---@type TransHoverRenderer
 local default = {
     str = function(hover, result)
         hover.buffer:setline(it(result.str, 'TransWord'))
@@ -50,106 +47,28 @@ local default = {
 ---@diagnostic disable-next-line: assign-type-mismatch
 default.__index = default
 
-local strategy = setmetatable({}, {
+---@type table<string, TransHoverRenderer>
+local renderer = setmetatable({}, {
     __index = function(tbl, key)
-        tbl[key] = default
-        return tbl[key]
+        local status, method = pcall(require, 'Trans.frontend.hover.' .. key)
+        if not status then
+            print(key)
+            return
+        end
+        tbl[key] = setmetatable(method, default)
+        return method
     end,
-    __newindex = function(tbl, key, value)
-        rawset(tbl, key, setmetatable(value, default))
-    end
 })
 
-
-strategy.offline = {
-    title = function(hover, result)
-        local title = result.title
-        if not title then return end
-
-        local icon     = hover.opts.icon
-
-        local word     = title.word
-        local oxford   = title.oxford
-        local collins  = title.collins
-        local phonetic = title.phonetic
-
-        hover.buffer:setline(f {
-            width = hover.opts.width,
-            text = t {
-                it(word, 'TransWord'),
-                t {
-                    it('['),
-                    it((phonetic and phonetic ~= '') and phonetic or icon.notfound, 'TransPhonetic'),
-                    it(']')
-                },
-
-                it(collins and icon.star:rep(collins) or icon.notfound, 'TransCollins'),
-                it(oxford == 1 and icon.yes or icon.no)
-            },
-        })
-    end,
-    tag = function(hover, result)
-        local tag = result.tag
-        if not tag then return end
-
-        local buffer = hover.buffer
-        buffer:setline(conjunction('标签'))
-
-        local size = #tag
-
-        for i = 1, size, 3 do
-            buffer:setline(
-                it(
-                    interval .. tag[i] ..
-                    (tag[i + 1] and interval .. tag[i + 1] ..
-                    (tag[i + 2] and interval .. tag[i + 2] or '') or ''),
-                    'TransTag'
-                )
-            )
-        end
-
-        buffer:setline('')
-    end,
-    exchange = function(hover, result)
-        local exchange = result.exchange
-        if not exchange then return end
-
-        local buffer = hover.buffer
-        buffer:setline(conjunction('词形变化'))
-
-        for description, value in pairs(exchange) do
-            buffer:setline(
-                it(interval .. description .. interval .. value, 'TransExchange')
-            )
-        end
-
-        buffer:setline('')
-    end,
-    pos = function(hover, result)
-        local pos = result.pos
-        if not pos then return end
-
-        local buffer = hover.buffer
-        buffer:setline(conjunction('词性'))
-
-        for description, value in pairs(pos) do
-            buffer:setline(
-                it(interval .. description .. interval .. value, 'TransPos')
-            )
-        end
-
-        buffer:setline('')
-    end,
-}
-
 -- FIXME :
 
+
 ---@class TransHover
 ---@field load fun(hover: TransHover, result: TransResult, name: string, order: string[])
 return function(hover, result, name, order)
     order = order or hover.opts.order.default
 
-    local method = strategy[name]
+    local method = renderer[name]
 
     for _, field in ipairs(order) do
         method[field](hover, result)
diff --git a/lua/Trans/frontend/hover/offline.lua b/lua/Trans/frontend/hover/offline.lua
new file mode 100644
index 0000000..3e2dacb
--- /dev/null
+++ b/lua/Trans/frontend/hover/offline.lua
@@ -0,0 +1,90 @@
+local node = require('Trans').util.node
+local it, t, f, co = node.item, node.text, node.format, node.conjunction
+local interval = (' '):rep(4)
+
+---@type TransHoverRenderer
+local M = {}
+
+function M.tag(hover, result)
+    local tag = result.tag
+    if not tag then return end
+
+    local buffer = hover.buffer
+    buffer:setline(co('标签'))
+
+    local size = #tag
+
+    for i = 1, size, 3 do
+        buffer:setline(
+            it(
+                interval .. tag[i] ..
+                (tag[i + 1] and interval .. tag[i + 1] ..
+                (tag[i + 2] and interval .. tag[i + 2] or '') or ''),
+                'TransTag'
+            )
+        )
+    end
+
+    buffer:setline('')
+end
+
+function M.exchange(hover, result)
+    local exchange = result.exchange
+    if not exchange then return end
+
+    local buffer = hover.buffer
+    buffer:setline(co('词形变化'))
+
+    for description, value in pairs(exchange) do
+        buffer:setline(
+            it(interval .. description .. interval .. value, 'TransExchange')
+        )
+    end
+
+    buffer:setline('')
+end
+
+function M.pos(hover, result)
+    local pos = result.pos
+    if not pos then return end
+
+    local buffer = hover.buffer
+    buffer:setline(co('词性'))
+
+    for description, value in pairs(pos) do
+        buffer:setline(
+            it(interval .. description .. interval .. value, 'TransPos')
+        )
+    end
+
+    buffer:setline('')
+end
+
+function M.title(hover, result)
+    local title = result.title
+    if not title then return end
+
+    local icon     = hover.opts.icon
+
+    local word     = title.word
+    local oxford   = title.oxford
+    local collins  = title.collins
+    local phonetic = title.phonetic
+
+    hover.buffer:setline(f {
+        width = hover.opts.width,
+        text = t {
+            it(word, 'TransWord'),
+            t {
+                it('['),
+                it((phonetic and phonetic ~= '') and phonetic or icon.notfound, 'TransPhonetic'),
+                it(']')
+            },
+
+            it(collins and icon.star:rep(collins) or icon.notfound, 'TransCollins'),
+            it(oxford == 1 and icon.yes or icon.no)
+        },
+    })
+end
+
+return M
diff --git a/lua/Trans/frontend/hover/youdao.lua b/lua/Trans/frontend/hover/youdao.lua
new file mode 100644
index 0000000..b2fd283
--- /dev/null
+++ b/lua/Trans/frontend/hover/youdao.lua
@@ -0,0 +1,8 @@
+---@type TransHoverRenderer
+local M = {}
+
+function M.web()
+
+end
+
+return M
diff --git a/lua/Trans/util/node.lua b/lua/Trans/util/node.lua
index 062b0d2..51d1ebf 100644
--- a/lua/Trans/util/node.lua
+++ b/lua/Trans/util/node.lua
@@ -26,38 +26,53 @@ text_meta.__index = function(self, key)
 end
 
 
+local function item(text, highlight)
+    return setmetatable({
+        [1] = text,
+        [2] = highlight,
+    }, item_meta)
+end
+
+local function text(items)
+    local strs = {}
+    local size = #items
+    assert(size > 1)
+    for i = 1, size do
+        strs[i] = items[i][1]
+    end
+
+    return setmetatable({
+        strs  = strs,
+        size  = size,
+        items = items,
+    }, text_meta)
+end
+
+local function format(opts)
+    local str   = opts.text
+    local size  = str.size
+    local width = opts.width
+    local spin  = opts.spin or ' '
+
+    local wid   = str[1]:width()
+    local space = math.max(math.floor((width - wid) / (size - 1)), 0)
+    if space > 0 then
+        str.step = spin:rep(space)
+    end
+    return str
+end
+
+
+---@type table<string, function>
 return {
-    item = function(text, highlight)
-        return setmetatable({
-            [1] = text,
-            [2] = highlight,
-        }, item_meta)
-    end,
-    text = function(items)
-        local strs = {}
-        local size = #items
-        assert(size > 1)
-        for i = 1, size do
-            strs[i] = items[i][1]
-        end
-
-        return setmetatable({
-            strs  = strs,
-            size  = size,
-            items = items,
-        }, text_meta)
-    end,
-    format = function(opts)
-        local text  = opts.text
-        local size  = text.size
-        local width = opts.width
-        local spin  = opts.spin or ' '
-
-        local wid   = text[1]:width()
-        local space = math.max(math.floor((width - wid) / (size - 1)), 0)
-        if space > 0 then
-            text.step = spin:rep(space)
-        end
-        return text
-    end,
+    item = item,
+    text = text,
+    format = format,
+    conjunction = function(str)
+        return {
+            item('', 'TransTitleRound'),
+            item(str, 'TransTitle'),
+            item('', 'TransTitleRound'),
+        }
+    end
 }