Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 1 addition & 10 deletions .github/scripts/setup-link-preview-tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,7 @@ set -euo pipefail

install_dir="${1:?Usage: setup-link-preview-tests.sh INSTALL_DIR}"
script_dir="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
snacks_revision=$(python3 -c 'import json, sys; print(json.load(open(sys.argv[1]))["snacks.nvim"]["commit"])' \
"$script_dir/../../nvim/.config/nvim/lazy-lock.json")
neovim_version=v0.11.5
bash "$script_dir/setup-neovim-tests.sh" "$install_dir"
html_revision=73a3947324f6efddf9e17c0ea58d454843590cc02
markdown_revision=f969cd3ae3f9fbd4e43205431d0ae286014c05b5

Expand All @@ -27,9 +25,6 @@ build_parser() {
-o "$parser_dir/$language.so"
}

download_archive \
"https://github.com/neovim/neovim/releases/download/$neovim_version/nvim-linux-x86_64.tar.gz" \
"$install_dir/nvim"
download_archive \
"https://github.com/tree-sitter/tree-sitter-html/archive/$html_revision.tar.gz" \
"$install_dir/html"
Expand All @@ -40,7 +35,3 @@ download_archive \
build_parser html "$install_dir/html/src"
build_parser markdown "$install_dir/markdown/tree-sitter-markdown/src"
build_parser markdown_inline "$install_dir/markdown/tree-sitter-markdown-inline/src"

download_archive \
"https://github.com/folke/snacks.nvim/archive/$snacks_revision.tar.gz" \
"$install_dir/snacks.nvim"
24 changes: 24 additions & 0 deletions .github/scripts/setup-neovim-tests.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#!/usr/bin/env bash
set -euo pipefail

install_dir="${1:?Usage: setup-neovim-tests.sh INSTALL_DIR}"
script_dir="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
snacks_revision=$(python3 -c 'import json, sys; print(json.load(open(sys.argv[1]))["snacks.nvim"]["commit"])' \
"$script_dir/../../nvim/.config/nvim/lazy-lock.json")
neovim_version=v0.11.5

download_archive() {
local url="$1"
local destination="$2"
mkdir -p "$destination"
curl --fail --silent --show-error --location --retry 2 "$url" \
| tar -xz --strip-components=1 -C "$destination"
}

download_archive \
"https://github.com/neovim/neovim/releases/download/$neovim_version/nvim-linux-x86_64.tar.gz" \
"$install_dir/nvim"

download_archive \
"https://github.com/folke/snacks.nvim/archive/$snacks_revision.tar.gz" \
"$install_dir/snacks.nvim"
2 changes: 2 additions & 0 deletions .github/workflows/test-link-preview.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ on:
- 'nvim/.config/nvim/lazy-lock.json'
- '.github/workflows/test-link-preview.yml'
- '.github/scripts/setup-link-preview-tests.sh'
- '.github/scripts/setup-neovim-tests.sh'
push:
branches: [main]
paths:
Expand All @@ -18,6 +19,7 @@ on:
- 'nvim/.config/nvim/lazy-lock.json'
- '.github/workflows/test-link-preview.yml'
- '.github/scripts/setup-link-preview-tests.sh'
- '.github/scripts/setup-neovim-tests.sh'

permissions:
contents: read
Expand Down
40 changes: 40 additions & 0 deletions .github/workflows/test-neovim.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
name: Test Neovim configuration

on:
pull_request:
paths:
- 'nvim/.config/nvim/init.lua'
- 'nvim/.config/nvim/lua/config/**'
- 'nvim/.config/nvim/lazy-lock.json'
- 'tests/daily-note.lua'
- '.github/workflows/test-neovim.yml'
- '.github/scripts/setup-neovim-tests.sh'
push:
branches: [main]
paths:
- 'nvim/.config/nvim/init.lua'
- 'nvim/.config/nvim/lua/config/**'
- 'nvim/.config/nvim/lazy-lock.json'
- 'tests/daily-note.lua'
- '.github/workflows/test-neovim.yml'
- '.github/scripts/setup-neovim-tests.sh'

permissions:
contents: read

concurrency:
group: neovim-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true

