nicer looking

This commit is contained in:
Joeri Exelmans 2025-05-17 09:25:13 +02:00
parent 8abbac4bc9
commit e850952738
14 changed files with 547 additions and 104 deletions

View file

@ -1,10 +1,9 @@
import { useContext, useEffect, useRef } from "react";
import { growEnv } from "dope2";
import { Editor, type EditorState } from "./Editor";
import { EnvContext } from "./EnvContext";
import { evalEditorBlock, evalLetInBlock, scoreResolved, type ResolvedType } from "./eval";
import { evalEditorBlock, evalLetInBlock, makeInnerEnv, scoreResolved } from "./eval";
import { type State2Props } from "./Editor";
import { autoInputWidth } from "./util/dom_trickery";
@ -22,40 +21,54 @@ interface LetInBlockProps extends State2Props<LetInBlockState,EditorState> {
suggestionPriority: (suggestion: SuggestionType) => number;
}
export function makeInnerEnv(env, name: string, value: ResolvedType) {
if (value.kind === "value") {
return growEnv(env)(name)(value)
}
return env;
export function LetInBlock({state, setState, suggestionPriority}: LetInBlockProps) {
return <span className="letIn">
<div className="decl">
<DeclColumns
state={state}
setState={setState}
suggestionPriority={suggestionPriority}
/>
</div>
<div className="inner">
<InnerMost
state={state}
setState={setState}
suggestionPriority={suggestionPriority}
/>
</div>
</span>
}
export function LetInBlock({state, setState, suggestionPriority}: LetInBlockProps) {
const {name, value, inner} = state;
function DeclColumns({state, setState, suggestionPriority}) {
const env = useContext(EnvContext);
const valueResolved = evalEditorBlock(value, env);
const innerEnv = makeInnerEnv(env, name, valueResolved);
const nameRef = useRef<HTMLInputElement>(null);
const {name, value, inner} = state;
const setInner = callback => setState(state => ({...state, inner: callback(state.inner)}));
const setValue = callback => setState(state => ({...state, value: callback(state.value)}));
const onChangeName = (e: React.ChangeEvent<HTMLInputElement>) => {
setState(state => ({...state, name: e.target.value}));
}
const valueSuggestionPriority = (suggestion: SuggestionType) => {
const innerEnv = makeInnerEnv(env, name, suggestion[2]);
const resolved = evalEditorBlock(inner, innerEnv);
return scoreResolved(resolved, suggestionPriority);
};
const innerSuggestionPriority = suggestionPriority;
const nameRef = useRef<HTMLInputElement>(null);
useEffect(() => {
nameRef.current?.focus();
}, []);
useEffect(() => autoInputWidth(nameRef, name, 60), [nameRef, name]);
console.log({innerEnv});
return <span className="letIn">
<div className="decl">
<span className="keyword">let</span>
&nbsp;
const valueResolved = evalEditorBlock(state.value, env);
const innerEnv = makeInnerEnv(env, state.name, valueResolved);
return <>
<span className="keyword column">let&nbsp;</span>
<span className="column rightAlign">
<input
ref={nameRef}
className='editable'
@ -63,30 +76,52 @@ export function LetInBlock({state, setState, suggestionPriority}: LetInBlockProp
placeholder="<name>"
onChange={onChangeName}
/>
<span className="keyword">&nbsp;=&nbsp;</span>
<Editor
state={value}
setState={setValue}
suggestionPriority={(suggestion: SuggestionType) => {
const innerEnv = makeInnerEnv(env, name, suggestion[2]);
const resolved = evalEditorBlock(inner, innerEnv);
return scoreResolved(resolved, suggestionPriority);
}}
onCancel={() => setState(state => state.inner)} // keep inner
/>
<span className="keyword">in</span>
</div>
<div className="inner">
<EnvContext value={innerEnv}>
</span>
<span className="keyword column">&nbsp;=&nbsp;</span>
<span className="column">
<Editor
state={value}
setState={setValue}
suggestionPriority={valueSuggestionPriority}
onCancel={() => setState(state => state.inner)} // keep inner
/>
</span>
{/* <span className="keyword column">in</span> */}
{inner.kind === "let" &&
<EnvContext value={innerEnv}>
<DeclColumns
state={inner}
setState={setInner}
suggestionPriority={(suggestion: SuggestionType) => {
return suggestionPriority(suggestion)
}}
onCancel={() => setState(state => state.value)} // keep value
suggestionPriority={innerSuggestionPriority}
/>
</EnvContext>
</div>
</span>
}
</>;
}
function InnerMost({state, setState, suggestionPriority}) {
const env = useContext(EnvContext);
const setInner = callback => setState(state => ({...state, inner: callback(state.inner)}));
const valueResolved = evalEditorBlock(state.value, env);
const innerEnv = makeInnerEnv(env, state.name, valueResolved);
const onCancel = () => setState(state => state.value);
if (state.inner.kind === "let") {
return <EnvContext value={innerEnv}>
<InnerMost
state={state.inner}
setState={setInner}
suggestionPriority={suggestionPriority}
/>
</EnvContext>;
}
else {
return <EnvContext value={innerEnv}>
<Editor
state={state.inner}
setState={setInner}
suggestionPriority={suggestionPriority}
onCancel={onCancel} // keep value
/>
</EnvContext>
}
}