sandwiches in eqcomplement and adjectives
This commit is contained in:
parent
e8ec806ecb
commit
5c9b7b7c3e
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@lingdocs/pashto-inflector",
|
"name": "@lingdocs/pashto-inflector",
|
||||||
"version": "2.5.6",
|
"version": "2.5.7",
|
||||||
"author": "lingdocs.com",
|
"author": "lingdocs.com",
|
||||||
"description": "A Pashto inflection and verb conjugation engine, inculding React components for displaying Pashto text, inflections, and conjugations",
|
"description": "A Pashto inflection and verb conjugation engine, inculding React components for displaying Pashto text, inflections, and conjugations",
|
||||||
"homepage": "https://verbs.lingdocs.com",
|
"homepage": "https://verbs.lingdocs.com",
|
||||||
|
|
|
@ -146,6 +146,7 @@ export function SandwichSelect<E extends T.Sandwich>(props: {
|
||||||
props.onChange(s);
|
props.onChange(s);
|
||||||
}
|
}
|
||||||
return <div style={divStyle}>
|
return <div style={divStyle}>
|
||||||
|
<div>Sandwich Base</div>
|
||||||
<Select
|
<Select
|
||||||
styles={customStyles}
|
styles={customStyles}
|
||||||
isSearchable={true}
|
isSearchable={true}
|
||||||
|
|
|
@ -92,6 +92,7 @@ function EPExplorer(props: {
|
||||||
onChange={payload => adjustEps({ type: "set predicate NP", payload })}
|
onChange={payload => adjustEps({ type: "set predicate NP", payload })}
|
||||||
opts={props.opts}
|
opts={props.opts}
|
||||||
/> : <EqCompPicker
|
/> : <EqCompPicker
|
||||||
|
phraseIsComplete={phraseIsComplete}
|
||||||
comp={eps.predicate.type === "Complement" ? eps.predicate.Complement : undefined}
|
comp={eps.predicate.type === "Complement" ? eps.predicate.Complement : undefined}
|
||||||
onChange={payload => adjustEps({ type: "set predicate comp", payload })}
|
onChange={payload => adjustEps({ type: "set predicate comp", payload })}
|
||||||
opts={props.opts}
|
opts={props.opts}
|
||||||
|
|
|
@ -6,6 +6,7 @@ import SandwichPicker from "../../np-picker/SandwichPicker";
|
||||||
const compTypes: T.EqCompType[] = ["adjective", "loc. adv.", "sandwich"];
|
const compTypes: T.EqCompType[] = ["adjective", "loc. adv.", "sandwich"];
|
||||||
|
|
||||||
function EqCompPicker(props: {
|
function EqCompPicker(props: {
|
||||||
|
phraseIsComplete: boolean,
|
||||||
onChange: (comp: T.EqCompSelection | undefined) => void,
|
onChange: (comp: T.EqCompSelection | undefined) => void,
|
||||||
comp: T.EqCompSelection | undefined,
|
comp: T.EqCompSelection | undefined,
|
||||||
opts: T.TextOptions,
|
opts: T.TextOptions,
|
||||||
|
@ -62,10 +63,11 @@ function EqCompPicker(props: {
|
||||||
<div style={{ minWidth: "9rem" }}>
|
<div style={{ minWidth: "9rem" }}>
|
||||||
{compType === "adjective" ?
|
{compType === "adjective" ?
|
||||||
<AdjectivePicker
|
<AdjectivePicker
|
||||||
entryFeeder={props.entryFeeder.adjectives}
|
entryFeeder={props.entryFeeder}
|
||||||
adjective={props.comp?.type === "adjective" ? props.comp : undefined}
|
adjective={props.comp?.type === "adjective" ? props.comp : undefined}
|
||||||
opts={props.opts}
|
opts={props.opts}
|
||||||
onChange={props.onChange}
|
onChange={props.onChange}
|
||||||
|
phraseIsComplete={props.phraseIsComplete}
|
||||||
/>
|
/>
|
||||||
: compType === "loc. adv."
|
: compType === "loc. adv."
|
||||||
? <LocativeAdverbPicker
|
? <LocativeAdverbPicker
|
||||||
|
@ -81,7 +83,7 @@ function EqCompPicker(props: {
|
||||||
sandwich={props.comp?.type === "sandwich" ? props.comp : undefined}
|
sandwich={props.comp?.type === "sandwich" ? props.comp : undefined}
|
||||||
entryFeeder={props.entryFeeder}
|
entryFeeder={props.entryFeeder}
|
||||||
// TODO: get phraseIsComplete working here
|
// TODO: get phraseIsComplete working here
|
||||||
phraseIsComplete={false}
|
phraseIsComplete={props.phraseIsComplete}
|
||||||
/>
|
/>
|
||||||
: null}
|
: null}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -4,9 +4,10 @@ import AdjectivePicker from "./AdjectivePicker";
|
||||||
|
|
||||||
function AdjectiveManager(props: {
|
function AdjectiveManager(props: {
|
||||||
adjectives: T.AdjectiveSelection[],
|
adjectives: T.AdjectiveSelection[],
|
||||||
entryFeeder: T.EntryFeederSingleType<T.AdjectiveEntry>,
|
entryFeeder: T.EntryFeeder,
|
||||||
opts: T.TextOptions,
|
opts: T.TextOptions,
|
||||||
onChange: (adjs: T.AdjectiveSelection[]) => void,
|
onChange: (adjs: T.AdjectiveSelection[]) => void,
|
||||||
|
phraseIsComplete: boolean,
|
||||||
}) {
|
}) {
|
||||||
const [adding, setAdding] = useState<boolean>(false);
|
const [adding, setAdding] = useState<boolean>(false);
|
||||||
function handleChange(i: number) {
|
function handleChange(i: number) {
|
||||||
|
@ -44,6 +45,7 @@ function AdjectiveManager(props: {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<AdjectivePicker
|
<AdjectivePicker
|
||||||
|
phraseIsComplete={props.phraseIsComplete}
|
||||||
noTitle
|
noTitle
|
||||||
adjective={undefined}
|
adjective={undefined}
|
||||||
entryFeeder={props.entryFeeder}
|
entryFeeder={props.entryFeeder}
|
||||||
|
@ -64,6 +66,7 @@ function AdjectiveManager(props: {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<AdjectivePicker
|
<AdjectivePicker
|
||||||
|
phraseIsComplete={props.phraseIsComplete}
|
||||||
noTitle
|
noTitle
|
||||||
key={`adj${i}`}
|
key={`adj${i}`}
|
||||||
adjective={adj}
|
adjective={adj}
|
||||||
|
|
|
@ -1,25 +1,54 @@
|
||||||
|
import { useState } from "react";
|
||||||
import * as T from "../../types";
|
import * as T from "../../types";
|
||||||
import EntrySelect from "../EntrySelect";
|
import EntrySelect from "../EntrySelect";
|
||||||
|
import SandwichPicker from "./SandwichPicker";
|
||||||
|
|
||||||
function AdjectivePicker(props: {
|
function AdjectivePicker(props: {
|
||||||
entryFeeder: T.EntryFeederSingleType<T.AdjectiveEntry>,
|
entryFeeder: T.EntryFeeder,
|
||||||
adjective: T.AdjectiveSelection | undefined,
|
adjective: T.AdjectiveSelection | undefined,
|
||||||
onChange: (p: T.AdjectiveSelection | undefined) => void,
|
onChange: (p: T.AdjectiveSelection | undefined) => void,
|
||||||
opts: T.TextOptions,
|
opts: T.TextOptions,
|
||||||
noTitle?: boolean,
|
noTitle?: boolean,
|
||||||
|
phraseIsComplete: boolean,
|
||||||
}) {
|
}) {
|
||||||
|
const [addingSandwich, setAddingSandwich] = useState<boolean>(false);
|
||||||
function onEntrySelect(entry: T.AdjectiveEntry | undefined) {
|
function onEntrySelect(entry: T.AdjectiveEntry | undefined) {
|
||||||
if (!entry) {
|
if (!entry) {
|
||||||
return props.onChange(undefined);
|
return props.onChange(undefined);
|
||||||
}
|
}
|
||||||
props.onChange(makeAdjectiveSelection(entry));
|
props.onChange(makeAdjectiveSelection(entry));
|
||||||
}
|
}
|
||||||
|
function handleSandwichChange(s: T.SandwichSelection<T.Sandwich> | undefined) {
|
||||||
|
if (!props.adjective) return;
|
||||||
|
props.onChange({
|
||||||
|
...props.adjective,
|
||||||
|
sandwich: s,
|
||||||
|
});
|
||||||
|
if (!s) {
|
||||||
|
setAddingSandwich(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
return <div style={{ maxWidth: "225px", minWidth: "125px" }}>
|
return <div style={{ maxWidth: "225px", minWidth: "125px" }}>
|
||||||
{!props.noTitle && <h6>Adjective</h6>}
|
{(props.adjective?.sandwich || addingSandwich) && <SandwichPicker
|
||||||
<div>
|
onChange={handleSandwichChange}
|
||||||
|
opts={props.opts}
|
||||||
|
sandwich={props.adjective?.sandwich}
|
||||||
|
entryFeeder={props.entryFeeder}
|
||||||
|
// TODO: get phraseIsComplete working here
|
||||||
|
phraseIsComplete={props.phraseIsComplete}
|
||||||
|
/>}
|
||||||
|
<div className="d-flex flex-row justify-content-between align-items-baseline">
|
||||||
|
{!props.noTitle && <div>
|
||||||
|
<h6>Adjective</h6>
|
||||||
|
</div>}
|
||||||
|
{(!addingSandwich && props.adjective && !props.adjective?.sandwich)
|
||||||
|
? <div className="clickable" onClick={() => setAddingSandwich(true)}>+ Sandwich</div>
|
||||||
|
: <div></div>}
|
||||||
|
</div>
|
||||||
|
<div className="mt-1">
|
||||||
<EntrySelect
|
<EntrySelect
|
||||||
value={props.adjective?.entry}
|
value={props.adjective?.entry}
|
||||||
entryFeeder={props.entryFeeder}
|
entryFeeder={props.entryFeeder.adjectives}
|
||||||
onChange={onEntrySelect}
|
onChange={onEntrySelect}
|
||||||
name="Adjective"
|
name="Adjective"
|
||||||
opts={props.opts}
|
opts={props.opts}
|
||||||
|
@ -32,6 +61,7 @@ function makeAdjectiveSelection(entry: T.AdjectiveEntry): T.AdjectiveSelection {
|
||||||
return {
|
return {
|
||||||
type: "adjective",
|
type: "adjective",
|
||||||
entry: entry,
|
entry: entry,
|
||||||
|
sandwich: undefined,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -60,6 +60,7 @@ function NPNounPicker(props: {
|
||||||
noun: T.NounSelection | undefined,
|
noun: T.NounSelection | undefined,
|
||||||
onChange: (p: T.NounSelection | undefined) => void,
|
onChange: (p: T.NounSelection | undefined) => void,
|
||||||
opts: T.TextOptions,
|
opts: T.TextOptions,
|
||||||
|
phraseIsComplete: boolean,
|
||||||
}) {
|
}) {
|
||||||
// const [patternFilter, setPatternFilter] = useState<FilterPattern | undefined>(undefined);
|
// const [patternFilter, setPatternFilter] = useState<FilterPattern | undefined>(undefined);
|
||||||
// const [showFilter, setShowFilter] = useState<boolean>(false)
|
// const [showFilter, setShowFilter] = useState<boolean>(false)
|
||||||
|
@ -99,8 +100,9 @@ function NPNounPicker(props: {
|
||||||
/>
|
/>
|
||||||
</div>} */}
|
</div>} */}
|
||||||
{props.noun && <AdjectiveManager
|
{props.noun && <AdjectiveManager
|
||||||
|
phraseIsComplete={props.phraseIsComplete}
|
||||||
adjectives={props.noun?.adjectives}
|
adjectives={props.noun?.adjectives}
|
||||||
entryFeeder={props.entryFeeder.adjectives}
|
entryFeeder={props.entryFeeder}
|
||||||
opts={props.opts}
|
opts={props.opts}
|
||||||
onChange={handelAdjectivesUpdate}
|
onChange={handelAdjectivesUpdate}
|
||||||
/>}
|
/>}
|
||||||
|
|
|
@ -52,7 +52,9 @@ function NPPicker(props: {
|
||||||
setNpType(ntp);
|
setNpType(ntp);
|
||||||
onChange(pronoun);
|
onChange(pronoun);
|
||||||
} else {
|
} else {
|
||||||
|
if (props.np) {
|
||||||
onChange(undefined);
|
onChange(undefined);
|
||||||
|
}
|
||||||
setNpType(ntp);
|
setNpType(ntp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -126,7 +128,7 @@ function NPPicker(props: {
|
||||||
}}>
|
}}>
|
||||||
<div className="d-flex flex-row text-muted mb-2">
|
<div className="d-flex flex-row text-muted mb-2">
|
||||||
<div>{possesiveLabel}:</div>
|
<div>{possesiveLabel}:</div>
|
||||||
{(props.np.possesor && !props.isShrunk) && <div className="clickable ml-3 mr-2" onClick={handleToggleShrunken}>
|
{(props.np.possesor && !props.isShrunk && props.phraseIsComplete) && <div className="clickable ml-3 mr-2" onClick={handleToggleShrunken}>
|
||||||
{!props.np.possesor.shrunken ? "🪄" : "👶"}
|
{!props.np.possesor.shrunken ? "🪄" : "👶"}
|
||||||
</div>}
|
</div>}
|
||||||
<div className="clickable ml-2" onClick={() => {
|
<div className="clickable ml-2" onClick={() => {
|
||||||
|
@ -160,6 +162,7 @@ function NPPicker(props: {
|
||||||
/>
|
/>
|
||||||
: npType === "noun"
|
: npType === "noun"
|
||||||
? <NounPicker
|
? <NounPicker
|
||||||
|
phraseIsComplete={props.phraseIsComplete}
|
||||||
entryFeeder={props.entryFeeder}
|
entryFeeder={props.entryFeeder}
|
||||||
noun={(props.np && props.np.type === "noun") ? props.np : undefined}
|
noun={(props.np && props.np.type === "noun") ? props.np : undefined}
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
|
|
|
@ -37,6 +37,14 @@ function SandwichPicker(props: {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return <div>
|
return <div>
|
||||||
|
<div className="d-flex flex-row justify-content-between">
|
||||||
|
<div></div>
|
||||||
|
<div className="text-center">🥪 Sandwich</div>
|
||||||
|
<div className="clickable" onClick={() => props.onChange(undefined)}>
|
||||||
|
<i className="fas fa-trash" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div style={{ border: "1px #6C757D solid", padding: "3px" }}>
|
||||||
{sandwichBase && <div className="mb-2" style={{ margin: "0 auto" }}>
|
{sandwichBase && <div className="mb-2" style={{ margin: "0 auto" }}>
|
||||||
<NPPicker
|
<NPPicker
|
||||||
onChange={handleNounChange}
|
onChange={handleNounChange}
|
||||||
|
@ -46,7 +54,9 @@ function SandwichPicker(props: {
|
||||||
role="object"
|
role="object"
|
||||||
cantClear={true}
|
cantClear={true}
|
||||||
entryFeeder={props.entryFeeder}
|
entryFeeder={props.entryFeeder}
|
||||||
phraseIsComplete={props.phraseIsComplete}
|
// TODO: the shrinking of possesives in sandwiches gets messed up with compilinig 😩
|
||||||
|
// disabling it for now
|
||||||
|
phraseIsComplete={false}
|
||||||
/>
|
/>
|
||||||
</div>}
|
</div>}
|
||||||
<SandwichSelect
|
<SandwichSelect
|
||||||
|
@ -56,6 +66,7 @@ function SandwichPicker(props: {
|
||||||
value={sandwichBase}
|
value={sandwichBase}
|
||||||
onChange={handleSandwichChange}
|
onChange={handleSandwichChange}
|
||||||
/>
|
/>
|
||||||
|
</div>
|
||||||
</div>;
|
</div>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -456,50 +456,71 @@ export function findPossesivesToShrinkInVP(VP: T.VPRendered, f: {
|
||||||
|
|
||||||
function findPossesives(...nps: (T.Rendered<T.NPSelection> | T.ObjectNP | undefined)[]): T.Rendered<T.NPSelection>[] {
|
function findPossesives(...nps: (T.Rendered<T.NPSelection> | T.ObjectNP | undefined)[]): T.Rendered<T.NPSelection>[] {
|
||||||
return nps.reduce((accum, curr) => {
|
return nps.reduce((accum, curr) => {
|
||||||
const res = findPossesiveInNP(curr);
|
const res = findPossesivesInNP(curr);
|
||||||
if (res) return [...accum, res];
|
if (res) return [...accum, ...res];
|
||||||
return accum;
|
return accum;
|
||||||
}, [] as T.Rendered<T.NPSelection>[]);
|
}, [] as T.Rendered<T.NPSelection>[]);
|
||||||
}
|
}
|
||||||
|
|
||||||
function findPossesiveInNP(NP: T.Rendered<T.NPSelection> | T.ObjectNP | undefined): T.Rendered<T.NPSelection> | undefined {
|
function findPossesivesInNP(NP: T.Rendered<T.NPSelection> | T.ObjectNP | undefined): T.Rendered<T.NPSelection>[] {
|
||||||
if (NP === undefined) return undefined;
|
if (NP === undefined) return [];
|
||||||
if (typeof NP !== "object") return undefined;
|
if (typeof NP !== "object") return [];
|
||||||
if (!NP.possesor) return undefined;
|
if (!NP.possesor) return [];
|
||||||
if (NP.possesor.shrunken) {
|
if (NP.adjectives) {
|
||||||
return NP.possesor.np;
|
const { adjectives, ...rest } = NP;
|
||||||
|
return [
|
||||||
|
...findPossesivesInAdjectives(adjectives),
|
||||||
|
...findPossesivesInNP(rest),
|
||||||
|
];
|
||||||
}
|
}
|
||||||
return findPossesiveInNP(NP.possesor.np);
|
if (NP.possesor.shrunken) {
|
||||||
|
return [NP.possesor.np];
|
||||||
|
}
|
||||||
|
return findPossesivesInNP(NP.possesor.np);
|
||||||
|
}
|
||||||
|
|
||||||
|
function findPossesivesInAdjectives(a: T.Rendered<T.AdjectiveSelection>[]): T.Rendered<T.NPSelection>[] {
|
||||||
|
return a.reduce((accum, curr): T.Rendered<T.NPSelection>[] => ([
|
||||||
|
...accum,
|
||||||
|
...findPossesivesInAdjective(curr),
|
||||||
|
]), [] as T.Rendered<T.NPSelection>[])
|
||||||
|
}
|
||||||
|
|
||||||
|
function findPossesivesInAdjective(a: T.Rendered<T.AdjectiveSelection>): T.Rendered<T.NPSelection>[] {
|
||||||
|
if (!a.sandwich) return [];
|
||||||
|
return findPossesivesInNP(a.sandwich.inside);
|
||||||
}
|
}
|
||||||
|
|
||||||
type FoundNP = {
|
type FoundNP = {
|
||||||
np: T.Rendered<T.NPSelection>,
|
np: T.Rendered<T.NPSelection>,
|
||||||
from: "subject" | "predicate",
|
from: "subject" | "predicate" | "AP",
|
||||||
};
|
};
|
||||||
|
|
||||||
export function findPossesivesToShrinkInEP(EP: T.EPRendered): FoundNP[] {
|
export function findPossesivesToShrinkInEP(EP: T.EPRendered): FoundNP[] {
|
||||||
const inSubject = findPossesiveInNP(EP.subject);
|
const inSubject: FoundNP[] = findPossesivesInNP(EP.subject).map(np => ({ np, from: "subject" }));
|
||||||
const inPredicate = (EP.predicate.type === "adjective" || EP.predicate.type === "loc. adv.")
|
const inPredicate: FoundNP[] = ((EP.predicate.type === "loc. adv.")
|
||||||
? undefined
|
? []
|
||||||
: findPossesiveInNP(
|
: (EP.predicate.type === "adjective")
|
||||||
|
? findPossesivesInAdjective(EP.predicate)
|
||||||
|
: findPossesivesInNP(
|
||||||
// @ts-ignore - ts being dumb
|
// @ts-ignore - ts being dumb
|
||||||
EP.predicate as T.NPSelection
|
EP.predicate as T.NPSelection
|
||||||
);
|
)).map(np => ({ np, from: "predicate" }));
|
||||||
return [
|
return [
|
||||||
...inSubject ? [{ np: inSubject, from: "subject"} as FoundNP] : [],
|
...inSubject,
|
||||||
...inPredicate ? [{ np: inPredicate, from: "predicate" } as FoundNP] : [],
|
...inPredicate,
|
||||||
].filter(found => !(found.from === "subject" && EP.omitSubject));
|
].filter(found => !(found.from === "subject" && EP.omitSubject));
|
||||||
}
|
}
|
||||||
|
|
||||||
export function findPossesiveToShrinkInVP(VP: T.VPRendered): T.Rendered<T.NPSelection> | undefined {
|
// export function findPossesiveToShrinkInVP(VP: T.VPRendered): T.Rendered<T.NPSelection>[] {
|
||||||
const obj: T.Rendered<T.NPSelection> | undefined = ("object" in VP && typeof VP.object === "object")
|
// const obj: T.Rendered<T.NPSelection> | undefined = ("object" in VP && typeof VP.object === "object")
|
||||||
? VP.object
|
// ? VP.object
|
||||||
: undefined;
|
// : undefined;
|
||||||
return (
|
// return [
|
||||||
findPossesiveInNP(VP.subject)
|
// ...findPossesivesInNP(VP.subject),
|
||||||
||
|
// ...findPossesivesInNP(obj),
|
||||||
findPossesiveInNP(obj)
|
// ];
|
||||||
);
|
// }
|
||||||
}
|
|
||||||
|
|
||||||
export function shrinkNP(np: T.Rendered<T.NPSelection>): Segment {
|
export function shrinkNP(np: T.Rendered<T.NPSelection>): Segment {
|
||||||
function getFirstSecThird(): 1 | 2 | 3 {
|
function getFirstSecThird(): 1 | 2 | 3 {
|
||||||
|
|
|
@ -9,7 +9,7 @@ function getBaseAndAdjectives(np: T.Rendered<T.NPSelection | T.EqCompSelection>)
|
||||||
if (np.type === "sandwich") {
|
if (np.type === "sandwich") {
|
||||||
return getSandwichPsBaseAndAdjectives(np);
|
return getSandwichPsBaseAndAdjectives(np);
|
||||||
}
|
}
|
||||||
const adjs = np.adjectives;
|
const adjs = "adjectives" in np && np.adjectives;
|
||||||
if (!adjs) {
|
if (!adjs) {
|
||||||
return np.ps;
|
return np.ps;
|
||||||
}
|
}
|
||||||
|
@ -75,9 +75,20 @@ function trimOffShrunkenPossesive(p: T.Rendered<T.NPSelection>): T.Rendered<T.NP
|
||||||
|
|
||||||
export function getPashtoFromRendered(np: T.Rendered<T.NPSelection> | T.Rendered<T.EqCompSelection>, subjectsPerson: false | T.Person): T.PsString[] {
|
export function getPashtoFromRendered(np: T.Rendered<T.NPSelection> | T.Rendered<T.EqCompSelection>, subjectsPerson: false | T.Person): T.PsString[] {
|
||||||
const base = getBaseAndAdjectives(np);
|
const base = getBaseAndAdjectives(np);
|
||||||
if (np.type === "loc. adv." || np.type === "adjective") {
|
if (np.type === "loc. adv.") {
|
||||||
return base;
|
return base;
|
||||||
}
|
}
|
||||||
|
if (np.type === "adjective") {
|
||||||
|
if (!np.sandwich) {
|
||||||
|
return base
|
||||||
|
}
|
||||||
|
const sandwichPs = getPashtoFromRendered(np.sandwich, false);
|
||||||
|
return base.flatMap(p => (
|
||||||
|
sandwichPs.flatMap(s => (
|
||||||
|
concatPsString(s, " ", p)
|
||||||
|
))
|
||||||
|
));
|
||||||
|
}
|
||||||
const trimmed = np.type === "sandwich" ? {
|
const trimmed = np.type === "sandwich" ? {
|
||||||
...np,
|
...np,
|
||||||
inside: trimOffShrunkenPossesive(np.inside),
|
inside: trimOffShrunkenPossesive(np.inside),
|
||||||
|
@ -184,9 +195,12 @@ export function getEnglishFromRendered(r: T.Rendered<T.NPSelection | T.EqCompSel
|
||||||
return getEnglishFromRenderedSandwich(r);
|
return getEnglishFromRenderedSandwich(r);
|
||||||
}
|
}
|
||||||
if (!r.e) return undefined;
|
if (!r.e) return undefined;
|
||||||
if (r.type === "loc. adv." || r.type === "adjective") {
|
if (r.type === "loc. adv.") {
|
||||||
return r.e;
|
return r.e;
|
||||||
}
|
}
|
||||||
|
if (r.type === "adjective") {
|
||||||
|
return getEnglishFromRenderedAdjective(r);
|
||||||
|
}
|
||||||
if (r.type !== "pronoun") {
|
if (r.type !== "pronoun") {
|
||||||
// TODO: shouldn't have to do this 'as' - should be automatically narrowing
|
// TODO: shouldn't have to do this 'as' - should be automatically narrowing
|
||||||
const np = r as T.Rendered<T.NounSelection>;
|
const np = r as T.Rendered<T.NounSelection>;
|
||||||
|
@ -201,3 +215,11 @@ function getEnglishFromRenderedSandwich(r: T.Rendered<T.SandwichSelection<T.Sand
|
||||||
if (!insideE) return undefined;
|
if (!insideE) return undefined;
|
||||||
return `${r.e} ${insideE}`;
|
return `${r.e} ${insideE}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getEnglishFromRenderedAdjective(a: T.Rendered<T.AdjectiveSelection>): string | undefined {
|
||||||
|
if (!a.sandwich) {
|
||||||
|
return a.e;
|
||||||
|
}
|
||||||
|
if (!a.e) return undefined;
|
||||||
|
return `${a.e} ${getEnglishFromRenderedSandwich(a.sandwich)}`;
|
||||||
|
}
|
|
@ -9,6 +9,7 @@ import {
|
||||||
personGender,
|
personGender,
|
||||||
personIsPlural,
|
personIsPlural,
|
||||||
} from "../../lib/misc-helpers";
|
} from "../../lib/misc-helpers";
|
||||||
|
import { renderSandwich } from "./render-sandwich";
|
||||||
|
|
||||||
function chooseInflection(inflections: T.UnisexSet<T.InflectionSet>, pers: T.Person, inflected?: boolean): T.ArrayOneOrMore<T.PsString> {
|
function chooseInflection(inflections: T.UnisexSet<T.InflectionSet>, pers: T.Person, inflected?: boolean): T.ArrayOneOrMore<T.PsString> {
|
||||||
const gender = personGender(pers);
|
const gender = personGender(pers);
|
||||||
|
@ -30,8 +31,8 @@ export function renderAdjectiveSelection(a: T.AdjectiveSelection, person: T.Pers
|
||||||
entry: a.entry,
|
entry: a.entry,
|
||||||
ps: [psStringFromEntry(a.entry)],
|
ps: [psStringFromEntry(a.entry)],
|
||||||
e,
|
e,
|
||||||
inflected: false,
|
inflected,
|
||||||
role,
|
sandwich: a.sandwich ? renderSandwich(a.sandwich) : undefined,
|
||||||
person,
|
person,
|
||||||
}
|
}
|
||||||
if (!infs.inflections || !isUnisexSet(infs.inflections)) {
|
if (!infs.inflections || !isUnisexSet(infs.inflections)) {
|
||||||
|
@ -42,8 +43,8 @@ export function renderAdjectiveSelection(a: T.AdjectiveSelection, person: T.Pers
|
||||||
entry: a.entry,
|
entry: a.entry,
|
||||||
ps: chooseInflection(infs.inflections, person, inflected),
|
ps: chooseInflection(infs.inflections, person, inflected),
|
||||||
e,
|
e,
|
||||||
inflected: false,
|
inflected,
|
||||||
role,
|
|
||||||
person,
|
person,
|
||||||
|
sandwich: a.sandwich ? renderSandwich(a.sandwich) : undefined,
|
||||||
};
|
};
|
||||||
}
|
}
|
11
src/types.ts
11
src/types.ts
|
@ -641,6 +641,7 @@ export type AdverbSelection = {
|
||||||
export type AdjectiveSelection = {
|
export type AdjectiveSelection = {
|
||||||
type: "adjective",
|
type: "adjective",
|
||||||
entry: AdjectiveEntry,
|
entry: AdjectiveEntry,
|
||||||
|
sandwich: SandwichSelection<Sandwich> | undefined,
|
||||||
}
|
}
|
||||||
|
|
||||||
export type LocativeAdverbSelection = {
|
export type LocativeAdverbSelection = {
|
||||||
|
@ -679,6 +680,16 @@ export type Rendered<T extends NPSelection | EqCompSelection | AdjectiveSelectio
|
||||||
? Omit<SandwichSelection<Sandwich>, "inside"> & {
|
? Omit<SandwichSelection<Sandwich>, "inside"> & {
|
||||||
inside: Rendered<NPSelection>,
|
inside: Rendered<NPSelection>,
|
||||||
}
|
}
|
||||||
|
: T extends AdjectiveSelection
|
||||||
|
? {
|
||||||
|
type: "adjective",
|
||||||
|
entry: AdjectiveEntry,
|
||||||
|
ps: PsString[],
|
||||||
|
e?: string,
|
||||||
|
sandwich: Rendered<SandwichSelection<Sandwich>> | undefined,
|
||||||
|
inflected: boolean,
|
||||||
|
person: Person,
|
||||||
|
}
|
||||||
: ReplaceKey<
|
: ReplaceKey<
|
||||||
Omit<T, "changeGender" | "changeNumber" | "changeDistance" | "adjectives" | "possesor">,
|
Omit<T, "changeGender" | "changeNumber" | "changeDistance" | "adjectives" | "possesor">,
|
||||||
"e",
|
"e",
|
||||||
|
|
Loading…
Reference in New Issue