Commit graph

28 commits

Author SHA1 Message Date
Horizontal42
e70c69df52 add lexer tests for lexLine 2026-07-29 14:14:48 +03:00
Horizontal42
6a88767edf extract evalAgg into an AGG_FUNCS lookup table 2026-07-29 14:14:48 +03:00
Horizontal42
f2deaa1b94 split lexLine's number/date matching into named helpers
lexLine had grown into one long function trying dates, hex/bin/oct,
grouped numbers, decimals and xrefs inline. Extracted each into a
tryLex* helper with the same fallback order, so the driving loop
reads as a priority list instead of nested ifs.
2026-07-08 15:48:40 +03:00
Horizontal42
d71ad92422 add tests for datetime.ts
Covers detectDateOrder, resolveZone, addToDate and isCalendarUnit —
none of it had direct unit coverage before, only indirectly through
the engine's date-arithmetic tests.
2026-07-08 14:01:34 +03:00
Horizontal42
0b2293f92f engine: configurable date formats, both input and display
Besides ISO, the lexer now accepts D.M.YYYY / M/D/YYYY literals
(31.12.2024, 12/31/2024) with a round-trip validity check so
out-of-range components (2026-13-45, 32.13.2024) fall back to plain
arithmetic instead of silently rolling over to a nearby valid date —
that rollover bug affected ISO literals too, not just the new forms.

Day/month order for ambiguous literals and display layout both come
from a new dateFormat setting (system/iso/dmy/mdy); "system" resolves
once via Intl against the OS locale. Intl.DateTimeFormat instances
are now cached by options key instead of rebuilt on every render.

