Compare commits
1 Commits
v2
...
experiment
Author | SHA1 | Date | |
---|---|---|---|
|
36865cc17d |
21
LICENCE
21
LICENCE
@ -1,21 +0,0 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2023 Zoran
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
263
README.md
263
README.md
@ -2,48 +2,51 @@
|
||||
|
||||
<!--toc:start-->
|
||||
|
||||
- [Trans.nvim](#transnvim)
|
||||
- [Trans.nvim](#transnvim) - [注意: 当前分支目前没有发布, README.md 的描述并不准确, 遇到问题请切换到 `main`分支或者联系我](#注意-当前分支目前没有发布-readmemd-的描述并不准确-遇到问题请切换到-main分支或者联系我)
|
||||
- [特点](#特点)
|
||||
- [屏幕截图](#屏幕截图)
|
||||
- [演示](#演示)
|
||||
- [离线查询](#离线查询)
|
||||
- [在线查询演示 (有道)](#在线查询演示-有道)
|
||||
- [\*在线查询\*\* (有道)](#在线查询-有道)
|
||||
- [主题](#主题)
|
||||
- [安装](#安装)
|
||||
- [配置](#配置)
|
||||
- [快捷键绑定](#快捷键绑定)
|
||||
- [高亮组](#高亮组)
|
||||
- [声明](#声明)
|
||||
- [感谢](#感谢)
|
||||
- [贡献](#贡献)
|
||||
- [从 v1 (main)分支迁移](#从-v1-main分支迁移)
|
||||
- [待办 (画大饼)](#待办-画大饼)
|
||||
- [项目情况](#项目情况)
|
||||
<!--toc:end-->
|
||||
|
||||
> **插件默认词库的路径为插件目录**
|
||||
|
||||
例如: `lazy` 用户应该在 `$HOME/.local/share/nvim/lazy/Trans.nvim`
|
||||
### 注意: 当前分支目前没有发布, README.md 的描述并不准确, 遇到问题请切换到 `main`分支或者联系我
|
||||
|
||||
## 特点
|
||||
|
||||
- `使用纯 lua 编写`
|
||||
- 使用纯 lua 编写, 速度极快
|
||||
|
||||
> `Lazy.nvim`的记录: <font color="#0099FF">`➜ Trans.nvim 0.82ms`</font>
|
||||
|
||||
- **可以定义快捷键读英文单词**
|
||||
|
||||
> 见 wiki
|
||||
|
||||
- 大部分功能可以自定义:
|
||||
- 🔍 高亮
|
||||
- 👀 悬浮大小
|
||||
- 📜 排版顺序
|
||||
- 💬 弹窗大小
|
||||
- 🎉 舒服窗口动画
|
||||
- 更多可以查看[配置](#配置)
|
||||
- `离线`和`在线`翻译的支持
|
||||
- 高亮
|
||||
- 悬浮大小
|
||||
- 排版顺序
|
||||
- 弹窗大小
|
||||
- `舒服窗口动画`
|
||||
- etc (更多可以查看[配置](#配置))
|
||||
- **完全离线** 的单词翻译体验 (可能后面会支持在线翻译)
|
||||
- 支持显示:
|
||||
- 🌟 柯林斯星级
|
||||
- 📚 牛津 3000 词汇
|
||||
- 🇨🇳 中文翻译
|
||||
- 🇺🇸 英文翻译 (不是英译中, 而是用英文解释)
|
||||
- 🌱 词根
|
||||
- 柯林斯星级
|
||||
- 牛津 3000 词汇
|
||||
- 中文翻译
|
||||
- 英文翻译 (不是英译中, 而是用英文解释)
|
||||
- 词根
|
||||
- etc
|
||||
- 支持`平滑动画`
|
||||
- 舒服的排版和`动画`
|
||||
- 支持 `normal`和 `visual`模式
|
||||
> <font color='#FF9900'>不支持 visual-block mode</font>
|
||||
- 本地词库单词量: `430w`
|
||||
@ -58,13 +61,13 @@
|
||||
|
||||
https://user-images.githubusercontent.com/107862700/226175984-1a95bea7-8d66-450e-87e1-ba9c91c37ab8.mp4
|
||||
|
||||
### 在线查询演示 (有道)
|
||||
### 在线查询 (有道)
|
||||
|
||||
https://user-images.githubusercontent.com/107862700/226176106-c2962dd3-d66c-499c-b44a-1f471b79fe38.mp4
|
||||
|
||||
**使用在线查询需要配置相应的 app_id 和 app_passwd**
|
||||
|
||||
配置说明见: [wiki](https://github.com/JuanZoran/Trans.nvim/wiki/%E9%85%8D%E7%BD%AE#%E5%9C%A8%E7%BA%BF%E6%9F%A5%E8%AF%A2%E9%85%8D%E7%BD%AE)
|
||||
在线查询配置见: [wiki](https://github.com/JuanZoran/Trans.nvim/wiki/%E9%85%8D%E7%BD%AE#%E5%9C%A8%E7%BA%BF%E6%9F%A5%E8%AF%A2%E9%85%8D%E7%BD%AE)
|
||||
|
||||
### 主题
|
||||
|
||||
@ -93,7 +96,7 @@ _安装之前, 首先需要明确本插件的依赖:_
|
||||
|
||||
```lua
|
||||
use {
|
||||
'JuanZoran/Trans.nvim',
|
||||
'JuanZoran/Trans.nvim'
|
||||
run = function() require('Trans').install() end, -- 自动下载使用的本地词库
|
||||
requires = 'kkharji/sqlite.lua', ,
|
||||
-- 如果你不需要任何配置的话, 可以直接按照下面的方式启动
|
||||
@ -136,13 +139,12 @@ use {
|
||||
```lua
|
||||
{
|
||||
"JuanZoran/Trans.nvim",
|
||||
build = function () require'Trans'.install() end,
|
||||
keys = {
|
||||
-- 可以换成其他你想映射的键
|
||||
{ 'mm', mode = { 'n', 'x' }, '<Cmd>Translate<CR>', desc = ' Translate' },
|
||||
{ 'mm', mode = { 'n', 'x' }, '<Cmd>Translate<CR>', desc = ' Translate' },
|
||||
{ 'mk', mode = { 'n', 'x' }, '<Cmd>TransPlay<CR>', desc = ' Auto Play' },
|
||||
-- 目前这个功能的视窗还没有做好,可以在配置里将view.i改成hover
|
||||
{ 'mi', '<Cmd>TranslateInput<CR>', desc = ' Translate From Input' },
|
||||
{ 'mi', '<Cmd>TranslateInput<CR>', desc = ' Translate From Input' },
|
||||
},
|
||||
dependencies = { 'kkharji/sqlite.lua', },
|
||||
opts = {
|
||||
@ -155,29 +157,40 @@ use {
|
||||
|
||||
<font color="#FF9900">**注意事项**: </font>
|
||||
|
||||
- `install.sh`
|
||||
|
||||
- 使用了 `wget`下载词库, 安装请确保你的环境变量中存在 wget
|
||||
- install.sh 下载后会自动将词库解压, 并移动到 `$HOME/.vim/dict`文件夹下
|
||||
- 目前仅在 `Ubuntu22.04`的环境下测试通过
|
||||
> 如果上述条件不符合, 请删掉 `run = 'install.sh'`部分, 考虑手动安装词库
|
||||
> 如果上述条件满足, 仍出现问题, 欢迎在 issue 里向我反馈,我会及时尝试解决
|
||||
|
||||
- 下载词典的过程中, 需要能够 `流畅的访问github下载`
|
||||
|
||||
如果下载出现问题, 正常是会自动下载
|
||||
> 词库文件压缩包大小为: **281M**
|
||||
> 解压缩后的大小大概为: 1.2G
|
||||
|
||||
> 词库文件压缩包大小为: **281M**
|
||||
> 解压缩后的大小大概为: **1.2G**
|
||||
- 安装后如果不能正常运行, 请尝试检查一下问题:
|
||||
|
||||
- 安装后如果不能正常运行, 清尝试运行 `checkhealth Trans`
|
||||
- 本机是否已经安装了 `sqlite3`
|
||||
> Linux 下安装:
|
||||
> `sudo pacman -S sqlite # Arch`
|
||||
> `sudo apt-get install sqlite3 libsqlite3-dev # Ubuntu`
|
||||
|
||||
- **`auto_play`** 的使用:
|
||||
> **尝试运行 `checkhealth Trans`**
|
||||
|
||||
- `Linux` 需要安装`festival`
|
||||
- **`auto_play`** 使用步骤:
|
||||
|
||||
> `sudo apt-get install festival festvox-kallpc16k`
|
||||
> linux 只需要安装`festival`
|
||||
> sudo apt-get install festival festvox-kallpc16k
|
||||
> **_如果你想要设置音色,发音可以访问:_** [Festival 官方](https://www.cstr.ed.ac.uk/projects/festival/morevoices.html)
|
||||
> 可以选择英音、美音、男声、女声
|
||||
|
||||
**如果你想要设置音色,发音可以访问:** [Festival 官方](https://www.cstr.ed.ac.uk/projects/festival/morevoices.html)
|
||||
可以选择英音、美音、男声、女声
|
||||
> 其他操作系统
|
||||
|
||||
- `Termux` 需要安装`termux-api`
|
||||
|
||||
- `Mac` 使用系统的`say`命令
|
||||
|
||||
- `Windows` 使用原生的 Powershell 命令, 感谢[PR](https://github.com/JuanZoran/Trans.nvim/pull/34)
|
||||
- 需要确保安装了`nodejs`
|
||||
- 进入插件的`tts`目录运行`npm install`
|
||||
> 如果`install`运行正常则自动安装,如果安装失败,请尝试手动安装
|
||||
|
||||
- `title`的配置,只对`neovim 0.9+`版本有效
|
||||
|
||||
@ -231,16 +244,12 @@ use {
|
||||
|
||||
## 配置
|
||||
|
||||
详细见**wiki**: [基本配置说明](https://github.com/JuanZoran/Trans.nvim/wiki/%E9%85%8D%E7%BD%AE)
|
||||
|
||||
<details>
|
||||
<summary>默认配置</summary>
|
||||
详细见**wiki**: [配置说明](https://github.com/JuanZoran/Trans.nvim/wiki/%E9%85%8D%E7%BD%AE)
|
||||
|
||||
```lua
|
||||
default_conf = {
|
||||
require 'Trans'.setup {
|
||||
---@type string the directory for database file and password file
|
||||
dir = require 'Trans'.plugin_dir,
|
||||
debug = true,
|
||||
---@type 'default' | 'dracula' | 'tokyonight' global Trans theme [see lua/Trans/style/theme.lua]
|
||||
theme = 'default', -- default | tokyonight | dracula
|
||||
strategy = {
|
||||
@ -259,7 +268,7 @@ default_conf = {
|
||||
border = 'rounded',
|
||||
title = vim.fn.has 'nvim-0.9' == 1 and {
|
||||
{ '', 'TransTitleRound' },
|
||||
{ ' Trans', 'TransTitle' },
|
||||
{ ' Trans', 'TransTitle' },
|
||||
{ '', 'TransTitleRound' },
|
||||
} or nil, -- need nvim-0.9+
|
||||
auto_play = true,
|
||||
@ -285,13 +294,11 @@ default_conf = {
|
||||
split_width = 60,
|
||||
padding = 10, -- padding for hover window width
|
||||
keymaps = {
|
||||
-- INFO : No default keymaps anymore, please set it yourself
|
||||
-- pageup = '<C-u>',
|
||||
-- pagedown = '<C-d>',
|
||||
-- pin = '<leader>[',
|
||||
-- close = '<leader>]',
|
||||
-- toggle_entry = '<leader>;',
|
||||
|
||||
pageup = '[[',
|
||||
pagedown = ']]',
|
||||
pin = '<leader>[',
|
||||
close = '<leader>]',
|
||||
toggle_entry = '<leader>;',
|
||||
-- play = '_', -- Deprecated
|
||||
},
|
||||
---@type string[] auto close events
|
||||
@ -326,7 +333,7 @@ default_conf = {
|
||||
-- or use emoji
|
||||
list = '●', -- ● | ○ | ◉ | ◯ | ◇ | ◆ | ▪ | ▫ | ⬤ | 🟢 | 🟡 | 🟣 | 🟤 | 🟠| 🟦 | 🟨 | 🟧 | 🟥 | 🟪 | 🟫 | 🟩 | 🟦
|
||||
star = '', -- ⭐ | ✴ | ✳ | ✲ | ✱ | ✰ | ★ | ☆ | 🌟 | 🌠 | 🌙 | 🌛 | 🌜 | 🌟 | 🌠 | 🌌 | 🌙 |
|
||||
notfound = ' ', --❔ | ❓ | ❗ | ❕|
|
||||
notfound = ' ', --❔ | ❓ | ❗ | ❕|
|
||||
yes = '✔', -- ✅ | ✔️ | ☑
|
||||
no = '', -- ❌ | ❎ | ✖ | ✘ | ✗ |
|
||||
cell = '■', -- ■ | □ | ▇ | ▏ ▎ ▍ ▌ ▋ ▊ ▉
|
||||
@ -342,8 +349,6 @@ default_conf = {
|
||||
}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
## 快捷键绑定
|
||||
|
||||
**示例:**
|
||||
@ -356,90 +361,66 @@ vim.keymap.set({'n', 'x'}, 'mm', '<Cmd>Translate<CR>')
|
||||
vim.keymap.set({'n', 'x'}, 'mk', '<Cmd>TransPlay<CR>') -- 自动发音选中或者光标下的单词
|
||||
```
|
||||
|
||||
**窗口快捷键**
|
||||
|
||||
```lua
|
||||
require 'Trans'.setup {
|
||||
frontend = {
|
||||
hover = {
|
||||
keymaps = {
|
||||
-- pageup = 'whatever you want',
|
||||
-- pagedown = 'whatever you want',
|
||||
-- pin = 'whatever you want',
|
||||
-- close = 'whatever you want',
|
||||
-- toggle_entry = 'whatever you want',
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
> 当窗口没有打开的时候, key 会被使用`vim.api.nvim_feedkey`来执行
|
||||
|
||||
## 高亮组
|
||||
|
||||
所有主题可见 `lua/Trans/style/theme.lua`
|
||||
|
||||
<details>
|
||||
|
||||
<summary>默认主题</summary>
|
||||
> 默认定义
|
||||
|
||||
```lua
|
||||
TransWord = {
|
||||
fg = '#7ee787',
|
||||
bold = true,
|
||||
}
|
||||
TransPhonetic = {
|
||||
link = 'Linenr'
|
||||
}
|
||||
TransTitle = {
|
||||
fg = '#0f0f15',
|
||||
bg = '#75beff',
|
||||
bold = true,
|
||||
}
|
||||
TransTitleRound = {
|
||||
fg = '#75beff',
|
||||
}
|
||||
TransTag = {
|
||||
-- fg = '#e5c07b',
|
||||
link = '@tag'
|
||||
}
|
||||
TransExchange = {
|
||||
link = 'TransTag',
|
||||
}
|
||||
TransPos = {
|
||||
link = 'TransTag',
|
||||
}
|
||||
TransTranslation = {
|
||||
link = 'TransWord',
|
||||
}
|
||||
TransDefinition = {
|
||||
link = 'Moremsg',
|
||||
}
|
||||
TransWin = {
|
||||
link = 'Normal',
|
||||
}
|
||||
TransBorder = {
|
||||
fg = '#89B4FA',
|
||||
}
|
||||
TransCollins = {
|
||||
fg = '#faf743',
|
||||
bold = true,
|
||||
}
|
||||
TransFailed = {
|
||||
fg = '#7aa89f',
|
||||
}
|
||||
TransWaitting = {
|
||||
link = 'MoreMsg'
|
||||
}
|
||||
TransWeb = {
|
||||
link = 'MoreMsg',
|
||||
}
|
||||
{
|
||||
TransWord = {
|
||||
fg = '#7ee787',
|
||||
bold = true,
|
||||
},
|
||||
TransPhonetic = {
|
||||
link = 'Linenr'
|
||||
},
|
||||
TransTitle = {
|
||||
fg = '#0f0f15',
|
||||
bg = '#75beff',
|
||||
bold = true,
|
||||
},
|
||||
TransTitleRound = {
|
||||
fg = '#75beff',
|
||||
},
|
||||
TransTag = {
|
||||
-- fg = '#e5c07b',
|
||||
link = '@tag'
|
||||
},
|
||||
TransExchange = {
|
||||
link = 'TransTag',
|
||||
},
|
||||
TransPos = {
|
||||
link = 'TransTag',
|
||||
},
|
||||
TransTranslation = {
|
||||
link = 'TransWord',
|
||||
},
|
||||
TransDefinition = {
|
||||
link = 'Moremsg',
|
||||
},
|
||||
TransWin = {
|
||||
link = 'Normal',
|
||||
},
|
||||
TransBorder = {
|
||||
fg = '#89B4FA',
|
||||
},
|
||||
TransCollins = {
|
||||
fg = '#faf743',
|
||||
bold = true,
|
||||
},
|
||||
TransFailed = {
|
||||
fg = '#7aa89f',
|
||||
},
|
||||
TransWaitting = {
|
||||
link = 'MoreMsg'
|
||||
},
|
||||
TransWeb = {
|
||||
-- TODO :
|
||||
link = 'MoreMsg',
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
## 声明
|
||||
|
||||
- 本插件词典基于[ECDICT](https://github.com/skywind3000/ECDICT)
|
||||
@ -452,24 +433,20 @@ TransWeb = {
|
||||
|
||||
## 贡献
|
||||
|
||||
> 更新比较频繁, 文档先鸽了 (wiki 写了一小部分
|
||||
> 更新比较频繁, 文档先鸽了
|
||||
> 如果你想要参加这个项目, 可以提 issue, 我会把文档补齐
|
||||
|
||||
## 从 v1 (main)分支迁移
|
||||
|
||||
见[wiki](<https://github.com/JuanZoran/Trans.nvim/wiki/%E4%BB%8E(v1)main%E5%88%86%E6%94%AF%E8%BF%81%E7%A7%BB>)
|
||||
|
||||
## 待办 (画大饼)
|
||||
|
||||
- [x] 快捷键定义
|
||||
- [x] 自动读音
|
||||
- [x] 在线多引擎异步查询
|
||||
- [x] `句子翻译` | `中翻英` 的支持
|
||||
- [x] 迁移文档
|
||||
- [ ] 迁移文档
|
||||
- [ ] 多风格样式查询
|
||||
- [ ] 重新录制屏幕截图示例
|
||||
- [ ] 变量命名的支持
|
||||
- [ ] 历史查询结果保存
|
||||
- [ ] 翻译结果替换
|
||||
|
||||
## 项目情况
|
||||
|
||||
|
@ -129,7 +129,7 @@ Packer.nvim ~
|
||||
requires = { 'kkharji/sqlite.lua', },
|
||||
config = function()
|
||||
require("Trans").setup {} -- 启动Trans
|
||||
vim.keymap.set({"n", 'x'}, "mm", '<Cmd>Translate<CR>', { desc = ' Translate' }) -- 自动判断virtual 还是 normal 模式
|
||||
vim.keymap.set({"n", 'x'}, "mm", '<Cmd>Translate<CR>', { desc = ' Translate' }) -- 自动判断virtual 还是 normal 模式
|
||||
vim.keymap.set({'n', 'x'}, 'mk', '<Cmd>TransPlay<CR>', {desc = ' 自动发音'}) -- 自动发音选中或者光标下的单词
|
||||
end
|
||||
}
|
||||
@ -142,11 +142,11 @@ Lazy.nvim ~
|
||||
"JuanZoran/Trans.nvim",
|
||||
keys = {
|
||||
-- 可以换成其他你想映射的键
|
||||
{ 'mm', mode = { 'n', 'x' }, '<Cmd>Translate<CR>', desc = ' Translate' },
|
||||
{ 'mm', mode = { 'n', 'x' }, '<Cmd>Translate<CR>', desc = ' Translate' },
|
||||
{ 'mk', mode = { 'n', 'x' }, '<Cmd>TransPlay<CR>', desc = ' 自动发音' },
|
||||
|
||||
-- 目前这个功能的视窗还没有做好,可以在配置里将view.i改成hover
|
||||
{ 'mi', '<Cmd>TranslateInput<CR>', desc = ' Translate From Input' },
|
||||
{ 'mi', '<Cmd>TranslateInput<CR>', desc = ' Translate From Input' },
|
||||
},
|
||||
dependencies = { 'kkharji/sqlite.lua', },
|
||||
opts = {
|
||||
@ -301,7 +301,7 @@ Festival配置(仅针对linux用户) ~
|
||||
-- or use emoji
|
||||
list = '●', -- ● | ○ | ◉ | ◯ | ◇ | ◆ | ▪ | ▫ | ⬤ | 🟢 | 🟡 | 🟣 | 🟤 | 🟦 | 🟨 | 🟧 | 🟥 | 🟪 | 🟫 | 🟩 | 🟠 | 🟦 | 🟨 | 🟧 | 🟥 | 🟪 | 🟫 | 🟩 | 🟠
|
||||
star = '', -- ⭐ | ✴ | ✳ | ✲ | ✱ | ✰ | ★ | ☆ | 🌟 | 🌠 | 🌙 | 🌛 | 🌜 | 🌟 | 🌠 | 🌌 | 🌙 |
|
||||
notfound = ' ', --❔ | ❓ | ❗ | ❕|
|
||||
notfound = ' ', --❔ | ❓ | ❗ | ❕|
|
||||
yes = '✔', -- ✅ | ✔️ | ☑
|
||||
no = '', -- ❌ | ❎ | ✖ | ✘ | ✗ |
|
||||
cell = '■', -- ■ | □ | ▇ | ▏ ▎ ▍ ▌ ▋ ▊ ▉ █
|
||||
|
@ -15,9 +15,4 @@
|
||||
- [ ] Unlimit width for sentence
|
||||
|
||||
|
||||
已知问题:
|
||||
1. 缓存了的单词, 无法使用toggle_entry 进入页面
|
||||
2. 加载配置需要输入所有表的key
|
||||
|
||||
|
||||
- default_strategy can't deal with table correctly
|
||||
|
@ -1,7 +1,7 @@
|
||||
local Trans = require 'Trans'
|
||||
|
||||
local db = require 'sqlite.db'
|
||||
local path = Trans.conf.dir .. '/ultimate.db'
|
||||
local path = Trans.conf.dir .. Trans.separator .. 'ultimate.db'
|
||||
local dict = db:open(path)
|
||||
local db_name = 'stardict'
|
||||
vim.api.nvim_create_autocmd('VimLeavePre', {
|
||||
@ -99,8 +99,6 @@ local formatter = {
|
||||
['p'] = '过去式 ',
|
||||
['r'] = '比较级 ',
|
||||
['t'] = '最高级 ',
|
||||
['b'] = '比较级 ',
|
||||
['z'] = '最高级 ',
|
||||
['s'] = '复数 ',
|
||||
['d'] = '过去分词 ',
|
||||
['i'] = '现在分词 ',
|
||||
|
@ -2,7 +2,7 @@ local api, fn = vim.api, vim.fn
|
||||
|
||||
---@class TransBuffer
|
||||
---@field bufnr integer buffer handle
|
||||
---@field [integer] string|TransNode|TransNode[] buffer[line] content
|
||||
---@field [number] string|TransNode|TransNode[] buffer[line] content
|
||||
local buffer = {}
|
||||
|
||||
-- INFO : corountine can't invoke C function
|
||||
@ -37,7 +37,7 @@ end
|
||||
|
||||
---Destory buffer
|
||||
function buffer:destroy()
|
||||
pcall(api.nvim_buf_delete, self.bufnr, { force = true })
|
||||
api.nvim_buf_delete(self.bufnr, { force = true })
|
||||
end
|
||||
|
||||
---Set buffer load keymap
|
||||
@ -91,7 +91,11 @@ end
|
||||
---@return integer
|
||||
function buffer:line_count()
|
||||
local line_count = api.nvim_buf_line_count(self.bufnr)
|
||||
return line_count == 1 and self[1] == '' and 0 or line_count
|
||||
if line_count == 1 and self[1] == '' then
|
||||
return 0
|
||||
end
|
||||
|
||||
return line_count
|
||||
end
|
||||
|
||||
---Set line content
|
||||
@ -147,11 +151,11 @@ buffer.__index = function(self, key)
|
||||
end
|
||||
end
|
||||
|
||||
buffer.__newindex = function(self, key, values)
|
||||
buffer.__newindex = function(self, key, nodes)
|
||||
if type(key) == 'number' then
|
||||
self:setline(values, key)
|
||||
self:setline(nodes, key)
|
||||
else
|
||||
rawset(self, key, values)
|
||||
rawset(self, key, nodes)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
return {
|
||||
---@type string the directory for database file and password file
|
||||
dir = require 'Trans'.plugin_dir,
|
||||
db_url = 'https://github.com/skywind3000/ECDICT-ultimate/releases/download/1.0.0/ecdict-ultimate-sqlite.zip',
|
||||
warning = true,
|
||||
debug = true,
|
||||
---@type 'default' | 'dracula' | 'tokyonight' global Trans theme [see lua/Trans/style/theme.lua]
|
||||
theme = 'default', -- default | tokyonight | dracula
|
||||
@ -25,10 +25,10 @@ return {
|
||||
query = 'fallback',
|
||||
border = 'rounded',
|
||||
title = vim.fn.has 'nvim-0.9' == 1 and {
|
||||
{ '', 'TransTitleRound' },
|
||||
{ ' Trans', 'TransTitle' },
|
||||
{ '', 'TransTitleRound' },
|
||||
} or nil, -- need nvim-0.9+
|
||||
{ '', 'TransTitleRound' },
|
||||
{ ' Trans', 'TransTitle' },
|
||||
{ '', 'TransTitleRound' },
|
||||
} or nil, -- need nvim-0.9+
|
||||
auto_play = true,
|
||||
---@type {open: string | boolean, close: string | boolean, interval: integer} Hover Window Animation
|
||||
animation = {
|
||||
@ -52,12 +52,11 @@ return {
|
||||
split_width = 60,
|
||||
padding = 10, -- padding for hover window width
|
||||
keymaps = {
|
||||
-- pageup = '<C-u>',
|
||||
-- pagedown = '<C-d>',
|
||||
-- pin = '<leader>[',
|
||||
-- close = '<leader>]',
|
||||
-- toggle_entry = '<leader>;',
|
||||
|
||||
pageup = '[[',
|
||||
pagedown = ']]',
|
||||
pin = '<leader>[',
|
||||
close = '<leader>]',
|
||||
toggle_entry = '<leader>;',
|
||||
-- play = '_', -- Deprecated
|
||||
},
|
||||
---@type string[] auto close events
|
||||
@ -92,7 +91,7 @@ return {
|
||||
-- or use emoji
|
||||
list = '●', -- ● | ○ | ◉ | ◯ | ◇ | ◆ | ▪ | ▫ | ⬤ | 🟢 | 🟡 | 🟣 | 🟤 | 🟠| 🟦 | 🟨 | 🟧 | 🟥 | 🟪 | 🟫 | 🟩 | 🟦
|
||||
star = '', -- ⭐ | ✴ | ✳ | ✲ | ✱ | ✰ | ★ | ☆ | 🌟 | 🌠 | 🌙 | 🌛 | 🌜 | 🌟 | 🌠 | 🌌 | 🌙 |
|
||||
notfound = ' ', --❔ | ❓ | ❗ | ❕|
|
||||
notfound = ' ', --❔ | ❓ | ❗ | ❕|
|
||||
yes = '✔', -- ✅ | ✔️ | ☑
|
||||
no = '', -- ❌ | ❎ | ✖ | ✘ | ✗ |
|
||||
cell = '■', -- ■ | □ | ▇ | ▏ ▎ ▍ ▌ ▋ ▊ ▉
|
||||
|
@ -37,7 +37,7 @@ function M.new(opts)
|
||||
data.backends[i] = Trans.backend[name]
|
||||
end
|
||||
|
||||
if Trans.util.is_english(str) then
|
||||
if Trans.util.is_English(str) then
|
||||
data.from = 'en'
|
||||
data.to = 'zh'
|
||||
else
|
||||
|
@ -5,7 +5,7 @@ return function()
|
||||
local fn = vim.fn
|
||||
-- INFO :Check ultimate.db exists
|
||||
local dir = Trans.conf.dir
|
||||
local path = dir .. '/ultimate.db'
|
||||
local path = dir .. 'ultimate.db'
|
||||
|
||||
if fn.isdirectory(dir) == 0 then
|
||||
fn.mkdir(dir, 'p')
|
||||
@ -17,16 +17,17 @@ return function()
|
||||
end
|
||||
|
||||
-- INFO :Download ultimate.db
|
||||
local uri = Trans.conf.db_url
|
||||
local zip = dir .. '/ultimate.zip'
|
||||
local uri = 'https://github.com/skywind3000/ECDICT-ultimate/releases/download/1.0.0/ecdict-ultimate-sqlite.zip'
|
||||
local zip = dir .. 'ultimate.zip'
|
||||
local continue = fn.filereadable(zip) == 1
|
||||
local handle = function(output)
|
||||
if output.exit == 0 and fn.filereadable(zip) then
|
||||
local cmd =
|
||||
Trans.system == 'win' and
|
||||
string.format('powershell.exe -Command "Expand-Archive -Force %s %s"', zip, dir) or
|
||||
fn.executable('unzip') == 1 and string.format('unzip %s -d %s', zip, dir) or
|
||||
error('unzip not found, Please unzip ' .. zip .. ' manually')
|
||||
if fn.executable 'unzip' == 0 then
|
||||
vim.notify('unzip not found, Please unzip ' .. zip .. 'manually', vim.log.ERROR)
|
||||
return
|
||||
end
|
||||
|
||||
local cmd = string.format('unzip %s -d %s', zip, dir)
|
||||
local status = os.execute(cmd)
|
||||
os.remove(zip)
|
||||
if status == 0 then
|
||||
@ -39,12 +40,18 @@ return function()
|
||||
vim.notify(debug_message, vim.log.ERROR)
|
||||
end
|
||||
|
||||
|
||||
Trans.curl.get(uri, {
|
||||
output = zip,
|
||||
callback = handle,
|
||||
extra = continue and { '-C', '-' } or nil,
|
||||
output = zip,
|
||||
callback = handle,
|
||||
extra = continue and { '-C', '-' } or nil,
|
||||
})
|
||||
|
||||
local message = continue and 'Continue download database' or 'Begin to download database'
|
||||
vim.notify(message, vim.log.levels.INFO)
|
||||
|
||||
-- INFO : Install tts dependencies
|
||||
if fn.has 'linux' == 0 and fn.has 'mac' == 0 then
|
||||
os.execute 'cd ./tts && npm install'
|
||||
end
|
||||
end
|
||||
|
@ -52,4 +52,12 @@ return function(opts)
|
||||
|
||||
set_strategy_opts(conf)
|
||||
define_highlights(conf)
|
||||
|
||||
if Trans.conf.warning then
|
||||
vim.notify([[
|
||||
新版本v2已经发布, 见:
|
||||
https://github.com/JuanZoran/Trans.nvim
|
||||
请使用当前默认(v2)分支
|
||||
]], vim.log.levels.WARN)
|
||||
end
|
||||
end
|
||||
|
@ -59,7 +59,8 @@ local strategy = {
|
||||
|
||||
local name = backend.name
|
||||
---@cast backend TransBackend
|
||||
while result[name] == nil and update(backend) do
|
||||
while result[name] == nil do
|
||||
if not update(backend) then break end
|
||||
end
|
||||
|
||||
if result[name] then return true end
|
||||
@ -71,13 +72,12 @@ local strategy = {
|
||||
}
|
||||
|
||||
|
||||
|
||||
-- HACK : Core process logic
|
||||
local function process(opts)
|
||||
opts = init_opts(opts)
|
||||
|
||||
|
||||
if not opts.str or opts.str == '' then return end
|
||||
local str = opts.str:match("(%w+)")
|
||||
local str = opts.str
|
||||
if not str or str == '' then return end
|
||||
|
||||
|
||||
-- Find in cache
|
||||
|
@ -3,23 +3,20 @@ local fn, api = vim.fn, vim.api
|
||||
---@class TransUtil
|
||||
local M = require 'Trans'.metatable 'util'
|
||||
|
||||
---Get the range of visual modes
|
||||
---@return table
|
||||
function M.get_range()
|
||||
local _start = fn.getpos 'v'
|
||||
local _end = fn.getpos '.'
|
||||
|
||||
local s_row, e_row = math.min(_start[2], _end[2]), math.max(_start[2], _end[2])
|
||||
local s_col, e_col = math.min(_start[3], _end[3]), math.max(_start[3], _end[3])
|
||||
|
||||
return { s_row, e_row, s_col, e_col }
|
||||
end
|
||||
|
||||
---Get selected text
|
||||
---@return string
|
||||
function M.get_select()
|
||||
local s_row, e_row, s_col, e_col = unpack(M.get_range())
|
||||
local _start = fn.getpos 'v'
|
||||
local _end = fn.getpos '.'
|
||||
|
||||
if _start[2] > _end[2] or (_start[3] > _end[3] and _start[2] == _end[2]) then
|
||||
_start, _end = _end, _start
|
||||
end
|
||||
local s_row, s_col = _start[2], _start[3]
|
||||
local e_row, e_col = _end[2], _end[3]
|
||||
|
||||
-- print(s_row, e_row, s_col, e_col)
|
||||
---@type string
|
||||
---@diagnostic disable-next-line: assign-type-mismatch
|
||||
local line = fn.getline(e_row)
|
||||
@ -27,6 +24,7 @@ function M.get_select()
|
||||
---@diagnostic disable-next-line: param-type-mismatch
|
||||
e_col = vim.str_byteindex(line, uidx)
|
||||
|
||||
|
||||
if s_row == e_row then
|
||||
return line:sub(s_col, e_col)
|
||||
else
|
||||
@ -34,43 +32,7 @@ function M.get_select()
|
||||
local e = #lines
|
||||
lines[1] = lines[1]:sub(s_col)
|
||||
lines[e] = line:sub(1, e_col)
|
||||
return table.concat(lines, ' ')
|
||||
end
|
||||
end
|
||||
|
||||
---Get selected text
|
||||
---@return string
|
||||
function M.get_lines()
|
||||
local s_row, e_row = unpack(M.get_range())
|
||||
|
||||
if s_row == e_row then
|
||||
return fn.getline(s_row)
|
||||
else
|
||||
local lines = fn.getline(s_row, e_row)
|
||||
return table.concat(lines, " ")
|
||||
end
|
||||
end
|
||||
|
||||
---Get selected text
|
||||
---@return string
|
||||
function M.get_block()
|
||||
local s_row, e_row, s_col, e_col = unpack(M.get_range())
|
||||
|
||||
---@type string
|
||||
---@diagnostic disable-next-line: assign-type-mismatch
|
||||
local line = fn.getline(e_row)
|
||||
local uidx = vim.str_utfindex(line, math.min(#line, e_col))
|
||||
---@diagnostic disable-next-line: param-type-mismatch
|
||||
e_col = vim.str_byteindex(line, uidx)
|
||||
|
||||
if s_row == e_row then
|
||||
return line:sub(s_col, e_col)
|
||||
else
|
||||
local lines = fn.getline(s_row, e_row)
|
||||
for col, l in pairs(lines) do
|
||||
lines[col] = l:sub(s_col,e_col)
|
||||
end
|
||||
return table.concat(lines, " ")
|
||||
return table.concat(lines)
|
||||
end
|
||||
end
|
||||
|
||||
@ -90,12 +52,7 @@ function M.get_str(mode)
|
||||
return fn.input '需要翻译的字符串: '
|
||||
end,
|
||||
V = function()
|
||||
api.nvim_input '<Esc>'
|
||||
return M.get_lines()
|
||||
end,
|
||||
[''] = function()
|
||||
api.nvim_input '<Esc>'
|
||||
return M.get_block()
|
||||
print 'TODO'
|
||||
end,
|
||||
})[mode]():match '^%s*(.-)%s*$'
|
||||
end
|
||||
@ -103,7 +60,6 @@ end
|
||||
---Puase coroutine for {ms} milliseconds
|
||||
---@param ms integer
|
||||
function M.pause(ms)
|
||||
assert(ms)
|
||||
local co = coroutine.running()
|
||||
vim.defer_fn(function()
|
||||
coroutine.resume(co)
|
||||
@ -114,7 +70,7 @@ end
|
||||
---Detect whether the string is English
|
||||
---@param str string
|
||||
---@return boolean
|
||||
function M.is_english(str)
|
||||
function M.is_English(str)
|
||||
local char = { str:byte(1, -1) }
|
||||
for i = 1, #str do
|
||||
if char[i] > 128 then
|
||||
@ -158,6 +114,7 @@ function M.center(node, win_width)
|
||||
end
|
||||
|
||||
local str = node[1]
|
||||
win_width = str:width()
|
||||
local space = math.max(0, math.floor((win_width - str:width()) / 2))
|
||||
node[1] = string.rep(' ', space) .. str
|
||||
return node
|
||||
@ -217,7 +174,7 @@ end
|
||||
---@param str string
|
||||
---@return boolean
|
||||
function M.is_word(str)
|
||||
return str:find '%W' == nil
|
||||
return str:match '%w+' == str
|
||||
end
|
||||
|
||||
---@param list any[]
|
||||
|
@ -124,8 +124,7 @@ function window:try_close()
|
||||
}
|
||||
end
|
||||
|
||||
|
||||
pcall(api.nvim_win_close, self.winid, true)
|
||||
api.nvim_win_close(self.winid, true)
|
||||
end
|
||||
|
||||
---Set window local highlight group
|
||||
@ -162,7 +161,21 @@ window.__index = window
|
||||
|
||||
|
||||
---@alias WindowOpts
|
||||
---|{style: string, border: string, focusable: boolean, noautocmd?: boolean, relative: 'mouse'|'cursor'|'editor'|'win', width: integer, height: integer, col: integer, row: integer, zindex?: integer, title?: table | string}
|
||||
---|{style: string, border: string, focusable: boolean, noautocmd?: boolean, relative: string, width: integer, height: integer, col: integer, row: integer, zindex?: integer, title?: table | string}
|
||||
|
||||
|
||||
---@class TransWindowOpts
|
||||
local default_opts = {
|
||||
enter = false,
|
||||
winid = -1,
|
||||
---@type WindowOpts
|
||||
win_opts = {
|
||||
style = 'minimal',
|
||||
border = 'rounded',
|
||||
focusable = false,
|
||||
noautocmd = true,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
---@class TransWindow
|
||||
@ -184,37 +197,11 @@ window.__index = window
|
||||
-- relative = relative,
|
||||
-- }
|
||||
|
||||
local default_opts = {
|
||||
enter = false,
|
||||
winid = -1,
|
||||
---@type WindowOpts
|
||||
win_opts = {
|
||||
-- INFO : ensured options
|
||||
-- col
|
||||
-- row
|
||||
-- width
|
||||
-- height
|
||||
-- relative
|
||||
-- zindex
|
||||
style = 'minimal',
|
||||
border = 'rounded',
|
||||
focusable = true,
|
||||
noautocmd = true,
|
||||
},
|
||||
}
|
||||
|
||||
---@class TransWindowOpts
|
||||
---@field buffer TransBuffer attached buffer object
|
||||
---@field enter? boolean cursor should [enter] window when open,default: false
|
||||
---@field win_opts WindowOpts window config [**When open**]
|
||||
---@field animation? table? Hover Window Animation
|
||||
|
||||
---Create new window
|
||||
---@param opts TransWindowOpts window config
|
||||
---@return TransWindow
|
||||
function window.new(opts)
|
||||
opts = vim.tbl_deep_extend('keep', opts, default_opts)
|
||||
opts.animation = opts.animation or { interval = 12 }
|
||||
|
||||
local win = setmetatable(opts, window)
|
||||
---@cast win TransWindow
|
||||
|
@ -1,6 +1,5 @@
|
||||
---@type Trans
|
||||
local Trans = require 'Trans'
|
||||
local util = Trans.util
|
||||
|
||||
-- FIXME :Adjust Window Size
|
||||
|
||||
@ -19,16 +18,16 @@ local M = Trans.metatable('frontend.hover', {
|
||||
M.__index = M
|
||||
|
||||
|
||||
---Set up function which will be invoked when this module is loaded
|
||||
function M.setup()
|
||||
local set = vim.keymap.set
|
||||
for action, key in pairs(M.opts.keymaps) do
|
||||
set('n', key, function()
|
||||
local instance = M.get_active_instance()
|
||||
|
||||
if instance then
|
||||
coroutine.wrap(instance.execute)(instance, action)
|
||||
else
|
||||
vim.api.nvim_feedkeys(vim.api.nvim_replace_termcodes(key, true, true, true), 'n', false)
|
||||
return key
|
||||
end
|
||||
end)
|
||||
end
|
||||
@ -93,13 +92,13 @@ function M:init_window(opts)
|
||||
buffer = self.buffer,
|
||||
animation = m_opts.animation,
|
||||
win_opts = {
|
||||
relative = opts.relative or 'cursor',
|
||||
col = opts.col or 1,
|
||||
row = opts.row or 1,
|
||||
width = opts.width or m_opts.width,
|
||||
height = opts.height or m_opts.height,
|
||||
relative = opts.relative or 'cursor',
|
||||
title = m_opts.title,
|
||||
title_pos = m_opts.title and 'center',
|
||||
title_pos = m_opts.title and 'center' or nil,
|
||||
zindex = 100,
|
||||
},
|
||||
}
|
||||
@ -119,6 +118,7 @@ end
|
||||
---Get Check function for waiting
|
||||
---@return fun(backend: TransBackend): boolean
|
||||
function M:wait()
|
||||
local util = Trans.util
|
||||
local opts = self.opts
|
||||
local buffer = self.buffer
|
||||
local pause = util.pause
|
||||
@ -126,7 +126,7 @@ function M:wait()
|
||||
local spinner = Trans.style.spinner[opts.spinner]
|
||||
local times = opts.width - spinner[1]:width()
|
||||
local size = #spinner
|
||||
local interval = math.floor(opts.timeout / times)
|
||||
local interval = math.floor(opts.timeout / opts.width)
|
||||
|
||||
self:init_window {
|
||||
height = 2,
|
||||
@ -154,7 +154,7 @@ function M:fallback()
|
||||
|
||||
local buffer = self.buffer
|
||||
buffer:wipe()
|
||||
buffer[1] = util.center(fallback_msg, opts.width)
|
||||
buffer[1] = Trans.util.center(fallback_msg, opts.width)
|
||||
buffer:add_highlight(1, 'TransFailed')
|
||||
if not self.window then
|
||||
self:init_window {
|
||||
@ -168,7 +168,7 @@ end
|
||||
|
||||
---Defer function when process done
|
||||
function M:defer()
|
||||
util.main_loop(function()
|
||||
Trans.util.main_loop(function()
|
||||
self.window:set('wrap', true)
|
||||
self.buffer:set('modifiable', false)
|
||||
|
||||
@ -204,6 +204,7 @@ function M:process(data)
|
||||
return
|
||||
end
|
||||
|
||||
local util = Trans.util
|
||||
local opts = self.opts
|
||||
local buffer = self.buffer
|
||||
|
||||
@ -226,11 +227,11 @@ function M:process(data)
|
||||
local width =
|
||||
valid and
|
||||
(opts.auto_resize and
|
||||
math.max(
|
||||
math.min(opts.width, util.display_width(lines) + opts.padding),
|
||||
math.min(data.str:width(), opts.split_width)
|
||||
)
|
||||
or opts.width)
|
||||
math.max(
|
||||
math.min(opts.width, util.display_width(lines) + opts.padding),
|
||||
math.min(data.str:width(), opts.split_width)
|
||||
)
|
||||
or opts.width)
|
||||
or math.min(opts.width, util.display_width(lines) + opts.padding)
|
||||
|
||||
local height = math.min(opts.height, util.display_height(lines, width))
|
||||
|
@ -36,16 +36,15 @@ local function check_binary_dependencies()
|
||||
local binary_dependencies = {
|
||||
'curl',
|
||||
'sqlite3',
|
||||
'unzip',
|
||||
}
|
||||
|
||||
binary_dependencies[3] = ({
|
||||
win = nil,
|
||||
mac = 'say',
|
||||
linux = 'festival',
|
||||
termux = 'termux-tts-speak',
|
||||
})[Trans.system]
|
||||
|
||||
if has 'linux' == 1 then
|
||||
binary_dependencies[3] = 'festival'
|
||||
elseif has 'mac' == 1 then
|
||||
binary_dependencies[3] = 'say'
|
||||
else
|
||||
binary_dependencies[3] = 'node'
|
||||
end
|
||||
|
||||
for _, dep in ipairs(binary_dependencies) do
|
||||
if executable(dep) == 1 then
|
||||
@ -57,7 +56,7 @@ local function check_binary_dependencies()
|
||||
end
|
||||
|
||||
local function check_database()
|
||||
local db_path = Trans.conf.dir .. '/ultimate.db'
|
||||
local db_path = Trans.conf.dir .. Trans.separator .. 'ultimate.db'
|
||||
if fn.filereadable(db_path) == 1 then
|
||||
ok [[ultimate database found ]]
|
||||
else
|
||||
@ -69,7 +68,7 @@ local function check_database()
|
||||
end
|
||||
|
||||
local function check_configure_file()
|
||||
local path = fn.expand(Trans.conf.dir .. '/Trans.json')
|
||||
local path = fn.expand(Trans.conf.dir .. Trans.separator .. 'Trans.json')
|
||||
if not fn.filereadable(path) then
|
||||
warn 'Backend configuration file[%s] not found'
|
||||
end
|
||||
|
@ -18,25 +18,28 @@ end
|
||||
---@field width function @Get string display width
|
||||
---@field play function @Use tts to play string
|
||||
|
||||
local uname = vim.loop.os_uname().sysname
|
||||
local system =
|
||||
uname == 'Darwin' and 'mac' or
|
||||
uname == 'Windows_NT' and 'win' or
|
||||
uname == 'Linux' and (vim.fn.executable 'termux-api-start' == 1 and 'termux' or 'linux') or
|
||||
error 'Unknown System, Please Report Issue'
|
||||
|
||||
local sep = vim.loop.os_uname().sysname == 'Windows' and '\\' or '/'
|
||||
---@class Trans
|
||||
---@field style table @Style module
|
||||
---@field cache table<string, TransData> @Cache for translated data object
|
||||
---@field plugin_dir string @Plugin directory
|
||||
---@field system 'mac'|'win'|'termux'|'linux' @Operating system
|
||||
---@field separator string @Path separator
|
||||
local M = metatable('core', {
|
||||
cache = {},
|
||||
style = metatable 'style',
|
||||
system = system,
|
||||
plugin_dir = vim.fn.fnamemodify(debug.getinfo(1, 'S').source:sub(2), ':p:h:h:h'),
|
||||
plugin_dir = debug.getinfo(1, 'S').source:sub(2):match('(.-)lua' .. sep .. 'Trans'),
|
||||
separator = sep,
|
||||
})
|
||||
|
||||
M.metatable = metatable
|
||||
|
||||
---Get abs_path of file
|
||||
---@param path string[]
|
||||
---@param is_dir boolean?
|
||||
---@return string
|
||||
function M.relative_path(path, is_dir)
|
||||
return M.plugin_dir .. table.concat(path, sep) .. (is_dir and sep or '')
|
||||
end
|
||||
|
||||
return M
|
||||
|
@ -29,469 +29,248 @@
|
||||
-- SOFTWARE.
|
||||
return {
|
||||
dots = {
|
||||
'⠋',
|
||||
'⠙',
|
||||
'⠹',
|
||||
'⠸',
|
||||
'⠼',
|
||||
'⠴',
|
||||
'⠦',
|
||||
'⠧',
|
||||
'⠇',
|
||||
'⠏',
|
||||
"⠋",
|
||||
"⠙",
|
||||
"⠹",
|
||||
"⠸",
|
||||
"⠼",
|
||||
"⠴",
|
||||
"⠦",
|
||||
"⠧",
|
||||
"⠇",
|
||||
"⠏",
|
||||
},
|
||||
dots_negative = { -- dots2
|
||||
'⣾',
|
||||
'⣽',
|
||||
'⣻',
|
||||
'⢿',
|
||||
'⡿',
|
||||
'⣟',
|
||||
'⣯',
|
||||
'⣷',
|
||||
"⣾",
|
||||
"⣽",
|
||||
"⣻",
|
||||
"⢿",
|
||||
"⡿",
|
||||
"⣟",
|
||||
"⣯",
|
||||
"⣷",
|
||||
},
|
||||
dots_snake = { -- dots3
|
||||
'⠋',
|
||||
'⠙',
|
||||
'⠚',
|
||||
'⠒',
|
||||
'⠂',
|
||||
'⠂',
|
||||
'⠒',
|
||||
'⠲',
|
||||
'⠴',
|
||||
'⠦',
|
||||
'⠖',
|
||||
'⠒',
|
||||
'⠐',
|
||||
'⠐',
|
||||
'⠒',
|
||||
'⠓',
|
||||
'⠋',
|
||||
"⠋",
|
||||
"⠙",
|
||||
"⠚",
|
||||
"⠒",
|
||||
"⠂",
|
||||
"⠂",
|
||||
"⠒",
|
||||
"⠲",
|
||||
"⠴",
|
||||
"⠦",
|
||||
"⠖",
|
||||
"⠒",
|
||||
"⠐",
|
||||
"⠐",
|
||||
"⠒",
|
||||
"⠓",
|
||||
"⠋",
|
||||
},
|
||||
dots_footsteps = { -- dots10
|
||||
'⢄',
|
||||
'⢂',
|
||||
'⢁',
|
||||
'⡁',
|
||||
'⡈',
|
||||
'⡐',
|
||||
'⡠',
|
||||
"⢄",
|
||||
"⢂",
|
||||
"⢁",
|
||||
"⡁",
|
||||
"⡈",
|
||||
"⡐",
|
||||
"⡠",
|
||||
},
|
||||
dots_hop = { -- dots11
|
||||
'⠁',
|
||||
'⠂',
|
||||
'⠄',
|
||||
'⡀',
|
||||
'⢀',
|
||||
'⠠',
|
||||
'⠐',
|
||||
'⠈',
|
||||
"⠁",
|
||||
"⠂",
|
||||
"⠄",
|
||||
"⡀",
|
||||
"⢀",
|
||||
"⠠",
|
||||
"⠐",
|
||||
"⠈",
|
||||
},
|
||||
line = {
|
||||
'-',
|
||||
'\\',
|
||||
'|',
|
||||
'/',
|
||||
"-",
|
||||
"\\",
|
||||
"|",
|
||||
"/",
|
||||
},
|
||||
pipe = {
|
||||
'┤',
|
||||
'┘',
|
||||
'┴',
|
||||
'└',
|
||||
'├',
|
||||
'┌',
|
||||
'┬',
|
||||
'┐',
|
||||
"┤",
|
||||
"┘",
|
||||
"┴",
|
||||
"└",
|
||||
"├",
|
||||
"┌",
|
||||
"┬",
|
||||
"┐",
|
||||
},
|
||||
dots_ellipsis = { -- simpleDots
|
||||
'. ',
|
||||
'.. ',
|
||||
'...',
|
||||
' ',
|
||||
". ",
|
||||
".. ",
|
||||
"...",
|
||||
" ",
|
||||
},
|
||||
dots_scrolling = { -- simpleDotsScrolling
|
||||
'. ',
|
||||
'.. ',
|
||||
'...',
|
||||
' ..',
|
||||
' .',
|
||||
' ',
|
||||
". ",
|
||||
".. ",
|
||||
"...",
|
||||
" ..",
|
||||
" .",
|
||||
" ",
|
||||
},
|
||||
star = {
|
||||
'✶',
|
||||
'✸',
|
||||
'✹',
|
||||
'✺',
|
||||
'✹',
|
||||
'✷',
|
||||
"✶",
|
||||
"✸",
|
||||
"✹",
|
||||
"✺",
|
||||
"✹",
|
||||
"✷",
|
||||
},
|
||||
flip = {
|
||||
'_',
|
||||
'_',
|
||||
'_',
|
||||
'-',
|
||||
'`',
|
||||
'`',
|
||||
"_",
|
||||
"_",
|
||||
"_",
|
||||
"-",
|
||||
"`",
|
||||
"`",
|
||||
"'",
|
||||
'´',
|
||||
'-',
|
||||
'_',
|
||||
'_',
|
||||
'_',
|
||||
"´",
|
||||
"-",
|
||||
"_",
|
||||
"_",
|
||||
"_",
|
||||
},
|
||||
hamburger = {
|
||||
'☱',
|
||||
'☲',
|
||||
'☴',
|
||||
"☱",
|
||||
"☲",
|
||||
"☴",
|
||||
},
|
||||
grow_vertical = { -- growVertical
|
||||
'▁',
|
||||
'▃',
|
||||
'▄',
|
||||
'▅',
|
||||
'▆',
|
||||
'▇',
|
||||
'▆',
|
||||
'▅',
|
||||
'▄',
|
||||
'▃',
|
||||
"▁",
|
||||
"▃",
|
||||
"▄",
|
||||
"▅",
|
||||
"▆",
|
||||
"▇",
|
||||
"▆",
|
||||
"▅",
|
||||
"▄",
|
||||
"▃",
|
||||
},
|
||||
grow_horizontal = { -- growHorizontal
|
||||
'▏',
|
||||
'▎',
|
||||
'▍',
|
||||
'▌',
|
||||
'▋',
|
||||
'▊',
|
||||
'▉',
|
||||
'▊',
|
||||
'▋',
|
||||
'▌',
|
||||
'▍',
|
||||
'▎',
|
||||
"▏",
|
||||
"▎",
|
||||
"▍",
|
||||
"▌",
|
||||
"▋",
|
||||
"▊",
|
||||
"▉",
|
||||
"▊",
|
||||
"▋",
|
||||
"▌",
|
||||
"▍",
|
||||
"▎",
|
||||
},
|
||||
noise = {
|
||||
'▓',
|
||||
'▒',
|
||||
'░',
|
||||
"▓",
|
||||
"▒",
|
||||
"░",
|
||||
},
|
||||
dots_bounce = { -- bounce
|
||||
'⠁',
|
||||
'⠂',
|
||||
'⠄',
|
||||
'⠂',
|
||||
"⠁",
|
||||
"⠂",
|
||||
"⠄",
|
||||
"⠂",
|
||||
},
|
||||
triangle = {
|
||||
'◢',
|
||||
'◣',
|
||||
'◤',
|
||||
'◥',
|
||||
"◢",
|
||||
"◣",
|
||||
"◤",
|
||||
"◥",
|
||||
},
|
||||
arc = {
|
||||
'◜',
|
||||
'◠',
|
||||
'◝',
|
||||
'◞',
|
||||
'◡',
|
||||
'◟',
|
||||
"◜",
|
||||
"◠",
|
||||
"◝",
|
||||
"◞",
|
||||
"◡",
|
||||
"◟",
|
||||
},
|
||||
circle = {
|
||||
'◡',
|
||||
'⊙',
|
||||
'◠',
|
||||
"◡",
|
||||
"⊙",
|
||||
"◠",
|
||||
},
|
||||
square_corners = { -- squareCorners
|
||||
'◰',
|
||||
'◳',
|
||||
'◲',
|
||||
'◱',
|
||||
"◰",
|
||||
"◳",
|
||||
"◲",
|
||||
"◱",
|
||||
},
|
||||
circle_quarters = { -- circleQuarters
|
||||
'◴',
|
||||
'◷',
|
||||
'◶',
|
||||
'◵',
|
||||
"◴",
|
||||
"◷",
|
||||
"◶",
|
||||
"◵",
|
||||
},
|
||||
circle_halves = { -- circleHalves
|
||||
'◐',
|
||||
'◓',
|
||||
'◑',
|
||||
'◒',
|
||||
"◐",
|
||||
"◓",
|
||||
"◑",
|
||||
"◒",
|
||||
},
|
||||
dots_toggle = { -- toggle
|
||||
'⊶',
|
||||
'⊷',
|
||||
"⊶",
|
||||
"⊷",
|
||||
},
|
||||
box_toggle = { -- toggle2
|
||||
'▫',
|
||||
'▪',
|
||||
"▫",
|
||||
"▪",
|
||||
},
|
||||
arrow = {
|
||||
'←',
|
||||
'↖',
|
||||
'↑',
|
||||
'↗',
|
||||
'→',
|
||||
'↘',
|
||||
'↓',
|
||||
'↙',
|
||||
"←",
|
||||
"↖",
|
||||
"↑",
|
||||
"↗",
|
||||
"→",
|
||||
"↘",
|
||||
"↓",
|
||||
"↙",
|
||||
},
|
||||
clock = {
|
||||
'🕛 ',
|
||||
'🕐 ',
|
||||
'🕑 ',
|
||||
'🕒 ',
|
||||
'🕓 ',
|
||||
'🕔 ',
|
||||
'🕕 ',
|
||||
'🕖 ',
|
||||
'🕗 ',
|
||||
'🕘 ',
|
||||
'🕙 ',
|
||||
'🕚 ',
|
||||
"🕛 ",
|
||||
"🕐 ",
|
||||
"🕑 ",
|
||||
"🕒 ",
|
||||
"🕓 ",
|
||||
"🕔 ",
|
||||
"🕕 ",
|
||||
"🕖 ",
|
||||
"🕗 ",
|
||||
"🕘 ",
|
||||
"🕙 ",
|
||||
"🕚 ",
|
||||
},
|
||||
earth = {
|
||||
'🌍 ',
|
||||
'🌎 ',
|
||||
'🌏 ',
|
||||
"🌍 ",
|
||||
"🌎 ",
|
||||
"🌏 ",
|
||||
},
|
||||
moon = {
|
||||
'🌑 ',
|
||||
'🌒 ',
|
||||
'🌓 ',
|
||||
'🌔 ',
|
||||
'🌕 ',
|
||||
'🌖 ',
|
||||
'🌗 ',
|
||||
'🌘 ',
|
||||
"🌑 ",
|
||||
"🌒 ",
|
||||
"🌓 ",
|
||||
"🌔 ",
|
||||
"🌕 ",
|
||||
"🌖 ",
|
||||
"🌗 ",
|
||||
"🌘 ",
|
||||
},
|
||||
dots_pulse = { -- point
|
||||
'∙∙∙',
|
||||
'●∙∙',
|
||||
'∙●∙',
|
||||
'∙∙●',
|
||||
'∙∙∙',
|
||||
},
|
||||
fistBump = {
|
||||
'🤜 🤛 ',
|
||||
'🤜 🤛 ',
|
||||
'🤜 🤛 ',
|
||||
' 🤜 🤛 ',
|
||||
' 🤜🤛 ',
|
||||
' 🤜✨🤛 ',
|
||||
'🤜 ✨ 🤛 ',
|
||||
},
|
||||
monkey = {
|
||||
'🙈 ',
|
||||
'🙈 ',
|
||||
'🙉 ',
|
||||
'🙊 '
|
||||
},
|
||||
soccerHeader = {
|
||||
' 🧑⚽️ 🧑 ',
|
||||
'🧑 ⚽️ 🧑 ',
|
||||
'🧑 ⚽️ 🧑 ',
|
||||
'🧑 ⚽️ 🧑 ',
|
||||
'🧑 ⚽️ 🧑 ',
|
||||
'🧑 ⚽️ 🧑 ',
|
||||
'🧑 ⚽️🧑 ',
|
||||
'🧑 ⚽️ 🧑 ',
|
||||
'🧑 ⚽️ 🧑 ',
|
||||
'🧑 ⚽️ 🧑 ',
|
||||
'🧑 ⚽️ 🧑 ',
|
||||
'🧑 ⚽️ 🧑 ',
|
||||
},
|
||||
weather = {
|
||||
'☀️ ',
|
||||
'☀️ ',
|
||||
'☀️ ',
|
||||
'🌤 ',
|
||||
'⛅️ ',
|
||||
'🌥 ',
|
||||
'☁️ ',
|
||||
'🌧 ',
|
||||
'🌨 ',
|
||||
'🌧 ',
|
||||
'🌨 ',
|
||||
'🌧 ',
|
||||
'🌨 ',
|
||||
'⛈ ',
|
||||
'🌨 ',
|
||||
'🌧 ',
|
||||
'🌨 ',
|
||||
'☁️ ',
|
||||
'🌥 ',
|
||||
'⛅️ ',
|
||||
'🌤 ',
|
||||
'☀️ ',
|
||||
'☀️ ',
|
||||
},
|
||||
speaker = {
|
||||
'🔈 ',
|
||||
'🔉 ',
|
||||
'🔊 ',
|
||||
'🔉 ',
|
||||
},
|
||||
smiley = {
|
||||
'😄 ',
|
||||
'😝 ',
|
||||
},
|
||||
toggle = {
|
||||
'⊶',
|
||||
'⊷'
|
||||
},
|
||||
toggle10 = {
|
||||
'㊂',
|
||||
'㊀',
|
||||
'㊁'
|
||||
},
|
||||
toggle11 = {
|
||||
'⧇',
|
||||
'⧆'
|
||||
},
|
||||
toggle12 = {
|
||||
'☗',
|
||||
'☖'
|
||||
},
|
||||
toggle13 = {
|
||||
'=',
|
||||
'*',
|
||||
'-'
|
||||
},
|
||||
toggle2 = {
|
||||
'▫',
|
||||
'▪'
|
||||
},
|
||||
toggle3 = {
|
||||
'□',
|
||||
'■'
|
||||
},
|
||||
toggle4 = {
|
||||
'■',
|
||||
'□',
|
||||
'▪',
|
||||
'▫'
|
||||
},
|
||||
toggle5 = {
|
||||
'▮',
|
||||
'▯'
|
||||
},
|
||||
toggle6 = {
|
||||
'ဝ',
|
||||
'၀'
|
||||
},
|
||||
toggle7 = {
|
||||
'⦾',
|
||||
'⦿'
|
||||
},
|
||||
toggle8 = {
|
||||
'◍',
|
||||
'◌'
|
||||
},
|
||||
toggle9 = {
|
||||
'◉',
|
||||
'◎'
|
||||
},
|
||||
star = {
|
||||
'✶',
|
||||
'✸',
|
||||
'✹',
|
||||
'✺',
|
||||
'✹',
|
||||
'✷'
|
||||
},
|
||||
star2 = {
|
||||
'+',
|
||||
'x',
|
||||
'*'
|
||||
},
|
||||
orangeBluePulse = {
|
||||
'🔸 ',
|
||||
'🔶 ',
|
||||
'🟠 ',
|
||||
'🟠 ',
|
||||
'🔶 ',
|
||||
'🔹 ',
|
||||
'🔷 ',
|
||||
'🔵 ',
|
||||
'🔵 ',
|
||||
'🔷 ',
|
||||
},
|
||||
orangePulse = {
|
||||
'🔸 ',
|
||||
'🔶 ',
|
||||
'🟠 ',
|
||||
'🟠 ',
|
||||
'🔶 '
|
||||
},
|
||||
mindblown = {
|
||||
'😐 ',
|
||||
'😐 ',
|
||||
'😮 ',
|
||||
'😮 ',
|
||||
'😦 ',
|
||||
'😦 ',
|
||||
'😧 ',
|
||||
'😧 ',
|
||||
'🤯 ',
|
||||
'💥 ',
|
||||
'✨ ',
|
||||
' ',
|
||||
' ',
|
||||
' ',
|
||||
},
|
||||
hearts = {
|
||||
'💛 ',
|
||||
'💙 ',
|
||||
'💜 ',
|
||||
'💚 ',
|
||||
'❤️ '
|
||||
},
|
||||
fingerDance = {
|
||||
'🤘 ',
|
||||
'🤟 ',
|
||||
'🖖 ',
|
||||
'✋ ',
|
||||
'🤚 ',
|
||||
'👆 '
|
||||
},
|
||||
christmas = {
|
||||
'🌲',
|
||||
'🎄'
|
||||
},
|
||||
circleHalves = {
|
||||
'◐',
|
||||
'◓',
|
||||
'◑',
|
||||
'◒'
|
||||
},
|
||||
bouncingBall = {
|
||||
'( ● )',
|
||||
'( ● )',
|
||||
'( ● )',
|
||||
'( ● )',
|
||||
'( ●)',
|
||||
'( ● )',
|
||||
'( ● )',
|
||||
'( ● )',
|
||||
'( ● )',
|
||||
'(● )',
|
||||
},
|
||||
bluePulse = {
|
||||
'🔹 ',
|
||||
'🔷 ',
|
||||
'🔵 ',
|
||||
'🔵 ',
|
||||
'🔷 '
|
||||
},
|
||||
betaWave = {
|
||||
'ρββββββ',
|
||||
'βρβββββ',
|
||||
'ββρββββ',
|
||||
'βββρβββ',
|
||||
'ββββρββ',
|
||||
'βββββρβ',
|
||||
'ββββββρ',
|
||||
"∙∙∙",
|
||||
"●∙∙",
|
||||
"∙●∙",
|
||||
"∙∙●",
|
||||
"∙∙∙",
|
||||
},
|
||||
}
|
||||
|
@ -4,63 +4,62 @@ local util = require 'Trans'.util
|
||||
---@field [1] string text to be rendered
|
||||
---@field render fun(self: TransNode, buffer: TransBuffer, line: number, col: number) render the node
|
||||
|
||||
local item = (function()
|
||||
---@class TransItem : TransNode
|
||||
local mt = {
|
||||
---@param self TransItem
|
||||
---@param buffer TransBuffer
|
||||
---@param line integer
|
||||
---@param col integer
|
||||
render = function(self, buffer, line, col)
|
||||
if self[2] then
|
||||
buffer:add_highlight(line, self[2], col, col + #self[1])
|
||||
end
|
||||
end,
|
||||
}
|
||||
mt.__index = mt
|
||||
|
||||
---Basic item node
|
||||
---@param tuple {[1]: string, [2]: string?}
|
||||
---@return TransItem
|
||||
return function(tuple)
|
||||
return setmetatable(tuple, mt)
|
||||
end
|
||||
end)()
|
||||
---@class TransItem : TransNode
|
||||
local item_meta = {
|
||||
---@param self TransItem
|
||||
---@param buffer TransBuffer
|
||||
---@param line integer
|
||||
---@param col integer
|
||||
render = function(self, buffer, line, col)
|
||||
if self[2] then
|
||||
buffer:add_highlight(line, self[2], col, col + #self[1])
|
||||
end
|
||||
end,
|
||||
}
|
||||
|
||||
local text = (function()
|
||||
---@class TransText : TransNode
|
||||
---@field step string
|
||||
---@field nodes TransNode[]
|
||||
---@class TransText : TransNode
|
||||
---@field step string
|
||||
---@field nodes TransNode[]
|
||||
local text_meta = {
|
||||
---@param self TransText
|
||||
---@param buffer TransBuffer
|
||||
---@param line integer
|
||||
---@param col integer
|
||||
render = function(self, buffer, line, col)
|
||||
local nodes = self.nodes
|
||||
local step = self.step
|
||||
local len = step and #step or 0
|
||||
|
||||
local mt = {
|
||||
---@param self TransText
|
||||
---@param buffer TransBuffer
|
||||
---@param line integer
|
||||
---@param col integer
|
||||
render = function(self, buffer, line, col)
|
||||
local nodes = self.nodes
|
||||
local step = self.step
|
||||
local len = step and #step or 0
|
||||
for _, node in ipairs(nodes) do
|
||||
node:render(buffer, line, col)
|
||||
col = col + #node[1] + len
|
||||
end
|
||||
end,
|
||||
}
|
||||
|
||||
for _, node in ipairs(nodes) do
|
||||
node:render(buffer, line, col)
|
||||
col = col + #node[1] + len
|
||||
end
|
||||
end,
|
||||
}
|
||||
item_meta.__index = item_meta
|
||||
text_meta.__index = text_meta
|
||||
|
||||
mt.__index = mt
|
||||
|
||||
---@param nodes {[number]: TransNode, step: string?}
|
||||
---@return TransText
|
||||
return function(nodes)
|
||||
return setmetatable({
|
||||
[1] = table.concat(util.list_fields(nodes, 1), nodes.step),
|
||||
step = nodes.step,
|
||||
nodes = nodes,
|
||||
}, mt)
|
||||
end
|
||||
end)()
|
||||
---Basic item node
|
||||
---@param tuple {[1]: string, [2]: string?}
|
||||
---@return TransItem
|
||||
local function item(tuple)
|
||||
return setmetatable(tuple, item_meta)
|
||||
end
|
||||
|
||||
|
||||
|
||||
---@param nodes {[number]: TransNode, step: string?}
|
||||
---@return TransText
|
||||
local function text(nodes)
|
||||
return setmetatable({
|
||||
[1] = table.concat(util.list_fields(nodes, 1), nodes.step),
|
||||
step = nodes.step,
|
||||
nodes = nodes,
|
||||
}, text_meta)
|
||||
end
|
||||
|
||||
|
||||
---@param args {[number]: TransNode, width: integer, spin: string?}
|
||||
@ -86,6 +85,7 @@ end
|
||||
---@class TransUtil
|
||||
---@field node TransNodes
|
||||
|
||||
|
||||
---@class TransNodes
|
||||
return {
|
||||
item = item,
|
||||
|
@ -6,7 +6,6 @@ _G.api = vim.api
|
||||
_G.fn = vim.fn
|
||||
_G.mock = require 'luassert.mock'
|
||||
_G.stub = require 'luassert.stub'
|
||||
string.width = api.nvim_strwidth
|
||||
|
||||
---@param func fun(buffer: TransBuffer)
|
||||
---@return fun()
|
||||
|
@ -1,92 +1,9 @@
|
||||
---@diagnostic disable: param-type-mismatch
|
||||
require 'test.setup'
|
||||
|
||||
local util = Trans.util
|
||||
|
||||
describe('util.display_height', function()
|
||||
describe('util.display_height', with_buffer(function(buffer)
|
||||
--- TODO :
|
||||
it('can calculate the height of lines when window with wrap option', function()
|
||||
local lines = {
|
||||
'1234567890',
|
||||
'1234567890',
|
||||
'1234567890',
|
||||
'1234567890',
|
||||
'1234567890',
|
||||
'1234567890',
|
||||
'1234567890',
|
||||
'1234567890',
|
||||
'1234567890',
|
||||
}
|
||||
|
||||
assert.are.equal(#lines, util.display_height(lines, 10))
|
||||
assert.are.equal(#lines, util.display_height(lines, 11))
|
||||
assert.are.equal(2 * #lines, util.display_height(lines, 9))
|
||||
|
||||
-- Unicode width test
|
||||
local u_lines = {
|
||||
'12345678👍', -- 10
|
||||
'あうえお', -- 8
|
||||
'𠮷野い𠮷家野家家', -- 16
|
||||
'👍👍👍お家', -- 10
|
||||
}
|
||||
|
||||
assert.are.equal(4, util.display_height(u_lines, 20))
|
||||
assert.are.equal(4, util.display_height(u_lines, 16))
|
||||
assert.are.equal(5, util.display_height(u_lines, 10))
|
||||
assert.are.equal(7, util.display_height(u_lines, 8))
|
||||
assert.are.equal(9, util.display_height(u_lines, 7))
|
||||
end)
|
||||
end)
|
||||
|
||||
describe('util.display_width', function()
|
||||
it('can calculate the max width of lines', function()
|
||||
local lines = {
|
||||
'1234567890',
|
||||
'123456789',
|
||||
'12345678',
|
||||
'1234567',
|
||||
'123456',
|
||||
'12345',
|
||||
'1234',
|
||||
'123',
|
||||
'12',
|
||||
'1',
|
||||
}
|
||||
|
||||
assert.are.equal(10, util.display_width(lines))
|
||||
-- Unicode width test
|
||||
local u_lines = {
|
||||
'12345678👍', -- 10
|
||||
'あうえお', -- 8
|
||||
'𠮷野い𠮷家野家家', -- 16
|
||||
'👍👍👍お家', -- 10
|
||||
}
|
||||
|
||||
assert.are.equal(16, util.display_width(u_lines))
|
||||
end)
|
||||
end)
|
||||
|
||||
describe('util.center', function()
|
||||
it('will return the node if its width more than width', function()
|
||||
local node = i { '1234567890' }
|
||||
assert.are.same(node, util.center(node, 9))
|
||||
end)
|
||||
|
||||
it('will auto padding space', function()
|
||||
local node = i { '1234567890' }
|
||||
assert.are.same(i { (' '):rep(2) .. '1234567890' }, util.center(node, 15))
|
||||
end)
|
||||
end)
|
||||
|
||||
describe('util.is_word', function()
|
||||
it('can detect word', function()
|
||||
for test, value in pairs {
|
||||
['あうえお'] = false,
|
||||
['hello'] = true,
|
||||
[' hello'] = false,
|
||||
['hello world'] = false,
|
||||
['test_cool'] = false,
|
||||
} do
|
||||
assert.are.same(util.is_word(test), value)
|
||||
end
|
||||
end)
|
||||
end)
|
||||
end))
|
||||
|
@ -1,100 +0,0 @@
|
||||
require 'test.setup'
|
||||
|
||||
|
||||
describe('window', with_buffer(function(buffer)
|
||||
local window
|
||||
before_each(function()
|
||||
buffer:wipe()
|
||||
window = Trans.window.new {
|
||||
buffer = buffer,
|
||||
win_opts = {
|
||||
col = 1,
|
||||
row = 1,
|
||||
width = 1,
|
||||
height = 1,
|
||||
relative = 'editor',
|
||||
},
|
||||
}
|
||||
window:set('wrap', false)
|
||||
end)
|
||||
|
||||
after_each(function()
|
||||
window:try_close()
|
||||
end)
|
||||
|
||||
it('can work well when no pass animation table', function()
|
||||
window:open()
|
||||
assert.is_true(api.nvim_win_is_valid(window.winid))
|
||||
end)
|
||||
|
||||
describe('smooth_expand', function()
|
||||
it('can work well when no pass animation table', function()
|
||||
for field, values in pairs {
|
||||
width = {
|
||||
10,
|
||||
6,
|
||||
8,
|
||||
5,
|
||||
},
|
||||
height = {
|
||||
10,
|
||||
6,
|
||||
3,
|
||||
},
|
||||
} do
|
||||
for _, value in ipairs(values) do
|
||||
window:smooth_expand { field = field, to = value }
|
||||
assert.are.same(value, window[field](window))
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
it("don't change window wrap option", function()
|
||||
window:smooth_expand { field = 'width', to = 10 }
|
||||
assert.is_false(window:option 'wrap')
|
||||
|
||||
|
||||
window:set('wrap', true)
|
||||
window:smooth_expand { field = 'width', to = 10 }
|
||||
assert.is_true(window:option 'wrap')
|
||||
|
||||
window:smooth_expand { field = 'height', to = 10 }
|
||||
assert.is_true(window:option 'wrap')
|
||||
end)
|
||||
end)
|
||||
|
||||
it("resize() don't change window wrap option", function()
|
||||
window:resize { width = 10, height = 10 }
|
||||
assert.is_false(window:option 'wrap')
|
||||
|
||||
|
||||
window:set('wrap', true)
|
||||
window:resize { width = 5, height = 5 }
|
||||
assert.is_true(window:option 'wrap')
|
||||
end)
|
||||
|
||||
it('adjust_height() can auto adjust window height to buffer display height', function()
|
||||
for idx, content in ipairs {
|
||||
'cool',
|
||||
'co10',
|
||||
'家👍',
|
||||
'👍ol',
|
||||
'cあl',
|
||||
'家野',
|
||||
} do
|
||||
buffer[idx] = content
|
||||
end
|
||||
|
||||
local max_height = vim.o.lines - 2
|
||||
for width, expect in ipairs {
|
||||
[2] = 12,
|
||||
[3] = 12,
|
||||
[4] = 6,
|
||||
[5] = 6,
|
||||
} do
|
||||
window:smooth_expand { field = 'width', to = width }
|
||||
window:adjust_height()
|
||||
assert.are.same(math.min(expect, max_height), window:height())
|
||||
end
|
||||
end)
|
||||
end))
|
2
makefile
2
makefile
@ -1,4 +1,4 @@
|
||||
.PHONE: test
|
||||
|
||||
test:
|
||||
nvim --headless --noplugin -u scripts/minimal_init.vim -c "PlenaryBustedDirectory lua/test/ { minimal_init = './scripts/minimal_init.vim' }" -c 'qa!'
|
||||
nvim --headless --noplugin -u script/minimal_init.vim -c "PlenaryBustedDirectory lua/test/ { minimal_init = './scripts/minimal_init.vim' }" -c 'qa!'
|
||||
|
@ -1,39 +1,34 @@
|
||||
local api, fn = vim.api, vim.fn
|
||||
|
||||
|
||||
--- INFO :Define plugin command
|
||||
local Trans = require 'Trans'
|
||||
local Trans = require("Trans")
|
||||
local command = api.nvim_create_user_command
|
||||
|
||||
command('Translate', function() Trans.translate() end,
|
||||
{ desc = ' Translate cursor word' })
|
||||
command("Translate", function()
|
||||
Trans.translate()
|
||||
end, { desc = " Translate cursor word" })
|
||||
|
||||
|
||||
command('TranslateInput', function() Trans.translate { mode = 'i' } end,
|
||||
{ desc = ' Translate input word' })
|
||||
command("TranslateInput", function()
|
||||
Trans.translate({ mode = 'i' })
|
||||
end, { desc = " Translate input word" })
|
||||
|
||||
command('TransPlay', function()
|
||||
command("TransPlay", function()
|
||||
local util = Trans.util
|
||||
local str = util.get_str(vim.fn.mode())
|
||||
if str and str ~= '' and util.is_english(str) then
|
||||
if str and str ~= "" and util.is_English(str) then
|
||||
str:play()
|
||||
end
|
||||
end, { desc = ' Auto play' })
|
||||
end, { desc = " Auto play" })
|
||||
|
||||
|
||||
string.width = api.nvim_strwidth
|
||||
|
||||
local system = Trans.system
|
||||
local f =
|
||||
(vim.fn.has 'wsl' == 1 or system == 'win') and
|
||||
'powershell.exe -Command "Add-Type -AssemblyName System.speech;(New-Object System.Speech.Synthesis.SpeechSynthesizer).Speak(\\\"%s\\\")"' or
|
||||
system == 'mac' and 'say %q' or
|
||||
system == 'termux' and 'termux-tts-speak %q' or
|
||||
system == 'linux' and 'echo %q | festival --tts' or
|
||||
error 'Unsupported system'
|
||||
|
||||
|
||||
fn.has('linux') == 1 and ([[echo %q | festival --tts]])
|
||||
or fn.has('mac') == 1 and ([[say %q]])
|
||||
or 'node' .. Trans.relative_path { 'tts', 'say.js' } .. ' %q'
|
||||
string.play = function(self)
|
||||
---@diagnostic disable-next-line: param-type-mismatch
|
||||
local s = string.gsub(self, '\"', ' ')
|
||||
fn.jobstart(f:format(s))
|
||||
fn.jobstart(f:format(self))
|
||||
end
|
||||
|
5
tts/package.json
Normal file
5
tts/package.json
Normal file
@ -0,0 +1,5 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"say": "^0.16.0"
|
||||
}
|
||||
}
|
4
tts/say.js
Normal file
4
tts/say.js
Normal file
@ -0,0 +1,4 @@
|
||||
const say = require('say')
|
||||
|
||||
// console.log(word)
|
||||
say.speak(process.argv.slice(2))
|
Loading…
x
Reference in New Issue
Block a user