display editable VPs
This commit is contained in:
parent
f6414985a4
commit
174e34f069
|
@ -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>
|
||||||
|
|
|
@ -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;
|
|
@ -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>
|
||||||
|
|
|
@ -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 ||
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue