change the way text suggestions are rendered + option to disable syntactic sugar
This commit is contained in:
parent
ea8c015eff
commit
2d81e42447
12 changed files with 357 additions and 291 deletions
|
|
@ -1,6 +1,6 @@
|
|||
import { useContext, useEffect, useMemo, useRef, useState } from "react";
|
||||
import { memo, useContext, useEffect, useMemo, useRef, useState } from "react";
|
||||
|
||||
import { Double, getType, Int, newDynamic, prettyT, trie } from "dope2";
|
||||
import { getType, prettyT, trie } from "dope2";
|
||||
|
||||
import { EnvContext } from "./EnvContext";
|
||||
import type { Dynamic } from "./eval";
|
||||
|
|
@ -8,7 +8,7 @@ import "./InputBlock.css";
|
|||
import { Type } from "./Type";
|
||||
import type { State2Props } from "./Editor";
|
||||
import { autoInputWidth, focusNextElement, focusPrevElement, setRightMostCaretPosition } from "./util/dom_trickery";
|
||||
import { parseDouble, parseInt } from "./util/parse";
|
||||
import { attemptParseLiteral } from "./eval";
|
||||
|
||||
interface Literal {
|
||||
kind: "literal";
|
||||
|
|
@ -38,13 +38,15 @@ interface InputBlockProps extends State2Props<InputBlockState> {
|
|||
}
|
||||
|
||||
const computeSuggestions = (text, env, suggestionPriority: (s: SuggestionType) => number): PrioritizedSuggestionType[] => {
|
||||
const asDouble = parseDouble(text);
|
||||
const asInt = parseInt(text);
|
||||
const literals = attemptParseLiteral(text);
|
||||
|
||||
const ls = [
|
||||
... (asDouble ? [["literal", asDouble.toString(), newDynamic(asDouble)(Double)]] : []),
|
||||
... (asInt ? [["literal", asInt.toString(), newDynamic(BigInt(asInt))(Int)]] : []),
|
||||
... trie.suggest(env.name2dyn)(text)(Infinity).map(([name,type]) => ["name", name, type]),
|
||||
// literals
|
||||
... literals.map((lit) => ["literal", text, lit]),
|
||||
|
||||
// names
|
||||
... trie.suggest(env.name2dyn)(text)(Infinity)
|
||||
.map(([name,type]) => ["name", name, type]),
|
||||
]
|
||||
// return ls;
|
||||
return ls
|
||||
|
|
@ -60,9 +62,9 @@ export function InputBlock({ state, setState, suggestionPriority, onCancel }: In
|
|||
const [haveFocus, setHaveFocus] = useState(false); // whether to render suggestions or not
|
||||
|
||||
const singleSuggestion = trie.growPrefix(env.name2dyn)(text);
|
||||
const suggestions = useMemo(() => computeSuggestions(text, env, suggestionPriority), [text]);
|
||||
const suggestions = useMemo(() => computeSuggestions(text, env, suggestionPriority), [text, suggestionPriority, env]);
|
||||
|
||||
useEffect(() => autoInputWidth(inputRef, text), [inputRef, text]);
|
||||
useEffect(() => autoInputWidth(inputRef, text+singleSuggestion), [inputRef, text, singleSuggestion]);
|
||||
|
||||
useEffect(() => {
|
||||
if (focus) {
|
||||
|
|
@ -81,7 +83,6 @@ export function InputBlock({ state, setState, suggestionPriority, onCancel }: In
|
|||
}
|
||||
|
||||
const onTextChange = newText => {
|
||||
const found = trie.get(env.name2dyn)(newText);
|
||||
setState(state => ({...state, text: newText}));
|
||||
}
|
||||
|
||||
|
|
@ -162,51 +163,67 @@ export function InputBlock({ state, setState, suggestionPriority, onCancel }: In
|
|||
}
|
||||
};
|
||||
|
||||
return <span>
|
||||
<span className="">
|
||||
{/* Dropdown suggestions */}
|
||||
{haveFocus &&
|
||||
<span style={{display:'inline-block'}}>
|
||||
return <span className="inputBlock">
|
||||
{/* Dropdown suggestions */}
|
||||
{haveFocus &&
|
||||
<span className="suggestionsPlaceholder">
|
||||
<Suggestions
|
||||
suggestions={suggestions}
|
||||
onSelect={onSelectSuggestion}
|
||||
i={i} setI={setI} />
|
||||
</span>
|
||||
}
|
||||
{/* Input box */}
|
||||
<input ref={inputRef}
|
||||
placeholder="<name or literal>"
|
||||
className="editable"
|
||||
value={text}
|
||||
onInput={onInput}
|
||||
onKeyDown={onKeyDown}
|
||||
onFocus={() => setHaveFocus(true)}
|
||||
onBlur={() => setHaveFocus(false)}
|
||||
spellCheck={false}/>
|
||||
{/* Single 'grey' suggestion */}
|
||||
<span className="text-block suggest">{singleSuggestion}</span>
|
||||
</span>
|
||||
</span>
|
||||
}
|
||||
{/* Single 'grey' suggestion */}
|
||||
<span className="editable suggest">{text}{singleSuggestion}</span>
|
||||
{/* Input box */}
|
||||
<input ref={inputRef}
|
||||
placeholder="<name or literal>"
|
||||
className="editable"
|
||||
value={text}
|
||||
onInput={onInput}
|
||||
onKeyDown={onKeyDown}
|
||||
onFocus={() => setHaveFocus(true)}
|
||||
onBlur={() => setHaveFocus(false)}
|
||||
spellCheck={false}/>
|
||||
</span>;
|
||||
}
|
||||
|
||||
function Suggestions({ suggestions, onSelect, i, setI }) {
|
||||
return <>{(suggestions.length > 0) &&
|
||||
<div className={"suggestions"}>
|
||||
{suggestions.map((suggestion, j) =>
|
||||
<SuggestionMemo key={j}
|
||||
{...{setI, j,
|
||||
onSelect,
|
||||
highlighted: i===j,
|
||||
suggestion}}/>)}
|
||||
</div>
|
||||
}</>;
|
||||
}
|
||||
|
||||
interface SuggestionProps {
|
||||
setI: any;
|
||||
j: number;
|
||||
onSelect: any;
|
||||
highlighted: boolean;
|
||||
suggestion: PrioritizedSuggestionType;
|
||||
}
|
||||
|
||||
function Suggestion({ setI, j, onSelect, highlighted, suggestion: [priority, kind, name, dynamic] }: SuggestionProps) {
|
||||
const onMouseEnter = j => () => {
|
||||
setI(j);
|
||||
};
|
||||
const onMouseDown = j => () => {
|
||||
setI(j);
|
||||
onSelect(suggestions[i]);
|
||||
onSelect([priority, kind, name, dynamic]);
|
||||
};
|
||||
return <>{(suggestions.length > 0) &&
|
||||
<div className={"suggestions"}>
|
||||
{suggestions.map(([priority, kind, name, dynamic], j) =>
|
||||
<div
|
||||
key={`${j}_${name}`}
|
||||
className={(i === j ? " selected" : "")}
|
||||
onMouseEnter={onMouseEnter(j)}
|
||||
onMouseDown={onMouseDown(j)}>
|
||||
({priority}) ({kind}) {name} :: <Type type={getType(dynamic)} />
|
||||
</div>)}
|
||||
</div>
|
||||
}</>;
|
||||
}
|
||||
return <div
|
||||
key={`${j}_${name}`}
|
||||
className={(highlighted ? " selected" : "")}
|
||||
onMouseEnter={onMouseEnter(j)}
|
||||
onMouseDown={onMouseDown(j)}>
|
||||
({priority}) ({kind}) {name} :: <Type type={getType(dynamic)} />
|
||||
</div>
|
||||
}
|
||||
|
||||
const SuggestionMemo = memo<SuggestionProps>(Suggestion);
|
||||
Loading…
Add table
Add a link
Reference in a new issue