Commit Graph

310 Commits

Author SHA1 Message Date
d4f6efd1c0 fix(upgrade): errors from Rust 2024 edition
- gen is a reserved keyword (→ renamed module to generator)
- ref in patterns with implicit borrowing (→ removed ref)
- & pattern with implicit borrowing (→ added & to outer pattern)
2026-04-11 00:38:30 -07:00
ee6739158e chore: update cargo files more 2026-04-11 00:31:43 -07:00
537819577a chore: update version 2026-04-11 00:28:00 -07:00
b2d30d5a20 feat: cargo dist info 2026-04-11 00:15:42 -07:00
a8dbb86d4f chore: disable lfs 2026-04-11 00:08:03 -07:00
4583b59520 chore: update casts and support scripts 2026-04-11 00:08:02 -07:00
21a5ea9d55 chore: update demo.gif 2026-04-11 00:08:02 -07:00
1817494db2 chore: update app initialization and example data
Update application initialization and example data.

- `App::new` now recomputes formulas on startup to ensure formula-derived
  values are available immediately.
- Updated `examples/demo.improv` to reflect changes in formula and category
  structure.

Co-Authored-By: fiddlerwoaroof/git-smart-commit (unsloth/gemma-4-26B-A4B-it-GGUF:UD-Q5_K_XL)
2026-04-11 00:08:02 -07:00
c701534053 refactor(persistence): improve Markdown formula and category handling
Update persistence logic for formulas and categories.

- Formulas targeting `_Measure` no longer include the category suffix in
  Markdown.
- `_Measure` items are now excluded from the category section in Markdown
  to avoid duplication with the formulas section.
- Improved Markdown parsing to correctly handle formulas without an
  explicit category suffix, defaulting them to `_Measure` .
- Added logic to skip virtual index and dimension categories during
  persistence.

Co-Authored-By: fiddlerwoaroof/git-smart-commit (unsloth/gemma-4-26B-A4B-it-GGUF:UD-Q5_K_XL)
2026-04-11 00:08:02 -07:00
7fea5f67ed refactor(command): improve formula commitment and buffer management
Refactor command execution and buffer management.

- `CommitFormula` now defaults to targeting `_Measure` .
- `CommitFormula` no longer automatically clears the buffer; buffer
  clearing is now handled by keymap sequences.
- Added `ClearBufferCmd` to the command registry.
- Updated `AddFormulaCmd` to support optional target category.
- Added `SetBuffer` effect to allow clearing buffers.

Co-Authored-By: fiddlerwoaroof/git-smart-commit (unsloth/gemma-4-26B-A4B-it-GGUF:UD-Q5_K_XL)
2026-04-11 00:08:02 -07:00
c3fb8669c2 feat(command): add keymap inheritance and sequence bindings
Implement keymap inheritance and sequence bindings.

- Added `parent` field to `Keymap` to support Emacs-style inheritance.
- Implemented `lookup` in `Keymap` to fall through to parent keymaps.
- Added `bind_seq` to allow multiple commands to be bound to a single key
  pattern.
- Refactored existing keymaps to use sequences for common patterns like
  Esc/Enter/Tab to clear buffers and change modes.

Co-Authored-By: fiddlerwoaroof/git-smart-commit (unsloth/gemma-4-26B-A4B-it-GGUF:UD-Q5_K_XL)
2026-04-11 00:08:01 -07:00
c8b9d29690 feat(model): introduce virtual '_Measure' category for formulas
Refactor formula handling to use a virtual '_Measure' category.

- Formulas now default to targeting '_Measure' if no category is specified.
- '_Measure' items are dynamically computed from existing data items and
  formula targets, preventing redundant item storage.
- Updated persistence to handle '_Measure' formulas and items correctly in
  Markdown.
- Updated UI and model to use 'effective_item_names' for layout and item
  resolution.
- Updated tests to reflect the new '_Measure' behavior.

Co-Authored-By: fiddlerwoaroof/git-smart-commit (unsloth/gemma-4-26B-A4B-it-GGUF:UD-Q5_K_XL)
2026-04-11 00:08:01 -07:00
1690fc317b test: use generic category name in formula parser tests
Replace "Measure" with "Foo" as target_category in formula parser
tests so they don't depend on a specific category name convention.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

Executed-By: spot
2026-04-11 00:08:01 -07:00
07c8f4a40a docs: update repo-map and design-principles for pest parser
- Document PEG grammar as single source of truth for .improv format
- Update file format section with v2025-04-09 syntax: version line,
  Initial View, pipe quoting, Views→Formulas→Categories→Data order
- Add pipe quoting convention and grammar-driven testing principles
- Update file inventory (persistence: 124+2291 lines, 83 tests)
- Add pest/pest_meta to dependency table
- Update persistence testing guidance for grammar-walking generator

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

Executed-By: spot
2026-04-11 00:08:01 -07:00
70e7cfbef7 chore: update gitignore and claude instructions 2026-04-11 00:08:01 -07:00
d34e8eb313 feat: replace ad-hoc .improv parser with pest grammar
- Add improv.pest PEG grammar as the single source of truth for the
  .improv file format (v2025-04-09)
- Replace hand-written line scanner with pest-derived parser that walks
  the grammar's parse tree
- Add grammar-walking test generator that reads improv.pest at test time
  via pest_meta and produces random valid files from the AST
- Fix 6 parser bugs: newlines in text, commas in names, brackets in
  names, float precision, view name ambiguity, group brackets
- New format: version line, Initial View header, pipe quoting (|...|),
  Views→Formulas→Categories→Data section order, comma-separated items
- Bare names restricted to [A-Za-z_][A-Za-z0-9_-]*, everything else
  pipe-quoted with \| \\ \n escapes
- Remove all unwrap() calls from production code, propagate errors
  with Result throughout parse_md
- Extract shared escape_pipe/unescape_pipe/pipe_quote helpers, deduplicate
  hidden/collapsed formatting, add w!() macro for infallible writeln

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

Executed-By: spot
2026-04-11 00:08:00 -07:00
4d7d91257d refactor: colocate cmd tests with their modules
Move tests from the monolithic tests.rs into #[cfg(test)] mod tests
blocks in each command module. Shared test helpers live in
mod.rs::test_helpers.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

Executed-By: fido
2026-04-11 00:08:00 -07:00
001744f5cf docs: update design-principles for _Measure and fixed-point eval
Add VirtualMeasure to CategoryKind description, document _Measure as
third always-present virtual category, add section on fixed-point
formula evaluation strategy.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 00:08:00 -07:00
326e245c48 docs: update repo-map for _Measure, CellValue::Error, fixed-point eval
Reflect _Measure virtual category, VirtualMeasure kind, CellValue::Error
variant, recompute_formulas fixed-point cache, and add_formula auto-adding
target items.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 00:08:00 -07:00
afbcf7b3ff chore: update demo data for new format 2026-04-11 00:08:00 -07:00
e6c93a24d9 chore: some dep updates 2026-04-11 00:07:59 -07:00
23a876d556 feat: rename Measure to _Measure (virtual), add fixed-point formula eval
_Measure is now a virtual category (CategoryKind::VirtualMeasure),
created automatically in Model::new() alongside _Index and _Dim.
Formula targets are added as items automatically by add_formula.

Formula evaluation uses a fixed-point cache: recompute_formulas()
iterates evaluation of all formula cells until values stabilize,
resolving refs through the cache for formula values and raw data
aggregation for non-formula values. This fixes formulas that
reference other measures when hidden dimensions are present.

evaluate_aggregated now checks the formula cache instead of
recursively evaluating formulas, breaking the dependency between
formula evaluation and aggregation.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 00:07:59 -07:00
fd69126cdc refactor: split cmd.rs 2026-04-11 00:07:59 -07:00
767d524d4b unwind LFS for now 2026-04-11 00:07:59 -07:00
24c59fbf40 fix: Model::add_formula auto-adds target item; fix formula panel display
Model::add_formula now ensures the formula target exists as an item in
the target category (same fix as AddFormula effect, but at the model
level — covers file loading and headless paths).

