fix(buffer): conceal in all modes, forge EOL labels, remove dash prefix (#167)

* fix(buffer): keep conceal active in all modes and add `%l` EOL forge labels

Problem: `concealcursor` was missing `i` and `v`, so concealed text
(task IDs, forge tokens) leaked in insert and visual modes. Forge
labels only rendered for the first span when multiple refs existed.

Solution: set `concealcursor = 'nicv'` to keep conceal in all modes.
Add `%l` EOL format specifier that renders all forge spans with
independent highlights. Update default `eol_format` to include `%l`.

* refactor: remove `- ` prefix from task line rendering

Problem: task lines rendered as `- [ ] description` with a redundant
markdown list marker prefix that added visual noise.

Solution: render task lines as `[ ] description` instead. Update all
line generation in `views.lua`, parsing patterns in `buffer.lua`,
`diff.lua`, `textobj.lua`, syntax rules, and corresponding specs.
This commit is contained in:
Barrett Ruth 2026-03-15 13:22:01 -04:00 committed by GitHub
parent 1266eaedd8
commit 98e4abffc7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
12 changed files with 156 additions and 141 deletions

View file

@ -22,11 +22,11 @@ describe('diff', function()
it('parses headers and tasks', function()
local lines = {
'# School',
'/1/- [ ] Do homework',
'/2/- [!] Read chapter 5',
'/1/[ ] Do homework',
'/2/[!] Read chapter 5',
'',
'# Errands',
'/3/- [ ] Buy groceries',
'/3/[ ] Buy groceries',
}
local result = diff.parse_buffer(lines)
assert.are.equal(6, #result)
@ -45,7 +45,7 @@ describe('diff', function()
it('handles new tasks without ids', function()
local lines = {
'# Inbox',
'- [ ] New task here',
'[ ] New task here',
}
local result = diff.parse_buffer(lines)
assert.are.equal(2, #result)
@ -57,7 +57,7 @@ describe('diff', function()
it('inline cat: token overrides header category', function()
local lines = {
'# Inbox',
'/1/- [ ] Buy milk cat:Work',
'/1/[ ] Buy milk cat:Work',
}
local result = diff.parse_buffer(lines)
assert.are.equal(2, #result)
@ -68,7 +68,7 @@ describe('diff', function()
it('extracts rec: token from buffer line', function()
local lines = {
'# Inbox',
'/1/- [ ] Take trash out rec:weekly',
'/1/[ ] Take trash out rec:weekly',
}
local result = diff.parse_buffer(lines)
assert.are.equal('weekly', result[2].recur)
@ -77,7 +77,7 @@ describe('diff', function()
it('extracts rec: with completion mode', function()
local lines = {
'# Inbox',
'/1/- [ ] Water plants rec:!daily',
'/1/[ ] Water plants rec:!daily',
}
local result = diff.parse_buffer(lines)
assert.are.equal('daily', result[2].recur)
@ -87,7 +87,7 @@ describe('diff', function()
it('inline due: token is parsed', function()
local lines = {
'# Inbox',
'/1/- [ ] Buy milk due:2026-03-15',
'/1/[ ] Buy milk due:2026-03-15',
}
local result = diff.parse_buffer(lines)
assert.are.equal(2, #result)
@ -100,8 +100,8 @@ describe('diff', function()
it('creates new tasks from buffer lines', function()
local lines = {
'# Inbox',
'- [ ] First task',
'- [ ] Second task',
'[ ] First task',
'[ ] Second task',
}
diff.apply(lines, s)
s:load()
@ -117,7 +117,7 @@ describe('diff', function()
s:save()
local lines = {
'# Inbox',
'/1/- [ ] Keep me',
'/1/[ ] Keep me',
}
diff.apply(lines, s)
s:load()
@ -133,7 +133,7 @@ describe('diff', function()
s:save()
local lines = {
'# Inbox',
'/1/- [ ] Renamed',
'/1/[ ] Renamed',
}
diff.apply(lines, s)
s:load()
@ -147,7 +147,7 @@ describe('diff', function()
s:save()
local lines = {
'# Inbox',
'/1/- [ ] Renamed',
'/1/[ ] Renamed',
}
diff.apply(lines, s)
s:load()
@ -161,8 +161,8 @@ describe('diff', function()
s:save()
local lines = {
'# Inbox',
'/1/- [ ] Original',
'/1/- [ ] Copy of original',
'/1/[ ] Original',
'/1/[ ] Copy of original',
}
diff.apply(lines, s)
s:load()
@ -175,7 +175,7 @@ describe('diff', function()
s:save()
local lines = {
'# Work',
'/1/- [ ] Moving task',
'/1/[ ] Moving task',
}
diff.apply(lines, s)
s:load()
@ -188,7 +188,7 @@ describe('diff', function()
s:save()
local lines = {
'# Inbox',
'/1/- [ ] Stable task',
'/1/[ ] Stable task',
}
diff.apply(lines, s)
s:load()
@ -204,7 +204,7 @@ describe('diff', function()
s:save()
local lines = {
'# Inbox',
'/1/- [ ] Pay bill',
'/1/[ ] Pay bill',
}
diff.apply(lines, s)
s:load()
@ -217,7 +217,7 @@ describe('diff', function()
s:save()
local lines = {
'# Inbox',
'/1/- [ ] Pay bill due:2026-04-01',
'/1/[ ] Pay bill due:2026-04-01',
}
diff.apply(lines, s)
s:load()
@ -228,7 +228,7 @@ describe('diff', function()
it('stores recur field on new tasks from buffer', function()
local lines = {
'# Inbox',
'- [ ] Take out trash rec:weekly',
'[ ] Take out trash rec:weekly',
}
diff.apply(lines, s)
s:load()
@ -242,7 +242,7 @@ describe('diff', function()
s:save()
local lines = {
'# Todo',
'/1/- [ ] Task rec:weekly',
'/1/[ ] Task rec:weekly',
}
diff.apply(lines, s)
s:load()
@ -255,7 +255,7 @@ describe('diff', function()
s:save()
local lines = {
'# Todo',
'/1/- [ ] Task',
'/1/[ ] Task',
}
diff.apply(lines, s)
s:load()
@ -266,7 +266,7 @@ describe('diff', function()
it('parses rec: with completion mode prefix', function()
local lines = {
'# Inbox',
'- [ ] Water plants rec:!weekly',
'[ ] Water plants rec:!weekly',
}
diff.apply(lines, s)
s:load()
@ -278,7 +278,7 @@ describe('diff', function()
it('returns forge refs for new tasks', function()
local lines = {
'# Inbox',
'- [ ] Fix bug gh:user/repo#42',
'[ ] Fix bug gh:user/repo#42',
}
local refs = diff.apply(lines, s)
assert.are.equal(1, #refs)
@ -303,7 +303,7 @@ describe('diff', function()
s:save()
local lines = {
'# Todo',
'/1/- [ ] Fix bug gh:user/repo#99',
'/1/[ ] Fix bug gh:user/repo#99',
}
local refs = diff.apply(lines, s)
assert.are.equal(1, #refs)
@ -327,7 +327,7 @@ describe('diff', function()
s:save()
local lines = {
'# Todo',
'/1/- [ ] Fix bug gh:user/repo#42',
'/1/[ ] Fix bug gh:user/repo#42',
}
local refs = diff.apply(lines, s)
assert.are.equal(0, #refs)
@ -336,7 +336,7 @@ describe('diff', function()
it('returns empty for tasks without forge refs', function()
local lines = {
'# Inbox',
'- [ ] Plain task',
'[ ] Plain task',
}
local refs = diff.apply(lines, s)
assert.are.equal(0, #refs)
@ -359,8 +359,8 @@ describe('diff', function()
s:save()
local lines = {
'# Todo',
'/1/- [ ] Fix bug gh:user/repo#42',
'/1/- [ ] Fix bug gh:user/repo#42',
'/1/[ ] Fix bug gh:user/repo#42',
'/1/[ ] Fix bug gh:user/repo#42',
}
local refs = diff.apply(lines, s)
assert.are.equal(1, #refs)
@ -372,7 +372,7 @@ describe('diff', function()
s:save()
local lines = {
'# Inbox',
'/1/- [ ] Task name',
'/1/[ ] Task name',
}
diff.apply(lines, s)
s:load()
@ -383,7 +383,7 @@ describe('diff', function()
it('sets priority from +!! token', function()
local lines = {
'# Inbox',
'- [ ] Pay bills +!!',
'[ ] Pay bills +!!',
}
diff.apply(lines, s)
s:load()
@ -396,7 +396,7 @@ describe('diff', function()
s:save()
local lines = {
'# Inbox',
'/1/- [!] Task name',
'/1/[!] Task name',
}
diff.apply(lines, s)
s:load()
@ -407,7 +407,7 @@ describe('diff', function()
it('parses metadata with forge ref on same line', function()
local lines = {
'# Inbox',
'- [ ] Fix bug due:2026-03-15 gh:user/repo#42',
'[ ] Fix bug due:2026-03-15 gh:user/repo#42',
}
diff.apply(lines, s)
s:load()