diff --git a/src/ast.ts b/src/ast.ts index a2d7953..cd38eca 100644 --- a/src/ast.ts +++ b/src/ast.ts @@ -180,7 +180,12 @@ export function prettyPrint(ast: AST, indent = 0): string { case 'literal': { const val = ast.value; if (val.kind === 'string') { - return `"${val.value}"`; + const escaped = val.value + .replace(/\\/g, '\\\\') + .replace(/"/g, '\\"') + .replace(/\n/g, '\\n') + .replace(/\t/g, '\\t'); + return `"${escaped}"`; } return `${val.value}`; } diff --git a/src/cg/05-palette.cg b/src/cg/05-palette.cg index a5ebc3e..14ce888 100644 --- a/src/cg/05-palette.cg +++ b/src/cg/05-palette.cg @@ -1,7 +1,8 @@ paletteState = { query = "", focusedIndex = 0, - scrollOffset = 0 + scrollOffset = 0, + opacity = 0.95 }; palette = config \ @@ -10,6 +11,13 @@ palette = config \ results = take 100 (config.search paletteState.query); + nextSelectable = items index direction \ + next = index + direction; + nth next items + | Some (Section _) \ nextSelectable items next direction + | Some (Item _) \ next + | None \ index; + effectiveIndex = nth paletteState.focusedIndex results | Some (Section _) \ nextSelectable results paletteState.focusedIndex 1 | _ \ paletteState.focusedIndex; @@ -23,13 +31,6 @@ palette = config \ contentHeight = windowHeight - (dialogPadding * 2); listHeight = contentHeight - 40; - nextSelectable = items index direction \ - next = index + direction; - nth next items - | Some (Section _) \ nextSelectable items next direction - | Some (Item _) \ next - | None \ index; - itemHeight = entry \ entry | Section _ \ sectionHeight | Item _ \ textInputHeight @@ -103,61 +104,65 @@ palette = config \ x = (config.viewport.width - windowWidth) / 2, y = (config.viewport.height - windowHeight) / 2, - child = ui.stack { - children = [ - ui.rect { w = windowWidth, h = windowHeight, color = "#063351", radius = 0, strokeWidth = 1, strokeColor = "#1A5F80" }, - ui.padding { - amount = dialogPadding, - child = ui.column { - gap = 0, - children = [ - textInput { - key = "palette-query", - initialValue = paletteState.query, - initialFocus = True, - color = "white", - backgroundColor = "rgba(0,0,0,0.2)", - w = contentWidth, - h = textInputHeight, - onChange = text \ batch [paletteState.query := text], - }, - - scrollable { - w = contentWidth, - h = listHeight, - totalHeight = totalHeight, - totalWidth = contentWidth, - scrollX = 0, - scrollY = paletteState.scrollOffset, - onScroll = onScroll, - child = ui.column { - gap = itemGap, - children = [ - ...(mapWithIndex (entry i \ entry - | Section title \ box { - w = contentWidth, - h = sectionHeight, - color = "transparent", - paddingLeft = 6, - paddingTop = 8, - child = ui.text { content = title, color = "#bbb" }, - } - | Item data \ paletteRow { - child = data.label, - w = contentWidth, - h = textInputHeight, - selected = (effectiveIndex == i), - onClick = _ \ onSelect data.label - } - | _ \ empty - ) results) - ] + child = ui.opacity { + + opacity = paletteState.opacity, + child = ui.stack { + children = [ + ui.rect { w = windowWidth, h = windowHeight, color = "#063351", radius = 0, strokeWidth = 1, strokeColor = "#1A5F80" }, + ui.padding { + amount = dialogPadding, + child = ui.column { + gap = 0, + children = [ + textInput { + key = "palette-query", + initialValue = paletteState.query, + initialFocus = True, + color = "white", + backgroundColor = "rgba(0,0,0,0.2)", + w = contentWidth, + h = textInputHeight, + onChange = text \ batch [paletteState.query := text], + }, + + scrollable { + w = contentWidth, + h = listHeight, + totalHeight = totalHeight, + totalWidth = contentWidth, + scrollX = 0, + scrollY = paletteState.scrollOffset, + onScroll = onScroll, + child = ui.column { + gap = itemGap, + children = [ + ...(mapWithIndex (entry i \ entry + | Section title \ box { + w = contentWidth, + h = sectionHeight, + color = "transparent", + paddingLeft = 6, + paddingTop = 8, + child = ui.text { content = title, color = "#bbb" }, + } + | Item data \ paletteRow { + child = data.label, + w = contentWidth, + h = textInputHeight, + selected = (effectiveIndex == i), + onClick = _ \ onSelect data.label + } + | _ \ empty + ) results) + ] + } } - } - ] + ] + } } - } - ] + ] + } } } }; diff --git a/src/cg/06-inspector.cg b/src/cg/06-inspector.cg index 8cf6b7c..57d06ea 100644 --- a/src/cg/06-inspector.cg +++ b/src/cg/06-inspector.cg @@ -6,6 +6,15 @@ inspector = config \ sourceLines = split "\n" source; lineHeight = 20; + val = eval config.name; + _ = debug "val" val; + + reflected = val + | Value v \ reflect v + | _ \ reflect 0; + + _ = debug "reflected" reflected; + dialogPadding = 0; textInputHeight = 40; @@ -20,25 +29,27 @@ inspector = config \ w = config.w, h = config.h - textInputHeight, totalWidth = config.w, - totalHeight = (len sourceLines) * lineHeight, + # totalHeight = (len sourceLines) * lineHeight, + totalHeight = 1000, onScroll = _ \ noOp, - child = ui.column { - gap = 0, - children = map (line \ - ui.positioned { - x = 8, - y = 2, - child = ui.text { content = line, color = "#ccc" } - } - ) sourceLines - } + child = tree { value = reflected, depth = 0 }, + # child = ui.column { + # gap = 0, + # children = map (line \ + # ui.positioned { + # x = 8, + # y = 2, + # child = ui.text { content = line, color = "#ccc" } + # } + # ) sourceLines + # } }, # definition bar textInput { key = "inspector-redefine-" & config.name, color = "white", - backgroundColor = "rgba(0,0,0,1)", + backgroundColor = "rgba(255,255,255,0.2)", w = config.w, h = textInputHeight, onSubmit = text \ redefine config.name text diff --git a/src/cg/06-tree.cg b/src/cg/06-tree.cg new file mode 100644 index 0000000..b3364a0 --- /dev/null +++ b/src/cg/06-tree.cg @@ -0,0 +1,46 @@ +tree = config \ + depth = config.depth; + indent = depth * 20; + + simple = content color \ + ui.positioned { x = indent, y = 0, + child = ui.text { content = content, color = color } + }; + + valueLabel = value \ value + | NumberValue n \ Some (show n) + | StringValue n \ Some ("\"" & n & "\"") + | ConstructorValue { tag = tag } \ Some tag + | FunctionValue _ \ Some "" + | _ \ None; + + config.value + | NumberValue n \ simple (show n) "#6cf" + | StringValue n \ simple ("\"" & n & "\"") "#f6a" + | ConstructorValue { tag = tag } \ simple tag "#fc6" + | FunctionValue _ \ simple "" "#888" + | RecordValue entries \ + ui.column { + gap = 0, + children = map (entry \ + (valueLabel entry.value) + | Some label \ simple (entry.key & " = " & label) "#aaa" + | None \ ui.column { gap = 0, children = [ + simple entry.key "#aaa", + tree { value = entry.value, depth = depth + 1 } + ]} + ) entries + } + | ListValue items \ + ui.column { + gap = 0, + children = mapWithIndex (item i \ + (valueLabel item) + | Some label \ simple ((show i) & ": " & label) "#aaa" + | None \ ui.column { gap = 0, children = [ + simple (show i) "#aaa", + tree { value = item, depth = depth + 1 } + ]} + ) items + } + | _ \ ui.text { content = "?", color = "#666" }; diff --git a/src/runtime-js.ts b/src/runtime-js.ts index 6f2d242..2ce788d 100644 --- a/src/runtime-js.ts +++ b/src/runtime-js.ts @@ -129,6 +129,31 @@ export const _rt = { return { _tag: 'Ok' }; }, + reflect: (value: any): any => { + if (value === null || value === undefined) return { _tag: 'NoneValue' }; + if (typeof value === 'number') return { _tag: 'NumberValue', _0: value }; + if (typeof value === 'string') return { _tag: 'StringValue', _0: value }; + if (Array.isArray(value)) return { _tag: 'ListValue', _0: value.map(_rt.reflect) }; + if (typeof value === 'function') { + const source = value._astId !== undefined && astRegistry.get(value._astId) + ? prettyPrint(astRegistry.get(value._astId)!) + : ''; + return { _tag: 'FunctionValue', _0: source }; + } + if (typeof value === 'object' && value._tag) { + if ('_0' in value) return { _tag: 'ConstructorValue', _0: { tag: value._tag, value: _rt.reflect(value._0) } }; + return { _tag: 'ConstructorValue', _0: { tag: value._tag } }; + } + if (typeof value === 'object') { + const entries = Object.entries(value).map(([k, v]) => ({ + key: k, + value: _rt.reflect(v) + })); + return { _tag: 'RecordValue', _0: entries }; + } + return { _tag: 'NoneValue' }; + }, + eval: (code: string) => { const trimmed = code.trim();