diff --git a/src/cg/05-palette.cg b/src/cg/05-palette.cg index 4667749..5f55adb 100644 --- a/src/cg/05-palette.cg +++ b/src/cg/05-palette.cg @@ -68,6 +68,11 @@ palette = config \ } }; + # local onSelect, calls passed in config.onSelect + onSelect = text \ text + | "" \ config.onSelect paletteState.query + | _ \ config.onSelect text; + ui.stateful { key = "palette", focusable = False, @@ -80,8 +85,8 @@ palette = config \ | Key { printable = True } \ { state = state.{ focusedIndex = 0 }, emit = [] } | Key { key = "ArrowUp" } \ { state = state.{ focusedIndex = max 0 (state.focusedIndex - 1) }, emit = [] } | Key { key = "ArrowDown" } \ { state = state.{ focusedIndex = min (len results - 1) (state.focusedIndex + 1) }, emit = [] } - | Key { key = "Enter" } \ _ = debug "Enter" []; { state = state, emit = [config.onSelect (unwrapOr "" (nth state.focusedIndex results))] } - | e \ _ = debug "event" e; { state = state, emit = [] }, + | Key { key = "Enter" } \ { state = state, emit = [onSelect (unwrapOr "" (nth state.focusedIndex results))] } + | _ \ { state = state, emit = [] }, view = state \ ui.positioned { @@ -127,7 +132,7 @@ palette = config \ w = contentWidth, h = textInputHeight, selected = (state.focusedIndex == i), - onClick = \ config.onSelect t + onClick = onSelect }) results) ] } diff --git a/src/cg/10-os.cg b/src/cg/10-os.cg index 32ecace..835d281 100644 --- a/src/cg/10-os.cg +++ b/src/cg/10-os.cg @@ -19,15 +19,17 @@ run = cmd \ | _ \ noOp; onSelect = item \ - _ = debug "onSelect" item; - item - | "" \ run osState.palette.query - | a \ inspect a; + # for now, if it matches a store item, inspect it + # if not, eval it + res = storeSearch item; + zeroth = nth 0 res; + (and (len res > 0) (nth 0 res == Some item)) + | True \ inspect item + | _ \ run item; inspect = item \ batch [ osState.palette.visible := False, - osState.palette.query := "", osState.inspector.visible := True, osState.inspector.name := item ]; diff --git a/src/runtime-compiled.ts b/src/runtime-compiled.ts index e73f2ff..54f62c2 100644 --- a/src/runtime-compiled.ts +++ b/src/runtime-compiled.ts @@ -241,10 +241,6 @@ export function runAppCompiled(app: App, canvas: HTMLCanvasElement, rt: any) { } }; - console.log("keydown", e) - console.log("componentInstances", componentInstances) - console.log("focusedComponentKey", focusedComponentKey) - if (focusedComponentKey) { // send to focused component handleComponentEvent(focusedComponentKey, event); diff --git a/src/runtime-js.ts b/src/runtime-js.ts index f910068..5d5a000 100644 --- a/src/runtime-js.ts +++ b/src/runtime-js.ts @@ -19,8 +19,8 @@ export const _rt = { max: (a: number) => (b: number) => Math.max(a, b), min: (a: number) => (b: number) => Math.min(a, b), - eq: (a: any) => (b: any) => ({ _tag: a === b ? 'True' : 'False' }), - neq: (a: any) => (b: any) => ({ _tag: a !== b ? 'True' : 'False' }), + eq: (a: any) => (b: any) => ({ _tag: deepEqual(a, b) ? 'True' : 'False' }), + neq: (a: any) => (b: any) => ({ _tag: deepEqual(a, b) ? 'False' : 'True' }), gt: (a: any) => (b: any) => ({ _tag: a > b ? 'True' : 'False' }), lt: (a: any) => (b: any) => ({ _tag: a < b ? 'True' : 'False' }), gte: (a: any) => (b: any) => ({ _tag: a >= b ? 'True' : 'False' }), @@ -142,7 +142,6 @@ export const _rt = { return printed; }, rebind: (name: string, pathOrValue: any, maybeValue?: any) => { - console.log("rebind", store, name, pathOrValue, maybeValue); if (maybeValue === undefined) { store[name] = pathOrValue; } else { @@ -202,13 +201,17 @@ export const _rt = { const parser = new Parser(tokens, wrapped); const defs = parser.parse(); const ast = defs[0].body; + // validate free vars - // const free = freeVars(ast); - // const allowed = new Set([ - // ...Object.keys(store), - // ...Object.keys(_rt), - // 'True' - // ]) + const free = freeVars(ast); + const allowed = new Set([ + ...Object.keys(store), + ...Object.keys(_rt) + ]); + const unknown = [...free].filter(v => !allowed.has(v)); + if (unknown.length > 0) { + return { _tag: 'Err', _0: `Unknown: ${unknown.join(', ')}` }; + } const compiled = compile(defs[0].body); const fn = new Function('_rt', 'store', `return ${compiled}`); @@ -314,3 +317,17 @@ export function syncToAst(name: string) { saveDefinitions(); } } + +function deepEqual(a: any, b: any): boolean { + if (a === b) return true; + if (a === null || b === null || typeof a !== 'object' || typeof b !== 'object') return false; + if (Array.isArray(a) !== Array.isArray(b)) return false; + if (Array.isArray(a)) { + if (a.length !== b.length) return false; + return a.every((v, i) => deepEqual(v, b[i])); + } + const keysA = Object.keys(a); + const keysB = Object.keys(b); + if (keysA.length !== keysB.length) return false; + return keysA.every(k => deepEqual(a[k], b[k])); +}