display editable VPs

This commit is contained in:
adueck 2023-09-26 15:53:28 -04:00
parent f6414985a4
commit 174e34f069
6 changed files with 179 additions and 42 deletions

View File

@ -138,7 +138,7 @@ function App() {
showing={showing === "parser"} showing={showing === "parser"}
handleChange={() => handleHiderClick("parser")} handleChange={() => handleHiderClick("parser")}
> >
<ParserDemo opts={textOptions} /> <ParserDemo opts={textOptions} entryFeeder={entryFeeder} />
</Hider> </Hider>
</div> </div>
</main> </main>

View File

@ -0,0 +1,91 @@
import * as T from "../../../types";
import { useEffect, useState } from "react";
import VPDisplay from "./VPDisplay";
import VPPicker from "./VPPicker";
import { vpsReducer } from "../../../lib/src/phrase-building/vps-reducer";
export function EditIcon() {
return <i className="fas fa-edit" />;
}
// TODO: Ability to show all variations
function EditableVP({
children,
opts,
formChoice,
noEdit,
length,
mode,
sub,
allVariations,
entryFeeder,
}: {
children: T.VPSelectionState;
opts: T.TextOptions;
formChoice?: boolean;
noEdit?: boolean;
length?: "long" | "short";
mode?: "text" | "blocks";
sub?: string | JSX.Element;
allVariations?: boolean;
entryFeeder: T.EntryFeeder;
}) {
const [editing, setEditing] = useState<boolean>(false);
const [selectedLength, setSelectedLength] = useState<"long" | "short">(
length || "short"
);
const [vps, setVps] = useState<T.VPSelectionState>({ ...children });
useEffect(() => {
setVps({ ...children });
}, [children]);
function handleReset() {
// TODO: this is crazy, how does children get changed after calling setVps ???
setVps(children);
setEditing(false);
}
function handleSetForm(form: T.FormVersion) {
setVps(vpsReducer(vps, { type: "set form", payload: form }));
}
return (
<div className="mt-2 mb-4">
{!noEdit && (
<div
className="text-left clickable mb-2"
style={{ marginBottom: editing ? "0.5rem" : "-0.5rem" }}
onClick={
editing
? handleReset
: () => {
setEditing(true);
}
}
>
{!editing ? <EditIcon /> : <i className="fas fa-undo" />}
</div>
)}
{editing && (
<VPPicker
opts={opts}
entryFeeder={entryFeeder}
vps={vps}
onChange={setVps}
/>
)}
<VPDisplay
opts={opts}
VPS={vps}
justify="left"
onlyOne={allVariations ? false : "concat"}
setForm={handleSetForm}
onLengthChange={setSelectedLength}
length={allVariations ? undefined : selectedLength}
mode={mode}
inlineFormChoice
/>
{sub && <div className="text-muted small">{sub}</div>}
</div>
);
}
export default EditableVP;

View File

@ -2,12 +2,9 @@ import { useState } from "react";
import * as T from "../types"; import * as T from "../types";
import { parsePhrase } from "../lib/src/parsing/parse-phrase"; import { parsePhrase } from "../lib/src/parsing/parse-phrase";
import { tokenizer } from "../lib/src/parsing/tokenizer"; import { tokenizer } from "../lib/src/parsing/tokenizer";
import { import { NPDisplay } from "../components/library";
CompiledPTextDisplay, import EditableVP from "../components/src/vp-explorer/EditableVP";
NPDisplay, import { uncompleteVPSelection } from "../lib/src/phrase-building/vp-tools";
compileVP,
renderVP,
} from "../components/library";
const working = [ const working = [
"limited demo vocab", "limited demo vocab",
@ -46,7 +43,13 @@ const examples = [
"وبه مې وینې", "وبه مې وینې",
]; ];
function ParserDemo({ opts }: { opts: T.TextOptions }) { function ParserDemo({
opts,
entryFeeder,
}: {
opts: T.TextOptions;
entryFeeder: T.EntryFeeder;
}) {
const [text, setText] = useState<string>(""); const [text, setText] = useState<string>("");
const [result, setResult] = useState< const [result, setResult] = useState<
ReturnType<typeof parsePhrase>["success"] ReturnType<typeof parsePhrase>["success"]
@ -129,29 +132,37 @@ function ParserDemo({ opts }: { opts: T.TextOptions }) {
"inflected" in res ? ( "inflected" in res ? (
<NPDisplay NP={res.selection} inflected={res.inflected} opts={opts} /> <NPDisplay NP={res.selection} inflected={res.inflected} opts={opts} />
) : "verb" in res ? ( ) : "verb" in res ? (
(() => { <EditableVP
try { opts={opts}
const rendered = renderVP(res); entryFeeder={entryFeeder}
const compiled = compileVP(rendered, res.form); formChoice={false}
return ( allVariations={true}
<div> >
<CompiledPTextDisplay compiled={compiled} opts={opts} /> {uncompleteVPSelection(res)}
{compiled.e && ( </EditableVP>
<div className={`text-muted mt-2 text-center`}>
{compiled.e.map((e, i) => (
<div key={i}>{e}</div>
))}
</div>
)}
</div>
);
} catch (e) {
console.error(e);
console.log({ res });
return <div>ERROR</div>;
}
})()
) : ( ) : (
// (() => {
// try {
// const rendered = renderVP(res);
// const compiled = compileVP(rendered, res.form);
// return (
// <div>
// <CompiledPTextDisplay compiled={compiled} opts={opts} />
// {compiled.e && (
// <div className={`text-muted mt-2 text-center`}>
// {compiled.e.map((e, i) => (
// <div key={i}>{e}</div>
// ))}
// </div>
// )}
// </div>
// );
// } catch (e) {
// console.error(e);
// console.log({ res });
// return <div>ERROR</div>;
// }
// })()
<samp> <samp>
<pre>{JSON.stringify(res, null, " ")}</pre> <pre>{JSON.stringify(res, null, " ")}</pre>
</samp> </samp>

View File

@ -1,6 +1,10 @@
import * as T from "../../../types"; import * as T from "../../../types";
import { concatPsString, psRemove, psStringEquals } from "../p-text-helpers"; import { concatPsString, psRemove, psStringEquals } from "../p-text-helpers";
import { isPerfectTense } from "../type-predicates"; import {
isImperativeTense,
isPerfectTense,
isVerbTense,
} from "../type-predicates";
import * as grammarUnits from "../grammar-units"; import * as grammarUnits from "../grammar-units";
import { isSecondPerson, randomNumber } from "../misc-helpers"; import { isSecondPerson, randomNumber } from "../misc-helpers";
import { import {
@ -278,6 +282,36 @@ export function completeVPSelection(
}; };
} }
export function uncompleteVPSelection(
vps: T.VPSelectionComplete
): T.VPSelectionState {
const tense = vps.verb.tense;
const tenseCategory = isVerbTense(tense)
? "basic"
: isPerfectTense(tense)
? "perfect"
: isImperativeTense(tense)
? "modal"
: "imperative";
return {
...vps,
verb: {
...vps.verb,
verbTense:
tenseCategory === "basic" ? (tense as T.VerbTense) : "presentVerb",
perfectTense:
tenseCategory === "perfect"
? (tense as T.PerfectTense)
: "presentPerfect",
imperativeTense:
tenseCategory === "imperative"
? (tense as T.ImperativeTense)
: "imperfectiveImperative",
tenseCategory,
},
};
}
export function isThirdPerson(p: T.Person): boolean { export function isThirdPerson(p: T.Person): boolean {
return ( return (
p === T.Person.ThirdSingMale || p === T.Person.ThirdSingMale ||

View File

@ -3,6 +3,17 @@ import { pashtoConsonants } from "./pashto-consonants";
import { endsWith } from "./p-text-helpers"; import { endsWith } from "./p-text-helpers";
import { countSyllables } from "./accent-helpers"; import { countSyllables } from "./accent-helpers";
const verbTenses: T.VerbTense[] = [
"presentVerb",
"subjunctiveVerb",
"perfectiveFuture",
"imperfectiveFuture",
"perfectivePast",
"imperfectivePast",
"habitualPerfectivePast",
"habitualImperfectivePast",
];
export function isTlulVerb(e: T.VerbEntry | T.VerbDictionaryEntry): boolean { export function isTlulVerb(e: T.VerbEntry | T.VerbDictionaryEntry): boolean {
const entry = "entry" in e ? e.entry : e; const entry = "entry" in e ? e.entry : e;
return ( return (
@ -276,16 +287,6 @@ export function isPerfectTense(tense: T.Tense): tense is T.PerfectTense {
} }
export function isVerbTense(tense: T.Tense): tense is T.VerbTense { export function isVerbTense(tense: T.Tense): tense is T.VerbTense {
const verbTenses: T.VerbTense[] = [
"presentVerb",
"subjunctiveVerb",
"perfectiveFuture",
"imperfectiveFuture",
"perfectivePast",
"imperfectivePast",
"habitualPerfectivePast",
"habitualImperfectivePast",
];
return verbTenses.some((x) => x === tense); return verbTenses.some((x) => x === tense);
} }

View File

@ -787,7 +787,7 @@ export type VerbFormName =
export type VerbSelectionComplete = Omit< export type VerbSelectionComplete = Omit<
VerbSelection, VerbSelection,
"object" | "verbTense" | "perfectTense" | "imperativeTense" | "tenseCategory" "verbTense" | "perfectTense" | "imperativeTense" | "tenseCategory"
> & { > & {
tense: VerbFormName; tense: VerbFormName;
}; };