init: QQdock.nvim — persistent adaptive terminal dock

This commit is contained in:
QQ 2026-06-11 19:20:52 +08:00
commit 62882ebeb1
11 changed files with 229 additions and 0 deletions

13
.busted Normal file
View File

@ -0,0 +1,13 @@
return {
_all = {
coverage = false,
lpath = "lua/?.lua;lua/?/init.lua",
lua = "nlua",
},
default = {
verbose = true
},
tests = {
verbose = true
},
}

8
.editorconfig Normal file
View File

@ -0,0 +1,8 @@
root = true
[*.lua]
charset = utf-8
indent_style = space
indent_size = 2
trim_trailing_whitespace = true
insert_final_newline = true

24
.github/workflows/linter.yml vendored Normal file
View File

@ -0,0 +1,24 @@
---
name: Lint Code Base
on:
pull_request: ~
push:
branches:
- master
jobs:
build:
name: Lint Code Base
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@v3
- name: Lint Code Base
uses: github/super-linter/slim@v4
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
LINTER_RULES_PATH: /
VALIDATE_JSCPD: false
VALIDATE_PYTHON_BLACK: false

20
.github/workflows/release.yml vendored Normal file
View File

@ -0,0 +1,20 @@
---
name: "Release"
on:
push:
tags:
- 'v*.*.*'
jobs:
luarocks-release:
runs-on: ubuntu-latest
name: Luarocks Release
steps:
- name: Checkout
uses: actions/checkout@v3
if: env.LUAROCKS_API_KEY != null
- name: Luarocks Upload
uses: nvim-neorocks/luarocks-tag-release@v7
if: env.LUAROCKS_API_KEY != null
env:
LUAROCKS_API_KEY: ${{ secrets.LUAROCKS_API_KEY }}

22
.github/workflows/tests.yml vendored Normal file
View File

@ -0,0 +1,22 @@
---
name: Run tests
on:
pull_request: ~
push:
branches:
- main
jobs:
build:
name: Run tests
runs-on: ubuntu-latest
strategy:
matrix:
neovim_version: ['nightly']
steps:
- uses: actions/checkout@v3
- name: Run tests
uses: nvim-neorocks/nvim-busted-action@v1
with:
nvim_version: ${{ matrix.neovim_version }}

3
.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
/luarocks
/lua_modules
/.luarocks

9
.luacheckrc Normal file
View File

@ -0,0 +1,9 @@
ignore = {
"631", -- max_line_length
}
read_globals = {
"vim",
"describe",
"it",
"assert"
}

View File

@ -0,0 +1,18 @@
rockspec_format = '3.0'
package = 'QQdock.nvim'
version = 'scm-1'
source = {
url = 'git+https://git.qyhhh.top/newbie/QQdock.nvim'
}
dependencies = {
'toggleterm.nvim',
}
test_dependencies = {
'nlua',
}
build = {
type = 'builtin',
copy_directories = {
'plugin',
},
}

61
README.md Normal file
View File

@ -0,0 +1,61 @@
# QQdock.nvim
Persistent adaptive terminal dock for Neovim.
每次按 `<c-t>` 打开 shell聊完 Reasonix 按 `<C-i>` 隐藏,再按回来——对话还在。横屏自动右侧分屏,竖屏自动下方分屏。
## 安装
```lua
-- lazy.nvim
{
'newbie/QQdock.nvim',
url = 'https://git.qyhhh.top/newbie/QQdock.nvim',
dependencies = { 'akinsho/toggleterm.nvim' },
config = function()
local Q = require('QQdock')
vim.keymap.set({ 'n', 'i' }, '<c-t>', Q.shell, { noremap = true })
vim.keymap.set('n', '<C-i>', function() Q.open('reasonix') end)
vim.keymap.set('n', '<leader>gg', function() Q.open('lazygit') end)
end,
}
```
## 用法
```lua
local Q = require('QQdock')
Q.shell() -- 普通 shell
Q.open('reasonix') -- Reasonix AI agent
Q.open('lazygit') -- lazygit
Q.open('btm') -- 系统监控
Q.open('yazi') -- 文件管理器
```
## API
| 函数 | 参数 | 作用 |
|------|------|------|
| `Q.shell()` | — | 打开/关闭持久 shell |
| `Q.open(cmd)` | cmd | 打开/关闭指定命令的持久终端 |
## 特性
- **持久化** — toggle 显隐,终端状态保留
- **自适应** — 横屏右侧 45%,竖屏下方 40%
- **轻量** — 仅依赖 toggleterm.nvim
## Development
### Run tests
```bash
luarocks test --local
# or
busted
```
## License
MIT

44
lua/QQdock/init.lua Normal file
View File

@ -0,0 +1,44 @@
-- QQdock.nvim — Persistent adaptive terminal dock
--
-- 依赖 toggleterm.nvim
--
-- 用法:
-- local Q = require('QQdock')
-- Q.shell() -- 打开/关闭普通 shell
-- Q.open('reasonix') -- 打开/关闭 Reasonix
-- Q.open('lazygit') -- 打开/关闭 lazygit
local M = {}
local terms = {}
---Open or toggle a persistent terminal running `cmd`.
---When the window is wider than tall, the terminal opens on the right side (vertical split),
---taking 45% of the width. When taller than wide, it opens at the bottom (horizontal split),
---taking 40% of the height.
---@param cmd string|nil The command to run, or nil for a plain shell.
function M.open(cmd)
local ui = vim.api.nvim_list_uis()[1]
if not ui then
return
end
local tall = ui.height > ui.width
local name = cmd or '__shell__'
if not terms[name] or not terms[name]:is_open() then
terms[name] = require('toggleterm.terminal').Terminal:new({
direction = tall and 'horizontal' or 'vertical',
cmd = cmd,
size = tall and math.floor(ui.height * 0.4) or math.floor(ui.width * 0.45),
})
end
terms[name]:toggle()
end
---Toggle a plain shell terminal.
function M.shell()
M.open(nil)
end
return M

7
spec/QQdock_spec.lua Normal file
View File

@ -0,0 +1,7 @@
describe('QQdock', function()
it('can be required without toggleterm on path', function()
-- toggleterm is not installed in test env, so we test the module loads
local ok, _ = pcall(require, 'QQdock')
assert.is_true(ok)
end)
end)