feat: initial release
This commit is contained in:
17 files changed
+339
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,14 @@
|
|||||||
|
# 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
|
||||||
|
|
||||||
|
[0.1.0]: https://github.com/swaits/tiny-spark.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,51 @@
|
|||||||
|
# tiny-spark.nvim
|
||||||
|
|
||||||
|
A tiny cursor jump animation for Neovim 0.12+. Flashes a brief highlight
|
||||||
|
at the cursor position after large jumps.
|
||||||
|
|
||||||
|
Zero config. ~55 lines of Lua.
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- Brief flash at cursor position after jumping 5+ lines
|
||||||
|
- Smooth fade-out animation via `winblend`
|
||||||
|
- Configurable threshold, duration, width, and highlight group
|
||||||
|
- Extremely lightweight — no dependencies, single timer
|
||||||
|
- Works out of the box — no setup call required
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
- Neovim >= 0.12
|
||||||
|
- A terminal that supports `winblend` (most modern terminals)
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
Add to your `vim.pack.add()` call:
|
||||||
|
|
||||||
|
```lua
|
||||||
|
"https://github.com/swaits/tiny-spark.nvim",
|
||||||
|
```
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
All options are optional. Call `setup()` only if you want to customize:
|
||||||
|
|
||||||
|
```lua
|
||||||
|
require("tiny-spark").setup({
|
||||||
|
threshold = 5, -- minimum line distance to trigger
|
||||||
|
duration = 150, -- fade duration in ms
|
||||||
|
width = 8, -- flash width in columns
|
||||||
|
hl = "CurSearch", -- highlight group
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
## How it works
|
||||||
|
|
||||||
|
On `CursorMoved`, the plugin compares the current cursor line to the
|
||||||
|
previous one. If the distance exceeds the threshold, it opens a small
|
||||||
|
floating window at the cursor position and fades it out by increasing
|
||||||
|
`winblend` from 0 to 100 over the configured duration.
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
[MIT](LICENSE)
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
*tiny-spark.txt* Cursor jump flash animation
|
||||||
|
|
||||||
|
Author: Stephen Waits <https://github.com/swaits>
|
||||||
|
License: MIT
|
||||||
|
|
||||||
|
==============================================================================
|
||||||
|
CONTENTS *tiny-spark-contents*
|
||||||
|
|
||||||
|
1. Introduction ............................ |tiny-spark-introduction|
|
||||||
|
2. Configuration ........................... |tiny-spark-configuration|
|
||||||
|
|
||||||
|
==============================================================================
|
||||||
|
1. INTRODUCTION *tiny-spark-introduction*
|
||||||
|
|
||||||
|
tiny-spark.nvim flashes a brief highlight at the cursor position after
|
||||||
|
large jumps, making it easy for your eye to follow the cursor.
|
||||||
|
|
||||||
|
==============================================================================
|
||||||
|
2. CONFIGURATION *tiny-spark-configuration*
|
||||||
|
|
||||||
|
*tiny-spark.setup()*
|
||||||
|
setup({opts})
|
||||||
|
|
||||||
|
Optional. All options shown with defaults: >lua
|
||||||
|
|
||||||
|
require("tiny-spark").setup({
|
||||||
|
threshold = 5, -- minimum line distance to trigger
|
||||||
|
duration = 150, -- fade duration in ms
|
||||||
|
width = 8, -- flash width in columns
|
||||||
|
hl = "CurSearch", -- highlight group
|
||||||
|
})
|
||||||
|
<
|
||||||
|
Fields: ~
|
||||||
|
{threshold} (number) Minimum line jump to trigger flash. Default: 5
|
||||||
|
{duration} (number) Fade-out duration in milliseconds. Default: 150
|
||||||
|
{width} (number) Width of flash in columns. Default: 8
|
||||||
|
{hl} (string) Highlight group. Default: "CurSearch"
|
||||||
|
|
||||||
|
==============================================================================
|
||||||
|
vim:tw=78:ts=8:ft=help:norl:
|
||||||
@@ -0,0 +1,92 @@
|
|||||||
|
local M = {}
|
||||||
|
|
||||||
|
function M.setup(opts)
|
||||||
|
opts = opts or {}
|
||||||
|
local threshold = opts.threshold or 3
|
||||||
|
local duration = opts.duration or 50
|
||||||
|
local step = math.ceil(1000 / 60)
|
||||||
|
local prev = { 0, 0 }
|
||||||
|
local ns = vim.api.nvim_create_namespace("tiny-spark")
|
||||||
|
|
||||||
|
local trail_chars = opts.chars or { "░", "▒", "▓", "█" }
|
||||||
|
local palette = opts.palette
|
||||||
|
or {
|
||||||
|
{ fg = "#552200" },
|
||||||
|
{ fg = "#cc4400" },
|
||||||
|
{ fg = "#ff8822" },
|
||||||
|
{ fg = "#ffcc44" },
|
||||||
|
{ fg = "#ffffff", bold = true },
|
||||||
|
}
|
||||||
|
for i, def in ipairs(palette) do
|
||||||
|
vim.api.nvim_set_hl(0, "TinySpark" .. i, def)
|
||||||
|
end
|
||||||
|
|
||||||
|
vim.api.nvim_create_autocmd("CursorMoved", {
|
||||||
|
group = vim.api.nvim_create_augroup("tiny-spark", { clear = true }),
|
||||||
|
callback = function()
|
||||||
|
local cur = vim.api.nvim_win_get_cursor(0)
|
||||||
|
local dy = cur[1] - prev[1]
|
||||||
|
local dx = cur[2] - prev[2]
|
||||||
|
local dist = math.abs(dy)
|
||||||
|
local old_prev = { prev[1], prev[2] }
|
||||||
|
prev = cur
|
||||||
|
if dist < threshold then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local buf = vim.api.nvim_get_current_buf()
|
||||||
|
local line_count = vim.api.nvim_buf_line_count(buf)
|
||||||
|
local dir = dy > 0 and 1 or -1
|
||||||
|
|
||||||
|
-- Build trail from origin to destination
|
||||||
|
local trail = {}
|
||||||
|
for i = 0, dist - 1 do
|
||||||
|
local t = dist > 1 and i / (dist - 1) or 1
|
||||||
|
local row = old_prev[1] - 1 + dir * i
|
||||||
|
local col = old_prev[2] + math.floor(dx * t + 0.5)
|
||||||
|
if row >= 0 and row < line_count and col >= 0 then
|
||||||
|
table.insert(trail, { row = row, col = col })
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local elapsed = 0
|
||||||
|
local timer = vim.uv.new_timer()
|
||||||
|
timer:start(
|
||||||
|
0,
|
||||||
|
step,
|
||||||
|
vim.schedule_wrap(function()
|
||||||
|
elapsed = elapsed + step
|
||||||
|
vim.api.nvim_buf_clear_namespace(buf, ns, 0, -1)
|
||||||
|
|
||||||
|
if elapsed >= duration or not vim.api.nvim_buf_is_valid(buf) or #trail == 0 then
|
||||||
|
timer:stop()
|
||||||
|
if not timer:is_closing() then
|
||||||
|
timer:close()
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Shrink trail from origin end (remove the dark/far end first)
|
||||||
|
local progress = elapsed / duration
|
||||||
|
local drop = math.floor(#trail * progress)
|
||||||
|
local start = drop + 1
|
||||||
|
|
||||||
|
for i = start, #trail do
|
||||||
|
local p = trail[i]
|
||||||
|
-- t=0 at start of visible trail (dimmest), t=1 at destination (brightest)
|
||||||
|
local t = (#trail - start) > 0 and (i - start) / (#trail - start) or 1
|
||||||
|
local char_idx = math.max(1, math.min(#trail_chars, math.ceil(t * #trail_chars)))
|
||||||
|
local hl_idx = math.max(1, math.min(#palette, math.ceil(t * #palette)))
|
||||||
|
pcall(vim.api.nvim_buf_set_extmark, buf, ns, p.row, 0, {
|
||||||
|
virt_text = { { trail_chars[char_idx], "TinySpark" .. hl_idx } },
|
||||||
|
virt_text_pos = "overlay",
|
||||||
|
virt_text_win_col = p.col,
|
||||||
|
})
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
)
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
return M
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
require("tiny-spark").setup()
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
-- Minimal init for testing tiny-spark.nvim
|
||||||
|
vim.opt.rtp:prepend(".")
|
||||||
|
vim.opt.rtp:prepend("deps/mini.nvim")
|
||||||
|
vim.cmd("runtime plugin/tiny-spark.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,24 @@
|
|||||||
|
local T = MiniTest.new_set()
|
||||||
|
local eq = MiniTest.expect.equality
|
||||||
|
|
||||||
|
T["setup"] = MiniTest.new_set()
|
||||||
|
|
||||||
|
T["setup"]["creates augroup"] = function()
|
||||||
|
local groups = vim.api.nvim_get_autocmds({ group = "tiny-spark" })
|
||||||
|
eq(#groups > 0, true)
|
||||||
|
end
|
||||||
|
|
||||||
|
T["setup"]["is idempotent"] = function()
|
||||||
|
require("tiny-spark").setup()
|
||||||
|
require("tiny-spark").setup()
|
||||||
|
local groups = vim.api.nvim_get_autocmds({ group = "tiny-spark" })
|
||||||
|
eq(#groups > 0, true)
|
||||||
|
end
|
||||||
|
|
||||||
|
T["setup"]["respects custom threshold"] = function()
|
||||||
|
require("tiny-spark").setup({ threshold = 10 })
|
||||||
|
local groups = vim.api.nvim_get_autocmds({ group = "tiny-spark" })
|
||||||
|
eq(#groups > 0, true)
|
||||||
|
end
|
||||||
|
|
||||||
|
return T
|
||||||
Reference in new issue
Block a user