update/cleanup task list
This commit is contained in:
parent
f12eb4e063
commit
bf80acec37
7 changed files with 2560 additions and 2521 deletions
|
|
@ -3,6 +3,9 @@
|
||||||
## References
|
## References
|
||||||
|
|
||||||
- #[[file:.kiro/specs/calculator/requirements.md]]
|
- #[[file:.kiro/specs/calculator/requirements.md]]
|
||||||
|
- #[[file:.kiro/specs/calculator/tasks.md]] (open work)
|
||||||
|
- #[[file:.kiro/specs/calculator/history.md]] (what was done and why; "Task 5.19" and
|
||||||
|
"open item 10" below refer to entries there)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
@ -1799,9 +1802,9 @@ and compares the result to the plain output byte for byte. `main` decides which,
|
||||||
`--color`, whether stdout supports escape codes, `NO_COLOR` and `TERM`, through a pure
|
`--color`, whether stdout supports escape codes, `NO_COLOR` and `TERM`, through a pure
|
||||||
`ColorChoice.resolve` that is tested on its own. Three choices behind it:
|
`ColorChoice.resolve` that is tested on its own. Three choices behind it:
|
||||||
|
|
||||||
- **The terminal's palette, not fixed RGB.** The TUI's Molokai triples (open item 17)
|
- **The terminal's palette, not fixed RGB.** The TUI's Molokai triples (tasks.md,
|
||||||
ignore the user's theme; SGR 31-36 are whatever the theme says, and a theme is built
|
"Themes") ignore the user's theme; SGR 31-36 are whatever the theme says, and a theme
|
||||||
so its own colors read on its own background.
|
is built so its own colors read on its own background.
|
||||||
- **No background, ever.** Forcing black was considered as insurance against an
|
- **No background, ever.** Forcing black was considered as insurance against an
|
||||||
unreadable hue and rejected: it would undo the theme on every light terminal to fix a
|
unreadable hue and rejected: it would undo the theme on every light terminal to fix a
|
||||||
problem the theme already solves.
|
problem the theme already solves.
|
||||||
|
|
@ -2004,7 +2007,7 @@ An earlier wireframe in this section showed a bordered "Bit Pattern (63 -> 0)" b
|
||||||
(`w:width s:sign e:endian y:yank`). None of that was built: there are no borders, the
|
(`w:width s:sign e:endian y:yank`). None of that was built: there are no borders, the
|
||||||
prefix appears only in the clipboard form, the width and sign keys are Ctrl-chords
|
prefix appears only in the clipboard form, the width and sign keys are Ctrl-chords
|
||||||
because plain letters are hex digits in an editable field (FR-7.8), and there is no
|
because plain letters are hex digits in an editable field (FR-7.8), and there is no
|
||||||
yank command yet (open item 14).
|
yank command yet (tasks.md, "Copying a result, and marking one approximate").
|
||||||
|
|
||||||
#### 8.2.1 Programmer Mode - Editable Fields (REVISED DESIGN)
|
#### 8.2.1 Programmer Mode - Editable Fields (REVISED DESIGN)
|
||||||
|
|
||||||
|
|
@ -2030,8 +2033,8 @@ Fields (navigable with Up/Down):
|
||||||
|
|
||||||
Field 8 was never built. `ProgField.expression` exists and Up/Down cycles through it,
|
Field 8 was never built. `ProgField.expression` exists and Up/Down cycles through it,
|
||||||
but no row is drawn for it and no key does anything there, so it reads as a keystroke
|
but no row is drawn for it and no key does anything there, so it reads as a keystroke
|
||||||
that did nothing (open item 18). The expression language is reachable from the input
|
that did nothing (tasks.md, "Programmer mode's value zone"). The expression language is
|
||||||
line instead, which is where it has always been.
|
reachable from the input line instead, which is where it has always been.
|
||||||
|
|
||||||
Navigation:
|
Navigation:
|
||||||
- Up/Down moves focus between fields
|
- Up/Down moves focus between fields
|
||||||
|
|
|
||||||
2317
.kiro/specs/calculator/history.md
Normal file
2317
.kiro/specs/calculator/history.md
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -16,7 +16,7 @@ A calculator application with three frontends (CLI, TUI, Android) sharing a comm
|
||||||
- **FR-1.4**: Support built-in functions: `sin`, `cos`, `tan`, `asin`, `acos`, `atan`, `log` (base-10), `ln` (natural), `sqrt`, `cbrt`, `abs`, `ceil`, `floor`, `round`, `factorial`. An argument outside a function's domain is reported as such, distinct from an unknown name: `asin(2)`, `ln(0)`, `log2(0)` and `factorial(-1)` report a domain error, `sqrt(-1)` reports "square root of a negative number", and only an unrecognized name reports an unknown function.
|
- **FR-1.4**: Support built-in functions: `sin`, `cos`, `tan`, `asin`, `acos`, `atan`, `log` (base-10), `ln` (natural), `sqrt`, `cbrt`, `abs`, `ceil`, `floor`, `round`, `factorial`. An argument outside a function's domain is reported as such, distinct from an unknown name: `asin(2)`, `ln(0)`, `log2(0)` and `factorial(-1)` report a domain error, `sqrt(-1)` reports "square root of a negative number", and only an unrecognized name reports an unknown function.
|
||||||
- **FR-1.5**: Support constants: `pi`, `e`, `tau`. These are fixed values, readable and not assignable.
|
- **FR-1.5**: Support constants: `pi`, `e`, `tau`. These are fixed values, readable and not assignable.
|
||||||
- **FR-1.6**: Support variable storage: any identifier as a named variable. (The original wording restricted this to `A-F, X, Y, Z`; the implementation accepts any name, which is a superset and the better behaviour, so the requirement follows the code.) A constant is not an assignment target: `pi = 3` reports an error rather than accepting the assignment and ignoring it.
|
- **FR-1.6**: Support variable storage: any identifier as a named variable. (The original wording restricted this to `A-F, X, Y, Z`; the implementation accepts any name, which is a superset and the better behaviour, so the requirement follows the code.) A constant is not an assignment target: `pi = 3` reports an error rather than accepting the assignment and ignoring it.
|
||||||
- **FR-1.6.1**: The last answer is a **pseudovariable**, not a constant: `Ans` (also `ans`) reads the result of the previous evaluation, the engine updates it on every successful evaluation, and the user cannot assign to it. It is a distinct concept from FR-1.5's constants, which never change, and from FR-1.6's variables, which only the user writes. The set is exactly one name: the immediately preceding answer. Earlier results are FR-1.7's history, reachable by replay rather than by name. See tasks.md open item 16: the engine currently folds `Ans` in with the constants and reports `AssignmentToConstant` ("cannot assign to a built-in constant") for `Ans = 5`, which misnames it.
|
- **FR-1.6.1**: The last answer is a **pseudovariable**, not a constant: `Ans` (also `ans`) reads the result of the previous evaluation, the engine updates it on every successful evaluation, and the user cannot assign to it. It is a distinct concept from FR-1.5's constants, which never change, and from FR-1.6's variables, which only the user writes. The set is exactly one name: the immediately preceding answer. Earlier results are FR-1.7's history, reachable by replay rather than by name. See tasks.md, "`Ans` is a pseudovariable, and the engine models it as a constant": the engine currently folds `Ans` in with the constants and reports `AssignmentToConstant` ("cannot assign to a built-in constant") for `Ans = 5`, which misnames it.
|
||||||
- **FR-1.7**: Maintain calculation history with replay capability.
|
- **FR-1.7**: Maintain calculation history with replay capability.
|
||||||
- **FR-1.8**: Commas accepted as digit separators in input, but only in thousands groups: a comma must be followed by exactly three digits (`1,000 * 2` is 2000, `1,234,567` is one number). A comma followed by any other number of digits is an argument separator, which is what makes `log(100,10)` two arguments rather than the number 10010. The ambiguous case `max(1,234)` resolves in favour of the grouping and reads as `max(1234)`; write a space to mean two arguments. A malformed group such as `1,00` is an error rather than a silently merged number. Spaces and underscores group hex/octal/binary literals (`0xFF FF`, `0xFF_FF`); commas do not.
|
- **FR-1.8**: Commas accepted as digit separators in input, but only in thousands groups: a comma must be followed by exactly three digits (`1,000 * 2` is 2000, `1,234,567` is one number). A comma followed by any other number of digits is an argument separator, which is what makes `log(100,10)` two arguments rather than the number 10010. The ambiguous case `max(1,234)` resolves in favour of the grouping and reads as `max(1234)`; write a space to mean two arguments. A malformed group such as `1,00` is an error rather than a silently merged number. Spaces and underscores group hex/octal/binary literals (`0xFF FF`, `0xFF_FF`); commas do not.
|
||||||
- **FR-1.9**: When a standard-mode expression contains any non-decimal literal (hex `0x`, octal `0o`, or binary `0b`) and the result is a non-negative integer, enrich the result display with hex/octal/binary representations inline (without leaving standard mode). Uses the smallest standard bit width (8/16/32/64/128) that holds the value. This does not change the evaluation semantics (still f64 arithmetic, `^` is still power); it only augments the display. Fractional or negative results show decimal only.
|
- **FR-1.9**: When a standard-mode expression contains any non-decimal literal (hex `0x`, octal `0o`, or binary `0b`) and the result is a non-negative integer, enrich the result display with hex/octal/binary representations inline (without leaving standard mode). Uses the smallest standard bit width (8/16/32/64/128) that holds the value. This does not change the evaluation semantics (still f64 arithmetic, `^` is still power); it only augments the display. Fractional or negative results show decimal only.
|
||||||
|
|
@ -178,7 +178,7 @@ comes out whole, which is easier while nothing but the CLI depends on it.
|
||||||
- **FR-7.7**: Every action must be reachable from the keyboard alone; the TUI is fully usable without a mouse.
|
- **FR-7.7**: Every action must be reachable from the keyboard alone; the TUI is fully usable without a mouse.
|
||||||
- **FR-7.8**: REMOVED. Quick-switch keys (`d`=dec, `h`=hex, `o`=oct, `b`=bin) to highlight the primary base cannot coexist with editable value fields: in the value zone those letters are hex and binary digits. The requirement predates editable fields, and the fields are the more useful feature. Base selection stays on the arrow keys and the mouse.
|
- **FR-7.8**: REMOVED. Quick-switch keys (`d`=dec, `h`=hex, `o`=oct, `b`=bin) to highlight the primary base cannot coexist with editable value fields: in the value zone those letters are hex and binary digits. The requirement predates editable fields, and the fields are the more useful feature. Base selection stays on the arrow keys and the mouse.
|
||||||
- **FR-7.9**: Support terminal resize gracefully.
|
- **FR-7.9**: Support terminal resize gracefully.
|
||||||
- **FR-7.9.3**: NOT IMPLEMENTED. The colour scheme is selectable rather than fixed. Molokai stays the default, and the requirement is that it is a default: a light theme, a terminal's own 16 colours, and a user's choice are all reachable without editing the source. Today `draw.C` is eleven literal RGB triples read directly by every view, which makes the palette a compile-time fact. Prerequisite is naming the roles the views use (error, focus, selection, accent) instead of the colours they happen to be; tasks.md open item 17 holds the detail.
|
- **FR-7.9.3**: NOT IMPLEMENTED. The colour scheme is selectable rather than fixed. Molokai stays the default, and the requirement is that it is a default: a light theme, a terminal's own 16 colours, and a user's choice are all reachable without editing the source. Today `draw.C` is eleven literal RGB triples read directly by every view, which makes the palette a compile-time fact. Prerequisite is naming the roles the views use (error, focus, selection, accent) instead of the colours they happen to be; tasks.md's "Themes" holds the detail.
|
||||||
- **FR-7.9.1**: Nothing in the TUI's own chrome is cut off mid-word at 60 columns or more. Status lines are lists of key hints, and a line too long for the terminal drops whole hints from the end rather than losing the last one's tail: each mode orders its hints so the keys that leave the current zone (`?:help`, `Tab:mode`, the zone toggle) come first and are the last to go. Status lines also leave the final column clear, which is what lets a rendered frame be checked for clipping at all: any row but the separator reaching the right edge is then a fault, not a maybe. Below 60 columns the notices themselves cannot fit, and shortening them further would leave them saying nothing.
|
- **FR-7.9.1**: Nothing in the TUI's own chrome is cut off mid-word at 60 columns or more. Status lines are lists of key hints, and a line too long for the terminal drops whole hints from the end rather than losing the last one's tail: each mode orders its hints so the keys that leave the current zone (`?:help`, `Tab:mode`, the zone toggle) come first and are the last to go. Status lines also leave the final column clear, which is what lets a rendered frame be checked for clipping at all: any row but the separator reaching the right edge is then a fault, not a maybe. Below 60 columns the notices themselves cannot fit, and shortening them further would leave them saying nothing.
|
||||||
- **FR-7.9.2**: Input is ASCII. A key event carrying non-ASCII text is dropped rather than stored: every column in the TUI is one byte, so an accented character would occupy a cell per UTF-8 byte, drawn as blanks, and then fail to tokenize. Refusing it keeps what is on screen equal to what is in the buffer. A wider fix is a different piece of work: the whole layout counts columns in bytes.
|
- **FR-7.9.2**: Input is ASCII. A key event carrying non-ASCII text is dropped rather than stored: every column in the TUI is one byte, so an accented character would occupy a cell per UTF-8 byte, drawn as blanks, and then fail to tokenize. Refusing it keeps what is on screen equal to what is in the buffer. A wider fix is a different piece of work: the whole layout counts columns in bytes.
|
||||||
- **FR-7.10**: Vi-style and Emacs-style keybinding options for expression input. NOT IMPLEMENTED: the prompt is a plain text field. Deferred, not dropped.
|
- **FR-7.10**: Vi-style and Emacs-style keybinding options for expression input. NOT IMPLEMENTED: the prompt is a plain text field. Deferred, not dropped.
|
||||||
|
|
@ -203,20 +203,19 @@ still required (FR-7.7): the mouse never becomes the only way to do something.
|
||||||
- **FR-7.11.12**: Clickable regions are rebuilt every frame from what was actually drawn, so hit targets can never drift out of sync with the display.
|
- **FR-7.11.12**: Clickable regions are rebuilt every frame from what was actually drawn, so hit targets can never drift out of sync with the display.
|
||||||
- **FR-7.11.13**: In financial mode, clicking a calculation chip selects that calculation and clicking a field row focuses it for editing; the mouse wheel scrolls the amortization schedule. In the help overlay the wheel scrolls and a click returns.
|
- **FR-7.11.13**: In financial mode, clicking a calculation chip selects that calculation and clicking a field row focuses it for editing; the mouse wheel scrolls the amortization schedule. In the help overlay the wheel scrolls and a click returns.
|
||||||
|
|
||||||
### FR-8: Android Frontend - WALKING SKELETON BUILT, UNVERIFIED ON A DEVICE
|
### FR-8: Android Frontend - THREE OF FOUR SCREENS BUILT
|
||||||
|
|
||||||
`android/` now holds a one-screen Compose app over the C ABI: an expression field, a
|
`android/` is a Compose app over the C ABI with three screens behind a hamburger drawer:
|
||||||
history, and the multi-base and conversion detail lines. The engine behind it is the
|
the standard calculator (design 9.2), programmer mode (9.3) and the converter (9.6), plus a
|
||||||
finished one, so exact arithmetic, units and the financial functions all work in that one
|
theme setting. Each reopens exactly as it was left. It has run on an Android 15 emulator
|
||||||
field already (FR-4.1, FR-5.7). Nothing in `android/` has been compiled: the machine it
|
with 16 KiB pages and on a Galaxy S23+ (arm64-v8a, Android 16).
|
||||||
was written on has no JDK, Gradle or SDK, by choice, so the version numbers and the
|
|
||||||
instrumented test are the first things to try.
|
|
||||||
|
|
||||||
What is built of the requirements below: FR-8.1 (Kotlin and Compose), FR-8.2 (JNI, via a
|
Built of the requirements below: FR-8.1 and FR-8.2 (JNI through a hand-written layer with
|
||||||
hand-written layer with no NDK - design 6.4), and the standard-mode half of FR-8.4.
|
no NDK, design 6.4), FR-8.4, FR-8.5 and FR-8.8. FR-8.3's bottom bar became the drawer, and
|
||||||
FR-8.3's navigation, the programmer and financial and convert screens, and everything from
|
FR-8.10's Material 3 is there without its dynamic colour, which was tried and dropped
|
||||||
FR-8.9 down are not started. FR-8.6 needs FR-3's engine, which now exists, and a C ABI
|
because it lit the keypad's bands in dark mode (design 9.1). Not built: the financial screen (FR-8.7), the struct sub-screen
|
||||||
export for it, which does not.
|
(FR-8.6, which needs a C ABI export of the struct engine), and FR-8.9, FR-8.11 and FR-8.12;
|
||||||
|
`tasks.md` has each.
|
||||||
|
|
||||||
- **FR-8.1**: Native Android app using Kotlin and Jetpack Compose.
|
- **FR-8.1**: Native Android app using Kotlin and Jetpack Compose.
|
||||||
- **FR-8.2**: Call into the Zig engine via JNI (C ABI shared library).
|
- **FR-8.2**: Call into the Zig engine via JNI (C ABI shared library).
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -43,9 +43,10 @@ $ tally -p '0xDEADBEEF and 0xFFFF'
|
||||||
terminal each member's row and bytes share a color. Every profile is checked against
|
terminal each member's row and bytes share a color. Every profile is checked against
|
||||||
clang at build time. Command line only, for now.
|
clang at build time. Command line only, for now.
|
||||||
|
|
||||||
The requirements and design, including what is planned and not built (a struct layout
|
The requirements and design are in [.kiro/specs/calculator](.kiro/specs/calculator),
|
||||||
view in the TUI and on Android, a financial screen on Android), are in
|
with the open work in [tasks.md](.kiro/specs/calculator/tasks.md) (among it a struct layout
|
||||||
[.kiro/specs/calculator](.kiro/specs/calculator).
|
view in the TUI and on Android, and a financial screen on Android) and the record of what
|
||||||
|
was done, and why, in [history.md](.kiro/specs/calculator/history.md).
|
||||||
|
|
||||||
## The three frontends
|
## The three frontends
|
||||||
|
|
||||||
|
|
@ -239,7 +240,7 @@ src/main.zig, src/cli/ the command line
|
||||||
src/tui.zig, src/tui/ the terminal UI (libvaxis)
|
src/tui.zig, src/tui/ the terminal UI (libvaxis)
|
||||||
android/ the Compose app; Kotlin parses no expressions and formats no numbers
|
android/ the Compose app; Kotlin parses no expressions and formats no numbers
|
||||||
build/ coverage (kcov) support for build.zig
|
build/ coverage (kcov) support for build.zig
|
||||||
.kiro/specs/ requirements, design and task history
|
.kiro/specs/ requirements, design, open tasks, and the history of finished ones
|
||||||
```
|
```
|
||||||
|
|
||||||
A few decisions shape everything else, and the design document explains each:
|
A few decisions shape everything else, and the design document explains each:
|
||||||
|
|
|
||||||
|
|
@ -314,8 +314,9 @@ const testing = std.testing;
|
||||||
///
|
///
|
||||||
/// This was `FormatOptions.plain`, documented as what the clipboard wants, until a
|
/// This was `FormatOptions.plain`, documented as what the clipboard wants, until a
|
||||||
/// look at the callers found all 24 of them in the tests below and none in a
|
/// look at the callers found all 24 of them in the tests below and none in a
|
||||||
/// frontend. The TUI has no yank command yet (tasks.md open item 14), so it lives
|
/// frontend. The TUI has no yank command yet (tasks.md, "Copying a result, and
|
||||||
/// here until something outside the tests asks for it.
|
/// marking one approximate"), so it lives here until something outside the tests
|
||||||
|
/// asks for it.
|
||||||
const canonical: FormatOptions = .{ .separators = false, .prefix = true };
|
const canonical: FormatOptions = .{ .separators = false, .prefix = true };
|
||||||
|
|
||||||
test "BitWidth.mask" {
|
test "BitWidth.mask" {
|
||||||
|
|
|
||||||
|
|
@ -871,7 +871,7 @@ test "a numeric span that is not a number is an invalid number, not an unexpecte
|
||||||
// It used to be recognised in prefix position, so it could appear wherever an
|
// It used to be recognised in prefix position, so it could appear wherever an
|
||||||
// operand could: `1 + x = 2` assigned 2 to `x` and evaluated to 3, and `f(x = 1)`
|
// operand could: `1 + x = 2` assigned 2 to `x` and evaluated to 3, and `f(x = 1)`
|
||||||
// was an argument list with a side effect. Both are the same bug, and both are now
|
// was an argument list with a side effect. Both are the same bug, and both are now
|
||||||
// parse errors (tasks.md open item 10).
|
// parse errors (history.md, open item 10).
|
||||||
|
|
||||||
test "assignment at the top of the input still parses" {
|
test "assignment at the top of the input still parses" {
|
||||||
const expr = try testParse("X = 42");
|
const expr = try testParse("X = 42");
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue