From 169fa29f167531ae9c53ed888f9d1e35da768a94 Mon Sep 17 00:00:00 2001 From: Lloyd Date: Sun, 18 Jan 2026 01:15:53 +1100 Subject: [PATCH] =?UTF-8?q?=F0=9F=99=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/src/evaluator/mod.rs | 23 +- backend/src/grid.rs | 4 +- backend/src/parser.rs | 3 +- backend/src/tokenizer.rs | 4 + frontend/src/app.css | 25 +- .../lib/components/grid/cell-header.svelte | 43 +- frontend/src/lib/components/grid/cell.svelte | 44 +- .../lib/components/grid/grid-mode.svelte.ts | 174 +++++++ .../components/grid/grid-selection.svelte.ts | 226 +++++++++ frontend/src/lib/components/grid/grid.svelte | 331 +++++-------- .../src/lib/components/grid/grid.svelte.ts | 459 +++++++++--------- .../lib/components/grid/position.svelte.ts | 36 ++ frontend/src/lib/components/grid/types.ts | 12 + frontend/src/lib/components/grid/vim.ts | 145 ++++++ frontend/src/routes/+page.svelte | 6 - 15 files changed, 1007 insertions(+), 528 deletions(-) create mode 100644 frontend/src/lib/components/grid/grid-mode.svelte.ts create mode 100644 frontend/src/lib/components/grid/grid-selection.svelte.ts create mode 100644 frontend/src/lib/components/grid/position.svelte.ts create mode 100644 frontend/src/lib/components/grid/types.ts create mode 100644 frontend/src/lib/components/grid/vim.ts diff --git a/backend/src/evaluator/mod.rs b/backend/src/evaluator/mod.rs index e424f45..529b302 100644 --- a/backend/src/evaluator/mod.rs +++ b/backend/src/evaluator/mod.rs @@ -6,6 +6,7 @@ use crate::{ evaluator::{numerics::*, utils::*}, grid::Grid, parser::*, + tokenizer::{Token, Tokenizer}, }; use std::{collections::HashSet, f64, fmt}; @@ -49,6 +50,27 @@ pub fn evaluate(str: String, grid: Option<&Grid>) -> (Eval, HashSet) { } } +pub fn evaluate_literal(input: String) -> Eval { + let mut tokenizer = match Tokenizer::new(&input) { + Ok(t) => t, + Err(_) => { + return Eval::Literal(Literal::String(input.to_owned())); + } + }; + + if tokenizer.len() != 1 { + return Eval::Literal(Literal::String(input.to_owned())); + } + + match tokenizer.next() { + Token::Literal(lit) => match lit { + Literal::Number(_) | Literal::String(_) => Eval::Literal(lit), + Literal::Boolean(_) => Eval::Literal(Literal::String(input.to_owned())), + }, + _ => Eval::Literal(Literal::String(input.to_owned())), + } +} + fn evaluate_expr( expr: &Expr, precs: &mut HashSet, @@ -266,7 +288,6 @@ fn eval_range( } } - fn eval_pos(val: &Eval) -> Result { match val { Eval::Literal(Literal::Number(it)) => Ok(Eval::Literal(Literal::Number(*it))), diff --git a/backend/src/grid.rs b/backend/src/grid.rs index 3c1574d..eb17824 100644 --- a/backend/src/grid.rs +++ b/backend/src/grid.rs @@ -5,7 +5,7 @@ use log::info; use crate::{ cell::{Cell, CellRef}, common::{LeadErr, LeadErrCode, Literal}, - evaluator::{Eval, evaluate}, + evaluator::{Eval, evaluate, evaluate_literal}, }; pub struct Grid { @@ -33,7 +33,7 @@ impl Grid { let mut updated_cells = vec![cell_ref]; if raw_val.chars().nth(0) != Some('=') { - eval = Eval::Literal(Literal::String(raw_val.to_owned())); + eval = evaluate_literal(raw_val.to_owned()); } else { // Evaluate raw expr and get precedents let (res_eval, res_precs) = evaluate(raw_val[1..].to_owned(), Some(&self)); diff --git a/backend/src/parser.rs b/backend/src/parser.rs index ae6cbd6..6f503b1 100644 --- a/backend/src/parser.rs +++ b/backend/src/parser.rs @@ -3,7 +3,7 @@ use log::info; use crate::{ cell::CellRef, common::{LeadErr, LeadErrCode, Literal}, - tokenizer::*, + tokenizer::{self, *}, }; use std::{collections::HashSet, fmt}; @@ -99,7 +99,6 @@ impl fmt::Display for Expr { } } -#[allow(dead_code)] impl Expr { pub fn pretty(&self) -> String { // entry point for users — root printed without └── diff --git a/backend/src/tokenizer.rs b/backend/src/tokenizer.rs index f051380..b5f48c5 100644 --- a/backend/src/tokenizer.rs +++ b/backend/src/tokenizer.rs @@ -124,6 +124,10 @@ impl Tokenizer { pub fn peek(&mut self) -> Token { self.tokens.last().cloned().unwrap_or(Token::Eof) } + + pub fn len(&self) -> usize { + self.tokens.len() + } } #[cfg(test)] diff --git a/frontend/src/app.css b/frontend/src/app.css index f7e7bb8..4627598 100644 --- a/frontend/src/app.css +++ b/frontend/src/app.css @@ -12,8 +12,8 @@ --card-foreground: oklch(0.141 0.005 285.823); --popover: oklch(1 0 0); --popover-foreground: oklch(0.141 0.005 285.823); - --primary: oklch(0.623 0.214 259.815); - --primary-foreground: oklch(0.97 0.014 254.604); + --primary: oklch(0.5928 0.1225 136.37); + --primary-foreground: oklch(0.982 0.018 155.826); --secondary: oklch(0.967 0.001 286.375); --secondary-foreground: oklch(0.21 0.006 285.885); --muted: oklch(0.967 0.001 286.375); @@ -23,7 +23,7 @@ --destructive: oklch(0.577 0.245 27.325); --border: oklch(0.92 0.004 286.32); --input: oklch(0.92 0.004 286.32); - --ring: oklch(0.623 0.214 259.815); + --ring: oklch(0.723 0.219 149.579); --chart-1: oklch(0.646 0.222 41.116); --chart-2: oklch(0.6 0.118 184.704); --chart-3: oklch(0.398 0.07 227.392); @@ -31,12 +31,12 @@ --chart-5: oklch(0.769 0.188 70.08); --sidebar: oklch(0.985 0 0); --sidebar-foreground: oklch(0.141 0.005 285.823); - --sidebar-primary: oklch(0.623 0.214 259.815); - --sidebar-primary-foreground: oklch(0.97 0.014 254.604); + --sidebar-primary: oklch(0.723 0.219 149.579); + --sidebar-primary-foreground: oklch(0.982 0.018 155.826); --sidebar-accent: oklch(0.967 0.001 286.375); --sidebar-accent-foreground: oklch(0.21 0.006 285.885); --sidebar-border: oklch(0.92 0.004 286.32); - --sidebar-ring: oklch(0.623 0.214 259.815); + --sidebar-ring: oklch(0.723 0.219 149.579); } .dark { @@ -46,8 +46,8 @@ --card-foreground: oklch(0.985 0 0); --popover: oklch(0.21 0.006 285.885); --popover-foreground: oklch(0.985 0 0); - --primary: oklch(0.546 0.245 262.881); - --primary-foreground: oklch(0.379 0.146 265.522); + --primary: oklch(0.5928 0.1225 136.37); + --primary-foreground: oklch(0.393 0.095 152.535); --secondary: oklch(0.274 0.006 286.033); --secondary-foreground: oklch(0.985 0 0); --muted: oklch(0.274 0.006 286.033); @@ -57,7 +57,7 @@ --destructive: oklch(0.704 0.191 22.216); --border: oklch(1 0 0 / 10%); --input: oklch(1 0 0 / 15%); - --ring: oklch(0.488 0.243 264.376); + --ring: oklch(0.527 0.154 150.069); --chart-1: oklch(0.488 0.243 264.376); --chart-2: oklch(0.696 0.17 162.48); --chart-3: oklch(0.769 0.188 70.08); @@ -65,14 +65,13 @@ --chart-5: oklch(0.645 0.246 16.439); --sidebar: oklch(0.21 0.006 285.885); --sidebar-foreground: oklch(0.985 0 0); - --sidebar-primary: oklch(0.546 0.245 262.881); - --sidebar-primary-foreground: oklch(0.379 0.146 265.522); + --sidebar-primary: oklch(0.696 0.17 162.48); + --sidebar-primary-foreground: oklch(0.393 0.095 152.535); --sidebar-accent: oklch(0.274 0.006 286.033); --sidebar-accent-foreground: oklch(0.985 0 0); --sidebar-border: oklch(1 0 0 / 10%); - --sidebar-ring: oklch(0.488 0.243 264.376); + --sidebar-ring: oklch(0.527 0.154 150.069); } - @theme inline { --radius-sm: calc(var(--radius) - 4px); --radius-md: calc(var(--radius) - 2px); diff --git a/frontend/src/lib/components/grid/cell-header.svelte b/frontend/src/lib/components/grid/cell-header.svelte index 3dea6cf..664fde6 100644 --- a/frontend/src/lib/components/grid/cell-header.svelte +++ b/frontend/src/lib/components/grid/cell-header.svelte @@ -2,8 +2,8 @@ import clsx from 'clsx'; let { - width = '80px', - height = '30px', + width = 80, + height = 30, setColWidth = () => {}, setRowHeight = () => {}, val, @@ -11,10 +11,10 @@ direction = 'col', // New prop: 'col' for right-side drag, 'row' for bottom-side resizeable = true }: { - width?: string; - height?: string; - setColWidth?: (width: string) => void; - setRowHeight?: (height: string) => void; + width?: number; + height?: number; + setColWidth?: (width: number) => void; + setRowHeight?: (height: number) => void; val: string; active: boolean; resizeable?: boolean; @@ -39,11 +39,11 @@ if (direction === 'col') { const dx = moveEvent.clientX - startX; // Enforce a minimum width of 40px - setColWidth(`${Math.max(40, startWidth + dx)}px`); + setColWidth(Math.max(40, startWidth + dx)); } else { const dy = moveEvent.clientY - startY; // Enforce a minimum height of 20px - setRowHeight(`${Math.max(30, startHeight + dy)}px`); + setRowHeight(Math.max(30, startHeight + dy)); } }; @@ -60,14 +60,17 @@
{val} @@ -88,7 +91,7 @@