feat: initial release
This commit is contained in:
17 files changed
+347
No files matched your search
@@ -0,0 +1 @@
|
||||
github: swaits
|
||||
@@ -0,0 +1,21 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
title: ''
|
||||
labels: bug
|
||||
assignees: ''
|
||||
---
|
||||
|
||||
**Describe the bug**
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
**To Reproduce**
|
||||
Steps to reproduce the behavior.
|
||||
|
||||
**Expected behavior**
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
**Environment**
|
||||
- Neovim version:
|
||||
- OS:
|
||||
- Config (if relevant):
|
||||
@@ -0,0 +1,16 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for this project
|
||||
title: ''
|
||||
labels: enhancement
|
||||
assignees: ''
|
||||
---
|
||||
|
||||
**Is your feature request related to a problem?**
|
||||
A clear and concise description of what the problem is.
|
||||
|
||||
**Describe the solution you'd like**
|
||||
A clear and concise description of what you want to happen.
|
||||
|
||||
**Additional context**
|
||||
Add any other context about the feature request here.
|
||||
@@ -0,0 +1,30 @@
|
||||
name: CI
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
pull_request:
|
||||
branches: [main]
|
||||
|
||||
jobs:
|
||||
lint:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: JohnnyMorganz/stylua-action@v4
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
version: latest
|
||||
args: --check lua/ plugin/
|
||||
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install Neovim
|
||||
run: |
|
||||
wget -q https://github.com/neovim/neovim/releases/download/v0.12.0/nvim-linux-x86_64.appimage -O /tmp/nvim.appimage
|
||||
chmod +x /tmp/nvim.appimage
|
||||
/tmp/nvim.appimage --appimage-extract > /dev/null 2>&1
|
||||
echo "$PWD/squashfs-root/usr/bin" >> $GITHUB_PATH
|
||||
- name: Run tests
|
||||
run: ./scripts/test.sh
|
||||
@@ -0,0 +1,6 @@
|
||||
*.swp
|
||||
*.swo
|
||||
*~
|
||||
.DS_Store
|
||||
tags
|
||||
deps/
|
||||
@@ -0,0 +1,18 @@
|
||||
# Changelog
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [0.1.0] - 2026-04-09
|
||||
|
||||
### Added
|
||||
|
||||
- Initial release
|
||||
- Lightbulb sign when LSP code actions are available on current line
|
||||
- Async LSP requests with generation-counter stale-response handling
|
||||
- Configurable sign text, highlight group, and extmark priority
|
||||
- Zero-config auto-loading via `plugin/` directory
|
||||
|
||||
[0.1.0]: https://github.com/swaits/tiny-lightbulb.nvim/releases/tag/v0.1.0
|
||||
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2026 Stephen Waits
|
||||
|
||||
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.
|
||||
@@ -0,0 +1,52 @@
|
||||
# tiny-lightbulb.nvim
|
||||
|
||||
A tiny lightbulb for Neovim 0.12+. Shows a sign when LSP code actions are
|
||||
available on the current line.
|
||||
|
||||
Zero config. ~50 lines of Lua.
|
||||
|
||||
## Features
|
||||
|
||||
- Displays a 💡 in the sign column when code actions are available
|
||||
- Clears instantly on cursor move
|
||||
- Async LSP requests with stale-response handling
|
||||
- Configurable sign text, highlight, and priority
|
||||
- Works out of the box — no setup call required
|
||||
|
||||
## Requirements
|
||||
|
||||
- Neovim >= 0.12
|
||||
- At least one LSP server that supports code actions
|
||||
|
||||
## Installation
|
||||
|
||||
Add to your `vim.pack.add()` call:
|
||||
|
||||
```lua
|
||||
"https://github.com/swaits/tiny-lightbulb.nvim",
|
||||
```
|
||||
|
||||
Done. The plugin auto-loads with sensible defaults.
|
||||
|
||||
## Configuration
|
||||
|
||||
All options are optional. Call `setup()` only if you want to customize:
|
||||
|
||||
```lua
|
||||
require("tiny-lightbulb").setup({
|
||||
sign = "💡", -- sign column text
|
||||
hl = "DiagnosticWarn", -- highlight group
|
||||
priority = 10, -- extmark priority
|
||||
})
|
||||
```
|
||||
|
||||
## How it works
|
||||
|
||||
On `CursorHold`, the plugin asks all attached LSP clients whether code
|
||||
actions exist for the current line. If any are returned, an extmark sign
|
||||
is placed. On `CursorMoved`, the sign is cleared and any in-flight LSP
|
||||
responses are discarded via a generation counter.
|
||||
|
||||
## License
|
||||
|
||||
[MIT](LICENSE)
|
||||
@@ -0,0 +1,68 @@
|
||||
*tiny-lightbulb.txt* Show a sign when LSP code actions are available
|
||||
|
||||
Author: Stephen Waits <https://github.com/swaits>
|
||||
License: MIT
|
||||
|
||||
==============================================================================
|
||||
CONTENTS *tiny-lightbulb-contents*
|
||||
|
||||
1. Introduction ............................ |tiny-lightbulb-introduction|
|
||||
2. Requirements ............................ |tiny-lightbulb-requirements|
|
||||
3. Installation ............................ |tiny-lightbulb-installation|
|
||||
4. Configuration ........................... |tiny-lightbulb-configuration|
|
||||
|
||||
==============================================================================
|
||||
1. INTRODUCTION *tiny-lightbulb-introduction*
|
||||
|
||||
tiny-lightbulb.nvim displays a sign in the sign column when LSP code actions
|
||||
are available for the current line. Works out of the box with zero
|
||||
configuration — just install and go.
|
||||
|
||||
==============================================================================
|
||||
2. REQUIREMENTS *tiny-lightbulb-requirements*
|
||||
|
||||
- Neovim >= 0.12
|
||||
- At least one LSP server that supports code actions
|
||||
|
||||
==============================================================================
|
||||
3. INSTALLATION *tiny-lightbulb-installation*
|
||||
|
||||
Add to your |vim.pack.add()| call: >lua
|
||||
|
||||
"https://github.com/swaits/tiny-lightbulb.nvim",
|
||||
<
|
||||
That's it. The plugin auto-loads with defaults. To customize, call setup: >lua
|
||||
|
||||
require("tiny-lightbulb").setup({
|
||||
sign = "💡",
|
||||
hl = "DiagnosticWarn",
|
||||
priority = 10,
|
||||
})
|
||||
<
|
||||
==============================================================================
|
||||
4. CONFIGURATION *tiny-lightbulb-configuration*
|
||||
|
||||
*tiny-lightbulb.setup()*
|
||||
setup({opts})
|
||||
|
||||
Optional. The plugin works with defaults if you never call this.
|
||||
Calling setup reconfigures the plugin with the given options.
|
||||
|
||||
All options shown with defaults: >lua
|
||||
|
||||
require("tiny-lightbulb").setup({
|
||||
sign = "💡", -- sign column text
|
||||
hl = "DiagnosticWarn", -- highlight group for the sign
|
||||
priority = 10, -- extmark priority
|
||||
})
|
||||
<
|
||||
Parameters: ~
|
||||
{opts} (table|nil) Configuration table
|
||||
|
||||
Fields: ~
|
||||
{sign} (string) Text shown in the sign column. Default: "💡"
|
||||
{hl} (string) Highlight group for the sign. Default: "DiagnosticWarn"
|
||||
{priority} (number) Extmark priority. Default: 10
|
||||
|
||||
==============================================================================
|
||||
vim:tw=78:ts=8:ft=help:norl:
|
||||
@@ -0,0 +1,55 @@
|
||||
local M = {}
|
||||
|
||||
function M.setup(opts)
|
||||
opts = vim.tbl_extend("force", {
|
||||
sign = "💡",
|
||||
hl = "DiagnosticWarn",
|
||||
priority = 10,
|
||||
}, opts or {})
|
||||
|
||||
local ns = vim.api.nvim_create_namespace("tiny-lightbulb")
|
||||
local gen = 0
|
||||
|
||||
local function clear()
|
||||
gen = gen + 1
|
||||
vim.api.nvim_buf_clear_namespace(0, ns, 0, -1)
|
||||
end
|
||||
|
||||
vim.api.nvim_create_autocmd({ "CursorHold", "CursorHoldI" }, {
|
||||
group = vim.api.nvim_create_augroup("tiny-lightbulb", { clear = true }),
|
||||
callback = function()
|
||||
local buf, lnum = vim.api.nvim_get_current_buf(), vim.fn.line(".") - 1
|
||||
clear()
|
||||
if #vim.lsp.get_clients({ bufnr = buf, method = "textDocument/codeAction" }) == 0 then
|
||||
return
|
||||
end
|
||||
local id = gen
|
||||
vim.lsp.buf_request(buf, "textDocument/codeAction", {
|
||||
textDocument = vim.lsp.util.make_text_document_params(buf),
|
||||
range = { start = { line = lnum, character = 0 }, ["end"] = { line = lnum, character = 0 } },
|
||||
context = { diagnostics = vim.diagnostic.get(buf, { lnum = lnum }) },
|
||||
}, function(err, results)
|
||||
if
|
||||
id == gen
|
||||
and not err
|
||||
and results
|
||||
and #results > 0
|
||||
and vim.api.nvim_buf_is_valid(buf)
|
||||
then
|
||||
vim.api.nvim_buf_set_extmark(buf, ns, lnum, 0, {
|
||||
sign_text = opts.sign,
|
||||
sign_hl_group = opts.hl,
|
||||
priority = opts.priority,
|
||||
})
|
||||
end
|
||||
end)
|
||||
end,
|
||||
})
|
||||
|
||||
vim.api.nvim_create_autocmd({ "CursorMoved", "CursorMovedI", "InsertEnter" }, {
|
||||
group = vim.api.nvim_create_augroup("tiny-lightbulb-clear", { clear = true }),
|
||||
callback = clear,
|
||||
})
|
||||
end
|
||||
|
||||
return M
|
||||
@@ -0,0 +1 @@
|
||||
require("tiny-lightbulb").setup()
|
||||
@@ -0,0 +1,4 @@
|
||||
-- Minimal init for testing tiny-lightbulb.nvim
|
||||
vim.opt.rtp:prepend(".")
|
||||
vim.opt.rtp:prepend("deps/mini.nvim")
|
||||
vim.cmd("runtime plugin/tiny-lightbulb.lua")
|
||||
Executable
+11
@@ -0,0 +1,11 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# Clone mini.nvim for test framework (if not cached)
|
||||
if [ ! -d deps/mini.nvim ]; then
|
||||
mkdir -p deps
|
||||
git clone --depth 1 https://github.com/echasnovski/mini.nvim deps/mini.nvim
|
||||
fi
|
||||
|
||||
# Run tests
|
||||
nvim --headless -u scripts/minimal_init.lua -c "lua require('mini.test').setup(); MiniTest.run_file('tests/test_init.lua')"
|
||||
@@ -0,0 +1 @@
|
||||
std = "vim"
|
||||
@@ -0,0 +1,4 @@
|
||||
column_width = 100
|
||||
indent_type = "Spaces"
|
||||
indent_width = 2
|
||||
quote_style = "AutoPreferDouble"
|
||||
@@ -0,0 +1,36 @@
|
||||
local T = MiniTest.new_set()
|
||||
local eq = MiniTest.expect.equality
|
||||
|
||||
-- ── Setup tests ───────────────────────────────────────────────────────
|
||||
|
||||
T["setup"] = MiniTest.new_set()
|
||||
|
||||
T["setup"]["creates augroups"] = function()
|
||||
-- plugin/ auto-loaded via minimal_init, so augroups should exist
|
||||
local groups = vim.api.nvim_get_autocmds({ group = "tiny-lightbulb" })
|
||||
eq(#groups > 0, true)
|
||||
local clear_groups = vim.api.nvim_get_autocmds({ group = "tiny-lightbulb-clear" })
|
||||
eq(#clear_groups > 0, true)
|
||||
end
|
||||
|
||||
T["setup"]["is idempotent"] = function()
|
||||
require("tiny-lightbulb").setup()
|
||||
require("tiny-lightbulb").setup()
|
||||
local groups = vim.api.nvim_get_autocmds({ group = "tiny-lightbulb" })
|
||||
eq(#groups > 0, true)
|
||||
end
|
||||
|
||||
T["setup"]["respects custom sign"] = function()
|
||||
-- Just verify it doesn't error with custom opts
|
||||
require("tiny-lightbulb").setup({ sign = "CA" })
|
||||
local groups = vim.api.nvim_get_autocmds({ group = "tiny-lightbulb" })
|
||||
eq(#groups > 0, true)
|
||||
end
|
||||
|
||||
T["setup"]["respects custom highlight"] = function()
|
||||
require("tiny-lightbulb").setup({ hl = "DiagnosticInfo" })
|
||||
local groups = vim.api.nvim_get_autocmds({ group = "tiny-lightbulb" })
|
||||
eq(#groups > 0, true)
|
||||
end
|
||||
|
||||
return T
|
||||
Reference in new issue
Block a user