Fixing bugs. escaping things when pretty printing. adding reflect host function. getting further with tree view

master
Dustin Swan 2 weeks ago
parent f27b946790
commit fec18486d8
Signed by: dustinswan
GPG Key ID: 30D46587E2100467

@ -180,7 +180,12 @@ export function prettyPrint(ast: AST, indent = 0): string {
case 'literal': { case 'literal': {
const val = ast.value; const val = ast.value;
if (val.kind === 'string') { 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}`; return `${val.value}`;
} }

@ -1,7 +1,8 @@
paletteState = { paletteState = {
query = "", query = "",
focusedIndex = 0, focusedIndex = 0,
scrollOffset = 0 scrollOffset = 0,
opacity = 0.95
}; };
palette = config \ palette = config \
@ -10,6 +11,13 @@ palette = config \
results = take 100 (config.search paletteState.query); 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 effectiveIndex = nth paletteState.focusedIndex results
| Some (Section _) \ nextSelectable results paletteState.focusedIndex 1 | Some (Section _) \ nextSelectable results paletteState.focusedIndex 1
| _ \ paletteState.focusedIndex; | _ \ paletteState.focusedIndex;
@ -23,13 +31,6 @@ palette = config \
contentHeight = windowHeight - (dialogPadding * 2); contentHeight = windowHeight - (dialogPadding * 2);
listHeight = contentHeight - 40; 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 itemHeight = entry \ entry
| Section _ \ sectionHeight | Section _ \ sectionHeight
| Item _ \ textInputHeight | Item _ \ textInputHeight
@ -103,61 +104,65 @@ palette = config \
x = (config.viewport.width - windowWidth) / 2, x = (config.viewport.width - windowWidth) / 2,
y = (config.viewport.height - windowHeight) / 2, y = (config.viewport.height - windowHeight) / 2,
child = ui.stack { child = ui.opacity {
children = [
ui.rect { w = windowWidth, h = windowHeight, color = "#063351", radius = 0, strokeWidth = 1, strokeColor = "#1A5F80" }, opacity = paletteState.opacity,
ui.padding { child = ui.stack {
amount = dialogPadding, children = [
child = ui.column { ui.rect { w = windowWidth, h = windowHeight, color = "#063351", radius = 0, strokeWidth = 1, strokeColor = "#1A5F80" },
gap = 0, ui.padding {
children = [ amount = dialogPadding,
textInput { child = ui.column {
key = "palette-query", gap = 0,
initialValue = paletteState.query, children = [
initialFocus = True, textInput {
color = "white", key = "palette-query",
backgroundColor = "rgba(0,0,0,0.2)", initialValue = paletteState.query,
w = contentWidth, initialFocus = True,
h = textInputHeight, color = "white",
onChange = text \ batch [paletteState.query := text], backgroundColor = "rgba(0,0,0,0.2)",
}, w = contentWidth,
h = textInputHeight,
scrollable { onChange = text \ batch [paletteState.query := text],
w = contentWidth, },
h = listHeight,
totalHeight = totalHeight, scrollable {
totalWidth = contentWidth, w = contentWidth,
scrollX = 0, h = listHeight,
scrollY = paletteState.scrollOffset, totalHeight = totalHeight,
onScroll = onScroll, totalWidth = contentWidth,
child = ui.column { scrollX = 0,
gap = itemGap, scrollY = paletteState.scrollOffset,
children = [ onScroll = onScroll,
...(mapWithIndex (entry i \ entry child = ui.column {
| Section title \ box { gap = itemGap,
w = contentWidth, children = [
h = sectionHeight, ...(mapWithIndex (entry i \ entry
color = "transparent", | Section title \ box {
paddingLeft = 6, w = contentWidth,
paddingTop = 8, h = sectionHeight,
child = ui.text { content = title, color = "#bbb" }, color = "transparent",
} paddingLeft = 6,
| Item data \ paletteRow { paddingTop = 8,
child = data.label, child = ui.text { content = title, color = "#bbb" },
w = contentWidth, }
h = textInputHeight, | Item data \ paletteRow {
selected = (effectiveIndex == i), child = data.label,
onClick = _ \ onSelect data.label w = contentWidth,
} h = textInputHeight,
| _ \ empty selected = (effectiveIndex == i),
) results) onClick = _ \ onSelect data.label
] }
| _ \ empty
) results)
]
}
} }
} ]
] }
} }
} ]
] }
} }
} }
}; };

@ -6,6 +6,15 @@ inspector = config \
sourceLines = split "\n" source; sourceLines = split "\n" source;
lineHeight = 20; lineHeight = 20;
val = eval config.name;
_ = debug "val" val;
reflected = val
| Value v \ reflect v
| _ \ reflect 0;
_ = debug "reflected" reflected;
dialogPadding = 0; dialogPadding = 0;
textInputHeight = 40; textInputHeight = 40;
@ -20,25 +29,27 @@ inspector = config \
w = config.w, w = config.w,
h = config.h - textInputHeight, h = config.h - textInputHeight,
totalWidth = config.w, totalWidth = config.w,
totalHeight = (len sourceLines) * lineHeight, # totalHeight = (len sourceLines) * lineHeight,
totalHeight = 1000,
onScroll = _ \ noOp, onScroll = _ \ noOp,
child = ui.column { child = tree { value = reflected, depth = 0 },
gap = 0, # child = ui.column {
children = map (line \ # gap = 0,
ui.positioned { # children = map (line \
x = 8, # ui.positioned {
y = 2, # x = 8,
child = ui.text { content = line, color = "#ccc" } # y = 2,
} # child = ui.text { content = line, color = "#ccc" }
) sourceLines # }
} # ) sourceLines
# }
}, },
# definition bar # definition bar
textInput { textInput {
key = "inspector-redefine-" & config.name, key = "inspector-redefine-" & config.name,
color = "white", color = "white",
backgroundColor = "rgba(0,0,0,1)", backgroundColor = "rgba(255,255,255,0.2)",
w = config.w, w = config.w,
h = textInputHeight, h = textInputHeight,
onSubmit = text \ redefine config.name text onSubmit = text \ redefine config.name text

@ -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 "<fn>"
| _ \ None;
config.value
| NumberValue n \ simple (show n) "#6cf"
| StringValue n \ simple ("\"" & n & "\"") "#f6a"
| ConstructorValue { tag = tag } \ simple tag "#fc6"
| FunctionValue _ \ simple "<fn>" "#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" };

@ -129,6 +129,31 @@ export const _rt = {
return { _tag: 'Ok' }; 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)!)
: '<native>';
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) => { eval: (code: string) => {
const trimmed = code.trim(); const trimmed = code.trim();

Loading…
Cancel
Save