Skip to content

Commit 57806a9

Browse files
authored
Merge pull request #4 from johnseth97/patch-1.1
Patch 1.1
2 parents 4df85f4 + 59d7998 commit 57806a9

8 files changed

Lines changed: 157 additions & 105 deletions

File tree

.github/workflows/ci.yml

Lines changed: 7 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -21,25 +21,18 @@ jobs:
2121
- name: Install Neovim ${{ matrix.neovim }}
2222
run: |
2323
set -euo pipefail
24-
2524
VERSION=${{ matrix.neovim }}
26-
27-
# All historic 0.x tags use nvim-linux64.tar.gz, everything newer uses -x86_64
2825
if [[ "$VERSION" =~ ^v0\.[0-9]+\. ]]; then
2926
FILENAME=nvim-linux64.tar.gz
3027
else
3128
FILENAME=nvim-linux-x86_64.tar.gz
3229
fi
33-
3430
URL="https://github.com/neovim/neovim/releases/download/${VERSION}/${FILENAME}"
3531
echo "Downloading $URL"
36-
37-
curl -fL -o nvim.tar.gz "$URL" # -f = fail on 4xx/5xx, -L = follow redirects
38-
32+
curl -fL -o nvim.tar.gz "$URL"
3933
mkdir nvim-extract
4034
tar -xzf nvim.tar.gz -C nvim-extract
41-
42-
DIR="$(ls nvim-extract | head -n1)" # should be nvim-linux64 or nvim-linux-x86_64
35+
DIR="$(ls nvim-extract | head -n1)"
4336
sudo mv "nvim-extract/$DIR" /opt/nvim
4437
echo "/opt/nvim/bin" >> "$GITHUB_PATH"
4538
@@ -55,32 +48,20 @@ jobs:
5548
run: |
5649
set -euo pipefail
5750
sudo apt-get update
58-
sudo apt-get install -y lua5.1 liblua5.1-0-dev luarocks
51+
sudo apt-get install -y lua5.1 liblua5.1-0-dev luarocks make
5952
luarocks --lua-version=5.1 --local install luacheck
6053
luarocks --lua-version=5.1 --local install luacov
6154
luarocks --lua-version=5.1 --local install luacov-reporter-lcov
62-
echo "$HOME/.luarocks/bin" >> $GITHUB_PATH
55+
echo "$HOME/.luarocks/bin" >> "$GITHUB_PATH"
6356
64-
- name: Run tests with coverage
57+
- name: Run tests and generate coverage
6558
run: |
6659
eval "$(luarocks --lua-version=5.1 path)"
67-
luarocks --lua-version=5.1 list # debug
68-
nvim --headless -u tests/minimal_init.lua -c "luafile tests/run_cov.lua"
69-
70-
luacov -r lcov > lcov.info
71-
sed -i 's|SF:.*/codex.nvim/codex.nvim/|SF:|g' lcov.info
72-
head -n 10 lcov.info # debug
73-
74-
# Debug output
75-
echo "=== first 20 lines of lcov.info ==="
76-
head -n 20 lcov.info
60+
make coverage
7761
78-
echo "=== all source-file entries ==="
79-
grep '^SF:' lcov.info | sed -e 's/^SF://g' | sort | uniq | head -n 10
80-
8162
- name: Upload code coverage
8263
uses: codecov/codecov-action@v4
8364
with:
84-
files: lcov.info # <-- new file
65+
files: lcov.info
8566
disable_search: true
8667
token: ${{ secrets.CODECOV_TOKEN }}

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
luacov.report.out
2+
luacov.stats.out

.luacheckrc

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
-- .luacheckrc
2-
std = "luajit"
3-
globals = { "vim" }
2+
std = 'luajit'
3+
globals = { 'vim', 'describe', 'it', 'before_each', 'after_each', 'pending', 'assert', 'eq' }
44
ignore = {
5-
"plugin/*", -- plugin loader shim
5+
'plugin/*', -- plugin loader shim
66
}
77

