Dead code. cleaning up parse. allowing trailing commas. starting to work on the 'os' palette
This commit is contained in:
parent
a30d2217b8
commit
2d687b5d38
5 changed files with 77 additions and 112 deletions
|
|
@ -13,9 +13,7 @@ import stdlibCode from './stdlib.cg?raw';
|
|||
import designTokensCode from './design-tokens.cg?raw';
|
||||
import uiComponentsCode from './ui-components.cg?raw';
|
||||
|
||||
import textInputCode from './textinput-test.cg?raw';
|
||||
// import testCode from './test.cg?raw';
|
||||
// import counterApp from './counter.cg?raw';
|
||||
import osCode from './os.cg?raw';
|
||||
|
||||
const canvas = document.createElement('canvas') as HTMLCanvasElement;
|
||||
document.body.appendChild(canvas);
|
||||
|
|
@ -28,7 +26,7 @@ if (clearButton) {
|
|||
const cgCode = stdlibCode + '\n' +
|
||||
designTokensCode + '\n' +
|
||||
uiComponentsCode + '\n' +
|
||||
textInputCode + '\n'
|
||||
osCode + '\n'
|
||||
|
||||
try {
|
||||
const tokens = tokenize(cgCode);
|
||||
|
|
@ -41,7 +39,8 @@ try {
|
|||
const persisted = loadStore();
|
||||
|
||||
for (const def of definitions) {
|
||||
const body = persisted?.[def.name]?.body ?? def.body;
|
||||
// const body = persisted?.[def.name]?.body ?? def.body;
|
||||
const body = def.body;
|
||||
|
||||
const deps = startTracking(def.name);
|
||||
const value = evaluate(body, env, cgCode);
|
||||
|
|
|
|||
41
src/os.cg
Normal file
41
src/os.cg
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
osState = {
|
||||
query = "",
|
||||
debug = "DEBUG",
|
||||
selectedPaletteIndex = 0
|
||||
};
|
||||
|
||||
init = {
|
||||
test = ""
|
||||
};
|
||||
|
||||
update = state event \ event
|
||||
| _ \ state;
|
||||
|
||||
view = state viewport \
|
||||
Positioned {
|
||||
x = 30,
|
||||
y = 30,
|
||||
child = Column {
|
||||
gap = 10,
|
||||
children = [
|
||||
textInput {
|
||||
key = "query",
|
||||
initialValue = osState.query,
|
||||
initialFocus = True,
|
||||
w = 300,
|
||||
h = 40,
|
||||
onChange = text \ osState.query := text,
|
||||
onKeyDown = key \ key
|
||||
| ArrowUp \ osState.selectedPaletteIndex := max 0 (osState.selectedPaletteIndex + 1)
|
||||
| ArrowDown \ osState.selectedPaletteIndex := osState.selectedPaletteIndex - 1
|
||||
},
|
||||
Text { content = osState.debug, x = 8, y = 16 },
|
||||
Column {
|
||||
gap = 10,
|
||||
children = map (t \ Text { content = t, x = 8, y = 16 }) (storeSearch osState.query)
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
|
||||
os = { init = init, update = update, view = view }
|
||||
|
|
@ -140,25 +140,7 @@ export class Parser {
|
|||
}
|
||||
|
||||
private parseExpression(): AST {
|
||||
// Lambda
|
||||
if (this.isLambdaStart()) {
|
||||
return this.parseLambda();
|
||||
}
|
||||
|
||||
// Let
|
||||
if ((this.current().kind === 'ident' || this.current().kind === 'underscore') && this.peek().kind === 'equals') {
|
||||
return this.parseLet();
|
||||
}
|
||||
|
||||
let expr = this.parseInfix();
|
||||
|
||||
// Rebind
|
||||
if (this.current().kind == 'colon-equals') {
|
||||
const token = this.current();
|
||||
this.advance();
|
||||
const value = this.parseExpression();
|
||||
return { kind: 'rebind', target: expr, value, ...this.getPos(token) };
|
||||
}
|
||||
let expr = this.parseExpressionNoMatch();
|
||||
|
||||
// Match
|
||||
if (this.current().kind === 'pipe') {
|
||||
|
|
@ -180,9 +162,18 @@ export class Parser {
|
|||
return this.parseLet();
|
||||
}
|
||||
|
||||
return this.parseInfix();
|
||||
}
|
||||
let expr = this.parseInfix();
|
||||
|
||||
// Rebind
|
||||
if (this.current().kind == 'colon-equals') {
|
||||
const token = this.current();
|
||||
this.advance();
|
||||
const value = this.parseExpression();
|
||||
return { kind: 'rebind', target: expr, value, ...this.getPos(token) };
|
||||
}
|
||||
|
||||
return expr;
|
||||
}
|
||||
|
||||
private parseMatch(expr: AST): AST {
|
||||
const token = this.current();
|
||||
|
|
@ -241,7 +232,10 @@ export class Parser {
|
|||
let spreadName: string | null = null;
|
||||
|
||||
while (this.current().kind !== 'close-bracket') {
|
||||
if (!first) this.expect('comma');
|
||||
if (!first) {
|
||||
this.expect('comma');
|
||||
if (this.current().kind === 'close-bracket') break; // trailing commas
|
||||
}
|
||||
first = false;
|
||||
|
||||
// Spread
|
||||
|
|
@ -271,7 +265,10 @@ export class Parser {
|
|||
let first = true;
|
||||
|
||||
while (this.current().kind !== 'close-brace') {
|
||||
if (!first) this.expect('comma');
|
||||
if (!first) {
|
||||
this.expect('comma');
|
||||
if (this.current().kind === 'close-brace') break; // trailing commas
|
||||
}
|
||||
first = false;
|
||||
|
||||
const keyToken = this.expect('ident');
|
||||
|
|
@ -409,6 +406,7 @@ export class Parser {
|
|||
while (this.current().kind !== 'close-brace') {
|
||||
if (!first) {
|
||||
this.expect('comma');
|
||||
if (this.current().kind === 'close-brace') break; // trailing commas
|
||||
}
|
||||
first = false;
|
||||
|
||||
|
|
@ -454,6 +452,7 @@ export class Parser {
|
|||
while (this.current().kind !== 'close-bracket') {
|
||||
if (!first) {
|
||||
this.expect('comma');
|
||||
if (this.current().kind === 'close-bracket') break; // trailing commas
|
||||
}
|
||||
first = false;
|
||||
|
||||
|
|
@ -481,6 +480,7 @@ export class Parser {
|
|||
while (this.current().kind !== 'close-brace') {
|
||||
if (!first) {
|
||||
this.expect('comma');
|
||||
if (this.current().kind === 'close-brace') break; // trailing commas
|
||||
}
|
||||
first = false;
|
||||
|
||||
|
|
|
|||
|
|
@ -64,46 +64,41 @@ textInput = config \ Stateful {
|
|||
|
||||
# update : State \ Event \ State
|
||||
update = state event \ event
|
||||
| ArrowLeft \ (
|
||||
| ArrowLeft \
|
||||
newCursorPos = max 0 (state.cursorPos - 1);
|
||||
newScroll = calcScrollOffset state.text newCursorPos state.scrollOffset 284;
|
||||
newState = state.{ text = state.text, cursorPos = newCursorPos, scrollOffset = newScroll };
|
||||
_ = debug "ArrowLeft" [];
|
||||
{ state = newState, emit = [] }
|
||||
)
|
||||
{ state = newState, emit = [config.onKeyDown] }
|
||||
|
||||
| ArrowRight \ (
|
||||
| ArrowRight \
|
||||
newCursorPos = min (len state.text) (state.cursorPos + 1);
|
||||
newScroll = calcScrollOffset state.text newCursorPos state.scrollOffset 284;
|
||||
newState = state.{ text = state.text, cursorPos = newCursorPos, scrollOffset = newScroll };
|
||||
{ state = newState, emit = [] }
|
||||
)
|
||||
{ state = newState, emit = [config.onKeyDown] }
|
||||
|
||||
| Backspace \ (
|
||||
| Backspace \
|
||||
newText = deleteChar state.text state.cursorPos;
|
||||
newCursorPos = max 0 (state.cursorPos - 1);
|
||||
newScroll = calcScrollOffset newText newCursorPos state.scrollOffset 284;
|
||||
newState = state.{ text = newText, cursorPos = newCursorPos, scrollOffset = newScroll };
|
||||
{ state = newState, emit = [config.onChange newText] }
|
||||
)
|
||||
{ state = newState, emit = [config.onChange newText, config.onKeyDown] }
|
||||
|
||||
| Char c \
|
||||
newText = insertChar state.text state.cursorPos c;
|
||||
newCursorPos = state.cursorPos + 1;
|
||||
newScroll = calcScrollOffset newText newCursorPos state.scrollOffset 284;
|
||||
newState = state.{ text = newText, cursorPos = newCursorPos, scrollOffset = newScroll };
|
||||
{ state = newState, emit = [config.onChange newText] }
|
||||
{ state = newState, emit = [config.onChange newText, config.onKeyDown] }
|
||||
|
||||
| Clicked coords \ (
|
||||
| Clicked coords \
|
||||
newCursorPos = findCursorPos state.text coords.x state.scrollOffset 8;
|
||||
newScroll = calcScrollOffset state.text newCursorPos state.scrollOffset 284;
|
||||
newState = state.{ text = state.text, cursorPos = newCursorPos, scrollOffset = newScroll };
|
||||
{ state = newState, emit = [] }
|
||||
)
|
||||
|
||||
| Focused \ { state = state.{ focused = True }, emit = [] }
|
||||
| Blurred \ { state = state.{ focused = False }, emit = [] }
|
||||
| _ \ { state = state, emit = [] },
|
||||
| event \ { state = state, emit = [config.onKeyDown event] },
|
||||
|
||||
view = state \
|
||||
textBeforeCursor = slice state.text 0 state.cursorPos;
|
||||
|
|
|
|||
70
src/ui.ts
70
src/ui.ts
|
|
@ -8,19 +8,7 @@ type ClickRegion = {
|
|||
event: Value;
|
||||
};
|
||||
|
||||
type TextInputRegion = {
|
||||
x: number;
|
||||
y: number;
|
||||
width: number;
|
||||
height: number;
|
||||
inputConstructor: Value;
|
||||
submitConstructor: Value;
|
||||
}
|
||||
|
||||
let clickRegions: ClickRegion[] = [];
|
||||
let textInputRegions: TextInputRegion[] = [];
|
||||
let focusedInput: Value | null = null;
|
||||
let focusedInputSubmit: Value | null = null;
|
||||
|
||||
export function render(ui: UIValue, canvas: HTMLCanvasElement) {
|
||||
const ctx = canvas.getContext('2d');
|
||||
|
|
@ -32,7 +20,6 @@ export function render(ui: UIValue, canvas: HTMLCanvasElement) {
|
|||
ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
|
||||
|
||||
clickRegions = [];
|
||||
textInputRegions = [];
|
||||
renderUI(ui, ctx, 0, 0);
|
||||
}
|
||||
}
|
||||
|
|
@ -209,60 +196,3 @@ export function hitTest(x: number, y: number): { event: Value, relativeX: number
|
|||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
let currentInputValue: string = '';
|
||||
|
||||
export function hitTestTextInput(x: number, y: number): boolean {
|
||||
for (const region of textInputRegions) {
|
||||
if (x >= region.x && x < region.x + region.width &&
|
||||
y >= region.y && y < region.y + region.height) {
|
||||
focusedInput = region.inputConstructor;
|
||||
focusedInputSubmit = region.submitConstructor;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
focusedInput = null;
|
||||
focusedInputSubmit = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
export function getFocusedInput(): Value | null {
|
||||
return focusedInput;
|
||||
}
|
||||
|
||||
export function handleKeyboard(key: string): Value | null {
|
||||
if (!focusedInput) return null;
|
||||
|
||||
if (key === 'Enter') {
|
||||
if (!focusedInputSubmit) return null;
|
||||
return {
|
||||
kind: 'constructor',
|
||||
name: (focusedInputSubmit as any).name,
|
||||
args: [{ kind: 'string', value: currentInputValue }]
|
||||
};
|
||||
}
|
||||
|
||||
if (key === 'Backspace') {
|
||||
const newValue = currentInputValue.slice(0, -1);
|
||||
currentInputValue = newValue;
|
||||
return {
|
||||
kind: 'constructor',
|
||||
name: (focusedInput as any).name,
|
||||
args: [{ kind: 'string', value: newValue }]
|
||||
};
|
||||
}
|
||||
|
||||
// Character
|
||||
if (key.length === 1) {
|
||||
const newValue = currentInputValue + key;
|
||||
currentInputValue = newValue;
|
||||
return {
|
||||
kind: 'constructor',
|
||||
name: (focusedInput as any).name,
|
||||
args: [{ kind: 'string', value: newValue }]
|
||||
};
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue