Commit Graph

20 Commits

Author SHA1 Message Date
Grok
700e70a355 fix: resolve golangci-lint v2.1.6 staticcheck failures
All checks were successful
CI / Test (push) Successful in 17s
Release / Create Release (push) Successful in 1m33s
CI / Lint (push) Successful in 22s
CI / Build (push) Successful in 20s
- SA9003 (empty branch): rewrote TestFormatLargeAndScientific to actually
  call FormatForDisplay and perform a minimal non-empty assertion instead of
  an if-with-no-body.
- SA1019 (deprecated keyStyle.Copy()): replaced all .Copy() with direct
  assignment or method chaining on the base keyStyle. lipgloss styles are
  immutable and their builder methods already return new instances.
- Removed now-unused "strings" import from calc_test.go.
- All changes pass go test -short, go build, go vet, and gofmt.

This makes the Lint job (which runs golangci-lint-action + staticcheck) green.
The v0.3.0 tag was already pushed from the prior commit; this is master
hygiene so future CI + any follow-up tags are clean.
2026-06-06 17:09:43 +01:00
Grok
17303d1446 feat(calc,ui): complete tight-mode HEX entry with cross-base chaining and result formatting
Some checks failed
CI / Test (push) Successful in 16s
Release / Create Release (push) Failing after 2m1s
CI / Build (push) Has been skipped
CI / Lint (push) Failing after 26s
- Add formatResultEntryForBase + update Equals/Mod/ChangeSign so committed results
  format in the active display base (e.g. HEX shows "C8", "1B0" not decimal).
- Robust per-line centering for dynamic A-F hexRow and keypad rows under display
  (prevents split key borders/decorations on bottom row).
- Updated test expectation for HEX result digits.
- Enables validated cross-base flow: DEC entry, Tab to HEX, continue op, see
  result in active base, Tab back converts displayed value correctly.
- style: gofmt -s all touched sources (ui_test.go, version_test.go etc.).
- ci: add lint and cross targets to Makefile.
  - cross produces the 6 platform binaries expected by release.yml on v* tags.
  - lint target for local parity (CI continues to use golangci-lint-action).

This is the v0.3.0 release-ready state (user-validated: 100 DEC -> Tab HEX +64 = C8 -> Tab DEC 200).
2026-06-06 17:04:11 +01:00
Grok
b78f6d7c2b test: add thorough test coverage for engine, UI model, and version
Some checks failed
Release / Create Release (push) Failing after 12s
CI / Test (push) Successful in 16s
CI / Build (push) Has been skipped
CI / Lint (push) Failing after 28s
- Expanded calc_test.go with additional cases for decimal point, backspace, sign change, mod, div0, multi-step ops, negatives, format, is-integer with entry, etc. (calc coverage to ~86%)
- New ui_test.go: unit tests for App (New, Update key sequences for digits/ops/MOD/HEX entry/base cycle/CERR/clears/flashes/pressed state, View contains checks). ui coverage ~82%
- New version_test.go: 100% for String()
- All tests pass (go test ./...); total project coverage ~81%
- Complements the HEX entry and UI polish work.
- Uses table-friendly and direct model testing suitable for the Bubble Tea spike.
2026-06-06 16:02:56 +01:00
Grok
b142d8305c ui: dynamic A-F buttons in keypad that only appear in HEX mode
- A-F (hex digits) now render as additional top row in the keypad *only* when CurrentBase() == HEX (i.e., after Tab).
- Used dedicated hexBtn + hexKey style (orange accent) for the A-F row to avoid label conflict with the 'C' clear button.
- Pressed flash works for A-F via existing pressedKey mechanism (set in the HEX entry keyboard handler).
- The numeric 4-row grid remains unchanged in other modes.
- Updated UI_DESIGN.md layout sketch and description to document the dynamic behavior.
- Matches the galculator-inspired 'only when in hex mode' and keeps the keypad clean otherwise.
- Build verified.
2026-06-06 15:59:22 +01:00
Grok
0812bc162f sketch: tight-scope HEX entry via keyboard (A-F only while base=HEX)
- Engine:
  * EnterDigit now accepts A-F (uppercased) only for BaseHEX; decimal path now validates 0-9.
  * EnterDecimalPoint ignored for non-DEC.
  * currentNumericValue parses entry using current base (ParseInt base 16 for HEX, extended to BIN/OCT for robustness).
  * FormatForDisplay prefers returning the raw (upper) entry string when active *and* base indicator matches (so typing 1A in HEX shows '1A', not 26).
  * CycleBase now commits any active entry (parsed with old base) before switching. This makes mid-entry Tab safe and preserves CERR semantics.