8-
max_line_length = false -- or turn it off completely
9-
8+
max_line_length = false -- or turn it off completely

README.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
# gh-dash.nvim
22
<img width="1477" alt="image" src="https://github.com/user-attachments/assets/84bffe05-a2c3-4bdb-9cbe-0ea0be0ea279" />
33

4-
54
## A Neovim plugin integrating the open-source gh-dash TUI for the `gh` CLI ([gh-dash](https://github.com/dlvhdr/gh-dash/))
65

76
> Latest version: ![GitHub tag (latest SemVer)](https://img.shields.io/github/v/tag/johnseth97/gh-dash.nvim?sort=semver)

lua/gh_dash/init.lua

Lines changed: 87 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,18 @@
1-
local vim = vim
2-
31
local M = {}
42

53
local config = {
64
keymaps = {},
75
border = 'single',
6+
custom_border = {
7+
{}, -- Top left corner
8+
{}, -- Top side
9+
{}, -- Top right corner
10+
{}, -- Right side
11+
{}, -- Bottom right corner
12+
{}, -- Bottom side
13+
{}, -- Bottom left corner
14+
{}, -- Left side
15+
},
816
width = 0.8,
917
height = 0.8,
1018
cmd = { 'gh', 'dash' },
@@ -33,6 +41,41 @@ function M.setup(user_config)
3341
end
3442
end
3543

44+
local styles = {
45+
single = {
46+
{ '', 'FloatBorder' },
47+
{ '', 'FloatBorder' },
48+
{ '', 'FloatBorder' },
49+
{ '', 'FloatBorder' },
50+
{ '', 'FloatBorder' },
51+
{ '', 'FloatBorder' },
52+
{ '', 'FloatBorder' },
53+
{ '', 'FloatBorder' },
54+
},
55+
double = {
56+
{ '', 'FloatBorder' },
57+
{ '', 'FloatBorder' },
58+
{ '', 'FloatBorder' },
59+
{ '', 'FloatBorder' },
60+
{ '', 'FloatBorder' },
61+
{ '', 'FloatBorder' },
62+
{ '', 'FloatBorder' },
63+
{ '', 'FloatBorder' },
64+
},
65+
square = {
66+
{ '', 'FloatBorder' },
67+
{ '', 'FloatBorder' },
68+
{ '', 'FloatBorder' },
69+
{ '', 'FloatBorder' },
70+
{ '', 'FloatBorder' },
71+
{ '', 'FloatBorder' },
72+
{ '', 'FloatBorder' },
73+
{ '', 'FloatBorder' },
74+
},
75+
custom = config.custom_border,
76+
none = nil,
77+
}
78+
3679
-- Create a floating window displaying the gh_dash buffer
3780
local function open_window()
3881
-- compute dimensions and position
@@ -43,40 +86,11 @@ local function open_window()
4386
-- resolve border style (string or table)
4487
local border = config.border
4588
if type(border) == 'string' then
46-
local styles = {
47-
single = {
48-
{ '', 'FloatBorder' },
49-
{ '', 'FloatBorder' },
50-
{ '', 'FloatBorder' },
51-
{ '', 'FloatBorder' },
52-
{ '', 'FloatBorder' },
53-
{ '', 'FloatBorder' },
54-
{ '', 'FloatBorder' },
55-
{ '', 'FloatBorder' },
56-
},
57-
double = {
58-
{ '', 'FloatBorder' },
59-
{ '', 'FloatBorder' },
60-
{ '', 'FloatBorder' },
61-
{ '', 'FloatBorder' },
62-
{ '', 'FloatBorder' },
63-
{ '', 'FloatBorder' },
64-
{ '', 'FloatBorder' },
65-
{ '', 'FloatBorder' },
66-
},
67-
square = {
68-
{ '', 'FloatBorder' },
69-
{ '', 'FloatBorder' },
70-
{ '', 'FloatBorder' },
71-
{ '', 'FloatBorder' },
72-
{ '', 'FloatBorder' },
73-
{ '', 'FloatBorder' },
74-
{ '', 'FloatBorder' },
75-
{ '', 'FloatBorder' },
76-
},
77-
none = nil,
78-
}
79-
border = styles[border] or styles.single
89+
if border == 'none' then
90+
border = 'none'
91+
else
92+
border = styles[border] or styles.single
93+
end
8094
end
8195
-- open floating window
8296
state.win = vim.api.nvim_open_win(state.buf, true, {
@@ -95,16 +109,22 @@ function M.open()
95109
vim.api.nvim_set_current_win(state.win)
96110
return
97111
end
98-
if not state.buf or not vim.api.nvim_buf_is_valid(state.buf) then
112+
if not state.buf or not vim.api.nvim_buf_is_valid(state.buf) or vim.api.nvim_buf_get_option(state.buf, 'modified') then
99113
-- create an unlisted scratch buffer for the terminal
100114
state.buf = vim.api.nvim_create_buf(false, false)
101115
-- buffer options
102116
vim.api.nvim_buf_set_option(state.buf, 'bufhidden', 'hide')
103117
vim.api.nvim_buf_set_option(state.buf, 'swapfile', false)
104118
vim.api.nvim_buf_set_option(state.buf, 'filetype', 'gh_dash')
105-
-- map <Esc> in terminal and normal modes to close the gh_dash window
106-
vim.api.nvim_buf_set_keymap(state.buf, 't', '<Esc>', [[<C-\><C-n><cmd>lua require('gh_dash').close()<CR>]], { noremap = true, silent = true })
107-
vim.api.nvim_buf_set_keymap(state.buf, 'n', '<Esc>', [[<cmd>lua require('gh_dash').close()<CR>]], { noremap = true, silent = true })
119+
-- Escape backgrounds the window cleanly
120+
-- Map <Esc> in terminal mode to hide the popup
121+
vim.api.nvim_buf_set_keymap(
122+
state.buf,
123+
't',
124+
'<Esc>',
125+
[[<C-\><C-n><cmd>lua vim.defer_fn(function() require('gh_dash').toggle() end, 10)<CR>]],
126+
{ noremap = true, silent = true }
127+
)
108128
end
109129
open_window()
110130
-- determine if config.cmd is a simple executable name (no args) for checking
@@ -120,40 +140,34 @@ function M.open()
120140
-- if simple command and not found, handle auto-install or notify
121141
if check_cmd and vim.fn.executable(check_cmd) == 0 then
122142
if config.autoinstall then
123-
if vim.fn.executable 'npm' == 1 then
143+
if vim.fn.executable 'gh' == 1 then
124144
-- install via npm in the floating terminal to show output
125145
do
126146
local shell_cmd = vim.o.shell or 'sh'
127147
local cmd = {
128148
shell_cmd,
129149
'-c',
130-
"echo 'Autoinstalling OpenAI gh_dash via npm...'; npm install -g @openai/gh_dash",
150+
"echo 'Autoinstalling gh_dash via gh CLI extensions...'; gh extension install dlvhdr/gh-dash",
131151
}
132152
state.job = vim.fn.termopen(cmd, {
133153
cwd = vim.loop.cwd(),
134-
on_exit = function(_, exit_code)
154+
on_exit = function(_, exit_code, _)
155+
state.job = nil
135156
if exit_code == 0 then
136-
vim.notify('[gh_dash.nvim] gh_dash CLI installed successfully', vim.log.levels.INFO)
137-
-- automatically re-launch gh_dash CLI now that it's installed
138157
vim.schedule(function()
139158
M.close()
140-
state.buf = nil
141-
M.open()
142159
end)
143-
else
144-
vim.notify('[gh_dash.nvim] failed to install gh_dash CLI', vim.log.levels.ERROR)
145160
end
146-
state.job = nil
147161
end,
148162
})
149163
end
150164
else
151165
-- show installation instructions in the gh_dash popup
152166
local msg = {
153-
'npm not found; cannot auto-install gh_dash CLI.',
167+
'gh CLI not found; cannot auto-install gh_dash extension.',
154168
'',
155-
'Please install via your system package manager, or manually run:',
156-
' npm install -g @openai/gh_dash',
169+
'Please install the gh CLI via your system package manager',
170+
'i.e. `brew install gh`',
157171
}
158172
vim.api.nvim_buf_set_lines(state.buf, 0, -1, false, msg)
159173
end
@@ -163,7 +177,7 @@ function M.open()
163177
'gh_dash CLI not found.',
164178
'',
165179
'Install with:',
166-
' npm install -g @openai/gh_dash',
180+
'gh extension install dlvhdr/gh-dash',
167181
'',
168182
'Or enable autoinstall in your plugin setup:',
169183
' require("gh_dash").setup{ autoinstall = true }',
@@ -175,9 +189,14 @@ function M.open()
175189
-- spawn the gh_dash CLI in the floating terminal buffer
176190
if not state.job then
177191
state.job = vim.fn.termopen(config.cmd, {
178-
cwd = vim.loop.cwd(),
179-
on_exit = function()
192+
wd = vim.loop.cwd(),
193+
on_exit = function(_, exit_code, _)
180194
state.job = nil
195+
if exit_code == 0 then
196+
vim.schedule(function()
197+
M.close()
198+
end)
199+
end
181200
end,
182201
})
183202
end
@@ -188,12 +207,22 @@ function M.close()
188207
vim.api.nvim_win_close(state.win, true)
189208
state.win = nil
190209
end
210+
if state.buf and vim.api.nvim_buf_is_valid(state.buf) then
211+
vim.api.nvim_buf_delete(state.buf, { force = true })
212+
state.buf = nil
213+
end
191214
end
192215

193216
function M.toggle()
194217
if state.win and vim.api.nvim_win_is_valid(state.win) then
195-
M.close()
218+
-- HIDE the window (don't kill the job)
219+
vim.api.nvim_win_close(state.win, true)
220+
state.win = nil
221+
elseif state.buf and vim.api.nvim_buf_is_valid(state.buf) then
222+
-- Reopen window into existing buffer
223+
open_window()
196224
else
225+
-- Full open if everything is gone
197226
M.open()
198227
end
199228
end
@@ -218,7 +247,7 @@ function M.status()
218247
return M.statusline() ~= ''
219248
end,
220249
-- gear icon
221-
icon = '',
250+
icon = '',
222251
-- default color (blue)
223252
color = { fg = '#51afef' },
224253
}

makefile

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# Makefile for gh_dash.nvim testing and coverage
2+
# Usage:
3+
# make test - run unit tests
4+
# make coverage - run tests + generate coverage (luacov + lcov.info)
5+
6+
# Force correct Lua version for Neovim (Lua 5.1)
7+
LUAROCKS_ENV = eval "$(luarocks --lua-version=5.1 path)"
8+
9+
# Headless Neovim test runner
10+
NVIM_TEST_CMD = nvim --headless -u tests/minimal_init.lua -c "PlenaryBustedDirectory tests/"
11+
12+
.PHONY: test coverage clean
13+
14+
test:
15+
$(LUAROCKS_ENV) && $(NVIM_TEST_CMD)
16+
17+
coverage:
18+
$(LUAROCKS_ENV) && nvim --headless -u tests/minimal_init.lua -c "luafile tests/run_cov.lua"
19+
ls -lh luacov.stats.out
20+
$(LUAROCKS_ENV) && luacov -t LcovReporter
21+
@echo "Generated coverage report: lcov.info"
22+
23+
clean:
24+
rm -f luacov.stats.out lcov.info
25+
@echo "Cleaned coverage artifacts"

0 commit comments

Comments
 (0)