conlanging.el/conlanging-eittlandic.el
Lucien Cartier-Tilet 3674d11cd2
Some checks failed
CI / build (29.4) (push) Failing after 1m8s
CI / build (snapshot) (push) Failing after 54s
fix: verb declensions in correct order
2024-09-14 14:51:56 +02:00

458 lines
20 KiB
EmacsLisp
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

;;; conlanging-eittlandic.el --- Helper functions for the Eittlandic language -*- lexical-binding: t -*-
;; Author: Lucien Cartier-Tilet <lucien@phundrak.com>
;; Maintainer: Lucien Cartier-Tilet <lucien@phundrak.com>
;; Version: 0.1.0
;; Homepage: https://labs.phundrak.com/phundrak/conlanging.el
;; Keywords: convenience
;; This file is not part of GNU Emacs
;; This program is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <https://www.gnu.org/licenses/>.
;;; Commentary:
;; This file includes functions to help write the documentation for
;; the Eittlandic language faster.
;;; Code:
(require 'dash)
(require 's)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Constants ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defconst conlanging-eittlandic--vowels
'("a" "e" "i" "o" "u" "y" "á" "é" "í" "ó" "ú" "ý")
"Vowels in Eittlandic.")
(defconst conlanging-eittlandic--rounded-vowels
'("o" "u" "y" "ó" "ú" "ý")
"Rounded vowels in Eittlandic.")
; Adjectives ;;;;;;;;;;;;;;;;;;;;;;;;;;
(defconst conlanging-eittlandic--adjective-inflexion-common
'("r" "" "um" "s" "ar" "" "um" "ar")
"Declensions of Eittlandic adjectives for the common gender.
See also `conlanging-eittlandic--strong-common-noun-declension'.")
(defconst conlanging-eittlandic--adjective-inflexion-neuter
'("t" "t" "um" "s" "" "" "um" "r")
"Declensions of Eittlandic adjectives for the neuter gender.
See also `conlanging-eittlandic--strong-common-noun-declension'.")
; Verbs ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defconst conlanging-eittlandic--generic-verb-inflexion-indicative-present
'(("" . "r") ("" . "r") ("" . "r") (nil . "um") (nil . "") (nil . ""))
"Generic indicative present declension for Eittlandic verbs.
This table shows the declension of verbs for the indicative
present. The order of the declensions is first, second, and
third person, first singular, then plural.
Each declension is a cons cell containing first the default
underlying vowel, and second the generic suffix.")
(defconst conlanging-eittlandic--generic-verb-inflexion-subjunctive-present
'((nil . "ir") (nil . "ir") (nil . "ir")
(nil . "im") (nil . "") (nil . ""))
"Generic subjunctive present declension for Eittlandic verbs.
See
`conlanging-eittlandic--generic-verb-inflexion-indicative-present'.")
(defconst conlanging-eittlandic--generic-verb-inflexion-past
'((nil . "t") (nil . "t") (nil . "t")
(nil . "um") (nil . "") (nil . ""))
"Generic past declension for Eittlandic verbs.
See
`conlanging-eittlandic--generic-verb-inflexion-indicative-present'.")
(defconst conlanging-eittlandic--strong-verb-inflexion-passive
'((nil . "umk") (nil . "sk") ("" . "sk")
(nil . "umk") ("" . "sk") ("" . "sk"))
"Strong passive inflexion for Eittlandic verbs.
See
`conlanging-eittlandic--generic-verb-inflexion-indicative-present'.")
(defconst conlanging-eittlandic--weak-verb-inflexion-passive
'((nil . "umk") ("" . "isk") ("" . "isk")
(nil . "umk") ("" . "isk") ("" . "isk"))
"Weak passive inflexion for Eittlandic verbs.
See
`conlanging-eittlandic--generic-verb-inflexion-indicative-present'.")
; Nouns ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defconst conlanging-eittlandic--strong-common-noun-declension
'((nil . "r") (nil . nil) (nil . nil) ("a" . "r")
(nil . "r") (nil . nil) (nil . "um") ("a" . "r"))
"Declensions of strong common nouns in Eittlandic.
The first element of a pair is the vowel to use if there is no
underlying vowel. The second element is the declension suffix.
The order of the suffixes go like this:
- singular nominative
- singular accusative
- singular dative
- singular genitive
- plural nominative
- plural accusative
- plural dative
- plural genitive")
(defconst conlanging-eittlandic--strong-common-definite-noun-declension
'(("i" . "nn") ("i" . "n") ("i" . "n") ("i" . "ns")
("i" . "nn") ("i" . "n") ("i" . "num") ("i" . "n"))
"Declension of definite strong common nouns in Eittlandic.
See `conlanging-eittlandic--strong-common-noun-declension' for more info.")
(defconst conlanging-eittlandic--strong-neuter-noun-declension
'((nil . nil) (nil . nil) (nil . nil) (nil . "s")
(nil . nil) (nil . nil) (nil . "um") (nil . "s"))
"Declensions of strong neuter nouns in Eittlandic.
See `conlanging-eittlandic--strong-common-noun-declension' for more info.")
(defconst conlanging-eittlandic--weak-noun-declension
'((nil . nil) (nil . nil) (nil . nil) (nil . "s")
(nil . "r") (nil . nil) (nil . "um") (nil . "s"))
"Declensions of weak nouns in Eittlandic.
See `conlanging-eittlandic--strong-common-noun-declension' for more info.")
(defconst conlanging-eittlandic--other-definite-noun-declension
'(("i" . "t") ("i" . "t") ("i" . "t") ("i" . "ts")
("i" . "tr") ("i" . "t") ("i" . "tum") ("i" . "t"))
"Declensions of definite strong neutral and weak nouns in Eittlandic.
See `conlanging-eittlandic--strong-common-noun-declension' for more info.")
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Functions ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Generic ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defun conlanging-eittlandic--string-ends-with-p (str suffix)
"Determine whether STR ends with SUFFIX."
(string-match (regexp-quote suffix) str (- (length str) (length suffix))))
(defun conlanging-eittlandic--maybe-underlying-vowel (underlying-vowel default-vowel)
"Return which underlying vowel should be used.
If DEFAULT-VOWEL is nil, it means there is no need to insert a
vowel. However, if it is not, it should be used, unless
UNDERLYING-VOWEL is non-nil."
(if default-vowel
(if underlying-vowel underlying-vowel default-vowel)
""))
(defun conlanging-eittlandic--split-list (list)
"Splits LIST int two halves and return both halves as a cons cell."
(let* ((half (floor (length list) 2))
(first-half (seq-subseq list 0 half))
(second-half (seq-subseq list half)))
(cons first-half second-half)))
(defun conlanging-eittlandic--generate-declension-from-table (root underlying-vowel table)
"Decline a ROOT (with maybe an UNDERLYING-VOWEL) with TABLE."
(reverse
(let (result)
(dolist (declension table result)
(push (concat root
(conlanging-eittlandic--maybe-underlying-vowel underlying-vowel (car declension))
(cdr declension))
result)))))
; Adjectives ;;;;;;;;;;;;;;;;;;;;;;;;;;
(defun conlanging-eittlandic--starts-with-any-p (str list)
"Check whether STR start with any element of LIST."
(seq-some (lambda (elt) (s-starts-with-p elt str)) list))
(defun conlanging-eittlandic--ends-with-any-p (str list)
"Check whether STR end with any element of LIST."
(seq-some (lambda (elt) (s-ends-with-p elt str)) list))
(defun conlanging-eittlandic--starts-with-a-vowel-p (str)
"Return whether STR start with a vowel."
(conlanging-eittlandic--starts-with-any-p str conlanging-eittlandic--vowels))
(defun conlanging-eittlandic--ends-with-a-vowel-p (str)
"Return whether STR start with a vowel."
(conlanging-eittlandic--ends-with-any-p str conlanging-eittlandic--vowels))
(defun conlanging-eittlandic--ends-with-a-rounded-vowel-p (str)
"Return whether STR start with a rounded vowel."
(conlanging-eittlandic--ends-with-any-p str conlanging-eittlandic--rounded-vowels))
(defun conlanging-eittlandic--generate-adjective-declension-from-table (root table)
"Generate an adjective's declensions from its ROOT.
The TABLE stores the adjectives declensions.
If the declension starts with a vowel, then a \"v\" will be
inserted before it if the root ends with a rounded vowel.
Otherwise, if any other vowel ends the root and the declension
starts with a vowel, the last onsonant of the declension will be
inserted before the declension itself.
We assume here any former long vowel cannot be unstressed."
(reverse
(let* (declensions
(root-ends-with-vowel (conlanging-eittlandic--ends-with-a-vowel-p root))
(root-ends-with-rounded-vowel (conlanging-eittlandic--ends-with-a-rounded-vowel-p root)))
(dolist (declension table declensions)
(push
(let ((declension-starts-with-vowel (conlanging-eittlandic--starts-with-a-vowel-p declension)))
(cond
((and root-ends-with-rounded-vowel declension-starts-with-vowel)
(concat root "v" declension))
((and root-ends-with-vowel declension-starts-with-vowel)
(concat root (s-right 1 declension) declension))
(t (concat root declension))))
declensions)))))
(defun conlanging-eittlandic--make-adjective-declension (root gender)
"Create declensions for an Eittlandic adjective.
The declension is based on the adjectives ROOT and the GENDER it
agrees with."
(conlanging-eittlandic--generate-adjective-declension-from-table
root
(if (eq 'common gender)
conlanging-eittlandic--adjective-inflexion-common
conlanging-eittlandic--adjective-inflexion-neuter)))
(defmacro conlanging-eittlandic--build-adjective-declension-org ()
"Just to avoid typing all of this out."
`(format "| | Common | Neuter |
|---------+--------+--------|
| Sg.Nom. | %s | %s |
| Acc.| %s | %s |
| Dat.| %s | %s |
| Gen.| %s | %s |
| Pl.Nom. | %s | %s |
| Acc.| %s | %s |
| Dat.| %s | %s |
| Gen.| %s | %s |"
,@(reverse (let ((i 0)
declensions)
(while (< i 8)
(dolist (gender '(common neuter) declensions)
(push `(nth ,i ,gender) declensions))
(setq i (1+ i)))
declensions))))
; Verbs ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defmacro conlanging-eittlandic--build-verb-declension-org ()
"Just to avoid typing all of this out."
`(format "Declensions:
- infinitive :: %s
- imperative :: %s
- imperative passive voice :: %s
- present participle :: %s
- past participle :: %s
| <c> | | | | | |
| person | | Ind. Pres. | Subj. Pres. | Past | Passive |
|--------+-+------------+-------------+------+---------|
| 1s | | %s | %s | %s | %s |
| 2s | | %s | %s | %s | %s |
| 3s | | %s | %s | %s | %s |
| 1p | | %s | %s | %s | %s |
| 2p | | %s | %s | %s | %s |
| 3p | | %s | %s | %s | %s |"
root root (concat root "ask") (concat root "and") (concat root "it")
,@(reverse
(let (accessor (i 0))
(while (< i 6)
(dolist (declension '(indicative-present subjunctive-present past passive))
(push `(nth ,i ,declension) accessor))
(setq i (1+ i)))
accessor))))
(defun conlanging-eittlandic--make-passive-verb-declension (root strength underlying-vowel passive-consonant passive-vowel)
"Create a verb declension for the passive mood.
Generates a passive declension for a verb with its ROOT based on
its STRENGTH and UNDERLYING-VOWEL. If there is no underlying
vowel for weak verbs, then the PASSIVE-VOWEL may be used instead.
If the verb is a verb is a strong verb, the PASSIVE-CONSONANT
will be used in some declensions."
(if (eq 'strong strength)
(conlanging-eittlandic--generate-declension-from-table root (or passive-vowel underlying-vowel)
conlanging-eittlandic--strong-verb-inflexion-passive)
(conlanging-eittlandic--generate-declension-from-table root passive-consonant
conlanging-eittlandic--weak-verb-inflexion-passive)))
(defun conlanging-eittlandic--make-verb-declension (root strength underlying-vowel passive-consonant passive-vowel mood tense)
"Create a verb declension based on its MOOD and TENSE.
Based on a verbs ROOT, STRENGTH, UNDERLYING-VOWEL, and potential
PASSIVE-CONSONANT or PASSIVE-VOWEL, create a verbs declension as
a list, in the following order:
- first person singular
- second person singular
- third person singular
- first person plural
- second person plural
- third person plural"
(if (eq 'passive mood)
(conlanging-eittlandic--make-passive-verb-declension root strength underlying-vowel passive-consonant passive-vowel)
(if (eq 'past tense)
(conlanging-eittlandic--generate-declension-from-table root underlying-vowel
conlanging-eittlandic--generic-verb-inflexion-past)
(conlanging-eittlandic--generate-declension-from-table
root underlying-vowel
(if (eq 'indicative mood)
conlanging-eittlandic--generic-verb-inflexion-indicative-present
conlanging-eittlandic--generic-verb-inflexion-subjunctive-present)))))
; Nouns ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defun conlanging-eittlandic--make-noun-declension (root gender strength underlying-vowel &optional definite)
"Create declensions of a word in Eittlandic.
Based on a words ROOT, GENDER, STRENGTH, UNDERLYING-VOWEL, and
whether its DEFINITE, create the declensions of a word as a
list, going in the following order:
- singular nominative
- singular accusative
- singular dative
- singular genitive
- plural nominative
- plural accusative
- plural dative
- plural genitive"
(conlanging-eittlandic--generate-declension-from-table
root underlying-vowel
(if definite
(if (and (eq 'strong strength) (eq 'common gender))
conlanging-eittlandic--strong-common-definite-noun-declension
conlanging-eittlandic--other-definite-noun-declension)
(if (eq 'weak strength)
conlanging-eittlandic--weak-noun-declension
(if (eq 'common gender)
conlanging-eittlandic--strong-common-noun-declension
conlanging-eittlandic--strong-neuter-noun-declension)))))
(defmacro conlanging-eittlandic--build-noun-declension-org ()
"Just to avoid typing all of this out."
`(format "| | Sg. | Def.Sg. | Pl. | Def.Pl. |
|------+-----+---------+-----+---------|
| Nom. | %s | %s | %s | %s |
| Acc. | %s | %s | %s | %s |
| Dat. | %s | %s | %s | %s |
| Gen. | %s | %s | %s | %s |"
,@(reverse (let (accessors i)
(dolist (case '(nominative accusative dative genitive) accessors)
(setq i 0)
(while (<= i 3)
(push `(nth ,i ,case) accessors)
(setq i (1+ i))))))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Public functions ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;###autoload
(defun conlanging-eittlandic-insert-adjective-declension (root)
"Insert adjective declensions of ROOT."
(interactive "sAdjective root: ")
(let ((common (conlanging-eittlandic--make-adjective-declension root 'common))
(neuter (conlanging-eittlandic--make-adjective-declension root 'neuter)))
(insert (conlanging-eittlandic--build-adjective-declension-org))))
;;;###autoload
(defun conlanging-eittlandic-insert-verb-declension (root strength underlying-vowel)
"Insert declensions of ROOT in org format at point.
Determines how to make declensions of the verb depending on its
STRENGTH and UNDERLYING-VOWEL."
(interactive
(list
(read-string "Verb root: ")
(pcase (completing-read "Strength: " '("strong" "weak") nil t)
("strong" 'strong)
("weak" 'weak)
(other (error (format "Unknown strength: %S" other))))
(let ((vowel (read-string "Underlying vowel (leave blank if none): ")))
(if (string= "" vowel) nil vowel))))
(let* ((passive-consonant (when (eq 'weak strength)
(completing-read "Consonant for passive declension: " '("d" "t" "ð") nil t)))
(passive-vowel (when (eq 'strong strength)
(completing-read "Vowel for passive declension: " '("a" "i") nil t)))
(indicative-present (conlanging-eittlandic--make-verb-declension root strength underlying-vowel
passive-consonant passive-vowel
'indicative 'present))
(subjunctive-present (conlanging-eittlandic--make-verb-declension root strength underlying-vowel
passive-consonant passive-vowel
'subjunctive 'present))
(past (conlanging-eittlandic--make-verb-declension root strength underlying-vowel passive-consonant
passive-vowel nil 'past))
(passive (conlanging-eittlandic--make-verb-declension root strength underlying-vowel
passive-consonant passive-vowel
'passive nil)))
(insert (conlanging-eittlandic--build-verb-declension-org))))
;;;###autoload
(defun conlanging-eittlandic-insert-noun-declensions (root gender strength underlying-vowel)
"Insert declensions of ROOT in org format at point.
The function will know how to create the declensions on ROOT
depending on its GENDER and its STRENGTH (whether it is a strong
or weak noun). The UNDERLYING-VOWEL may or may not be nil and
can influence the word's declensions."
(interactive
(list
(read-string "Word root: ")
(pcase (completing-read "Gender: " '("masculine" "feminine" "common" "neuter") nil t)
("masculine" 'common)
("feminine" 'common)
("common" 'common)
("neuter" 'neuter)
(other (error (format "Unknown gender: %S" other))))
(pcase (completing-read "Strength: " '("strong" "weak") nil t)
("strong" 'strong)
("weak" 'weak)
(other (error (format "Unknown strength: %S" other))))
(let ((vowel (read-string "Underlying vowel (leave blank if none): ")))
(if (string= "" vowel) nil vowel))))
(let* ((indefinite (conlanging-eittlandic--make-noun-declension root gender strength underlying-vowel))
(definite (conlanging-eittlandic--make-noun-declension root gender strength underlying-vowel t))
(indefinite-split (conlanging-eittlandic--split-list indefinite))
(definite-split (conlanging-eittlandic--split-list definite))
(zipped (-zip (car indefinite-split) (car definite-split) (cdr indefinite-split) (cdr definite-split)))
(nominative (nth 0 zipped))
(accusative (nth 1 zipped))
(dative (nth 2 zipped))
(genitive (nth 3 zipped)))
(insert (conlanging-eittlandic--build-noun-declension-org))))
(provide 'conlanging-eittlandic)
;;; conlanging-eittlandic.el ends here