- UI: added A-F/a-f key handling in Update (only when CurrentBase()==HEX). Sets pressedKey (harmless since no visual A-F buttons in tight scope).
- Tests: added 4 focused tests for hex digit acceptance, decimal ignore, mode gating, and mid-entry base switch + subsequent arithmetic.
- All existing behavior (DEC, CERR, etc.) preserved.
- Build + tests green.

This is the minimal 'keyboard only while indicator says HEX' scope requested. No visual A-F keypad buttons, no fractional hex, no changes to BIN/OCT entry.
2026-06-06 15:55:02 +01:00
Grok
8ea6015223 docs: add comprehensive README.md
Some checks failed
CI / Test (push) Successful in 16s
CI / Lint (push) Failing after 26s
CI / Build (push) Has been skipped
Covers essentials modeled after gostations:
- Project description and galculator GTK inspiration
- MVP features (decimal math, BASE cycling via Tab, CERR policy, MOD, display layout, tactile keypad)
- Requirements
- Install via one-liner release scripts (Linux/macOS + PowerShell)
- Usage: display row, key bindings (Tab:BASE, m:MOD, Backspace:C, Del:AC, etc.)
- Building from source (make build/install/test)
- Development notes (links to spec.md, docs/ARCHITECTURE.md, docs/UI_DESIGN.md, workflows, engine/UI separation)
- Ties to personal apps/ ecosystem and REXX launcher

All naming is now consistently 'gralculator' (folder, binary, repo).
2026-06-06 15:38:07 +01:00
Grok
27a4a0fc4d fix: update install scripts to use correct gralculator repo name in GITEA_BASE URLs
Some checks failed
CI / Test (push) Successful in 37s
CI / Lint (push) Failing after 28s
CI / Build (push) Has been skipped
All references now consistently use 'gralculator' for the project:
- local folder: apps/gralculator
- binary: gralculator
- remote repo: gmgauthier/gralculator (renamed via tea)
- scripts and workflows updated
2026-06-06 15:35:04 +01:00
Grok
428acea198 ci: add ci-build.sh, install scripts, and lint job
- ci-build.sh for parity with gostations (Linux Build step in workflow)
- scripts/gralculator-install.sh and .ps1 modeled directly on gostations (platform detection, download, checksum verify with sha256sum/shasum, extract, install to ~/.local/bin, versioned)
- Updated build.yml: Linux Build now calls ./ci-build.sh; added lint job (golangci-lint-action@v7 v2.1.6 like grokkit) after test, build now needs [test, lint]
- release.yml already prepared to include the scripts if present
- All modeled closely on gostations/grokkit for consistency
2026-06-06 15:30:50 +01:00
Grok
db2c51f9dc ci: add Gitea Actions workflows (build/CI + release) modeled after gostations and grokkit
- build.yml: CI on push/PR with Go 1.24.2, test-short via Makefile, Linux build, verify binary (go mod tidy to ensure clean sums for deps like lipgloss/bubbletea)
- release.yml: on v* tags, cross build via make cross (with VERSION/COMMIT/DATE ldflags), prepare tar.gz + checksums (gralculator-*), conditional install scripts, create Gitea release via API (RELEASE_TOKEN), upload assets. Customized release notes for this TUI calculator project.
- Very close structure, caching, tidy steps, asset prep, and release creation/upload logic to the reference projects.
- Uses our existing Makefile cross target and internal/version ldflags.
- No external ci-build.sh needed; leverages Makefile directly for simplicity.
2026-06-06 15:21:02 +01:00
Grok
2ddb6f73fa ui: simplify hint and remap clear keys
- Hint now exactly: "Tab:BASE  m:MOD  BackSpace:C  Del:AC"
- Removed all operator keys, numbers, equals, q:quit etc. from the hint per request.
- Remapped:
  - backspace key -> ClearEntry (flashes the visual 'C' button)
  - delete/del key -> AllClear (flashes the visual 'AC' button)
