diff --git a/conlanging-eittlandic.el b/conlanging-eittlandic.el new file mode 100644 index 0000000..629cc26 --- /dev/null +++ b/conlanging-eittlandic.el @@ -0,0 +1,180 @@ +;;; conlanging-eittlandic.el --- Helper functions for the Eittlandic language -*- lexical-binding: t -*- + +;; Author: Lucien Cartier-Tilet +;; Maintainer: Lucien Cartier-Tilet +;; Version: 0.1.0 +;; Package-Requires: ((emacs "29.1") (dash "2.19")) +;; 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 . + +;;; Code: + +(require 'dash) + +(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.") + +(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--make-noun-declension-from-table (root underlying-vowel table) + "Decline a noun ROOT (with maybe an UNDERLYING-VOWEL) with TABLE." + (seq-reverse + (let (result) + (dolist (declension table result) + (push (concat root + (conlanging-eittlandic--maybe-underlying-vowel underlying-vowel (car declension)) + (cdr declension)) + result))))) + +(defun conlanging-eittlandic--make-noun-declension (root gender strength underlying-vowel &optional definite) + "Create declensions of a word in Eittlandic. + +Based on a word’s ROOT, GENDER, STRENGTH, UNDERLYING-VOWEL, and +whether it’s 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--make-noun-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)))))))) + +;;;###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 diff --git a/conlanging.el b/conlanging.el index 88dd125..5a9f6d7 100644 --- a/conlanging.el +++ b/conlanging.el @@ -41,6 +41,7 @@ (require 'counsel) (require 'ivy) (require 'conlanging-graphviz) +(require 'conlanging-eittlandic) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Vuepress headings ;