jobs:
test:
runs-on: ubuntu-24.04
timeout-minutes: 5
steps:
- uses: actions/checkout@v7
- name: Install test dependencies
run: |
bash .github/scripts/setup-neovim-tests.sh "$RUNNER_TEMP/neovim"
echo "$RUNNER_TEMP/neovim/nvim/bin" >> "$GITHUB_PATH"
- name: Test daily note editor state
run: SNACKS_TEST_DIR="$RUNNER_TEMP/neovim/snacks.nvim" nvim --headless -u NONE -l tests/daily-note.lua
26 changes: 26 additions & 0 deletions fish/.config/fish/functions/__daily_notes_dir.fish
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
function __daily_notes_dir --description 'Find the daily notes repository'
if set -q DAILY_NOTES_DIR; and test -n "$DAILY_NOTES_DIR"
if not test -d "$DAILY_NOTES_DIR"; or not test -f "$DAILY_NOTES_DIR/justfile"
echo 'DAILY_NOTES_DIR must point to a directory containing a justfile.' >&2
return 1
end
path resolve -- "$DAILY_NOTES_DIR"
return
end

set -l source_file (path resolve -- (status filename))
set -l parent (path resolve -- (path dirname -- "$source_file")/../../../../..)
set -l matches
for justfile in "$parent"/*/justfile
set -l recipes (command just --justfile "$justfile" --summary 2>/dev/null | string split ' ')
if contains -- daily $recipes
set -a matches (path dirname -- "$justfile")
end
end

if test (count $matches) -ne 1
echo 'Expected one sibling directory with a daily recipe. Set DAILY_NOTES_DIR to choose explicitly.' >&2
return 1
end
printf '%s\n' "$matches[1]"
end
4 changes: 4 additions & 0 deletions fish/.config/fish/functions/daily.fish
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
function daily --description 'Open today’s note using the configured daily recipe'
set -l directory (__daily_notes_dir); or return 1
DAILY_NOTE_PROSE=1 command just --justfile "$directory/justfile" --working-directory "$directory" daily $argv
end
10 changes: 10 additions & 0 deletions nvim/.config/nvim/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,13 @@ require("config.lazy")
vim.filetype.add({
extension = { pkl = "pkl" },
})

if vim.env.DAILY_NOTE_PROSE == "1" then
vim.env.DAILY_NOTE_PROSE = nil
vim.api.nvim_create_autocmd("VimEnter", {
once = true,
callback = function()
require("config.prose").enable()
end,
})
end
44 changes: 25 additions & 19 deletions nvim/.config/nvim/lua/config/keymaps.lua
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,30 @@

local map = vim.keymap.set

map("n", "<leader>nd", function()
local result = vim.system({
"fish", "-c",
'__daily_notes_dir; and printf "%s\\n" "$DAILY_NOTES_FORMAT"',
}, { text = true }):wait()
if result.code ~= 0 then
vim.notify(vim.trim(result.stderr), vim.log.levels.ERROR)
return
end
local settings = vim.split(result.stdout, "\n", { plain = true })
local directory, format = settings[1], settings[2]
if not format or format == "" then
vim.notify("Set the Fish universal variable DAILY_NOTES_FORMAT to the relative note date format.", vim.log.levels.WARN)
return
end

local path = vim.fs.joinpath(directory, os.date(format))
vim.fn.mkdir(vim.fs.dirname(path), "p")
if vim.fn.bufnr(path) ~= vim.api.nvim_get_current_buf() then
vim.api.nvim_cmd({ cmd = "edit", args = { path }, magic = { file = false, bar = false } }, {})
end
require("config.prose").enable()
end, { desc = "Open Daily Note" })

map("n", "<leader>gd", function()
Snacks.terminal({ "gh", "dash" }, { win = { position = "float" } })
end, { desc = "GitHub Dashboard" })
Expand All @@ -12,23 +36,5 @@ map("n", "<leader>bo", "<cmd>BufOnly<cr>", { desc = "Delete all other buffers" }
map("n", "<leader>yp", "<cmd>let @+ = expand('%:p')<cr>", { desc = "Copy absolute path to clipboard" })

map("n", "<leader>p", function()
Snacks.zen({
toggles = { dim = false, git_signs = false, mini_diff_signs = false },
win = {
width = 90,
wo = {
wrap = true,
linebreak = true,
breakindent = true,
spell = true,
number = false,
relativenumber = false,
signcolumn = "no",
foldcolumn = "0",
cursorline = false,
colorcolumn = "",
list = false,
},
},
})
require("config.prose").toggle()
end, { desc = "Toggle Prose Mode" })
37 changes: 37 additions & 0 deletions nvim/.config/nvim/lua/config/prose.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
local M = {}
local prose_win

function M.toggle()
prose_win = Snacks.zen({
toggles = { dim = false, git_signs = false, mini_diff_signs = false },
win = {
width = 90,
wo = {
wrap = true,
linebreak = true,
breakindent = true,
spell = true,
number = false,
relativenumber = false,
signcolumn = "no",
foldcolumn = "0",
cursorline = false,
colorcolumn = "",
list = false,
},
},
})
end

function M.enable()
local win = Snacks.zen.win
if win and win:valid() then
if win == prose_win then
return
end
win:close()
end
M.toggle()
end

return M
69 changes: 69 additions & 0 deletions tests/daily-note.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
local root = vim.fn.fnamemodify(debug.getinfo(1, "S").source:sub(2), ":p:h:h")
vim.opt.rtp:prepend(root .. "/nvim/.config/nvim")
vim.opt.rtp:prepend(vim.env.SNACKS_TEST_DIR or vim.fn.stdpath("data") .. "/lazy/snacks.nvim")
require("snacks").setup({})
vim.o.hidden = true
vim.o.columns = 140

local directory = vim.fn.tempname()
vim.fn.mkdir(directory, "p")

-- Keep repository discovery outside these editor-state regression tests.
vim.system = function()
return {
wait = function()
return { code = 0, stdout = directory .. "\n%Y-%m-%d.md\n" }
end,
}
end
require("config.keymaps")
local daily
for _, map in ipairs(vim.api.nvim_get_keymap("n")) do
if map.desc == "Open Daily Note" then
daily = map.callback
end
end
assert(daily, "daily note mapping was not registered")

local function assert_prose()
assert(Snacks.zen.win and Snacks.zen.win:valid(), "prose window is missing")
assert(vim.wo.wrap and vim.wo.linebreak and vim.wo.spell, "prose options were not applied")
assert(not vim.wo.number and not vim.wo.relativenumber, "line numbers are still enabled")
assert(vim.api.nvim_win_get_width(0) == 90, "prose window has the wrong width")
end

local function run()
vim.api.nvim_cmd({ cmd = "edit", args = { directory .. "/" .. os.date("%Y-%m-%d.md") } }, {})
local note = vim.api.nvim_get_current_buf()
vim.api.nvim_buf_set_lines(note, 0, -1, false, { "unsaved daily note" })
daily()
assert(vim.api.nvim_get_current_buf() == note, "daily shortcut replaced the note buffer")
assert(vim.bo.modified and vim.api.nvim_get_current_line() == "unsaved daily note", "unsaved text was lost")
assert_prose()
local prose_window = vim.api.nvim_get_current_win()
daily()
assert(vim.api.nvim_get_current_win() == prose_window, "repeated shortcut recreated prose mode")
Snacks.zen.win:close()

for _, mode in ipairs({ "zoom", "zen" }) do
vim.cmd.enew()
vim.wo.wrap = false
vim.wo.spell = false
Snacks.zen[mode]()
daily()
assert(vim.api.nvim_get_current_buf() == note, mode .. " did not open the existing note")
assert(vim.bo.modified and vim.api.nvim_get_current_line() == "unsaved daily note", "hidden note edits were lost")
assert_prose()
require("config.prose").toggle()
assert(not (Snacks.zen.win and Snacks.zen.win:valid()), "prose toggle did not close the window")
end
end

local ok, err = xpcall(run, debug.traceback)
vim.fn.delete(directory, "rf")
if not ok then
io.stderr:write(err .. "\n")
vim.cmd("cquit 1")
end
print("Daily note regression tests passed")
vim.cmd("qa!")