- Removed the old 'c','C' and 'ac','ctrl+l' handlers to match the new keymap.
- Updated docs/UI_DESIGN.md example to the new minimal hint.

The visual 'C' and 'AC' buttons remain in the grid for reference; their functions are now on Backspace and Del.
2026-06-06 15:11:14 +01:00
Grok
7d6c4937f8 ui: remove on-screen BASE button from keypad grid
- BASE is now Tab-only (still fully functional, with clear hint: 'Tab:BASE').
- Deleted the special baseRow / fullRowWidth centering logic and the single-button bottom row.
- The keypad grid is now a clean, regular 4-row block of keys.
- This eliminates the persistent bottom-border alignment bug on the BASE key (chopped + shifted).
- Updated Tab handler to use the 'base' flash on the display label instead of trying to highlight a non-existent button.
- Cleaned up unused baseKey style and related comments.
- Updated docs/UI_DESIGN.md to document that BASE is keyboard-only via Tab.

As the user noted: with a good hint, the visual key was unnecessary and was causing layout friction. The keypad now looks much more balanced.
2026-06-06 15:05:53 +01:00
Grok
67d93acbaf ui: remove keypad background container and its border
Per user request: eliminate the enclosing dark panel (bg 234 + NormalBorder)
around the entire key grid. Only the individual key styling remains
(bordered mini-panels with per-type colors, Height(2), pressed flash inversion).

- The rawGrid is now centered directly under the display using
  Width(dispW).Align(Center).
- BASE button still appears nicely centered on its row thanks to the
  uniform row width padding we added earlier.
- Keys sit directly on the main card background.
- Updated docs/UI_DESIGN.md to match.

Much cleaner and closer to a pure 'tactile keys only' look.
2026-06-06 15:01:40 +01:00
Grok
9c27901c8e ui: fix chopped BASE button border and mismatched keypad background
Root cause: rowBase was much narrower than the other rows. When we did
Width(dispW).Align(Center).Render(rawGrid) the vertical join produced
a non-rectangular block, so the panel's bottom border was drawn around
the centered narrow line (chopped + shifted under BASE) and the bg 234
had large empty side regions on the bottom row.

Fix:
- Compute fullRowWidth from a complete row.
- Render the BASE key centered inside a string of that exact width.
- Now rawGrid is a true rectangle (all 5 rows same width).
- Render the backing panel *tightly* to rawGrid first (no forced width).
- Then center the resulting compact panel under the display with
  Width(dispW).Align(Center).

Result:
- Clean, straight bottom border under the BASE button.
- The black keypad background now exactly matches the bounding box
  of the actual keys (including the centered BASE row).
- No more dangling empty black space on the sides at the bottom.

The rest of the tactile key styles, per-key pressed flash, and wide
integrated display row are unchanged.
2026-06-06 14:56:54 +01:00
Grok
b0dfc31767 ui: decorate keypad grid for tactile calculator look
- Individual keys now use bordered mini-panels (NormalBorder 238) + dedicated bg/fg per type:
  - Numbers: neutral dark
  - Operators: 63 accent
  - Clears (C/AC): red-tinted warning
  - MOD: orange highlight
  - BASE: 63 border + bold (stands out)
- Height(2) + padding for chunkier physical-button presence.
- Pressed state inverts to flashStyle (bright 63 bg + white bold) for 140ms on every key action — direct 'click' feedback.
- Gaps between keys + full-width backing panel (bg 234 + border) create a 'faceplate' effect so keys look like they sit on a real calculator keyboard.
- Updated per-key tracking (pressedKey) in model + Update so flash is applied to the correct button.
- Documented the new tactile decoration in docs/UI_DESIGN.md (replaced old plain-text description).
- Matches the wide integrated display row from previous iteration.