Formula panel now shows raw formula text instead of debug-formatted
string with redundant target name and quotes.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 00:07:59 -07:00
4686f47026 fix: scroll tile bar to keep selected tile visible
When there are more tiles than fit in the available width, the tile
bar now auto-scrolls to ensure the selected tile is always visible.
Overflow indicators (◀ ▶) show when tiles exist beyond the visible
area. Scroll offset is computed fresh each frame from tile_cat_idx.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 00:07:58 -07:00
737d14a5c0 fix: add depth limit to formula evaluation, propagate errors
Circular or self-referencing formulas now return CellValue::Error
instead of stack overflowing. eval_expr uses Result<f64, String>
internally so errors (circular refs, div/0, missing refs) propagate
immediately through the expression tree via ?. The depth limit (16)
is checked per evaluate_depth call — normal 1-2 level chains are
unaffected.

Also adds CellValue::Error variant for displaying ERR:reason in the
grid, and handles it in format, persistence, and search.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 00:07:58 -07:00
32d215f3d6 fix: AddFormula now adds target item to category
When adding a formula interactively, the target (e.g. "Margin") was
registered as a formula but never added as an item to the target
category. The grid layout never created cells for it, making the
formula invisible. Now AddFormula::apply calls add_item before
registering the formula.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 00:07:58 -07:00
a61d7aa229 feat(demo): add asciinema casts for pivot, drill, formulas, import
Four recorded casts at 100x30 with 2s idle cap:
- pivot.cast: axis reassignment with tile mode
- drill.cast: drill-down into aggregated cells
- formulas.cast: formula panel and adding formulas
- import.cast: CSV import wizard walkthrough

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 00:07:58 -07:00
e00f2e032e feat(demo): add VHS demo tape and generated GIF
Create docs/demo.tape scripting a ~15s pivot axis reassignment demo.
Hide shell startup and quit so the GIF opens directly on the TUI.
Set up git-lfs for docs/*.gif. Merge LFS hooks with existing beads hooks.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 00:07:57 -07:00
280339ea10 feat(nix): add asciinema, vhs, and cargo-dist to dev shell
Add demo recording tools (asciinema, vhs) and release tooling
(cargo-dist) to nativeBuildInputs. Include a cargo-dist wrapper so
`cargo dist` works as a subcommand. Add scripts/record-demo.sh for
consistent asciinema cast recording at 100x30.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 00:07:57 -07:00
6239ac83ad chore: fmt + clippy 2026-04-11 00:07:57 -07:00
08df85664e feat: add examples/demo.csv and examples/demo.improv
40-row CSV with obviously-fake sales data (fictional companies like
Acme Corp, Wonka Industries, Cyberdyne Systems). demo.improv generated
via headless import with Profit formula and a default view showing
Region+Product on rows, Date_Month+Measure on columns. Added the
import command to the README quick-start section.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 00:07:57 -07:00
d3d1df0be2 docs: expand README with concrete details
Add dedicated sections for the data model (formula examples), views and
axes (tile mode, records mode, drill-down), the .improv file format
(annotated example), import wizard and headless scripting, and the
command/effect architecture. Link docs/design-notes.md from the "Why"
section. Update build instructions to use `nix build .`.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 00:07:57 -07:00
4751b800fd chore: remove stale SPEC.md, salvage vision into docs/design-notes.md
Audited SPEC.md against code — mostly accurate but redundant with
repo-map.md and design-principles.md. Minor drift in storage internals,
wizard step count, and mode representation. Salvaged product vision and
non-goals into docs/design-notes.md with staleness disclaimer.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 00:07:57 -07:00
ecd001e589 chore: add Apache-2.0 LICENSE file
Pulled from apache.org/licenses/LICENSE-2.0.txt.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 00:07:57 -07:00
3338601a6c chore: fix stale MIT reference in repo-map to Apache-2.0
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 00:07:57 -07:00
861b142dec chore: change license to Apache-2.0
Update both README and Cargo.toml.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 00:07:57 -07:00
769a5eb443 docs: write README for Show HN launch
All 10 sections per the launch plan: title, pitch, demo GIF placeholder,
Lotus Improv context, quick start, key bindings, installation (Nix/crates.io/
prebuilt), codebase overview, expectations disclaimer, license. Under 100
lines, no badges or TOC.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 00:07:56 -07:00
b610f7ad66 chore: update CLAUDe.md 2026-04-11 00:07:56 -07:00
ad9ea30fc2 test(csv): add RFC 4180 edge case tests for CSV quote handling
Audit confirms the csv crate correctly handles all RFC 4180 cases:
- Embedded commas in quoted fields
- Escaped quotes ("") within quoted fields
- Embedded newlines in quoted fields
- Combined commas + escaped quotes

No bugs found — added 4 regression tests to document compliance.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 00:07:56 -07:00
11bcc5d04d Merge branch 'main' of git.fiddlerwoaroof.com:u/edwlan/improvise 2026-04-11 00:07:48 -07:00
fb8b6ca053 feat(formula): support pipe-quoted identifiers |...|
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 00:06:51 -07:00
ab7e00a217 feat(formula): support pipe-quoted identifiers |...|
Add CL/SQL-style symbol quoting using pipe delimiters for formula
identifiers. This allows category and item names that collide with
keywords (WHERE, SUM, IF, etc.) or contain special characters
(parens, operators, spaces) to be used unambiguously in formulas:

  |WHERE| + |Revenue (USD)|
  SUM(|Net Revenue| WHERE |Region Name| = |East Coast|)

Pipes produce Token::Ident (same as bare identifiers), so they work
everywhere: expressions, aggregates, WHERE clauses. Double-quoted
strings remain Token::Str for backward compatibility.

Also updates split_where and parse_where to skip/strip pipe delimiters.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 00:06:51 -07:00
35ed6a13bf fix: add missing Cargo.toml package metadata
Add repository, homepage, readme, keywords, and categories fields.
Update description to match project vision. Use GitHub URLs for
public discoverability.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 00:06:51 -07:00
637178f3f6 fix: add missing Cargo.toml package metadata
Add repository, homepage, readme, keywords, and categories fields.
Update description to match project vision.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 00:06:51 -07:00
09df7bf181 docs: update design principles and repo map after test audit
- Add virtual category boundary rule: use regular_category_names() for
  user-facing logic, never expose _Index/_Dim
- Document formula tokenizer keyword-aware identifier breaking
- Update repo-map test counts (356 → 510) and add regular_category_names

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 00:06:51 -07:00
96d783a1c5 chore: update gitignore 2026-04-11 00:06:51 -07:00
e67f4d5a92 fix(formula): break tokenizer identifiers when current word is a keyword
The tokenizer already broke multi-word identifiers when the NEXT word
was a keyword, but not when the identifier collected SO FAR was a
keyword. This meant "WHERE Region" was merged into one token when
tokenizing "SUM(Revenue WHERE Region = East)".

Now the tokenizer also checks if the identifier built up to the current
space IS a keyword (WHERE, SUM, AVG, MIN, MAX, COUNT, IF), which
correctly produces separate tokens for "Revenue", "WHERE", "Region".

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 00:06:51 -07:00
4c8ba6400b refactor: use regular_category_names in command and import wizard
Updates `CommitFormula` and `ImportPipeline` to use
`regular_category_names` instead of `category_names` . This ensures that
these components do not target or default to virtual categories (_Index,
_Dim) when no regular categories are present.

Includes updated tests for `CommitFormula` to verify it correctly handles
cases with no regular categories.

Co-Authored-By: fiddlerwoaroof/git-smart-commit (unsloth/gemma-4-26B-A4B-it-GGUF:UD-Q5_K_XL)
2026-04-11 00:06:50 -07:00