include imperative
This commit is contained in:
parent
875237439b
commit
10532cb3bb
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@lingdocs/pashto-inflector",
|
||||
"version": "2.1.2",
|
||||
"version": "2.1.3",
|
||||
"author": "lingdocs.com",
|
||||
"description": "A Pashto inflection and verb conjugation engine, inculding React components for displaying Pashto text, inflections, and conjugations",
|
||||
"homepage": "https://verbs.lingdocs.com",
|
||||
|
|
|
@ -69,7 +69,6 @@ function App() {
|
|||
}, [theme])
|
||||
|
||||
const handleVerbIndexChange = (e: any) => {
|
||||
console.log("changing to", e.target.value);
|
||||
setVerbTs(parseInt(e.target.value));
|
||||
}
|
||||
const handleTypeSelection = (e: any) => {
|
||||
|
|
|
@ -14,7 +14,6 @@ type PsStringWSub = T.PsString & { sub?: any };
|
|||
|
||||
function EnglishContent({ children }: { children: (string | JSX.Element)[] | (string | JSX.Element) }) {
|
||||
if (Array.isArray(children)) {
|
||||
console.log(children);
|
||||
return <>
|
||||
{children.map((x) => <EnglishContent>{x}</EnglishContent>)}
|
||||
</>
|
||||
|
|
|
@ -40,7 +40,7 @@ function agreementInfo(info: T.NonComboVerbInfo, displayForm: T.DisplayForm): Re
|
|||
}
|
||||
|
||||
function VerbFormDisplay({ displayForm, textOptions, info, showingFormInfo, english, shortDefault }: {
|
||||
displayForm: T.DisplayForm | T.VerbForm,
|
||||
displayForm: T.DisplayForm | T.VerbForm | T.ImperativeForm,
|
||||
english?: T.EnglishBlock | string,
|
||||
textOptions: T.TextOptions,
|
||||
showingFormInfo: boolean,
|
||||
|
|
|
@ -8,6 +8,7 @@ import {
|
|||
} from "../../lib/np-tools";
|
||||
import { useState, useEffect } from "react";
|
||||
import * as T from "../../types";
|
||||
import { isSecondPerson } from "../../lib/phrase-building/vp-tools";
|
||||
// import { capitalizeFirstLetter } from "../../lib/text-tools";
|
||||
|
||||
const npTypes: T.NPType[] = ["pronoun", "noun", "participle"];
|
||||
|
@ -19,6 +20,7 @@ function NPPicker(props: {
|
|||
asObject?: boolean,
|
||||
opts: T.TextOptions,
|
||||
cantClear?: boolean,
|
||||
is2ndPersonPicker?: boolean,
|
||||
} & ({
|
||||
nouns: (s: string) => T.NounEntry[],
|
||||
verbs: (s: string) => T.VerbEntry[],
|
||||
|
@ -28,6 +30,9 @@ function NPPicker(props: {
|
|||
nouns: T.NounEntry[],
|
||||
verbs: T.VerbEntry[],
|
||||
})) {
|
||||
if (props.is2ndPersonPicker && ((props.np?.type !== "pronoun") || !isSecondPerson(props.np.person))) {
|
||||
throw new Error("can't use 2ndPerson NPPicker without a pronoun");
|
||||
}
|
||||
const [npType, setNpType] = useState<T.NPType | undefined>(props.np ? props.np.type : undefined);
|
||||
useEffect(() => {
|
||||
setNpType(props.np ? props.np.type : undefined);
|
||||
|
@ -78,6 +83,7 @@ function NPPicker(props: {
|
|||
pronoun={props.np}
|
||||
onChange={props.onChange}
|
||||
clearButton={clearButton}
|
||||
is2ndPersonPicker={props.is2ndPersonPicker}
|
||||
opts={props.opts}
|
||||
/>
|
||||
: npType === "noun"
|
||||
|
|
|
@ -2,6 +2,9 @@ import * as T from "../../types";
|
|||
import ButtonSelect from "../ButtonSelect";
|
||||
import useStickyState from "../../lib/useStickyState";
|
||||
import classNames from "classnames";
|
||||
import {
|
||||
isSecondPerson, isThirdPerson,
|
||||
} from "../../lib/phrase-building/vp-tools";
|
||||
|
||||
const gColors = {
|
||||
masc: "LightSkyBlue",
|
||||
|
@ -53,15 +56,18 @@ function pickerStateToPerson(s: PickerState): T.Person {
|
|||
+ (6 * s.col);
|
||||
}
|
||||
|
||||
function NPPronounPicker({ onChange, pronoun, asObject, clearButton, opts }: {
|
||||
function NPPronounPicker({ onChange, pronoun, asObject, clearButton, opts, is2ndPersonPicker }: {
|
||||
pronoun: T.PronounSelection,
|
||||
onChange: (p: T.PronounSelection) => void,
|
||||
asObject?: boolean,
|
||||
clearButton?: JSX.Element,
|
||||
opts: T.TextOptions,
|
||||
is2ndPersonPicker?: boolean,
|
||||
}) {
|
||||
if (is2ndPersonPicker && !isSecondPerson(pronoun.person)) {
|
||||
throw new Error("can't use 2ndPerson NPProunounPicker without a pronoun");
|
||||
}
|
||||
const [display, setDisplay] = useStickyState<"persons" | "p" | "e">("e", "prounoun-picker-display");
|
||||
|
||||
const p = personToPickerState(pronoun.person);
|
||||
function handleClick(row: number, col: number) {
|
||||
const person = pickerStateToPerson({ ...p, row, col });
|
||||
|
@ -92,11 +98,14 @@ function NPPronounPicker({ onChange, pronoun, asObject, clearButton, opts }: {
|
|||
setDisplay(newPerson);
|
||||
}
|
||||
const prs = labels(!!asObject)[display];
|
||||
const pSpec = "near" in prs ? prs[pronoun.distance] : prs;
|
||||
const pSpecA = "near" in prs ? prs[pronoun.distance] : prs;
|
||||
const pSpec = is2ndPersonPicker
|
||||
? [pSpecA[1]]
|
||||
: pSpecA;
|
||||
return <div style={{ maxWidth: "145px", padding: 0 }}>
|
||||
{clearButton}
|
||||
<div className="d-flex flex-row justify-content-around mb-3">
|
||||
<ButtonSelect
|
||||
<div className="d-flex flex-row justify-content-between mb-3">
|
||||
{isThirdPerson(pronoun.person) ? <ButtonSelect
|
||||
xSmall
|
||||
options={[
|
||||
{ label: "Far", value: "far" },
|
||||
|
@ -104,7 +113,7 @@ function NPPronounPicker({ onChange, pronoun, asObject, clearButton, opts }: {
|
|||
]}
|
||||
value={pronoun.distance}
|
||||
handleChange={(g) => handlePronounTypeChange(g as "far" | "near")}
|
||||
/>
|
||||
/> : <div>{` `}</div>}
|
||||
<button className="btn btn-sm btn-outline-secondary" onClick={handleDisplayChange}>
|
||||
{display === "persons" ? "#" : display === "p" ? "PS" : "EN"}
|
||||
</button>
|
||||
|
@ -114,9 +123,13 @@ function NPPronounPicker({ onChange, pronoun, asObject, clearButton, opts }: {
|
|||
{pSpec.map((rw, i) => (
|
||||
<tr>
|
||||
{rw.map((r, j) => {
|
||||
const active = (p.row === i && p.col === j)
|
||||
const active = is2ndPersonPicker
|
||||
? (p.col === j)
|
||||
: (p.row === i && p.col === j);
|
||||
return <td
|
||||
onClick={() => handleClick(i, j)}
|
||||
onClick={() => {
|
||||
handleClick(is2ndPersonPicker ? 1 : i, j);
|
||||
}}
|
||||
className={classNames({ "table-active": active, "text-on-gender-color": active })}
|
||||
style={{
|
||||
backgroundColor: active ? gColors[p.gender] : "inherit",
|
||||
|
|
|
@ -16,7 +16,7 @@ function ChartDisplay({ VS, opts }: { VS: T.VerbSelection, opts: T.TextOptions }
|
|||
: ("transitive" in rawConjugations)
|
||||
? rawConjugations[VS.transitivity === "grammatically transitive" ? "grammaticallyTransitive" : "transitive"]
|
||||
: rawConjugations;
|
||||
const form = getTenseVerbForm(conjugations, getTenseFromVerbSelection(VS), VS.voice);
|
||||
const form = getTenseVerbForm(conjugations, getTenseFromVerbSelection(VS), VS.voice, VS.negative);
|
||||
return <div className="mb-4">
|
||||
<VerbFormDisplay
|
||||
displayForm={form}
|
||||
|
|
|
@ -4,7 +4,8 @@ import {
|
|||
} from "../np-picker/picker-tools";
|
||||
import * as T from "../../types";
|
||||
import ButtonSelect from "../ButtonSelect";
|
||||
import { isModalTense, isPerfectTense, isVerbTense } from "../../lib/type-predicates";
|
||||
import { isImperativeTense, isModalTense, isPerfectTense, isVerbTense } from "../../lib/type-predicates";
|
||||
import { ensure2ndPersSubjPronounAndNoConflict } from "../../lib/phrase-building/vp-tools";
|
||||
|
||||
const verbTenseOptions: { label: string | JSX.Element, value: T.VerbTense }[] = [{
|
||||
label: <div><i className="fas fa-video mr-2" />present</div>,
|
||||
|
@ -55,8 +56,16 @@ const perfectTenseOptions: { label: string | JSX.Element, value: T.PerfectTense
|
|||
value: "pastSubjunctivePerfect",
|
||||
}];
|
||||
|
||||
export function getRandomTense(o?: T.PerfectTense | T.VerbTense | T.ModalTense): T.PerfectTense | T.VerbTense | T.ModalTense {
|
||||
let tns: T.PerfectTense | T.VerbTense | T.ModalTense;
|
||||
const imperativeTenseOptions: { label: string | JSX.Element, value: T.ImperativeTense }[] = [{
|
||||
label: <div><i className="fas fa-video mr-2" />imperfective imp.</div>,
|
||||
value: "imperfectiveImperative",
|
||||
}, {
|
||||
label: <div><i className="fas fa-camera mr-2" />perfective imp.</div>,
|
||||
value: "perfectiveImperative",
|
||||
}];
|
||||
|
||||
export function getRandomTense(o?: T.PerfectTense | T.VerbTense | T.ModalTense | T.ImperativeTense): T.PerfectTense | T.VerbTense | T.ModalTense | T.ImperativeTense {
|
||||
let tns: T.PerfectTense | T.VerbTense | T.ModalTense | T.ImperativeTense;
|
||||
const oldTenseCategory = !o
|
||||
? undefined
|
||||
: getTenseCategory(o);
|
||||
|
@ -64,6 +73,8 @@ export function getRandomTense(o?: T.PerfectTense | T.VerbTense | T.ModalTense):
|
|||
? perfectTenseOptions
|
||||
: oldTenseCategory === "modal"
|
||||
? verbTenseOptions.map(x => ({ ...x, value: `${x.value}Modal` as T.ModalTense }))
|
||||
: oldTenseCategory === "imperative"
|
||||
? imperativeTenseOptions
|
||||
: verbTenseOptions;
|
||||
do {
|
||||
tns = tenseOptions[
|
||||
|
@ -81,7 +92,7 @@ function TensePicker(props: ({
|
|||
onChange: (p: T.VPSelection) => void,
|
||||
mode: "charts" | "phrases" | "quiz",
|
||||
}) {
|
||||
function onTenseSelect(o: { value: T.VerbTense | T.PerfectTense } | null) {
|
||||
function onTenseSelect(o: { value: T.VerbTense | T.PerfectTense | T.ImperativeTense } | null) {
|
||||
if ("vpsComplete" in props) return;
|
||||
const value = o?.value ? o.value : undefined;
|
||||
if (props.vps.verb && value) {
|
||||
|
@ -94,6 +105,15 @@ function TensePicker(props: ({
|
|||
tenseCategory: "perfect",
|
||||
},
|
||||
});
|
||||
} else if (isImperativeTense(value)) {
|
||||
props.onChange({
|
||||
...props.vps,
|
||||
verb: {
|
||||
...props.vps.verb,
|
||||
imperativeTense: value,
|
||||
tenseCategory: "imperative",
|
||||
},
|
||||
});
|
||||
} else {
|
||||
props.onChange({
|
||||
...props.vps,
|
||||
|
@ -112,9 +132,19 @@ function TensePicker(props: ({
|
|||
if ("vpsComplete" in props) return;
|
||||
if (!props.vps.verb) return;
|
||||
return () => {
|
||||
const tenses = props.vps.verb.tenseCategory === "perfect" ? perfectTenseOptions : verbTenseOptions;
|
||||
// TODO: ABSTRACT THIS - SAFER
|
||||
const tenses = props.vps.verb.tenseCategory === "perfect"
|
||||
? perfectTenseOptions
|
||||
: props.vps.verb.tenseCategory === "imperative"
|
||||
? imperativeTenseOptions
|
||||
: verbTenseOptions;
|
||||
const currIndex = tenses.findIndex(tn => tn.value === props.vps.verb[
|
||||
props.vps.verb.tenseCategory === "perfect" ? "perfectTense" : "verbTense"
|
||||
// TODO: ABSTRACT THIS? - SAFER
|
||||
props.vps.verb.tenseCategory === "perfect"
|
||||
? "perfectTense"
|
||||
: props.vps.verb.tenseCategory === "imperative"
|
||||
? "imperativeTense"
|
||||
: "verbTense"
|
||||
]);
|
||||
if (currIndex === -1) {
|
||||
console.error("error moving tense", dir);
|
||||
|
@ -139,9 +169,19 @@ function TensePicker(props: ({
|
|||
});
|
||||
}
|
||||
}
|
||||
function onTenseCategorySelect(value: "basic" | "modal" | "perfect") {
|
||||
function onTenseCategorySelect(value: "basic" | "modal" | "perfect" | "imperative") {
|
||||
if ("vpsComplete" in props) return;
|
||||
if (props.vps.verb) {
|
||||
if (value === "imperative") {
|
||||
props.onChange(ensure2ndPersSubjPronounAndNoConflict({
|
||||
...props.vps,
|
||||
verb: {
|
||||
...props.vps.verb,
|
||||
tenseCategory: value,
|
||||
},
|
||||
}));
|
||||
return;
|
||||
}
|
||||
props.onChange({
|
||||
...props.vps,
|
||||
verb: {
|
||||
|
@ -153,40 +193,47 @@ function TensePicker(props: ({
|
|||
}
|
||||
const tOptions = ("vps" in props && (props.vps.verb?.tenseCategory === "perfect"))
|
||||
? perfectTenseOptions
|
||||
: ("vps" in props && (props.vps.verb?.tenseCategory === "imperative"))
|
||||
? imperativeTenseOptions
|
||||
: verbTenseOptions;
|
||||
return <div>
|
||||
<div style={{ maxWidth: "300px", minWidth: "250px", margin: "0 auto" }}>
|
||||
<div className="d-flex flex-row justify-content-between align-items-center">
|
||||
<div className="h5">Tense:</div>
|
||||
{("vpsComplete" in props || props.vps.verb) && <div className="mb-2">
|
||||
<ButtonSelect
|
||||
small
|
||||
value={"vpsComplete" in props
|
||||
? getTenseCategory(props.vpsComplete.verb.tense)
|
||||
: props.vps.verb.tenseCategory}
|
||||
options={[{
|
||||
label: "Basic",
|
||||
value: "basic",
|
||||
}, {
|
||||
label: "Perfect",
|
||||
value: "perfect",
|
||||
}, {
|
||||
label: "Modal",
|
||||
value: "modal",
|
||||
}]}
|
||||
handleChange={props.mode !== "quiz" ? onTenseCategorySelect : () => null}
|
||||
/>
|
||||
</div>}
|
||||
</div>
|
||||
<div className="h5">Tense:</div>
|
||||
{("vpsComplete" in props || props.vps.verb) && <div className="mb-2">
|
||||
<ButtonSelect
|
||||
small
|
||||
value={"vpsComplete" in props
|
||||
? getTenseCategory(props.vpsComplete.verb.tense)
|
||||
: props.vps.verb.tenseCategory}
|
||||
options={[{
|
||||
label: "Basic",
|
||||
value: "basic",
|
||||
}, {
|
||||
label: "Perfect",
|
||||
value: "perfect",
|
||||
}, {
|
||||
label: "Modal",
|
||||
value: "modal",
|
||||
}, {
|
||||
label: "Imperative",
|
||||
value: "imperative",
|
||||
}]}
|
||||
handleChange={props.mode !== "quiz" ? onTenseCategorySelect : () => null}
|
||||
/>
|
||||
</div>}
|
||||
{"vpsComplete" in props
|
||||
? <div style={{ fontSize: "larger" }} className="mb-3">
|
||||
{[...verbTenseOptions, ...perfectTenseOptions].find(o => o.value === props.vpsComplete.verb.tense)?.label}
|
||||
{[...verbTenseOptions, ...perfectTenseOptions, ...imperativeTenseOptions].find(o => o.value === props.vpsComplete.verb.tense)?.label}
|
||||
</div>
|
||||
: <Select
|
||||
isSearchable={false}
|
||||
// for some reason can't use tOptions with find here;
|
||||
value={props.vps.verb && ([...verbTenseOptions, ...perfectTenseOptions].find(o => o.value === props.vps.verb[
|
||||
props.vps.verb.tenseCategory === "perfect" ? "perfectTense" : "verbTense"
|
||||
value={props.vps.verb && ([...verbTenseOptions, ...perfectTenseOptions, ...imperativeTenseOptions].find(o => o.value === props.vps.verb[
|
||||
props.vps.verb.tenseCategory === "perfect"
|
||||
? "perfectTense"
|
||||
: props.vps.verb.tenseCategory === "imperative"
|
||||
? "imperativeTense"
|
||||
: "verbTense"
|
||||
]))}
|
||||
onChange={onTenseSelect}
|
||||
className="mb-2"
|
||||
|
@ -219,7 +266,7 @@ function TensePicker(props: ({
|
|||
|
||||
export default TensePicker;
|
||||
|
||||
function getTenseCategory(tense: T.VerbTense | T.PerfectTense | T.ModalTense): "basic" | "perfect" | "modal" {
|
||||
function getTenseCategory(tense: T.VerbTense | T.PerfectTense | T.ModalTense | T.ImperativeTense): "basic" | "perfect" | "modal" | "imperative" {
|
||||
if (isPerfectTense(tense)) {
|
||||
return "perfect";
|
||||
}
|
||||
|
@ -229,5 +276,8 @@ function getTenseCategory(tense: T.VerbTense | T.PerfectTense | T.ModalTense): "
|
|||
if (isModalTense(tense)) {
|
||||
return "modal";
|
||||
}
|
||||
if (isImperativeTense(tense)) {
|
||||
return "imperative";
|
||||
}
|
||||
throw new Error("can't catagorize tense");
|
||||
}
|
|
@ -17,6 +17,10 @@ import VPExplorerQuiz from "./VPExplorerQuiz";
|
|||
import { switchSubjObj } from "../../lib/phrase-building/vp-tools";
|
||||
import VPExplorerExplanationModal, { roleIcon } from "./VPExplorerExplanationModal";
|
||||
|
||||
// TO FINISH IMPERATIVE STUFF!!
|
||||
// TODO: English Builders for imperatives
|
||||
// TODO: Quiz with imperatives
|
||||
|
||||
// TODO: make answerFeedback emojis appear at random translate angles a little bit
|
||||
// add energy drinks?
|
||||
|
||||
|
@ -48,7 +52,7 @@ export function VPExplorer(props: {
|
|||
})) {
|
||||
const [vps, setVps] = useStickyState<T.VPSelection>(
|
||||
savedVps => makeVPSelectionState(props.verb, savedVps),
|
||||
"vpsState2",
|
||||
"vpsState5",
|
||||
);
|
||||
const [mode, setMode] = useStickyState<"charts" | "phrases" | "quiz">(
|
||||
savedMode => {
|
||||
|
@ -129,10 +133,16 @@ export function VPExplorer(props: {
|
|||
{ label: "Phrases", value: "phrases" },
|
||||
{ label: "Quiz", value: "quiz" },
|
||||
]}
|
||||
handleChange={setMode}
|
||||
handleChange={(x) => {
|
||||
// TODO: remove this and implement the imperative in quiz
|
||||
// if (x === "quiz") {
|
||||
|
||||
// }
|
||||
setMode(x);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
{(vps.verb && (typeof vps.verb.object === "object") && (vps.verb.isCompound !== "dynamic") && (mode === "phrases")) &&
|
||||
{(vps.verb && (typeof vps.verb.object === "object") && (vps.verb.isCompound !== "dynamic") && (vps.verb.tenseCategory !== "imperative") &&(mode === "phrases")) &&
|
||||
<div className="text-center mt-4">
|
||||
<button onClick={handleSubjObjSwap} className="btn btn-sm btn-light">
|
||||
<i className="fas fa-exchange-alt mr-2" /> subj/obj
|
||||
|
@ -154,6 +164,7 @@ export function VPExplorer(props: {
|
|||
nouns: props.nouns,
|
||||
verbs: props.verbs,
|
||||
}}
|
||||
is2ndPersonPicker={vps.verb.tenseCategory === "imperative"}
|
||||
np={vps.subject}
|
||||
counterPart={vps.verb ? vps.verb.object : undefined}
|
||||
onChange={handleSubjectChange}
|
||||
|
|
|
@ -16,6 +16,7 @@ import Keyframes from "../Keyframes";
|
|||
import energyDrink from "./energy-drink.jpg";
|
||||
import { flattenLengths } from "../../lib/phrase-building/compile-vp";
|
||||
import { concatPsString } from "../../lib/p-text-helpers";
|
||||
import { isImperativeTense } from "../../lib/type-predicates";
|
||||
|
||||
const correctEmoji = ["✅", '🤓', "✅", '😊', "🌹", "✅", "✅", '🥳', "👏", "✅", "💯", "😎", "✅", "👍"];
|
||||
|
||||
|
@ -384,6 +385,7 @@ function completeVPs(vps: T.VPSelection): T.VPSelectionComplete {
|
|||
obj: oldObj,
|
||||
}
|
||||
);
|
||||
const t = getTenseFromVerbSelection(vps.verb);
|
||||
const verb: T.VerbSelectionComplete = {
|
||||
...vps.verb,
|
||||
object: (
|
||||
|
@ -397,7 +399,7 @@ function completeVPs(vps: T.VPSelection): T.VPSelectionComplete {
|
|||
person: obj,
|
||||
}
|
||||
: vps.verb.object,
|
||||
tense: getTenseFromVerbSelection(vps.verb),
|
||||
tense: isImperativeTense(t) ? "presentVerb" : t,
|
||||
};
|
||||
return {
|
||||
...vps,
|
||||
|
|
|
@ -53,6 +53,7 @@ export function makeVPSelectionState(
|
|||
dynAuxVerb,
|
||||
verbTense: os ? os.verb.verbTense : "presentVerb",
|
||||
perfectTense: os ? os.verb.perfectTense : "presentPerfect",
|
||||
imperativeTense: os ? os.verb.imperativeTense : "imperfectiveImperative",
|
||||
tenseCategory: os ? os.verb.tenseCategory : "basic",
|
||||
object,
|
||||
transitivity,
|
||||
|
|
|
@ -103,6 +103,7 @@ const kedulStatModal: T.ModalContent = {
|
|||
};
|
||||
|
||||
const kawulStatOrDynImperfectivePassive: T.AspectContentPassive = {
|
||||
imperative: undefined,
|
||||
nonImperative: [
|
||||
[[{p: "کول کېږم", f: "kawul kéGum"}], [{p: "کول کېږو", f: "kawul kéGoo"}]],
|
||||
[[{p: "کول کېږم", f: "kawul kéGum"}], [{p: "کول کېږو", f: "kawul kéGoo"}]],
|
||||
|
@ -1303,6 +1304,7 @@ export const kawulStat: T.VerbConjugation = {
|
|||
passive: {
|
||||
imperfective: kawulStatOrDynImperfectivePassive,
|
||||
perfective: {
|
||||
imperative: undefined,
|
||||
nonImperative: [
|
||||
[[{p: "وکړل شم", f: "óokRul shum"}], [{p: "وکړل شو", f: "óokRul shoo"}]],
|
||||
[[{p: "وکړل شم", f: "óokRul shum"}], [{p: "وکړل شو", f: "óokRul shoo"}]],
|
||||
|
@ -1808,6 +1810,7 @@ export const kawulDyn: T.VerbConjugation = {
|
|||
passive: {
|
||||
imperfective: kawulStatOrDynImperfectivePassive,
|
||||
perfective: {
|
||||
imperative: undefined,
|
||||
nonImperative: [
|
||||
[[{p: "کړل شم", f: "kRul shum"}], [{p: "کړل شو", f: "kRul shoo"}]],
|
||||
[[{p: "کړل شم", f: "kRul shum"}], [{p: "کړل شو", f: "kRul shoo"}]],
|
||||
|
|
|
@ -12,7 +12,7 @@ import {
|
|||
removeBa,
|
||||
removeDuplicates,
|
||||
} from "./vp-tools";
|
||||
import { isModalTense, isPerfectTense } from "../type-predicates";
|
||||
import { isImperativeTense, isModalTense, isPerfectTense } from "../type-predicates";
|
||||
|
||||
type Form = T.FormVersion & { OSV?: boolean };
|
||||
export function compileVP(VP: T.VPRendered, form: Form): { ps: T.SingleOrLengthOpts<T.PsString[]>, e?: string [] };
|
||||
|
@ -159,7 +159,9 @@ function arrangeVerbWNegative(head: T.PsString | undefined, restRaw: T.PsString[
|
|||
headSegment ? [headSegment, rest] : [rest],
|
||||
];
|
||||
}
|
||||
const nu: T.PsString = { p: "نه", f: "nú" };
|
||||
const nu: T.PsString = isImperativeTense(V.tense)
|
||||
? { p: "مه", f: "mú" }
|
||||
: { p: "نه", f: "nú" };
|
||||
if (!headSegment) {
|
||||
if ("front" in rest) {
|
||||
return [
|
||||
|
|
|
@ -2,6 +2,7 @@ import * as T from "../../types";
|
|||
import { getVerbBlockPosFromPerson, parseEc } from "../misc-helpers";
|
||||
import * as grammarUnits from "../grammar-units";
|
||||
import {
|
||||
isImperativeTense,
|
||||
isPerfectTense,
|
||||
isVerbTense,
|
||||
// isModalTense,
|
||||
|
@ -232,11 +233,24 @@ export function renderEnglishVPBase({ subjectPerson, object, vs }: {
|
|||
`$SUBJ would${n ? " not" : ""} be able to be ${v[4]}`,
|
||||
]),
|
||||
};
|
||||
const imperativeBuilders: Record<
|
||||
T.ImperativeTense,
|
||||
(s: T.Person, v: T.EnglishVerbConjugationEc, n: boolean) => string[]
|
||||
> = {
|
||||
imperfectiveImperative: (s: T.Person, ec: T.EnglishVerbConjugationEc, n: boolean) => ([
|
||||
`${n ? "don't " : ""}${ec[0]}`,
|
||||
]),
|
||||
perfectiveImperative: (s: T.Person, ec: T.EnglishVerbConjugationEc, n: boolean) => ([
|
||||
`${n ? "don't " : ""}${ec[0]}`,
|
||||
]),
|
||||
};
|
||||
const base = (
|
||||
isPerfectTense(vs.tense)
|
||||
? (vs.voice === "active" ? perfectBuilders : passivePerfectBuilders)[vs.tense]
|
||||
: isVerbTense(vs.tense)
|
||||
? (vs.voice === "active" ? basicBuilders : passiveBasicBuilders)[vs.tense]
|
||||
: isImperativeTense(vs.tense)
|
||||
? imperativeBuilders[vs.tense]
|
||||
: (vs.voice === "active" ? modalBuilders : passiveModalBuilders)[vs.tense])(subjectPerson, ec, vs.negative);
|
||||
return base.map(b => `${b}${typeof object === "object" ? " $OBJ" : ""}${ep ? ` ${ep}` : ""}`);
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ import {
|
|||
hasBaParticle,
|
||||
psStringFromEntry,
|
||||
getLong,
|
||||
isImperativeBlock,
|
||||
} from "../p-text-helpers";
|
||||
import { removeAccents } from "../accent-helpers";
|
||||
import {
|
||||
|
@ -26,6 +27,7 @@ import {
|
|||
isPerfectTense,
|
||||
} from "../type-predicates";
|
||||
import { renderEnglishVPBase } from "./english-vp-rendering";
|
||||
import { personGender } from "../../library";
|
||||
|
||||
// TODO: ISSUE GETTING SPLIT HEAD NOT MATCHING WITH FUTURE VERBS
|
||||
|
||||
|
@ -157,7 +159,8 @@ function getPsVerbConjugation(conj: T.VerbConjugation, vs: T.VerbSelectionComple
|
|||
},
|
||||
hasBa: boolean,
|
||||
} {
|
||||
const f = getTenseVerbForm(conj, vs.tense, vs.voice);
|
||||
// TODO: handle the imperative form here
|
||||
const f = getTenseVerbForm(conj, vs.tense, vs.voice, vs.negative);
|
||||
const block = getMatrixBlock(f, objectPerson, person);
|
||||
const perfective = isPerfective(vs.tense);
|
||||
const verbForm = getVerbFromBlock(block, person);
|
||||
|
@ -178,8 +181,11 @@ function getPsVerbConjugation(conj: T.VerbConjugation, vs: T.VerbSelectionComple
|
|||
return { hasBa, ps: { head: undefined, rest: verbForm }};
|
||||
}
|
||||
|
||||
function getVerbFromBlock(block: T.SingleOrLengthOpts<T.VerbBlock>, person: T.Person): T.SingleOrLengthOpts<T.PsString[]> {
|
||||
function grabFromBlock(b: T.VerbBlock, [row, col]: [ row: number, col: number ]): T.PsString[] {
|
||||
function getVerbFromBlock(block: T.SingleOrLengthOpts<T.VerbBlock | T.ImperativeBlock>, person: T.Person): T.SingleOrLengthOpts<T.PsString[]> {
|
||||
function grabFromBlock(b: T.VerbBlock | T.ImperativeBlock, [row, col]: [ row: number, col: number ]): T.PsString[] {
|
||||
if (isImperativeBlock(b)) {
|
||||
return b[personGender(person) === "masc" ? 0 : 1][col];
|
||||
}
|
||||
return b[row][col];
|
||||
}
|
||||
const pos = getVerbBlockPosFromPerson(person);
|
||||
|
@ -326,7 +332,7 @@ function isFirstOrSecondPersPronoun(o: "none" | T.NPSelection | T.Person.ThirdPl
|
|||
return [0,1,2,3,6,7,8,9].includes(o.person);
|
||||
}
|
||||
|
||||
function isPerfective(t: T.VerbTense | T.PerfectTense | T.ModalTense): boolean {
|
||||
function isPerfective(t: T.Tense): boolean {
|
||||
if (isPerfectTense(t)) return false;
|
||||
if (t === "presentVerb" || t === "imperfectiveFuture" || t === "imperfectivePast" || t === "habitualImperfectivePast") {
|
||||
return false;
|
||||
|
@ -337,7 +343,10 @@ function isPerfective(t: T.VerbTense | T.PerfectTense | T.ModalTense): boolean {
|
|||
if (t === "perfectiveFutureModal" || t === "subjunctiveVerbModal" || t === "perfectivePastModal" || t === "habitualPerfectivePastModal") {
|
||||
return true;
|
||||
}
|
||||
throw new Error("tense not implemented yet");
|
||||
if (t === "perfectiveImperative") {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function isMascSingAnimatePattern4(np: T.NPSelection): boolean {
|
||||
|
|
|
@ -4,8 +4,9 @@ import {
|
|||
psRemove,
|
||||
psStringEquals,
|
||||
} from "../../lib/p-text-helpers";
|
||||
import { isPerfectTense } from "../type-predicates";
|
||||
import { isImperativeTense, isPerfectTense } from "../type-predicates";
|
||||
import * as grammarUnits from "../../lib/grammar-units";
|
||||
import { randomNumber } from "../../lib/misc-helpers";
|
||||
|
||||
export function isInvalidSubjObjCombo(subj: T.Person, obj: T.Person): boolean {
|
||||
const firstPeople = [
|
||||
|
@ -27,8 +28,23 @@ export function isInvalidSubjObjCombo(subj: T.Person, obj: T.Person): boolean {
|
|||
);
|
||||
}
|
||||
|
||||
export function getTenseVerbForm(conjR: T.VerbConjugation, tense: T.VerbTense | T.PerfectTense | T.ModalTense, voice: "active" | "passive"): T.VerbForm {
|
||||
export function getTenseVerbForm(
|
||||
conjR: T.VerbConjugation,
|
||||
tense: T.VerbTense | T.PerfectTense | T.ModalTense | T.ImperativeTense,
|
||||
voice: "active" | "passive",
|
||||
negative: boolean,
|
||||
): T.VerbForm | T.ImperativeForm {
|
||||
const conj = (voice === "passive" && conjR.passive) ? conjR.passive : conjR;
|
||||
if (isImperativeTense(tense)) {
|
||||
const impPassError = new Error("can't use imperative tenses with passive voice")
|
||||
if (voice === "passive") {
|
||||
throw impPassError;
|
||||
}
|
||||
if (!conj.imperfective.imperative || !conj.perfective.imperative) throw impPassError;
|
||||
return (tense === "perfectiveImperative" && !negative)
|
||||
? conj.perfective.imperative
|
||||
: conj.imperfective.imperative;
|
||||
}
|
||||
if (tense === "presentVerb") {
|
||||
return conj.imperfective.nonImperative;
|
||||
}
|
||||
|
@ -123,7 +139,7 @@ export function removeBa(ps: T.PsString): T.PsString {
|
|||
return psRemove(ps, concatPsString(grammarUnits.baParticle, " "));
|
||||
}
|
||||
|
||||
export function getTenseFromVerbSelection(vs: T.VerbSelection): T.VerbTense | T.PerfectTense | T.ModalTense {
|
||||
export function getTenseFromVerbSelection(vs: T.VerbSelection): T.VerbTense | T.PerfectTense | T.ModalTense | T.ImperativeTense {
|
||||
function verbTenseToModalTense(tn: T.VerbTense): T.ModalTense {
|
||||
if (tn === "presentVerb") {
|
||||
return "presentVerbModal";
|
||||
|
@ -157,11 +173,14 @@ export function getTenseFromVerbSelection(vs: T.VerbSelection): T.VerbTense | T.
|
|||
if (vs.tenseCategory === "perfect") {
|
||||
return vs.perfectTense;
|
||||
}
|
||||
if (vs.tenseCategory === "imperative") {
|
||||
return vs.imperativeTense;
|
||||
}
|
||||
// vs.tenseCategory === "modal"
|
||||
return verbTenseToModalTense(vs.verbTense);
|
||||
}
|
||||
|
||||
export function isPastTense(tense: T.VerbTense | T.PerfectTense | T.ModalTense): boolean {
|
||||
export function isPastTense(tense: T.Tense): boolean {
|
||||
if (isPerfectTense(tense)) return true;
|
||||
return tense.toLowerCase().includes("past");
|
||||
}
|
||||
|
@ -178,7 +197,7 @@ export function switchSubjObj(vps: T.VPSelection): T.VPSelection;
|
|||
export function switchSubjObj(vps: T.VPSelectionComplete): T.VPSelectionComplete;
|
||||
export function switchSubjObj(vps: T.VPSelection | T.VPSelectionComplete): T.VPSelection | T.VPSelectionComplete {
|
||||
if ("tenseCategory" in vps.verb) {
|
||||
if (!vps.subject || !(typeof vps.verb.object === "object")) {
|
||||
if (!vps.subject || !(typeof vps.verb.object === "object") || (vps.verb.tenseCategory === "imperative")) {
|
||||
return vps;
|
||||
}
|
||||
return {
|
||||
|
@ -223,3 +242,90 @@ export function completeVPSelection(vps: T.VPSelection): T.VPSelectionComplete |
|
|||
verb,
|
||||
};
|
||||
}
|
||||
|
||||
export function isSecondPerson(p: T.Person): boolean {
|
||||
return (
|
||||
p === T.Person.SecondSingMale ||
|
||||
p === T.Person.SecondSingFemale ||
|
||||
p === T.Person.SecondPlurMale ||
|
||||
p === T.Person.SecondPlurFemale
|
||||
);
|
||||
}
|
||||
|
||||
export function isThirdPerson(p: T.Person): boolean {
|
||||
return (
|
||||
p === T.Person.ThirdSingMale ||
|
||||
p === T.Person.ThirdSingFemale ||
|
||||
p === T.Person.ThirdPlurMale ||
|
||||
p === T.Person.ThirdPlurFemale
|
||||
);
|
||||
}
|
||||
|
||||
export function ensure2ndPersSubjPronounAndNoConflict(vps: T.VPSelection): T.VPSelection {
|
||||
console.log("checking more...", vps);
|
||||
const subjIs2ndPerson = (vps.subject?.type === "pronoun") && isSecondPerson(vps.subject.person);
|
||||
const objIs2ndPerson = (typeof vps.verb.object === "object")
|
||||
&& (vps.verb.object.type === "pronoun")
|
||||
&& isSecondPerson(vps.verb.object.person);
|
||||
console.log({ subjIs2ndPerson, objIs2ndPerson });
|
||||
const default2ndPersSubject: T.PronounSelection = {
|
||||
type: "pronoun",
|
||||
distance: "far",
|
||||
person: T.Person.SecondSingMale,
|
||||
};
|
||||
function getNon2ndPersPronoun() {
|
||||
let newObjPerson: T.Person;
|
||||
do {
|
||||
newObjPerson = randomNumber(0, 12);
|
||||
} while(isSecondPerson(newObjPerson));
|
||||
return newObjPerson;
|
||||
}
|
||||
if (subjIs2ndPerson && !objIs2ndPerson) {
|
||||
return vps;
|
||||
}
|
||||
if (subjIs2ndPerson && objIs2ndPerson) {
|
||||
if (typeof vps.verb.object !== "object" || vps.verb.object.type !== "pronoun") {
|
||||
return vps;
|
||||
}
|
||||
return {
|
||||
...vps,
|
||||
verb: {
|
||||
...vps.verb,
|
||||
object: {
|
||||
...vps.verb.object,
|
||||
person: getNon2ndPersPronoun(),
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
if (!subjIs2ndPerson && objIs2ndPerson) {
|
||||
if (typeof vps.verb.object !== "object" || vps.verb.object.type !== "pronoun") {
|
||||
return {
|
||||
...vps,
|
||||
subject: default2ndPersSubject,
|
||||
};
|
||||
}
|
||||
return {
|
||||
...vps,
|
||||
subject: default2ndPersSubject,
|
||||
verb: {
|
||||
...vps.verb,
|
||||
object: {
|
||||
...vps.verb.object,
|
||||
person: getNon2ndPersPronoun(),
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
if (!subjIs2ndPerson && !objIs2ndPerson) {
|
||||
console.log("returning last");
|
||||
return {
|
||||
...vps,
|
||||
subject: default2ndPersSubject,
|
||||
verb: {
|
||||
...vps.verb,
|
||||
},
|
||||
};
|
||||
}
|
||||
throw new Error("error ensuring compatible VPSelection for imperative verb");
|
||||
}
|
|
@ -160,11 +160,11 @@ export function isArrayOneOrMore<U>(a: U[]): a is T.ArrayOneOrMore<U> {
|
|||
return a.length > 0;
|
||||
}
|
||||
|
||||
export function isPerfectTense(tense: T.VerbTense | T.EquativeTense | T.ModalTense | T.PerfectTense): tense is T.PerfectTense {
|
||||
export function isPerfectTense(tense: T.Tense): tense is T.PerfectTense {
|
||||
return tense.endsWith("Perfect");
|
||||
}
|
||||
|
||||
export function isVerbTense(tense: T.VerbTense | T.EquativeTense | T.ModalTense | T.PerfectTense): tense is T.VerbTense {
|
||||
export function isVerbTense(tense: T.Tense): tense is T.VerbTense {
|
||||
const verbTenses: T.VerbTense[] = [
|
||||
"presentVerb",
|
||||
"subjunctiveVerb",
|
||||
|
@ -178,12 +178,15 @@ export function isVerbTense(tense: T.VerbTense | T.EquativeTense | T.ModalTense
|
|||
return verbTenses.some(x => x === tense);
|
||||
}
|
||||
|
||||
export function isModalTense(tense: T.VerbTense | T.EquativeTense | T.ModalTense | T.PerfectTense): tense is T.ModalTense {
|
||||
export function isModalTense(tense: T.Tense): tense is T.ModalTense {
|
||||
return tense.endsWith("Modal");
|
||||
}
|
||||
|
||||
export function isEquativeTense(t: T.VerbTense | T.EquativeTense | T.PerfectTense | T.ModalTense): t is T.EquativeTense {
|
||||
export function isEquativeTense(t: T.Tense): t is T.EquativeTense {
|
||||
return (t === "present" || t === "future" || t === "habitual" || t === "past" || t === "wouldBe" || t === "subjunctive" || t === "pastSubjunctive");
|
||||
}
|
||||
|
||||
export function isImperativeTense(tense: T.Tense): tense is T.ImperativeTense {
|
||||
return tense === "imperfectiveImperative" || tense === "perfectiveImperative";
|
||||
}
|
||||
|
||||
|
|
|
@ -106,11 +106,11 @@ export function conjugateVerb(entry: T.DictionaryEntry, complement?: T.Dictionar
|
|||
}
|
||||
|
||||
function conjugateDynamicCompound(info: T.DynamicCompoundVerbInfo): T.VerbConjugation {
|
||||
const willUseImperative = !(
|
||||
info.type === "dynamic compound"
|
||||
&& info.transitivity === "intransitive"
|
||||
&& info.auxVerb.p === "کېدل"
|
||||
);
|
||||
// const willUseImperative = !(
|
||||
// info.type === "dynamic compound"
|
||||
// && info.transitivity === "intransitive"
|
||||
// && info.auxVerb.p === "کېدل"
|
||||
// );
|
||||
const auxConj = enforceObject(
|
||||
conjugateVerb(info.auxVerb, info.auxVerbComplement) as T.VerbConjugation,
|
||||
info.objComplement.person,
|
||||
|
@ -136,18 +136,14 @@ function conjugateDynamicCompound(info: T.DynamicCompoundVerbInfo): T.VerbConjug
|
|||
const ac = auxConj[aspect];
|
||||
const nonImperative = addToForm([complement, " "], ac.nonImperative);
|
||||
const future = addToForm([baParticle, " "], nonImperative);
|
||||
const imperative = (ac.imperative && willUseImperative)
|
||||
? addToForm([complement, " "], ac.imperative)
|
||||
: null;
|
||||
const imperative = addToForm([complement, " "], ac.imperative);
|
||||
const past = addToForm([complement, " "], auxConj[aspect].past);
|
||||
const habitualPast = addToForm([baParticle, " "], past);
|
||||
const modal = makeDynamicModalContent();
|
||||
return {
|
||||
nonImperative,
|
||||
future,
|
||||
...imperative ? {
|
||||
imperative,
|
||||
} : {},
|
||||
imperative,
|
||||
past,
|
||||
habitualPast,
|
||||
modal,
|
||||
|
@ -183,6 +179,7 @@ function conjugateDynamicCompound(info: T.DynamicCompoundVerbInfo): T.VerbConjug
|
|||
const habitualPast = addToForm([baParticle, " "], past);
|
||||
const modal = makePassiveModalSection([complement, " "], stativeAux.intransitive.imperfective.modal);
|
||||
return {
|
||||
imperative: undefined,
|
||||
nonImperative,
|
||||
future,
|
||||
past,
|
||||
|
@ -317,9 +314,7 @@ function makeStativeCompoundSeperatedAspectContent(info: T.StativeCompoundVerbIn
|
|||
stativeAux[transitivity][aspect].nonImperative,
|
||||
);
|
||||
const future = addToForm([baParticle, " "], nonImperative);
|
||||
const imperative = aux.imperative
|
||||
? addToForm([presentComplement, " "], aux.imperative)
|
||||
: null;
|
||||
const imperative = addToForm([presentComplement, " "], aux.imperative);
|
||||
const past = addToForm([info.complement, " "], aux.past);
|
||||
const habitualPast = addToForm([baParticle, " "], past);
|
||||
return {
|
||||
|
@ -327,9 +322,7 @@ function makeStativeCompoundSeperatedAspectContent(info: T.StativeCompoundVerbIn
|
|||
future,
|
||||
past,
|
||||
habitualPast,
|
||||
...imperative ? {
|
||||
imperative,
|
||||
} : {},
|
||||
imperative,
|
||||
modal: info.transitivity === "transitive"
|
||||
? makeTransitiveStativeModalContent()
|
||||
: makeJoinedModalContent(info, "imperfective"),
|
||||
|
@ -458,6 +451,7 @@ function makePassiveContent(info: T.NonComboVerbInfo): {
|
|||
noPersInfs(info.root.imperfective).long, " ",
|
||||
], stativeAux.intransitive.imperfective.modal);
|
||||
return {
|
||||
imperative: undefined,
|
||||
nonImperative,
|
||||
future,
|
||||
past,
|
||||
|
@ -474,6 +468,7 @@ function makePassiveContent(info: T.NonComboVerbInfo): {
|
|||
const auxModal = aux.modal;
|
||||
const modal = makePassiveModalSection([noPersInfs(info.root.imperfective).long, " "], auxModal);
|
||||
return {
|
||||
imperative: undefined,
|
||||
nonImperative, // ROOT LONG + kedulStat[aspect].nonImperative
|
||||
future, // به ba + ROOT LONG + this.nonImperative
|
||||
past, // ROOT LONG + kedulStat[aspect].past
|
||||
|
@ -560,9 +555,7 @@ function enforceObject(conj: T.VerbConjugation, person: T.Person): T.VerbConjuga
|
|||
const modifyPastInAspect = (as: T.AspectContent): T.AspectContent => ({
|
||||
nonImperative: allOnePersonInflection(as.nonImperative, person),
|
||||
future: allOnePersonInflection(as.future, person),
|
||||
...as.imperative ? {
|
||||
imperative: allOnePersonInflection(as.imperative, person),
|
||||
} : {},
|
||||
imperative: allOnePersonInflection(as.imperative, person),
|
||||
past: allOnePersonVerbForm(as.past, person),
|
||||
habitualPast: allOnePersonInflection(as.habitualPast, person),
|
||||
modal: {
|
||||
|
@ -586,6 +579,7 @@ function enforceObject(conj: T.VerbConjugation, person: T.Person): T.VerbConjuga
|
|||
pastSubjunctiveHypothetical: allOnePersonVerbForm(perf.pastSubjunctiveHypothetical, person),
|
||||
});
|
||||
const modifyPassiveAspect = (as: T.AspectContentPassive): T.AspectContentPassive => ({
|
||||
imperative: undefined,
|
||||
nonImperative: allOnePersonVerbForm(as.nonImperative, person),
|
||||
future: allOnePersonVerbForm(as.future, person),
|
||||
past: allOnePersonVerbForm(as.past, person),
|
||||
|
|
28
src/types.ts
28
src/types.ts
|
@ -296,13 +296,17 @@ export type AspectContent = {
|
|||
// ROOT = info.root[ASPECT]
|
||||
nonImperative: VerbForm; // STEM + pres ending
|
||||
future: VerbForm; // به + this.nonImperative
|
||||
imperative?: ImperativeForm; // STEM + imperative ending
|
||||
// -- optional because not used for intransitive verison of kawul dynamic compounds
|
||||
imperative: ImperativeForm; // STEM + imperative ending
|
||||
past: VerbForm; // ROOT + past ending
|
||||
habitualPast: VerbForm; // ba + past
|
||||
modal: ModalContent;
|
||||
}
|
||||
|
||||
// ASPECT -> AspectContentPssive
|
||||
export type AspectContentPassive = Omit<AspectContent, "imperative"> & {
|
||||
imperative: undefined,
|
||||
};
|
||||
|
||||
export type ModalContent = {
|
||||
nonImperative: VerbForm; // ROOT + ey + kedulStat.perfective.nonImperative
|
||||
future: VerbForm; // به + this.nonImperative
|
||||
|
@ -311,16 +315,6 @@ export type ModalContent = {
|
|||
hypotheticalPast: VerbForm; // ROOT + ey + shw + ey
|
||||
}
|
||||
|
||||
// ASPECT -> AspectContentPssive
|
||||
export type AspectContentPassive = {
|
||||
// ROOT = info.root[ASPECT]
|
||||
nonImperative: VerbForm; // ROOT LONG + kedulStat[ASPECT].nonImperative
|
||||
future: VerbForm; // ba + this.nonImperative
|
||||
past: VerbForm; // ROOT LONG + kedulStat[ASPECT].past
|
||||
habitualPast: VerbForm;
|
||||
modal: ModalContent,
|
||||
}
|
||||
|
||||
export type ParticipleForm = SingleOrLengthOpts<UnisexInflections> | SingleOrLengthOpts<PsString>;
|
||||
|
||||
export type ParticipleContent = {
|
||||
|
@ -531,12 +525,13 @@ export type VerbTense = "presentVerb"
|
|||
| "imperfectivePast"
|
||||
| "habitualPerfectivePast"
|
||||
| "habitualImperfectivePast";
|
||||
|
||||
export type EquativeTense = "present" | "subjunctive" | "habitual" | "past" | "future" | "wouldBe" | "pastSubjunctive";
|
||||
export type NounNumber = "singular" | "plural";
|
||||
|
||||
export type EquativeTense = "present" | "subjunctive" | "habitual" | "past" | "future" | "wouldBe" | "pastSubjunctive";
|
||||
export type PerfectTense = `${EquativeTense}Perfect`;
|
||||
export type ModalTense = `${VerbTense}Modal`;
|
||||
export type ImperativeTense = `${Aspect}Imperative`;
|
||||
export type Tense = EquativeTense | VerbTense | PerfectTense | ModalTense | ImperativeTense;
|
||||
|
||||
export type VPSelection = {
|
||||
subject: NPSelection | undefined,
|
||||
|
@ -550,7 +545,7 @@ export type VPSelectionComplete = {
|
|||
|
||||
export type VerbSelectionComplete = Omit<VerbSelection, "object" | "verbTense" | "perfectTense" | "tenseCategory"> & {
|
||||
object: Exclude<VerbObject, undefined>,
|
||||
tense: VerbTense | PerfectTense | ModalTense,
|
||||
tense: VerbTense | PerfectTense | ModalTense | ImperativeTense,
|
||||
}
|
||||
|
||||
export type VerbSelection = {
|
||||
|
@ -569,7 +564,8 @@ export type VerbSelection = {
|
|||
negative: boolean,
|
||||
verbTense: VerbTense,
|
||||
perfectTense: PerfectTense,
|
||||
tenseCategory: "basic" | "modal" | "perfect",
|
||||
imperativeTense: ImperativeTense,
|
||||
tenseCategory: "basic" | "modal" | "perfect" | "imperative",
|
||||
};
|
||||
|
||||
export type VerbRendered = Omit<VerbSelectionComplete, "object"> & {
|
||||
|
|
Loading…
Reference in New Issue