The keypad now feels much more tactile and calculator-like while staying true to the lipgloss + gostations patterns.
2026-06-06 14:50:03 +01:00
Grok
4f58ee9f2d ui: integrate base indicator into main wide display row + full width span
- Refactored View() display to a single wide row inside the LCD panel:
  - Leading base indicator on the left: [BIN], [HEX], etc. (flashes on successful cycle)
  - Number (or CERR) right-aligned in the remaining maximal width (spans full available inside the card)
  - LCD container uses full dispW (based on terminal width) + vertical padding for visual weight
  - CERR still flashes the number slot (base label remains visible on left)
- Keypad grid and hint now also respect the wide dispW and are centered under the display
- Updated docs/UI_DESIGN.md and ARCHITECTURE.md with the new integrated layout (replaced old separate two-row description and ASCII)
- Matches user request: main display spans full maximal width; base begins the main display row (e.g. [ [BIN] [              3465... ] ] inside the panel)

This is iterative polish on the phase 3 spike. Paper trail updated.
2026-06-06 14:43:08 +01:00
Grok
316ce708ac feat(tui): focused rendering spike for galculator-inspired two-row display + single BASE (phase 3)
- internal/ui/ui.go: full Bubble Tea App
  - Large tall LCD-style number area + small current-base row (only the active label highlighted)
  - CERR flash (~600ms color 63) on BASE when value is non-integer (exact policy from spec)
  - 140ms key action flashes (same style as gostations volume/skip/stop)
  - Minimal usable keypad grid (digits, + - * / = . +/- MOD C AC, prominent BASE button)
  - Tab (and button) drives engine.CycleBase()
  - Content-sized centered card (lipgloss.Place + rounded 63 border), subtle 238 inners
  - Minimal non-wrapping hint row
  - Reuses gostations lipgloss idioms (Join*, Width/Align/Center, flashStyle, NormalBorder, etc.)
- main.go: now actually launches tea.NewProgram (with AltScreen)
- Binary: build/gralculator is runnable
- Demonstrates: enter 23/6 = (or 1/3), press Tab → CERR blink, base stays DEC; integer values cycle cleanly and reformat (HEX etc.)

All three phases complete. Architecture + design notes live in docs/. Full commit history for backtracking.
2026-06-06 14:30:08 +01:00
Grok
0af68d45eb fix(engine): remove unused fmt import
Engine now builds and all CERR + arithmetic tests pass cleanly.
2026-06-06 14:29:42 +01:00
Grok
a3ed82c6d9 feat(engine): implement core calculation engine (phase 2)
- float64 decimal math + classic entry buffer (in-progress digits visible)
- CycleBase() with IsInteger() (epsilon) + ErrConversionNotPossible (CERR)
- FormatForDisplay() for DEC/HEX/BIN/OCT (integer formatting for non-DEC)
- Basic ops: + - * / and MOD (math.Mod)
- Equals, SetOperator, EnterDigit/DecimalPoint, ClearEntry, AllClear, ChangeSign, Backspace
- Comprehensive tests covering the critical CERR path (23/6, 1/3 + BASE) plus arithmetic and MOD

This completes the pure engine. The engine is now usable by the upcoming TUI spike. Paper trail updated.
2026-06-06 14:29:36 +01:00
Grok
2a26148c8a chore(skeleton): minimal Go project layout + build system
- go.mod (1.24.2 + initial bubbletea/lipgloss)
- Makefile (build, install to ~/.local/bin/gralculator, test, clean; ldflags version injection)
- internal/version (ldflags-compatible String())
- main.go stub (version flag + placeholder)
- internal/calc/ (Engine skeleton with Base, CycleBase, IsInteger, ErrConversionNotPossible, FormatForDisplay stub + basic tests for CERR path)
- internal/ui/ (App model stub with Tab handling placeholder + lipgloss import for future rendering)

This establishes the three-phase foundation. Next: flesh out engine (phase 2), then TUI spike (phase 3). Paper trail continues.
2026-06-06 14:28:59 +01:00
Grok
0c7473943d chore: initialize git repository and create docs/ with ARCHITECTURE.md and UI_DESIGN.md
- Capture key decisions (single BASE cycle with Tab to reserve A-F, decimal math + display formatting only, CERR policy on non-integers, two-row galculator-inspired display, gostations lipgloss patterns).
- Establish docs/ as home for architecture and design notes (per request).
- Include references to spec.md and gostations patterns.
- Paper trail begins here for backtracking.
2026-06-06 14:28:30 +01:00