feat(cli): de-gutter homogeneous container listings (TTY only) - #368
feat(cli): de-gutter homogeneous container listings (TTY only)#368mikegreiling wants to merge 2 commits into
Conversation
38cc83b to
5f852ae
Compare
Rebased onto
|
The ratified per-view law: a row keeps its uuid gutter iff its title is not a first-class handle for acting on it. Container titles ARE first-class refs (name resolution + the liveness law + the fused fallback), so three homogeneous listings shed the gutter and disambiguate colliding live twins with the fused `Title [8charPrefix]` suffix instead: - `things areas` → `⬡ Family`, fused `⬡ Split [8char]` on a live twin - `things projects` (sidebar) → `( ) ★ New Stuff ‹8/8› #home`, twins fused - `things project show` heading subheads → `Backlog`, `Dup [8char]` on a within-project title collision (project-scoped predicate) All three reuse the shared promotion machinery (new `fusedTitleSuffix` over the render-time RefPromoter/roundTrips — the SAME predicate JSON `*Uuid` emission, the inline container hints, and the `≡` canonical-ref echo consult; no fork). formatItem gains `noGutter` + `selfRef` opts; the fused suffix rides the FIXED tail so it survives width truncation. Untouched (locked by tests): mixed item views (today/inbox/anytime/someday/ upcoming, area-show + project-show CHILD rows, search) keep per-view gutters on every row; to-do rows keep gutters everywhere; trash and logbook keep gutters; the predicate is liveness-scoped (a trashed same-title twin never promotes); `--json` is byte-identical (human-render-only change). Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RYbJensXxHpJK1v1VDXYUD
…rojects --area, anytime/someday headings)
The shipped law ("mixed item VIEWS keep gutters on every row") was drawn one
level too coarse — `things area Family` still showed the uuid gutter on its
PROJECT rows. Ratified refinement: gutters are per-SECTION, not per-view. A
section/block whose rows are ALL containers renders bare titles with the fused
`[8charPrefix]` on promotion (same shared predicate); any list that intermixes
to-do rows keeps the gutter on every row in it.
Newly de-guttered under the refined law (all via the existing noGutter/selfRef
+ fusedTitleSuffix machinery — no fork):
- `things area show <ref>` (and the `loose` pseudo-area): the PROJECTS section
and the Someday-projects block. The direct-to-dos block and the mixed
Upcoming section keep gutters (they contain to-dos).
- `things projects --area <ref>`: the flat area-scoped listing (new
`renderContainerList`); the `(Area)` suffix stays (no header names the scope).
- Group-HEADING renders (underlined project titles heading their children) in
`things anytime` / `things someday` — headers, not rows. `project show`
heading subheads were already de-guttered; this brings the anytime/someday
headings to the same law. Child to-do rows under a heading keep gutters.
Width stays computed over the whole card/view, so the guttered to-do rows are
byte-identical (the de-guttered project rows remain in the width set they no
longer draw from). `--json` byte-identical (human-render-only).
Tests: flipped the area-show project-row unit test to assert plain de-guttered
rows; added e2e coverage for the area-show projects section, `projects --area`,
and anytime headings (fused-on-collision, child/direct rows stay guttered);
byte-identity + gutter-lock tests stay green. CHANGELOG + `things-cli` SKILL.md
updated to the per-SECTION law.
Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RYbJensXxHpJK1v1VDXYUD
5f852ae to
c6a1b6b
Compare
|
Re-rebased onto |
What & why
TTY listings shed the redundant left uuid gutter where a container's title is already a first-class write handle, disambiguating a colliding LIVE twin with the fused
Title [8charPrefix]suffix instead.Ratified refinement (this revision). The first cut drew the law per-VIEW ("mixed item views keep gutters on every row"), which was one level too coarse —
things area Familystill showed the uuid gutter on its PROJECT rows. The law is now per-SECTION:TTY presentation only —
--jsonis byte-identical (verified by a TTY-vs-piped byte-identity test). The gutter width is still computed over the whole card/view, so the guttered to-do rows are byte-identical (the de-guttered project rows stay in the width set they no longer draw from).Before / after (real CLI output, synthetic fixture)
things area show Family— the reported bug (projects section)Count chip / tags intact; the area name stays suppressed (the card header names it). The
loosepseudo-area view follows the same path.things projects --area Family(the flagged flat variant — now resolved)De-guttered, but the
(Family)context suffix STAYS — no── ⬡ Family ──header precedes these rows, so it is the row's sole area label.things anytime— group HEADINGS de-gutter, children keep gutters(
things areasandthings projectssidebar were de-guttered in the first commit and are unchanged here.)Audit — every TTY section classified (view → section → verdict)
things areasthings projects(sidebar)things projects --area <ref>things area show <ref>things area show <ref>things area show <ref>things area show <ref>things area show <ref>things project show <ref>things project show <ref>things anytimethings anytimethings somedaythings somedaythings somedaythings today/--eveningthings upcomingthings inboxthings searchthings logbookthings trashGroup-HEADING note. The underlined project titles that head their own children ARE headers, not rows:
project showsubheads were already de-guttered (1st commit); theanytimeandsomeday(From-active-projects) headings carried a gutter and are de-guttered here.renderSections— the type-correct SidebarSection[] fallback that is never reached in TTY (anytime/someday always hand back precomputed lines) but is still exercised directly by unit tests — was kept consistent withrenderAnytimePreviewso the two never diverge.Untouched (locked by tests)
--jsonbyte-identical (TTY-vs-piped comparison, elapsedMs normalized).Shared machinery (no fork)
fusedTitleSuffix(ref, kind, projectUuid?)andformatItem'snoGutter+selfRefopts (1st commit) drive every de-guttered section, over the SAME render-timeRefPromoter/roundTripspredicate the JSON*Uuidemission, the inline container hints, and the≡canonical-ref echo consult. New this revision:renderContainerList(the de-guttered counterpart torenderListfor a flat all-container list), andnoGutter/selfRefthreaded through the area-show projects section and the anytime/someday/renderSections headings.Files
src/cli/commands/area.ts— area-show projects section (+ someday-projects block) de-guttersrc/cli/commands/reads.ts—projects --arearoutes throughrenderContainerListsrc/cli/render.ts—renderContainerList;renderAnytimePreview/renderSections/renderSomedayPreviewheading de-gutter (plus 1st-commitfusedTitleSuffix/noGutter/selfRef/ sidebar)src/cli/commands/project.ts— heading section-header de-gutter (1st commit)test/cli/e2e.test.ts— area-show /projects --area/ anytime coverage (+ 1st-commit areas/projects/heading/liveness/byte-identity)test/cli/render.test.ts— area-show project-row unit test flipped to de-guttered plain rowstest/unit/render-styling.test.ts—noGutter+selfRefmechanics (1st commit)CHANGELOG.md,skills/things-cli/SKILL.mdFlagged (did not improvise)
render-language.md/width-aware-tty.md) still describe the id column as always-present fixed furniture. Not in the ratified cascade, so left unedited — you may want the per-SECTION gutter law recorded there.things someday's "own" block lists someday projects FIRST then direct to-dos; because they share one truncation block that CAN contain to-dos, it is treated as a mixed block and KEEPS gutters (rather than de-guttering a project-only leading sub-run). Called out in case you want that leading run treated as its own pure-container block.🤖 Generated with Claude Code