From 0a875bca3a157d523941f62b9be343726b243606 Mon Sep 17 00:00:00 2001
From: JuanZoran <1430359574@qq.com>
Date: Mon, 30 Jan 2023 22:00:27 +0800
Subject: [PATCH 1/2] docs: better doc style
---
README.md | 30 ++++++++++++++++++++----------
1 file changed, 20 insertions(+), 10 deletions(-)
diff --git a/README.md b/README.md
index d4622dc..ac22edc 100644
--- a/README.md
+++ b/README.md
@@ -4,8 +4,9 @@
- [Trans.nvim](#transnvim)
- [特点](#特点)
- [屏幕截图](#屏幕截图)
+ - [演示](#演示)
+ - [主题](#主题)
- [安装](#安装)
- - [Festival配置](#festival配置)
- [配置](#配置)
- [快捷键绑定](#快捷键绑定)
- [高亮组](#高亮组)
@@ -16,7 +17,9 @@
## 特点
-- 使用纯lua编写
+- 使用纯lua编写, 速度极快
+> `Lazy.nvim`的记录: `➜ Trans.nvim 0.82ms`
+
- 大部分功能可以自定义:
- 高亮
- 悬浮大小
@@ -34,7 +37,7 @@
- etc
- 舒服的排版和`动画`
- 支持 `normal`和 `visual`模式
- > 不支持 visual-block mode
+ > 不支持 visual-block mode
- 本地词库单词量: `430w`
@@ -63,8 +66,9 @@ https://user-images.githubusercontent.com/107862700/213752097-2eee026a-ddee-4531
- sqlite.lua: 操作数据库所用的库
- sqlite3: 数据库
+
+ Packer.nvim
-- `Packer.nvim`示例
```lua
use {
'JuanZoran/Trans.nvim'
@@ -97,8 +101,11 @@ use {
end
}
```
+
+
+
+ Lazy.nvim
-- `lazy.nvim`示例
```lua
{
"JuanZoran/Trans.nvim",
@@ -115,8 +122,9 @@ use {
}
}
```
+
-**注意事项**:
+**注意事项**:
- `install.sh`
- 使用了 `wget`下载词库, 安装请确保你的环境变量中存在wget
- install.sh 下载后会自动将词库解压, 并移动到 `$HOME/.vim/dict`文件夹下
@@ -148,8 +156,8 @@ use {
> 如果`install.sh`运行正常则自动安装,如果安装失败,请尝试手动安装
- `title`的配置,只对`neovim 0.9`版本有效
-## Festival配置
-> 仅针对`linux`用户说明
+
+ Festival配置(仅针对linux用户)
- 配置文件
- 全局配置: `/usr/share/festival/siteinit.scm`
- 用户配置: `~/.festivalrc`
@@ -162,7 +170,7 @@ use {
> `sudo mkdir /usr/share/festival/voices/my_voices`
- 下载想要的voices文件并解压
- > 正常均需要
+ > 可能需要
- 试听[在这里](https://www.cstr.ed.ac.uk/projects/festival/morevoices.html))
- 下载[在这里](http://festvox.org/packed/festival/2.5/voices/))
@@ -182,11 +190,13 @@ use {
- 安装完成
- 相关说明网站
- > 正常均需要
+ > 可能需要
- [wiki](https://archlinux.org/packages/community/any/festival-us/) 查看更多详细配置
- [官方网站](http://festvox.org/dbs/index.html)
- [用户手册](http://www.festvox.org/docs/manual-2.4.0/festival_toc.html)
+
+
## 配置
```lua
require'Trans'.setup {
From 1a27ef4abaeb1593b0159dfb0d1530379a220664 Mon Sep 17 00:00:00 2001
From: JuanZoran <1430359574@qq.com>
Date: Tue, 31 Jan 2023 11:45:45 +0800
Subject: [PATCH 2/2] fix: fix pin action and close action
---
lua/Trans/content.lua | 15 +-
lua/Trans/init.lua | 39 ++++--
lua/Trans/node.lua | 7 +-
lua/Trans/util/spinner.lua | 276 +++++++++++++++++++++++++++++++++++++
lua/Trans/view/float.lua | 3 +
lua/Trans/view/hover.lua | 102 +++++++-------
lua/Trans/window.lua | 94 +++++++------
7 files changed, 425 insertions(+), 111 deletions(-)
create mode 100644 lua/Trans/util/spinner.lua
diff --git a/lua/Trans/content.lua b/lua/Trans/content.lua
index 912589a..812dbaf 100644
--- a/lua/Trans/content.lua
+++ b/lua/Trans/content.lua
@@ -75,8 +75,9 @@ local content = {
end
end,
- format = function(self, ...)
- local nodes = { ... }
+ format = function(self, opt)
+ local win_width = opt.width or self.window.width
+ local nodes = opt.nodes
local size = #nodes
assert(size > 1, 'check items size')
local width = 0
@@ -87,8 +88,11 @@ local content = {
width = width + str:width()
end
- local space = math.floor(((self.window.width - width) / (size - 1)))
- assert(space > 0, 'try to expand the window')
+ local space = math.floor(((win_width - width) / (size - 1)))
+ if opt.strict and space < 0 then
+ return false
+ end
+
local interval = (' '):rep(space)
return setmetatable({
text = table.concat(strs, interval),
@@ -121,6 +125,7 @@ local content = {
end
}
+content.__index = content
---content的构造函数
---@param window table 链接的窗口
@@ -136,5 +141,5 @@ return function(window)
hl_size = 0,
lines = {},
highlights = {},
- }, { __index = content })
+ }, content)
end
diff --git a/lua/Trans/init.lua b/lua/Trans/init.lua
index 03f582f..b88bec4 100644
--- a/lua/Trans/init.lua
+++ b/lua/Trans/init.lua
@@ -40,6 +40,8 @@ M.conf = {
},
auto_play = true,
timeout = 3000,
+ spinner = 'dots', -- 查看所有样式: /lua/Trans/util/spinner
+ -- spinner = 'moon'
},
float = {
width = 0.8,
@@ -74,8 +76,11 @@ M.conf = {
icon = {
star = '',
notfound = ' ',
- yes = ' ',
- no = ''
+ yes = '✔',
+ no = '',
+ -- --- char: ■ | □ | ▇ | ▏ ▎ ▍ ▌ ▋ ▊ ▉ █
+ -- --- ◖■■■■■■■◗▫◻ ▆ ▆ ▇⃞ ▉⃞
+ cell = '■',
-- star = '⭐',
-- notfound = '❔',
-- yes = '✔️',
@@ -107,6 +112,7 @@ M.conf = {
-- TODO :add online translate engine
}
+local times = 0
M.setup = function(opts)
if opts then
M.conf = vim.tbl_deep_extend('force', M.conf, opts)
@@ -122,24 +128,27 @@ M.setup = function(opts)
float.width = math.floor(vim.o.columns * float.width)
end
- M.translate = require('Trans.translate')
+ times = times + 1
+ if times == 1 then
+ M.translate = require('Trans.translate')
- if vim.fn.executable('sqlite3') ~= 1 then
- error('Please check out sqlite3')
- end
+ if vim.fn.executable('sqlite3') ~= 1 then
+ error('Please check out sqlite3')
+ end
- vim.api.nvim_create_user_command('Translate', function()
- require("Trans").translate()
- end, { desc = ' 单词翻译', })
+ vim.api.nvim_create_user_command('Translate', function ()
+ M.translate()
+ end, { desc = ' 单词翻译', })
- vim.api.nvim_create_user_command('TranslateInput', function()
- require("Trans").translate('i')
- end, { desc = ' 搜索翻译' })
+ vim.api.nvim_create_user_command('TranslateInput', function()
+ M.translate('i')
+ end, { desc = ' 搜索翻译' })
- local hls = require('Trans.theme')[M.conf.theme]
- for hl, opt in pairs(hls) do
- vim.api.nvim_set_hl(0, hl, opt)
+ local hls = require('Trans.theme')[M.conf.theme]
+ for hl, opt in pairs(hls) do
+ vim.api.nvim_set_hl(0, hl, opt)
+ end
end
end
diff --git a/lua/Trans/node.lua b/lua/Trans/node.lua
index 33d5b99..0eada96 100644
--- a/lua/Trans/node.lua
+++ b/lua/Trans/node.lua
@@ -21,13 +21,16 @@ local text_meta = {
end,
}
+item_meta.__index = item_meta
+text_meta.__index = text_meta
+
return {
item = function(text, hl)
return setmetatable({
text = text,
hl = hl,
- }, { __index = item_meta })
+ }, item_meta)
end,
@@ -42,6 +45,6 @@ return {
return setmetatable({
text = table.concat(strs),
items = items,
- }, { __index = text_meta })
+ }, text_meta)
end,
}
diff --git a/lua/Trans/util/spinner.lua b/lua/Trans/util/spinner.lua
new file mode 100644
index 0000000..30836b1
--- /dev/null
+++ b/lua/Trans/util/spinner.lua
@@ -0,0 +1,276 @@
+-- Spinners adapted from: https://github.com/sindresorhus/cli-spinners
+--
+-- Some designs' names are made more descriptive; differences noted in comments.
+-- Other designs are omitted for brevity.
+--
+-- You may want to adjust spinner_rate according to the number of frames of your
+-- chosen spinner.
+
+-- MIT License
+--
+-- Copyright (c) Sindre Sorhus (https://sindresorhus.com)
+--
+-- 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.
+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
+ "∙∙∙",
+ "●∙∙",
+ "∙●∙",
+ "∙∙●",
+ "∙∙∙",
+ },
+}
diff --git a/lua/Trans/view/float.lua b/lua/Trans/view/float.lua
index d687dd0..9c36e1b 100644
--- a/lua/Trans/view/float.lua
+++ b/lua/Trans/view/float.lua
@@ -69,6 +69,9 @@ return function(word)
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 = {
diff --git a/lua/Trans/view/hover.lua b/lua/Trans/view/hover.lua
index 601b377..d291ca4 100644
--- a/lua/Trans/view/hover.lua
+++ b/lua/Trans/view/hover.lua
@@ -32,16 +32,18 @@ local process = {
line = it(m_result.word, 'TransWord')
else
- line = m_content:format(
- 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)
- )
+ line = 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)
+ },
+ }
end
m_content:addline(line)
end,
@@ -197,36 +199,42 @@ action = {
pcall(api.nvim_del_autocmd, cmd_id)
m_window:set('wrap', false)
- m_window:try_close(function()
- m_window:reopen(false, {
- relative = 'editor',
- row = 1,
- col = vim.o.columns - m_window.width - 3,
- }, function()
- m_window:set('wrap', true)
- end)
+ m_window:try_close {
+ callback = function()
+ m_window:reopen {
+ win_opt = {
+ relative = 'editor',
+ row = 1,
+ col = vim.o.columns - m_window.width - 3,
+ },
+ opt = {
+ callback = function()
+ m_window:set('wrap', true)
+ m_window:bufset('bufhidden', 'wipe')
+ end
+ },
+ }
- m_window:bufset('bufhidden', 'wipe')
- vim.keymap.del('n', conf.hover.keymap.pin, { buffer = true })
-
- --- NOTE : 只允许存在一个pin窗口
- local buf = m_window.bufnr
- pin = true
- local toggle = conf.hover.keymap.toggle_entry
- if toggle then
- next = m_window.winid
- vim.keymap.set('n', toggle, action.toggle_entry, { silent = true, buffer = buf })
- end
-
- api.nvim_create_autocmd('BufWipeOut', {
- callback = function(opt)
- if opt.buf == buf then
- pin = false
- api.nvim_del_autocmd(opt.id)
- end
+ vim.keymap.del('n', conf.hover.keymap.pin, { buffer = true })
+ --- NOTE : 只允许存在一个pin窗口
+ local buf = m_window.bufnr
+ pin = true
+ local toggle = conf.hover.keymap.toggle_entry
+ if toggle then
+ next = m_window.winid
+ vim.keymap.set('n', toggle, action.toggle_entry, { silent = true, buffer = buf })
end
- })
- end)
+
+ api.nvim_create_autocmd('BufWipeOut', {
+ callback = function(opt)
+ if opt.buf == buf then
+ pin = false
+ api.nvim_del_autocmd(opt.id)
+ end
+ end
+ })
+ end
+ }
end,
close = function()
@@ -294,14 +302,14 @@ local function online_query(word)
end
m_window:open()
+ local icon = conf.icon
+ local cell = icon.cell
+ local spinner = require('Trans.util.spinner')[conf.hover.spinner]
+ local range = #spinner
local timeout = conf.hover.timeout
- local interval = math.floor(timeout / m_window.width)
-
- -- --- char: ■ | □ | ▇ | ▏ ▎ ▍ ▌ ▋ ▊ ▉ █
- -- --- ◖■■■■■■■◗▫◻ ▆ ▆ ▇⃞ ▉⃞
- local cell = '▇'
-
+ local interval = math.floor(timeout / (m_window.width - spinner[1]:width()))
+ local f = '%s %s'
local i = 1
local do_progress
do_progress = function()
@@ -314,7 +322,6 @@ local function online_query(word)
handle()
m_content:attach()
- -- TODO :Animation
m_window.height = m_content:actual_height(true)
m_window:open {
animation = 'fold',
@@ -337,7 +344,7 @@ local function online_query(word)
else
m_content:addline(
- it(cell:rep(i), 'MoreMsg')
+ it(f:format(spinner[i % range + 1], cell:rep(i)), 'MoreMsg')
)
i = i + 1
m_content:attach()
@@ -365,7 +372,8 @@ return function(word)
row = 1,
})
- m_content = m_window.contents[1]
+
+ m_content = m_window:new_content()
m_result = require('Trans.query.offline')(word)
if m_result then
diff --git a/lua/Trans/window.lua b/lua/Trans/window.lua
index 1b8d271..b36b5ae 100644
--- a/lua/Trans/window.lua
+++ b/lua/Trans/window.lua
@@ -1,10 +1,6 @@
local api = vim.api
+local new_content = require('Trans.content')
---- TODO : progress bar
---- char: ■ | □ | ▇ | ▏ ▎ ▍ ▌ ▋ ▊ ▉ █
---- ◖■■■■■■■◗▫◻ ▆ ▆ ▇⃞ ▉⃞
-
----@diagnostic disable-next-line: duplicate-set-field
function string:width()
---@diagnostic disable-next-line: param-type-mismatch
return vim.fn.strwidth(self)
@@ -17,6 +13,14 @@ local function check_busy()
end
end
+---@class window
+---@field winid integer 窗口的handle
+---@field bufnr integer 窗口对应buffer的handle
+---@field width integer 窗口当前的宽度
+---@field height integer 窗口当前的高度
+---@field hl integer 窗口highlight的namespace
+---@field contents table[] 窗口内容的对象数组
+
---@type window
local window = {
set = function(self, option, value)
@@ -70,9 +74,10 @@ local window = {
open = function(self, opts)
self:draw()
- opts = opts or {}
- local interval = self.animation.interval
+ opts = opts or {}
+ local interval = self.animation.interval
local animation = opts.animation or self.animation.open
+ local callback = opts.callback
if animation then
check_busy()
@@ -90,8 +95,8 @@ local window = {
else
busy = false
- if opts.callback then
- opts.callback()
+ if callback then
+ callback()
end
end
end
@@ -103,11 +108,16 @@ local window = {
}
handler[animation]()
+
+ elseif callback then
+ callback()
end
end,
---安全的关闭窗口
- try_close = function(self, callback)
+ try_close = function(self, opts)
+ opts = opts or {}
+ local callback = opts.callback
if self:is_open() then
check_busy()
self.config = api.nvim_win_get_config(self.winid)
@@ -153,31 +163,38 @@ local window = {
end
end,
- reopen = function(self, entry, opt, callback)
+ reopen = function(self, opts)
+ local entry = opts.entry or false
+ local win_opt = opts.win_opt
+ local opt = opts.opt
+
check_busy()
self.config.win = nil
- if opt then
- for k, v in pairs(opt) do
+ if win_opt then
+ for k, v in pairs(win_opt) do
self.config[k] = v
end
end
self.winid = api.nvim_open_win(self.bufnr, entry, self.config)
- self:open(callback)
+ self:open(opt)
end,
set_hl = function(self, name, hl)
api.nvim_set_hl(self.hl, name, hl)
- end
+ end,
+
+ new_content = function(self)
+ local index = self.size + 1
+ self.size = index + 1
+ self.contents[index] = new_content(self)
+
+ return self.contents[index]
+ end,
}
----@class window
----@field winid integer 窗口的handle
----@field bufnr integer 窗口对应buffer的handle
----@field width integer 窗口当前的宽度
----@field height integer 窗口当前的高度
----@field hl integer 窗口highlight的namespace
----@field contents table[] 窗口内容的对象数组
+window.__index = window
+
---窗口对象的构造器
@@ -192,13 +209,13 @@ return function(entry, option)
}
local opt = {
- relative = option.relative,
- width = option.width,
- height = option.height,
- border = option.border,
- title = option.title,
- col = option.col,
- row = option.row,
+ relative = option.relative,
+ width = option.width,
+ height = option.height,
+ border = option.border,
+ title = option.title,
+ col = option.col,
+ row = option.row,
title_pos = nil,
focusable = false,
@@ -206,9 +223,6 @@ return function(entry, option)
style = 'minimal',
}
- if opt.title then
- opt.title_pos = 'center'
- end
if opt.title then
opt.title_pos = 'center'
end
@@ -227,20 +241,16 @@ return function(entry, option)
height = opt.height,
animation = option.animation,
hl = api.nvim_create_namespace('TransWinHl'),
- contents = setmetatable({}, {
- __index = function(self, key)
- assert(type(key) == 'number')
- self[key] = require('Trans.content')(win)
- return self[key]
- end
- })
+ size = 0,
+ contents = {}
}
- setmetatable(win, { __index = window })
- -- FIXME :config this
+ ---@diagnostic disable-next-line: param-type-mismatch
+ setmetatable(win, window)
+
+
win:bufset('filetype', 'Trans')
win:bufset('buftype', 'nofile')
-
api.nvim_win_set_hl_ns(win.winid, win.hl)
win:set_hl('Normal', { link = 'TransWin' })
win:set_hl('FloatBorder', { link = 'TransBorder' })