diff --git a/.gitignore b/.gitignore
index 931afad..fcc24f7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,5 @@
lua/Trans/test/
-note/
+wiki/
demo.mp4
screenshot.gif
tts/node_modules/
diff --git a/README.md b/README.md
index f89962d..ba84dc8 100644
--- a/README.md
+++ b/README.md
@@ -20,6 +20,9 @@
- 使用纯lua编写, 速度极快
> `Lazy.nvim`的记录: `➜ Trans.nvim 0.82ms`
+- **可以定义快捷键读英文单词**
+> 见wiki
+
- 大部分功能可以自定义:
- 高亮
- 悬浮大小
@@ -315,7 +318,8 @@ require'Trans'.setup {
**示例:**
> 示例中展示, 将`mm`映射成快捷键
```lua
-vim.keymap.set({'n', 'v'}, 'mm', 'Translate')
+vim.keymap.set({'n', 'x'}, 'mm', 'Translate')
+vim.keymap.set({'n', 'x'}, 'mk', 'TransPlay') -- 自动发音选中或者光标下的单词
vim.keymap.set('n', 'mi', 'TranslateInput')
```
diff --git a/lua/Trans/init.lua b/lua/Trans/init.lua
index 8f981ad..4822031 100644
--- a/lua/Trans/init.lua
+++ b/lua/Trans/init.lua
@@ -7,6 +7,28 @@ local title = vim.fn.has('nvim-0.9') == 1 and {
} or nil
+string.width = vim.fn.strwidth
+string.isEn = function(self)
+ local char = { self:byte(1, -1) }
+ for i = 1, #self do
+ if char[i] > 127 then
+ return false
+ end
+ end
+ return true
+end
+
+
+string.play = vim.fn.has('linux') == 1 and function(self)
+ local cmd = ([[echo "%s" | festival --tts]]):format(self)
+ vim.fn.jobstart(cmd)
+end or function(self)
+ local seperator = vim.fn.has('unix') and '/' or '\\'
+ local file = debug.getinfo(1, "S").source:sub(2):match('(.*)lua') .. seperator .. 'tts' .. seperator .. 'say.js'
+ vim.fn.jobstart('node ' .. file .. ' ' .. self)
+end
+
+
M.conf = {
view = {
i = 'float',
@@ -132,28 +154,93 @@ M.setup = function(opts)
times = times + 1
if times == 1 then
- M.translate = require('Trans.translate')
+ local api = vim.api
+
+ local get_mode = api.nvim_get_mode
+ local set_hl = api.nvim_set_hl
+ local new_command = api.nvim_create_user_command
if vim.fn.executable('sqlite3') ~= 1 then
error('Please check out sqlite3')
end
- vim.api.nvim_create_user_command('Translate', function()
+ new_command('Translate', function()
M.translate()
end, { desc = ' 单词翻译', })
- vim.api.nvim_create_user_command('TranslateInput', function()
+ new_command('TranslateInput', function()
M.translate('i')
end, { desc = ' 搜索翻译' })
+ new_command('TransPlay', function()
+ local word = M.get_word(get_mode().mode)
+ if word ~= '' and word:isEn() then
+ word:play()
+ end
+ end, { desc = ' 自动发音' })
local hls = require('Trans.ui.theme')[conf.theme]
for hl, opt in pairs(hls) do
- vim.api.nvim_set_hl(0, hl, opt)
+ set_hl(0, hl, opt)
end
end
end
+local function get_select()
+ local s_start = vim.fn.getpos("v")
+ local s_end = vim.fn.getpos(".")
+ if s_start[2] > s_end[2] or s_start[3] > s_end[3] then
+ s_start, s_end = s_end, s_start
+ end
+
+ local n_lines = math.abs(s_end[2] - s_start[2]) + 1
+ local lines = vim.api.nvim_buf_get_lines(0, s_start[2] - 1, s_end[2], false)
+ lines[1] = string.sub(lines[1], s_start[3], -1)
+ if n_lines == 1 then
+ lines[n_lines] = string.sub(lines[n_lines], 1, s_end[3] - s_start[3] + 1)
+ else
+ lines[n_lines] = string.sub(lines[n_lines], 1, s_end[3])
+ end
+ return table.concat(lines, '')
+end
+
+M.get_word = function(mode)
+ local word
+ if mode == 'n' then
+ word = vim.fn.expand('')
+ elseif mode == 'v' then
+ vim.api.nvim_input('')
+ word = get_select()
+ elseif mode == 'i' then
+ -- TODO Use Telescope with fuzzy finder
+ vim.ui.input({ prompt = '请输入需要查询的单词: ' }, function(input)
+ word = input
+ end)
+ else
+ error('invalid mode: ' .. mode)
+ end
+ return word
+end
+
+
+M.translate = function(mode, view)
+ vim.validate {
+ mode = { mode, 's', true },
+ view = { view, 's', true }
+ }
+
+ mode = mode or vim.api.nvim_get_mode().mode
+ view = view or M.conf.view[mode]
+ assert(mode and view)
+ local word = M.get_word(mode)
+ if word == nil or word == '' then
+ return
+ else
+ require('Trans.view.' .. view)(word:gsub('^%s+', '', 1))
+ end
+end
+
+
M.augroup = vim.api.nvim_create_augroup('Trans', { clear = true })
return M
diff --git a/lua/Trans/query/baidu.lua b/lua/Trans/query/baidu.lua
index 73c0d52..d98c0ec 100644
--- a/lua/Trans/query/baidu.lua
+++ b/lua/Trans/query/baidu.lua
@@ -10,8 +10,8 @@ end
local post = require('Trans.util.curl').POST
-local function get_field(word)
- local to = 'zh'
+local function get_field(word, isEn)
+ local to = isEn and 'zh' or 'en'
local tmp = appid .. word .. salt .. appPasswd
local sign = require('Trans.util.md5').sumhexa(tmp)
@@ -25,12 +25,12 @@ local function get_field(word)
}
end
---- this is a nice plugin
---返回一个channel
---@param word string
---@return table
return function(word)
- local query = get_field(word)
+ local isEn = word:isEn()
+ local query = get_field(word, isEn)
local result = {}
post(uri, {
@@ -39,11 +39,11 @@ return function(word)
content_type = "application/x-www-form-urlencoded",
},
callback = function(str)
- local res = vim.json.decode(str)
- if res and res.trans_result then
+ local ok, res = pcall(vim.json.decode, str)
+ if ok and res and res.trans_result then
result.value = {
word = word,
- translation = res.trans_result[1].dst,
+ [isEn and 'translation' or 'definition'] = res.trans_result[1].dst,
}
if result.callback then
diff --git a/lua/Trans/translate.lua b/lua/Trans/translate.lua
deleted file mode 100644
index 9794528..0000000
--- a/lua/Trans/translate.lua
+++ /dev/null
@@ -1,53 +0,0 @@
-local function get_select()
- local s_start = vim.fn.getpos("v")
- local s_end = vim.fn.getpos(".")
- if s_start[2] > s_end[2] or s_start[3] > s_end[3] then
- s_start, s_end = s_end, s_start
- end
-
- local n_lines = math.abs(s_end[2] - s_start[2]) + 1
- local lines = vim.api.nvim_buf_get_lines(0, s_start[2] - 1, s_end[2], false)
- lines[1] = string.sub(lines[1], s_start[3], -1)
- if n_lines == 1 then
- lines[n_lines] = string.sub(lines[n_lines], 1, s_end[3] - s_start[3] + 1)
- else
- lines[n_lines] = string.sub(lines[n_lines], 1, s_end[3])
- end
- return table.concat(lines, '')
-end
-
-local function get_word(mode)
- local word
- if mode == 'n' then
- word = vim.fn.expand('')
- elseif mode == 'v' then
- vim.api.nvim_input('')
- word = get_select()
- elseif mode == 'i' then
- -- TODO Use Telescope with fuzzy finder
- vim.ui.input({ prompt = '请输入需要查询的单词: ' }, function(input)
- word = input
- end)
- else
- error('invalid mode: ' .. mode)
- end
-
- return word
-end
-
-return function(mode, view)
- vim.validate {
- mode = { mode, 's', true },
- view = { view, 's', true }
- }
-
- 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)
- if word == nil or word == '' then
- return
- else
- require('Trans.view.' .. view)(word:gsub('^%s+', '', 1))
- end
-end
diff --git a/lua/Trans/util/animation.lua b/lua/Trans/util/animation.lua
index 684f71a..0ad00a8 100644
--- a/lua/Trans/util/animation.lua
+++ b/lua/Trans/util/animation.lua
@@ -11,13 +11,14 @@ local display = function(self)
self:frame(i)
end
end
+
else
while self.run do
self:frame()
end
- callback()
end
+ callback()
else
local frame
if self.times then
diff --git a/lua/Trans/util/is_Chinese.lua b/lua/Trans/util/is_Chinese.lua
deleted file mode 100644
index 09ec9e5..0000000
--- a/lua/Trans/util/is_Chinese.lua
+++ /dev/null
@@ -1,6 +0,0 @@
----判断单词是否含有中文
----@param word string 需要判断的单词
----@return boolean 判断结果
-return function (word)
- return false
-end
diff --git a/lua/Trans/view/hover.lua b/lua/Trans/view/hover.lua
index 1d18494..16e3a5e 100644
--- a/lua/Trans/view/hover.lua
+++ b/lua/Trans/view/hover.lua
@@ -105,7 +105,7 @@ local process = {
d = '限定词determiner ',
}
- local f = '%s %s%%'
+ local f = '%s %2s%%'
for pos in vim.gsplit(m_result.pos, '/', true) do
m_content:addline(
it(m_indent .. f:format(pos_map[pos:sub(1, 1)], pos:sub(3)), 'TransPos')
@@ -143,12 +143,14 @@ local process = {
end,
translation = function()
- title('中文翻译')
+ if exist(m_result.translation) then
+ title('中文翻译')
- for trs in vim.gsplit(m_result.translation, '\n', true) do
- m_content:addline(
- it(m_indent .. trs, 'TransTranslation')
- )
+ for trs in vim.gsplit(m_result.translation, '\n', true) do
+ m_content:addline(
+ it(m_indent .. trs, 'TransTranslation')
+ )
+ end
end
m_content:newline('')
@@ -251,19 +253,15 @@ action = {
end
end,
- play = vim.fn.has('linux') == 1 and function()
- local cmd = ([[echo "%s" | festival --tts]]):format(m_result.word)
- vim.fn.jobstart(cmd)
- end or function()
- local seperator = vim.fn.has('unix') and '/' or '\\'
- local file = debug.getinfo(1, "S").source:sub(2):match('(.*)lua') .. seperator .. 'tts' .. seperator .. 'say.js'
- vim.fn.jobstart('node ' .. file .. ' ' .. m_result.word)
+ play = function()
+ m_result.word:play()
end,
}
+
local function handle()
local hover = conf.hover
- if hover.auto_play then
+ if m_result.translation and hover.auto_play then
local ok = pcall(action.play)
if not ok then
vim.notify('自动发音失败, 请检查README发音部分', vim.log.WARN)
@@ -280,20 +278,21 @@ local function handle()
end
local function online_query(word)
- -- TODO :Progress Bar
local lists = {}
local engines = conf.engines
local size = #engines
local icon = conf.icon
local error_msg = icon.notfound .. ' 没有找到相关的翻译'
+
m_window:set_height(1)
- local width = m_window.width
+ local origin_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
@@ -307,16 +306,19 @@ local function online_query(word)
local timeout = conf.hover.timeout
local interval = math.floor(timeout / (m_window.width - spinner[1]:width()))
+ local width = m_window.width
+
local f = '%s %s'
require('Trans.util.animation')({
- times = m_window.width,
+ times = width,
+ interval = interval,
frame = function(self, times)
m_content:wipe()
for i, v in ipairs(lists) do
local res = v.value
if res then
m_result = res
- m_window:set_width(width)
+ m_window:set_width(origin_width)
handle()
m_content:attach()
@@ -327,26 +329,24 @@ local function online_query(word)
self.run = false
return
- elseif res == 'false' then
+
+ elseif res == false then
table.remove(lists, i)
size = size - 1
end
end
- if size == 0 then
- m_content:addline(
- it(error_msg, 'TransFailed')
- )
- m_content:attach()
-
+ local line
+ if size == 0 or times == width then
+ line = it(error_msg, 'TransFailed')
+ self.run = false
else
- m_content:addline(
- it(f:format(spinner[times % range + 1], cell:rep(times)), 'MoreMsg')
- )
- m_content:attach()
+ line = it(f:format(spinner[times % range + 1], cell:rep(times)), 'MoreMsg')
end
+
+ m_content:addline(line)
+ m_content:attach()
end,
- interval = interval,
}):display()
end
diff --git a/lua/Trans/window.lua b/lua/Trans/window.lua
index f3b3869..35da5e0 100644
--- a/lua/Trans/window.lua
+++ b/lua/Trans/window.lua
@@ -2,7 +2,6 @@ local api = vim.api
local new_content = require('Trans.content')
local new_animation = require('Trans.util.animation')
-string.width = vim.fn.strwidth
local busy = false
local function lock()