App-side wiring (settings UI, persistence) comes in a follow-up commit.
2026-07-03 11:35:47 +03:00
Horizontal42
3a264c4a3f registry: split buildRegistry into per-category functions
The 290-line function is now registerCoreVocab / registerUnits /
registerAreaVolume / registerCurrencies / registerExtraUnits /
registerCrypto / registerCompletions, called in the same order —
phrase-collision priority depends on that order, unchanged. Pure
reorganization, no behavior change.
2026-07-03 11:31:02 +03:00
Horizontal42
af83ac6539 a URL in a line got truncated at the comment marker
rawLine.indexOf("//") matched the "//" inside "https://..." too, so
any line with a URL lost everything after it. A comment now only
starts at the beginning of a line or after whitespace.
2026-07-03 11:30:45 +03:00
Horizontal42
a9aaff5490 "time in Europe/Berlin" dropped the second word
Two independent traps. The noise filter only keeps word tokens right
after a conversion token (in/as/...); any other token type resets
that, so the "/" in a slash-form IANA id ("Europe/Berlin") reset it
before the parser ever saw "Berlin". The word-collecting loop in
parseTarget() had the same blind spot even once the token was there.
Both needed the same exception, or "Europe/Berlin" still degrades to
just "Europe".
2026-07-03 11:25:56 +03:00
Horizontal42
ef6244dc84 exp() silently evaluated as a no-op
"exp" was also listed as a scientific-notation alias ("123456 in
exp"). Phrases register first-come-first-served, and that alias was
registered before the exp() function, so the function itself never
got the phrase — exp(1) parsed as a bare (1) and returned 1. Drop
exp from the scientific-notation aliases; sci/exponent/exponential
still work.
2026-07-03 11:25:29 +03:00
Horizontal42
deea37ba21 multiplying same-dimension quantities keeps a sane unit
"2 kg * 500 g" multiplied the raw numbers (1000) and slapped the
left unit on top, giving "1000 kg" instead of "1 kg". Convert the
right operand into the left unit first for same-dimension products;
cross-dimension multiplication ($12 * 3, 5 hours * 2) is unaffected.
2026-07-03 11:25:01 +03:00
Horizontal42
df7761401b random() with no arguments threw before reaching its own branch
evalCall checked args[0] and threw "needs an argument" before ever
falling into the random case, which is the one built-in that's
valid with zero args. Dispatch it first.
2026-07-03 11:21:24 +03:00
Horizontal42
0345d2a33f workspace: don't cache exports from a cycle-interrupted evaluation
In an A<->B cycle, exportsFor(B) run while A is mid-resolution would
compute a wrong export set (assignments dropped by the nested
"circular reference" error) and cache it anyway. Later queries then
served that stale, cycle-broken result even after the cycle-causing
outer call had unwound, giving inconsistent error messages across
repeated evaluations of the same cyclic setup.

Skip caching whenever any line in the result carries a "circular
reference" error - that's a precise, local signal the pass was
cycle-affected, so the sheet gets re-evaluated fresh until an edit
actually breaks the cycle. Normal (non-cyclic) caching is untouched.

Also adds a positive-path test confirming LineResult.error stays
undefined on an ordinary successful line, and a workspace-level test
proving a genuine cycle now reports a stable error across repeated
queries.
2026-07-02 05:50:40 +03:00
Horizontal42
677f940043 engine: @Sheet.key cross-sheet reference syntax and resolver hook 2026-07-02 05:26:25 +03:00
Horizontal42
fbeca06f2e historical rates: 1000 USD in EUR on 2024-01-01 via frankfurter.app 2026-07-01 22:23:35 +03:00
Horizontal42
d5f458dce3 goal seek: ? * 1.2 = 1000 → 833.33 2026-07-01 22:11:55 +03:00
Horizontal42
f8f9095fca add ISO date literals and days until/since 2026-07-01 20:27:55 +03:00
Horizontal42
eff90d3219 add chart/spark sparkline keyword — renders inline SVG in results column 2026-07-01 20:05:24 +03:00
Horizontal42
1d77ee45d8 add random() with deterministic line-seeded PRNG 2026-07-01 20:01:40 +03:00
Horizontal42
532c3265ad add block aggregates count/min/max/product, Ctrl+W close sheet 2026-07-01 19:58:54 +03:00
Horizontal42
7f9c83bbfe add fluid ounce (fl oz) unit, EN/RU 2026-07-01 13:10:06 +03:00
Horizontal42
b0c46c390c RU math phrases, half/полтора constants, export button
- vocab: EN+RU aliases for abs/log/ln/round; RU already had sqrt/cbrt
- engine: "half"/"a half"/"one half"/"половина" → 0.5; "one and a half"/"полтора"/"полторы" → 1.5 as named constants; widen const union in parser/tokenizer/evaluator/registry
- export: ⤓ button in statusbar dropdown — copy sheet, save .sum, export .txt, print/PDF; write_text_file Tauri command; print media CSS hides chrome
2026-06-24 00:27:06 +03:00
Horizontal42
db37218b66 кк = млн, ккк = млрд 2026-06-23 23:57:48 +03:00
Horizontal42
b0ad123fcc add trillion scale; RU к = тысяча 2026-06-23 23:56:13 +03:00
Horizontal42
4c05d63b55 expand vocab: more RU cases for currencies/units, Tab-only autocomplete
- EUR: add "Euros"; CHF: add "franc,francs"; INR: add "rupee,rupees"; USD: add "buck,bucks"; CNY: add "renminbi"
- RU USD: full declension + slang бакс/баксов/...; JPY: all 8 cases for иена/йена; UAH: all гривна cases; TRY: bare лира declension; CNY: жэньминьби + full cases; CHF: all франк cases; BRL/KRW/PLN: extended declension
- RU units: fill missing dative/instrumental/prepositional/accusative for час/минута/секунда/день/неделя/месяц/год/метр/грамм/литр/тонна/унция/фут/дюйм/миля/ярд
- RU scales: тысяча/миллион/миллиард full declension
- RU conversion: добавить "перевести в / конвертировать в"
- editor: autocompletion defaultKeymap:false so Enter only newlines, Tab accepts suggestion
2026-06-23 23:48:40 +03:00
Horizontal42
37fd32501b add sterling/quid/стерлинг phrases for GBP 2026-06-23 23:30:11 +03:00
Horizontal42
ec09c93770 remove Numi brand mentions from code and lockfile 2026-06-18 21:51:31 +03:00
Horizontal42
f55266f70b v1.1.0: bug fixes, atomic writes, safe quit, .sum files, CI
Engine: fix BigInt crash on NaN, KM/KG case-insensitive units, space-grouped
and comma-decimal number parsing, variable-vs-unit shadowing, small value
display (1 mm in km), DST-safe date arithmetic, month-end clamp, log mustTouch,
avg counted, 50% of 50%, 100 USD + 20 after conversion, percent power.

Rust: atomic writes (temp+rename) for documents.json, safe quit (app-quit event
+ 2s watchdog so tray-quit doesn't lose edits), .sum file association + open,
migration safety (canonicalize + all_copied guard), opener API for backups and
extensions folders.

UI: decimal separator setting, hotkey rollback on failure, corrupted JSON guard,
ru welcome sheet, orange cursor visibility.

CI: windows-latest workflow (tsc + vitest + cargo clippy).
2026-06-11 12:57:39 +03:00
Horizontal42
0cef414e9a feat: Summarum — natural language calculator notebook for Windows
Write plain text, get live results per line. English + Russian, units,
live currency rates with crypto, percents, dates and timezones, bitwise
ops, variables and sheet totals. Tauri 2 + TypeScript engine +
CodeMirror 6; daily backups and a deleted-sheets bin.

Inspired by Numi for macOS (numi.app); built from scratch for Windows.
2026-06-10 22:19:24 +03:00