diff options
-rw-r--r-- | Master/texmf-dist/doc/lualatex/ekdosis/README.md | 130 | ||||
-rw-r--r-- | Master/texmf-dist/doc/lualatex/ekdosis/ekdosis.el | 150 | ||||
-rw-r--r-- | Master/texmf-dist/doc/lualatex/ekdosis/ekdosis.pdf | bin | 0 -> 362094 bytes | |||
-rw-r--r-- | Master/texmf-dist/doc/lualatex/ekdosis/samples/Caesar_BG-6-13-1-tei.xml | 225 | ||||
-rw-r--r-- | Master/texmf-dist/doc/lualatex/ekdosis/samples/Caesar_BG-6-13-1.pdf | bin | 0 -> 17989 bytes | |||
-rw-r--r-- | Master/texmf-dist/doc/lualatex/ekdosis/samples/Caesar_BG-6-13-1.tex | 118 | ||||
-rw-r--r-- | Master/texmf-dist/source/lualatex/ekdosis/Makefile | 109 | ||||
-rw-r--r-- | Master/texmf-dist/source/lualatex/ekdosis/ekdosis.dtx | 5388 | ||||
-rw-r--r-- | Master/texmf-dist/source/lualatex/ekdosis/ekdosis.ins | 62 | ||||
-rw-r--r-- | Master/texmf-dist/tex/lualatex/ekdosis/ekdosis.lua | 1694 | ||||
-rw-r--r-- | Master/texmf-dist/tex/lualatex/ekdosis/ekdosis.sty | 959 | ||||
-rwxr-xr-x | Master/tlpkg/bin/tlpkg-ctan-check | 2 | ||||
-rw-r--r-- | Master/tlpkg/tlpsrc/collection-luatex.tlpsrc | 1 | ||||
-rw-r--r-- | Master/tlpkg/tlpsrc/ekdosis.tlpsrc | 0 |
14 files changed, 8837 insertions, 1 deletions
diff --git a/Master/texmf-dist/doc/lualatex/ekdosis/README.md b/Master/texmf-dist/doc/lualatex/ekdosis/README.md new file mode 100644 index 00000000000..4baa1e9727e --- /dev/null +++ b/Master/texmf-dist/doc/lualatex/ekdosis/README.md @@ -0,0 +1,130 @@ +--- +author: +- Robert Alessi +title: 'The ekdosis package – README file' +--- + +Overview +======== +`ekdosis` is a LuaLaTeX package designed for multilingual critical +editions. It can be used to typeset texts and different layers of +critical notes in any direction accepted by LuaTeX. Texts can be +arranged in running paragraphs or on facing pages, in any number of +columns which in turn can be synchronized or not. In addition to +printed texts, `ekdosis` can convert `.tex` source files so as to +produce `TEI xml` compliant critical editions. Database-driven +encoding under LaTeX then allows extraction of texts entered segment +by segment according to various criteria: main edited text, variant +readings, translations or annotated borrowings between texts. It is +published under the terms of the GNU General Public License (GPL) +version 3. + +Notice to the Gentle Reader +=========================== +The current state of this documentation covers the basics of +`ekdosis`, namely what should be enough to start a new document and +see how it works. v1.0 with a full documentation should be out by the +end of July. Until then, there is a web page that can be accessed, +<http://www.robertalessi.net/ekdosis>, with a mailing list that one can +subscribe to and a section entitled “Literature” where one will find +some slides and a paper submitted to a journal. + +License and Disclamer +===================== +ekdosis – Typesetting TEI xml Compliant Critical Editions + +Copyright ⓒ 2020 Robert Alessi + +Please send error reports and suggestions for improvements to Robert +Alessi: + +- email: <alessi@robertalessi.net> + +- website: <http://www.robertalessi.net/ekdosis> + +- comments, feature requests, bug reports: + <https://gitlab.com/ralessi/ekdosis/issues> + +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 <http://www.gnu.org/licenses/>. + +This release of icite consists of the following source files: + +- `ekdosis.dtx` + +- `ekdosis.ins` + +- `ekdosis.el` + +- `Makefile` + +License Applicable to the Documentation +--------------------------------------- +Copyright ⓒ 2020 Robert Alessi + +The documentation file `ekdosis.pdf` that is generated from the +`ekdosis.dtx` source file is licensed under the GNU Free Documentation +License, as follows:--- + +Permission is granted to copy, distribute and/or modify this document + under the terms of the GNU Free Documentation License, Version 1.3 + or any later version published by the Free Software Foundation; with + no Invariant Sections, no Front-Cover Texts, and no Back-Cover + Texts. A copy of the license is included in the section entitled + “GNU Free Documentation License”. + +Installation +============ +1. Run `'latex ekdosis.ins'` to produce the `ekdosis.sty` and + `ekdosis.lua` files. + +2. To finish the installation you have to move the `ekdosis.sty` and + `ekdosis.lua` files into a directory where LaTeX can find it. See + the FAQ on `texfaq.org` at <https://texfaq.org/FAQ-inst-wlcf> for + more on this. + +Development, Git Repository +=========================== + +Browse the Code +--------------- +You can browse icite repository on the web: +<http://git.robertalessi.net/ekdosis> + +From this page, you can download all the releases of `ekdosis`. For +instructions on how to install `ekdosis`, please see above. + +Comments, Feature Requests, Bug Reports +--------------------------------------- +<https://gitlab.com/ralessi/ekdosis/issues> + + +Download the Repository +----------------------- +`ekdosis` development is facilitated by git, a distributed version +control system. You will need to install git (most GNU/Linux +distributions package it in their repositories). + +Use this command to download the repository + + git clone http://git.robertalessi.net/ekdosis + +A new directory named icite will have been created, containing +`ekdosis`. + +Git Hosting +----------- +Make an account on <https://gitlab.com> and navigate (while logged in) +to <https://gitlab.com/ralessi/ekdosis>. Click *Fork* and you will +have in your account your own repository of `ekdosis` where you will +be able to make whatever changes you like to. diff --git a/Master/texmf-dist/doc/lualatex/ekdosis/ekdosis.el b/Master/texmf-dist/doc/lualatex/ekdosis/ekdosis.el new file mode 100644 index 00000000000..3d1547b4c80 --- /dev/null +++ b/Master/texmf-dist/doc/lualatex/ekdosis/ekdosis.el @@ -0,0 +1,150 @@ +;;; ekdosis.el --- AUCTeX style for `ekdosis.sty' +;; This file is part of the `ekdosis' package + +;; ekdosis -- TEI xml compliant critical editions +;; Copyright (C) 2020 Robert Alessi + +;; Please send error reports and suggestions for improvements to Robert +;; Alessi <alessi@robertalessi.net> + +;; 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 +;; <http://www.gnu.org/licenses/>. + +(defvar LaTeX-ekdosis-preamble-options + '(("parnotes" ("true" "false" "roman")) + ("teiexport" ("true" "false" "tidy")) + ("layout" ("float" "footins"))) + "Package options for the ekdosis package.") + +(defun LaTeX-ekdosis-package-options () + "Prompt for package options for ekdosis package." + (TeX-read-key-val t LaTeX-ekdosis-preamble-options)) + +(defun LaTeX-ekdosis-long-key-val (optional arg) + (let ((crm-local-completion-map + (remove (assoc 32 crm-local-completion-map) + crm-local-completion-map)) + (minibuffer-local-completion-map + (remove (assoc 32 minibuffer-local-completion-map) + minibuffer-local-completion-map))) + (TeX-argument-insert + (TeX-read-key-val optional arg) + optional))) + +(defvar LaTeX-ekdosis-declarewitness-options + '(("settlement") + ("repository") + ("msName") + ("origDate") + ("idno")) + "List of local options for DeclareWitness macro.") + +(defvar LaTeX-ekdosis-app-options + '(("type")) + "Local option for app|note macro.") + +(defvar LaTeX-ekdosis-lem-options + '(("wit") + ("alt") + ("pre") + ("post") + ("prewit") + ("postwit") + ("sep") + ("nolem" ("true" "false")) + ("nosep" ("true" "false"))) + "Local options for lem macro") + +(defvar LaTeX-ekdosis-rdg-options + '(("wit") + ("alt") + ("pre") + ("post") + ("prewit") + ("postwit") + ("nordg" ("true" "false"))) + "Local options for rdg macro.") + +(defvar LaTeX-ekdosis-note-options + '(("type") + ("lem") + ("labelb") + ("labele") + ("sep") + ("pre") + ("post")) + "Local options for note macro.") + +(defvar LaTeX-ekdosis-note-star-options + '(("pre") + ("post")) + "Local options for note* macro.") + +(defvar LaTeX-ekdosis-alignment-key-val-options + '(("tcols") + ("lcols") + ("texts") + ("apparatus") + ("flush" ("true" "false")) + ("paired" ("true" "false")) + ("pagelineation" ("true" "false"))) + "Local options for alignment env.") + +(TeX-add-style-hook + "ekdosis" + (lambda () + ;; Folding features: + (add-to-list (make-local-variable 'LaTeX-fold-macro-spec-list) + '("{1}" ("app")) + t) + (add-to-list (make-local-variable 'LaTeX-fold-macro-spec-list) + '("{7}||{6}||{5}||{4}||{3}||{2}||{1}" ("lem")) + t) + (add-to-list (make-local-variable 'LaTeX-fold-macro-spec-list) + '("[r]" ("rdg")) + t) + (add-to-list (make-local-variable 'LaTeX-fold-macro-spec-list) + '("[n]" ("note")) + t) + (add-to-list (make-local-variable 'LaTeX-fold-macro-spec-list) + '("[l]" ("linelabel")) + t) + ;; This package relies on lualatex, so check for it: + (TeX-check-engine-add-engines 'luatex) + (TeX-add-symbols + '("DeclareWitness" "xml:id" "rendition" "description" + [ LaTeX-ekdosis-long-key-val LaTeX-ekdosis-declarewitness-options ] + 0) + '("app" [ TeX-arg-key-val LaTeX-ekdosis-app-options ] + t) + '("lem" [ LaTeX-ekdosis-long-key-val LaTeX-ekdosis-lem-options ] + t) + '("rdg" [ LaTeX-ekdosis-long-key-val LaTeX-ekdosis-rdg-options ] + t) + '("note" [ LaTeX-ekdosis-long-key-val LaTeX-ekdosis-note-options ] + t) + '("note*" [ LaTeX-ekdosis-long-key-val LaTeX-ekdosis-note-star-options ] + t) + '("SetEkdosisAlignment" + (TeX-arg-key-val LaTeX-ekdosis-alignment-key-val-options)) + ) + (LaTeX-add-environments + "ekdosis" + '("alignment" LaTeX-env-args + [ TeX-arg-key-val LaTeX-ekdosis-alignment-key-val-options ] + )) + ) + LaTeX-dialect) + +;;; ekdosis.el ends here diff --git a/Master/texmf-dist/doc/lualatex/ekdosis/ekdosis.pdf b/Master/texmf-dist/doc/lualatex/ekdosis/ekdosis.pdf Binary files differnew file mode 100644 index 00000000000..ef69e146fa5 --- /dev/null +++ b/Master/texmf-dist/doc/lualatex/ekdosis/ekdosis.pdf diff --git a/Master/texmf-dist/doc/lualatex/ekdosis/samples/Caesar_BG-6-13-1-tei.xml b/Master/texmf-dist/doc/lualatex/ekdosis/samples/Caesar_BG-6-13-1-tei.xml new file mode 100644 index 00000000000..b9e4f9a23ad --- /dev/null +++ b/Master/texmf-dist/doc/lualatex/ekdosis/samples/Caesar_BG-6-13-1-tei.xml @@ -0,0 +1,225 @@ +<?xml version="1.0" encoding="utf-8"?> +<TEI xmlns="http://www.tei-c.org/ns/1.0"> + <teiHeader> + <fileDesc> + <titleStmt> + <title> + <!-- Title --> + </title> + <respStmt> + <resp> + <!-- Edited by --> + </resp> + <name> + <!-- Name --> + </name> + </respStmt> + </titleStmt> + <publicationStmt> + <distributor> + <!-- Distributor name --> + </distributor> + </publicationStmt> + <sourceDesc> + <listWit> + <witness xml:id="A"> + <abbr type="siglum">A</abbr> + <emph>Bongarsianus</emph>81 + <msDesc> + <msIdentifier> + <settlement>Amsterdam</settlement> + <institution>University Library</institution> + <idno>81</idno> + <msName> + <emph>Bongarsianus</emph> + </msName> + </msIdentifier> + <physDesc> + <handDesc hands="1"> + <handNote xml:id="A1"> + <abbr type="siglum">A + <hi rend="sup">1</hi></abbr> + <p> + <emph>Emendationes scribae ipsius</emph> + </p> + </handNote> + </handDesc> + </physDesc> + <history> + <origin> + <origDate>s. IX--X</origDate> + </origin> + </history> + </msDesc></witness> + <witness xml:id="M"> + <abbr type="siglum">M</abbr> + <emph>Parisinus Lat.</emph>5056 + <msDesc> + <msIdentifier /> + <history> + <origin> + <origDate>s. XII</origDate> + </origin> + </history> + </msDesc></witness> + <witness xml:id="B"> + <abbr type="siglum">B</abbr> + <emph>Parisinus Lat.</emph>5763 + <msDesc> + <msIdentifier /> + <history> + <origin> + <origDate>s. IX--X</origDate> + </origin> + </history> + </msDesc></witness> + <witness xml:id="R"> + <abbr type="siglum">R</abbr> + <emph>Vaticanus Lat.</emph>3864 + <msDesc> + <msIdentifier /> + <history> + <origin> + <origDate>s. X</origDate> + </origin> + </history> + </msDesc></witness> + <witness xml:id="S"> + <abbr type="siglum">S</abbr> + <emph>Laurentianus</emph>R 33 + <msDesc> + <msIdentifier /> + <history> + <origin> + <origDate>s. X</origDate> + </origin> + </history> + </msDesc></witness> + <witness xml:id="L"> + <abbr type="siglum">L</abbr> + <emph>Londinensis</emph>Br. Mus. 10084 + <msDesc> + <msIdentifier /> + <history> + <origin> + <origDate>s. XI</origDate> + </origin> + </history> + </msDesc></witness> + <witness xml:id="N"> + <abbr type="siglum">N</abbr> + <emph>Neapolitanus</emph>IV, c. 11 + <msDesc> + <msIdentifier /> + <history> + <origin> + <origDate>s. XII</origDate> + </origin> + </history> + </msDesc></witness> + <witness xml:id="T"> + <abbr type="siglum">T</abbr> + <emph>Parisinus Lat.</emph>5764 + <msDesc> + <msIdentifier /> + <history> + <origin> + <origDate>s. XI</origDate> + </origin> + </history> + </msDesc></witness> + <witness xml:id="f"> + <abbr type="siglum"> + <emph>f</emph> + </abbr> + <emph>Vindobonensis</emph>95 + <msDesc> + <msIdentifier /> + <history> + <origin> + <origDate>s. XII</origDate> + </origin> + </history> + </msDesc></witness> + <witness xml:id="U"> + <abbr type="siglum">U</abbr> + <emph>Vaticanus Lat.</emph>3324 + <msDesc> + <msIdentifier /> + <history> + <origin> + <origDate>s. XI</origDate> + </origin> + </history> + </msDesc></witness> + <witness xml:id="l"> + <abbr type="siglum"> + <emph>l</emph> + </abbr> + <emph>Laurentianus</emph>Riccard. 541 + <msDesc> + <msIdentifier /> + <history> + <origin> + <origDate>s. XI--XII</origDate> + </origin> + </history> + </msDesc></witness> + </listWit> + </sourceDesc> + </fileDesc> + <encodingDesc> + <variantEncoding method="parallel-segmentation" + location="internal" /> + </encodingDesc> + </teiHeader> + <text> + <body> + <div xml:id="div-latin_1" xml:lang="la"> + <div type="section" n="6.13"> + <head>XIII</head> + <p>In omni Gallia eorum hominum qui + <app> + <lem wit="#A #M #B #R #S #L #N">aliquo</lem> + <rdg wit="#T #f #U #l">in aliquo</rdg> + </app>sunt numero atque honore genera sunt duo. Nam + plebes paene seruorum habetur loco, quae + <app> + <lem wit="#A #M">nihil audet per se</lem> + <rdg wit="#A1">nihil aut et per se</rdg> + <rdg wit="#R #S #L #N">nihil habet per se</rdg> + <rdg wit="#T #f #U #l">per se nihil audet</rdg> + </app>, + <app> + <lem wit="#A #M #B #R #S #L #N">nullo</lem> + <rdg wit="#T #f #U #l">nulli</rdg> + </app>adhibetur + <app> + <lem>consilio</lem> + <rdg wit="#T #U">concilio</rdg> + </app>.</p> + </div> + </div> + <div xml:id="div-english_1" xml:lang="en"> + <div type="section" n="6.13"> + <head>XIII</head> + <p>Throughout all Gaul there are two orders of those men + who are of any rank and dignity: for the commonality is + held almost in the condition of slaves, and dares to + undertake nothing of itself, and is admitted to no + deliberation.</p> + </div> + </div> + <div xml:id="div-french_1" xml:lang="fr"> + <div type="section" n="6.13"> + <head>XIII</head> + <p>Partout en Gaule il y a deux classes d'hommes qui + comptent et qui sont considérés. Quant aux gens du + peuple, ils ne sont guère traités autrement que des + esclaves, ne pouvant se permettre aucune initiative, + n'étant consultés sur rien.</p> + </div> + </div> + </body> + </text> +</TEI> diff --git a/Master/texmf-dist/doc/lualatex/ekdosis/samples/Caesar_BG-6-13-1.pdf b/Master/texmf-dist/doc/lualatex/ekdosis/samples/Caesar_BG-6-13-1.pdf Binary files differnew file mode 100644 index 00000000000..4f80ccc1372 --- /dev/null +++ b/Master/texmf-dist/doc/lualatex/ekdosis/samples/Caesar_BG-6-13-1.pdf diff --git a/Master/texmf-dist/doc/lualatex/ekdosis/samples/Caesar_BG-6-13-1.tex b/Master/texmf-dist/doc/lualatex/ekdosis/samples/Caesar_BG-6-13-1.tex new file mode 100644 index 00000000000..8002aec9e23 --- /dev/null +++ b/Master/texmf-dist/doc/lualatex/ekdosis/samples/Caesar_BG-6-13-1.tex @@ -0,0 +1,118 @@ +\documentclass[12pt]{article} +\usepackage{fontspec} +\usepackage[latin.classic,french,english]{babel} +\babelfont{rm}{Old Standard} +\babelfont{sf}{NewComputerModern Sans} +\babelfont{tt}{NewComputerModern Mono} + +\usepackage{nextpage} +\usepackage{xltabular} + +\usepackage[teiexport=tidy]{ekdosis} +\DeclareApparatus{default}[ + delim=\hskip0.75em, + ehook=.] + +\ekdfmtdiv{2}{}{.} + +\SetEkdosisAlignment{ + tcols=3, + lcols=1, + texts=latin[xml:lang="la"]; + english[xml:lang="en"]; + french[xml:lang="fr"], + apparatus=latin, + segmentation=auto} + +\AtBeginEnvironment{latin}{\selectlanguage{latin}} +\AtBeginEnvironment{english}{\sloppy\selectlanguage{english}} +\AtBeginEnvironment{french}{\sloppy\selectlanguage{french}} + +\DeclareWitness{A}{A}{\emph{Bongarsianus} 81}[ + msName=\emph{Bongarsianus}, + settlement=Amsterdam, + idno=81, + institution=University Library, + origDate=s. IX--X] +\DeclareHand{A1}{A}{A\textsuperscript{1}}[\emph{Emendationes + scribae ipsius}] +\DeclareWitness{M}{M}{\emph{Parisinus Lat.} 5056}[ + origDate={s. XII}] +\DeclareWitness{B}{B}{\emph{Parisinus Lat.} 5763}[ + origDate={s. IX--X}] +\DeclareWitness{R}{R}{\emph{Vaticanus Lat.} 3864}[ + origDate={s. X}] +\DeclareWitness{S}{S}{\emph{Laurentianus} R 33}[ + origDate={s. X}] +\DeclareWitness{L}{L}{\emph{Londinensis} Br. Mus. 10084}[ + origDate={s. XI}] +\DeclareWitness{N}{N}{\emph{Neapolitanus} IV, c. 11}[ + origDate={s. XII}] +\DeclareWitness{T}{T}{\emph{Parisinus Lat.} 5764}[ + origDate={s. XI}] +\DeclareWitness{f}{\emph{f}}{\emph{Vindobonensis} 95}[ + origDate={s. XII}] +\DeclareWitness{U}{U}{\emph{Vaticanus Lat.} 3324}[ + origDate={s. XI}] +\DeclareWitness{l}{\emph{l}}{\emph{Laurentianus} Riccard. 541}[ + origDate={s. XI--XII}] +\DeclareShorthand{a}{α}{A,M,B,R,S,L,N} +\DeclareShorthand{b}{β}{T,f,U,l} + +\begin{document} + +\begin{xltabular}[c]{0.75\linewidth}{lXl} + \caption*{\textbf{Conspectus siglorum}\label{tab:conspectus-siglorum}}\\ + \multicolumn{3}{c}{\emph{Familia} \getsiglum{a}}\\ + \SigLine{A}\\ + & \getsiglum{A1} \emph{Emendationes scribae ipsius} & \\ + \SigLine{M}\\ + \SigLine{B}\\ + \SigLine{R}\\ + \SigLine{S}\\ + \SigLine{L}\\ + \SigLine{N}\\ + \multicolumn{3}{c}{\emph{Familia} \getsiglum{b}}\\ + \SigLine{T}\\ + \SigLine{f}\\ + \SigLine{U}\\ + \SigLine{l}\\ +\end{xltabular} + +\cleartoevenpage + +\begin{alignment} + \begin{latin} + \ekddiv{head=XIII, depth=2, n=6.13, type=section} + In omni Gallia eorum hominum qui \app{ + \lem[wit=a]{aliquo} + \rdg[wit=b, alt=in al-]{in aliquo}} + sunt numero atque honore genera sunt duo. Nam plebes paene + seruorum habetur loco, quae \app{ + \lem[wit={A,M}, alt={nihil audet (aut et \getsiglum{A1}) + per se}]{nihil audet per se} + \rdg[wit=A1,nordg]{nihil aut et per se} + \rdg[wit={R,S,L,N}]{nihil habet per se} + \rdg[wit=b]{per se nihil audet}}, \app{ + \lem[wit=a]{nullo} + \rdg[wit=b]{nulli}} adhibetur \app{ + \lem{consilio} + \rdg[wit={T, U}, alt=conc-]{concilio}}. + \end{latin} + \begin{english} + \ekddiv{head=XIII, depth=2, n=6.13, type=section} + Throughout all Gaul there are two orders of those men who are of + any rank and dignity: for the commonality is held almost in the + condition of slaves, and dares to undertake nothing of itself, + and is admitted to no deliberation. + \end{english} + \begin{french} + \ekddiv{head=XIII, depth=2, n=6.13, type=section} + Partout en Gaule il y a deux classes d'hommes qui comptent et qui + sont considérés. Quant aux gens du peuple, ils ne sont guère + traités autrement que des esclaves, ne pouvant se permettre aucune + initiative, n'étant consultés sur rien. + \end{french} +\end{alignment} + +\end{document} diff --git a/Master/texmf-dist/source/lualatex/ekdosis/Makefile b/Master/texmf-dist/source/lualatex/ekdosis/Makefile new file mode 100644 index 00000000000..b57cb54116f --- /dev/null +++ b/Master/texmf-dist/source/lualatex/ekdosis/Makefile @@ -0,0 +1,109 @@ +NAME = ekdosis +SHELL = bash +CMP = lualatex-dev +PWD = $(shell pwd) +VERS = $(shell ltxfileinfo -v $(NAME).dtx|sed -e 's/^v//') +LOCAL = $(shell kpsewhich --var-value TEXMFLOCAL) +UTREE = $(shell kpsewhich --var-value TEXMFHOME) +HOMEDIR := $$HOME + +exts := md html ins dtx el +texsamples := $(basename $(wildcard $(PWD)/samples/*.tex)) +texsamplesout := $(notdir $(basename $(wildcard $(PWD)/samples/*.tex))) +findopts := $(foreach ext,$(exts),-or -iname "*.$(ext)") + +define dosamples + $(CMP) --output-dir=$(PWD)/TMP --shell-escape $1 >/dev/null + $(CMP) --output-dir=$(PWD)/TMP --shell-escape $1 >/dev/null + $(CMP) --output-dir=$(PWD)/TMP --shell-escape $1 >/dev/null + $(CMP) --output-dir=$(PWD)/TMP --shell-escape $1 >/dev/null +endef + +all: sty $(NAME).pdf + +sty: clean + $(CMP) $(NAME).ins >/dev/null + +$(NAME).pdf: $(NAME).dtx + @ echo "Make the sample files first..." + if [ ! -d $(PWD)/TMP ]; then mkdir $(PWD)/TMP; fi + $(foreach file,$(texsamples), $(call dosamples, $(file))) + mv TMP/*.pdf samples/ + mv $(texsamplesout)-tei.xml samples/ + @ echo "Build the documentation of $(NAME)..." + $(CMP) --shell-escape -recorder -interaction=batchmode $(NAME).dtx >/dev/null + biber $(NAME) >/dev/null + if [ -f $(NAME).glo ]; then makeindex -q -s gglo.ist -o $(NAME).gls $(NAME).glo; fi + if [ -f $(NAME).idx ]; then makeindex -q -s gind.ist -o $(NAME).ind $(NAME).idx; fi + $(CMP) --shell-escape --recorder --interaction=nonstopmode $(NAME).dtx > /dev/null + $(CMP) --shell-escape --recorder --interaction=nonstopmode $(NAME).dtx > /dev/null + $(CMP) --shell-escape --recorder --interaction=nonstopmode $(NAME).dtx > /dev/null + $(CMP) --shell-escape --recorder --interaction=nonstopmode $(NAME).dtx > /dev/null + $(CMP) --shell-escape --recorder --interaction=nonstopmode $(NAME).dtx > /dev/null + +samples: clean sty + if [ ! -d $(PWD)/TMP ]; then mkdir $(PWD)/TMP; fi + $(foreach file,$(texsamples), $(call dosamples, $(file))) + mv TMP/*{\.pdf,-tei\.xml} samples/ + +clean: + rm -rf auto + rm -f $(NAME).bib $(PWD)/TMP/*.bib + rm -rf .backup + find -iname "*~" -or -iname "*.pdf" | xargs rm -rf + find ./* -type f -iname "Makefile" $(findopts) > ls-R + find ./* -type f -iname "*.tex" | grep '/samples/' >> ls-R + rsync -aPr --files-from=ls-R . .backup + rm -rf * + cp -p -r .backup/* . + rm -rf .backup + pandoc -s README.md -o about.html + +auctex: + if [ ! -d "$(HOMEDIR)/.emacs.d/auctex/auto" ]; then \ + mkdir -p $(HOMEDIR)/.emacs.d/auctex/auto; \ + fi + cp $(NAME)*.el $(HOMEDIR)/.emacs.d/auctex/auto + +distclean: clean uninst + +uninst: + rm -rf $(UTREE)/{tex,source,doc}/lualatex/$(NAME) + rm -rf $(HOMEDIR)/.emacs.d/auctex/auto/$(NAME).{el,elc} + +inst: uninst auctex all + mkdir -p $(UTREE)/{tex,source,doc}/lualatex/$(NAME) + cp $(NAME).dtx $(UTREE)/source/lualatex/$(NAME) + cp $(NAME).sty $(UTREE)/tex/lualatex/$(NAME) + cp $(NAME).lua $(UTREE)/tex/lualatex/$(NAME) + cp $(NAME).pdf $(UTREE)/doc/lualatex/$(NAME) + cp -r samples/ $(UTREE)/doc/lualatex/$(NAME) + +local: uninst auctex + $(CMP) $(NAME).ins + mkdir -p $(UTREE)/{tex,source,doc}/lualatex/$(NAME) + cp $(NAME).sty $(UTREE)/tex/lualatex/$(NAME) + cp $(NAME).lua $(UTREE)/tex/lualatex/$(NAME) + +zip: all + ln -sf . $(NAME) + zip -Drq $(PWD)/$(NAME)-$(VERS).zip $(NAME)/{samples,README.md,$(NAME).{pdf,sty,lua,el}} + rm $(NAME) + +package: distclean all + mkdir $(NAME)/ + cp Makefile README.md $(NAME).{ins,dtx,pdf} $(NAME)/ + cp -r samples/ $(NAME)/ + mkdir -p tex/lualatex/$(NAME)/ + cp *.lua *.sty tex/lualatex/$(NAME)/ + mkdir -p doc/lualatex/$(NAME)/ + cp README.md *.el *.pdf doc/lualatex/$(NAME)/ + cp -r samples/ doc/lualatex/$(NAME)/ + mkdir -p source/lualatex/$(NAME)/ + cp Makefile *.ins *.dtx source/lualatex/$(NAME)/ + zip -r $(NAME).tds.zip tex doc source + rm -rf tex/ source/ doc/ + tar czf $(NAME)-$(VERS).tar.gz $(NAME).tds.zip $(NAME)/ + rm -rf $(NAME)/ + +.PHONY: all clean distclean inst local uninst install uninstall zip package samples diff --git a/Master/texmf-dist/source/lualatex/ekdosis/ekdosis.dtx b/Master/texmf-dist/source/lualatex/ekdosis/ekdosis.dtx new file mode 100644 index 00000000000..f2700aa972a --- /dev/null +++ b/Master/texmf-dist/source/lualatex/ekdosis/ekdosis.dtx @@ -0,0 +1,5388 @@ +% \iffalse meta-comment +% +% ekdosis -- Typesetting TEI xml compliant critical editions +% Copyright (C) 2020 Robert Alessi +% +% Please send error reports and suggestions for improvements to Robert +% Alessi <alessi@robertalessi.net> +% +% 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 +% <http://www.gnu.org/licenses/>. +% +%<*internal> +\iffalse +%</internal> +%<*luapre> +--[[ +This file is part of the `ekdosis' package + +ekdosis -- Typesetting TEI xml compliant critical editions +Copyright (C) 2020 Robert Alessi + +Please send error reports and suggestions for improvements to Robert +Alessi <alessi@robertalessi.net> + +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 +<http://www.gnu.org/licenses/>. +--]] + +%</luapre> +%<*internal> +\fi +%</internal> +% \fi +% +% \iffalse +%<*driver> +\ProvidesFile{ekdosis.dtx} +%</driver> +%<package>\NeedsTeXFormat{LaTeX2e}[1999/12/01] +%<package>\ProvidesPackage{ekdosis} +%<*package> + [2020/07/08 v0.99a Typesetting TEI xml compliant critical editions] +%</package> +%<*driver> +\begin{filecontents}[overwrite]{\jobname.bib} +@Article{Alessi2020, + author = {Alessi, Robert}, + title = {ekdosis: Using Lua\LaTeX{} for Producing \texttt{TEI + xml} Compliant Critical Editions and Highlighting + Parallel Writings}, + journaltitle = {Journal of Data Mining and Digital Humanities}, + date = 2020, + pubstate = {submitted}, + issuetitle = {Collecting, Preserving, and Disseminating Endangered + Cultural Heritage for New Understandings through + Multilingual Approaches}, + eprinttype = {hal}, + eprint = {hal-02779803} +} + +@Book{Caesar-BG-v2, + author = {{Caesar}}, + title = {Gallic War}, + origtitle = {Guerre des Gaules}, + date = 1987, + origdate = 1926, + editor = {Constans, L.-A.}, + volume = 2, + pagination = {none}, + series = {Collection des Universités de France}, + publisher = {Les Belles Lettres}, + location = {Paris} +} + +@Book{CaesarTr, + author = {{Caesar}}, + title = {Gallic War}, + date = 1869, + editor = {McDevitte, W. A., and Bohn, W. S.}, + edition = 1, + series = {Harper's New Classical Library}, + publisher = {Harper \& Brothers}, + location = {New York}} + +@Online{DLL-TC, + author = {{Digital Latin Library}}, + title = {Textual Criticism}, + url = + {https://digitallatin.org/library-digital-latin-texts/textual-criticism}, + urldate = {2020-05-24} +} + +@Online{Mastronarde.Tarrant2017, + author = {Mastronarde, Donald J. and Tarrant, Richard J.}, + title = {Review: Guidelines for Encoding Critical Editions + for the Library of Digital Latin Texts}, + date = {2017-12-04}, + url = + {https://classicalstudies.org/scs-blog/donald-j-mastronarde/review-guidelines-encoding-critical-editions-library-digital-latin}, + organization = {Society for Classical Studies} +} +\end{filecontents} +\begin{filecontents}[overwrite]{\jobname-cfg.tex} +\footnotelayout{m} +\DeclareApparatus{default}[ + delim=\hskip0.75em, + ehook=.] +\DeclareWitness{M}{M}{\emph{Marcianus Gr.} 269}[ + settlement=Venice, + institution=Marciana Library, + msName=\emph{Marcianus Gr.}, + idno=269, + origDate=s. X] +\DeclareHand{M1}{M}{M\textsuperscript{1}}[Emendatio scribae ipsius] +\DeclareHand{M2}{M}{M\textsuperscript{2}}[Manus posterior] +% Peter and John Story: +\DeclareWitness{pjA}{A}{Manuscript A Call No 123} +\DeclareWitness{pjB}{B}{Manuscript B Call No 456} +% Caesar's Gallic War: +\DeclareWitness{cA}{A}{\emph{Bongarsianus} 81}[ + msName=\emph{Bongarsianus}, + settlement=Amsterdam, + idno=81, + institution=University Library, + origDate=s. IX--X] +\DeclareHand{cA1}{cA}{A\textsuperscript{1}}[\emph{Emendationes + scribae ipsius}] +\DeclareWitness{cM}{M}{\emph{Parisinus Lat.} 5056}[ + origDate={s. XII}] +\DeclareWitness{cB}{B}{\emph{Parisinus Lat.} 5763}[ + origDate={s. IX--X}] +\DeclareWitness{cR}{R}{\emph{Vaticanus Lat.} 3864}[ + origDate={s. X}] +\DeclareWitness{cS}{S}{\emph{Laurentianus} R 33}[ + origDate={s. X}] +\DeclareWitness{cL}{L}{\emph{Londinensis} Br. Mus. 10084}[ + origDate={s. XI}] +\DeclareWitness{cN}{N}{\emph{Neapolitanus} IV, c. 11}[ + origDate={s. XII}] +\DeclareWitness{cT}{T}{\emph{Parisinus Lat.} 5764}[ + origDate={s. XI}] +\DeclareWitness{cf}{\emph{f}}{\emph{Vindobonensis} 95}[ + origDate={s. XII}] +\DeclareWitness{cU}{U}{\emph{Vaticanus Lat.} 3324}[ + origDate={s. XI}] +\DeclareWitness{cl}{\emph{l}}{\emph{Laurentianus} Riccard. 541}[ + origDate={s. XI--XII}] +\DeclareShorthand{ca}{α}{cA,cM,cB,cR,cS,cL,cN} +\DeclareShorthand{cb}{β}{cT,cf,cU,cl} +\end{filecontents} +\documentclass{ltxdoc} + %\usepackage[letterpaper,margin=25mm,left=50mm,nohead]{geometry} +\usepackage[letterpaper,margin=1.25in,left=50mm,nohead]{geometry} +\usepackage{dox} +\doxitem{Option}{option}{options} +\usepackage{microtype} +\usepackage[no-math]{fontspec} +\usepackage[latin.classic,greek.ancient,american]{babel} +\babelfont{rm}[ + SlantedFont={Old Standard}, + SlantedFeatures={FakeSlant=0.25}, + BoldSlantedFont={Old Standard}, + BoldSlantedFeatures={FakeBold=1.5,FakeSlant=0.25}]{Old Standard} +\babelfont{sf}{NewComputerModern Sans} +\babelfont{tt}{NewComputerModern Mono} +\babelfont[greek]{rm}[ + Script=Greek, RawFeature={+ss05;+ss06}, + SlantedFont={Old Standard}, + SlantedFeatures={FakeSlant=0.25}, + BoldSlantedFont={Old Standard}, + BoldSlantedFeatures={FakeBold=1.5,FakeSlant=0.25}]{Old Standard} +\babelfont[greek]{sf}[Script=Greek]{NewComputerModern Sans} +\babelfont[greek]{tt}[Script=Greek]{NewComputerModern Mono} +\babeltags{ancientgreek = greek} +\def\sg#1{\textancientgreek{#1}} +\usepackage[Old Standard]{mathfont} +\usepackage{arabluatex} +\usepackage[parnotes=roman,teiexport=tidy]{ekdosis} +\input{ekdosis-cfg} +\usepackage{xltabular} +\usepackage[prevent-all]{widows-and-orphans} +\usepackage[shortcuts,nospacearound]{extdash} +\usepackage[american]{isodate} +\usepackage{nextpage} +\usepackage{spacingtricks} +\usepackage{csquotes} +\usepackage{relsize} +\usepackage{enumitem} +\setlist{nosep} +\setlist[itemize]{label=\textendash} +\setlist[enumerate,1]{label=(\alph*)} +\newlist{remarks}{enumerate}{10} +\setlist[remarks]{ + label*=\textsc{Rem.} \arabic*, + left=0.25in, + before=\smaller} +\usepackage{manfnt} +\usepackage{lettrine} +\newcommand\danger{\lettrine[loversize=-.5]{\textdbend}{\hskip6pt}} +\usepackage{metalogox} +\usepackage{hologo} +\usepackage{xcolor} +\newbool{nocolordoc} +\definecolor{ekdcolor}{RGB}{243,241,235} +\definecolor{cinnamon}{rgb}{0.82, 0.41, 0.12} +\ifbool{nocolordoc}{ + \colorlet{ekdcolor}{white} + \colorlet{cinnamon}{black}}{} +\definecolor{gainsboro}{RGB}{222,222,222} +\PassOptionsToPackage{bookmarks=true}{hyperref} +\usepackage{xurl} +\usepackage[numbered]{hypdoc} +\usepackage[loadlang=en]{metastr} +\hypersetup{ + colorlinks, + allcolors=cinnamon, + linktocpage=true, + pdftype={Text} +} +\usepackage{uri} +\labelformat{section}{sect.~#1} +\labelformat{subsection}{sect.~#1} +\labelformat{subsubsection}{sect.~#1} +\labelformat{figure}{fig.~#1} +\newcounter{dummy} +\newcommand{\dummy}{\refstepcounter{dummy}} +\usepackage[nospace,american]{varioref} +\usepackage[style=oxnotes-inote,dashed]{biblatex} +\DeclareSourcemap{ + \maps[datatype=bibtex]{ + \map{ + \step[fieldsource=issuetitle] + \step[fieldset=journalsubtitle,origfieldval] + } + } +} +\ifbool{nocolordoc} +{ + \usepackage{fontawesome} + \def\oasymbol{\faUnlock} + \usepackage{biblatex-ext-oa} +} +{\usepackage[symbolpackage=l3draw]{biblatex-ext-oa}} +\DeclareDelimFormat[bib,biblist]{nametitledelim}{\addcomma\space} +\DeclareDelimFormat[bib,biblist]{innametitledelim}{\addcomma\space} +\renewcommand*\newunitpunct{\addcomma\space} +\newcommand*{\halurl}[1]{http://hal.archives-ouvertes.fr/#1} +\DeclareFieldFormat{eprint:hal}{% + \ifhyperref + {\href{\halurl{#1}}{hal:~\nolinkurl{#1}}} + {hal:~\nolinkurl{#1}}} +\DeclareFieldAlias{eprint:HAL}{eprint:hal} +\DeclareOpenAccessEprintUrl[always]{hal}{% + http://hal.archives-ouvertes.fr/\thefield{eprint}} +\DeclareOpenAccessEprintAlias{HAL}{hal} +\addbibresource{ekdosis.bib} +\metaset{titletext}{% + \metapick[#1]{title}% + \metacompose[#1]{subtitle}{\metaget[sep]{subtitle}}{}{}} +\metaset[print]{titletext}{% + \metatitleline[print]{title}% + \metatitleline[print]{subtitle}% + \metatitleline[print]{author}% + \metatitleline[print]{contactemail}% + \metatitlelinetwo[print]{date}[print]{draft}} +\metaset[skip]{subtitle}{\vspace{1ex}} +\metaset[skip]{author}{\vspace{2ex}} +\metaset[skip]{date}{\vspace{1ex}} +\metaset[style]{title}{\LARGE} +\metaset[style]{author}{\large} +\metaset[sep]{draft}{ -- } +\metasetlang{en-US} +\metaset{title}{ἔκδοσις} +\metaset{date}{\filedate} +\metaset{draft}{\fileversion} +\metaset{subject}{TEI xml compliant critical editions} +\metaset{subtitle}{Typesetting TEI xml Compliant Critical Editions} +\metaset[print]{subtitle}{Typesetting \texttt{TEI xml} Compliant + Critical Editions} +\metaset{author}{Robert Alessi} +\metaset{keywords}{LaTeX, Lua, TEI xml, multilingual critical + editions, alignment, segmentation} +\metaset{contactemail}{alessi@roberalessi.net} +\metaset[print]{contactemail}{\mailto[ekdosis]{alessi@robertalessi.net}} +\metaset{contacturl}{http://www.roberalessi.net} +\metaset{partof}{The ekdosis Package} +\metaset[print]{partof}{The \textsf{ekdosis} Package} +\metaset{copyrightowner}{\metapick[#1]{author}} +\metaset{copyrightdate}{2020} +\metaset{licensemessage}{Permission is granted to copy, distribute + and/or modify this document under the terms of the GNU Free + Documentation License, Version 1.3 or any later version published by + the Free Software Foundation; with no Invariant Sections, no + Front-Cover Texts, and no Back-Cover Texts. A copy of the license + is included in the section entitled ``GNU Free Documentation + License''.} +\metaset{licenseurl}{https://www.gnu.org/licenses/fdl-1.3.html} +\metaset[print]{licenseurl}{% + \url{https://www.gnu.org/licenses/fdl-1.3.html}} +\metaset[cmd]{licenselogo}{\includegraphics[scale=0.75]{#1}} +\metawritepdfinfo +\metawritepdfaux +\metawritepdfpreamble +\metawritepdfcontact +\metawritepdfrights +\usepackage{multicol} +\setlength\IndexMin{100pt} +\usepackage{tocloft} +\newlistof{listing}{lol}{List of listings} +\renewcommand\cfttocprehook{\begin{multicols}{2}} +\renewcommand\cfttocposthook{\end{multicols}} +\renewcommand\cfttoctitlefont{\Large\bfseries} +\renewcommand\cftlolprehook{\begin{multicols}{2}} +\renewcommand\cftlolposthook{\end{multicols}} +\renewcommand\cftloltitlefont{\Large\bfseries} +\usepackage{units} +\newcommand*\tred[1]{\textcolor{red}{#1}} +\usepackage{fbox} +\usepackage{tikz} +\usetikzlibrary{tikzmark} +\NewDocumentCommand{\pointto}{m}{% + \tikz[remember picture] \draw[>->,color=blue,overlay] (0em,0.5ex) to + ([shift={(0.5em,0pt)}]pic cs:#1);% + \tikz[remember picture] \draw[color=gray, overlay] + ([shift={(0.5em,0.5ex)}]pic cs:#1) circle [radius=8pt];} +\NewDocumentCommand{\pointtol}{m}{% + \tikz[remember picture] \draw[>->,color=blue,overlay] (0em,0.5ex) to + [bend left] ([shift={(0.5em,0pt)}]pic cs:#1);% + \tikz[remember picture] \draw[color=gray, overlay] + ([shift={(0.5em,0.5ex)}]pic cs:#1) circle [radius=8pt];} +\NewDocumentCommand{\pointtor}{m}{% + \tikz[remember picture] \draw[>->,color=blue,overlay] (0em,0.5ex) to + [bend right] ([shift={(0.5em,0pt)}]pic cs:#1);% + \tikz[remember picture] \draw[color=gray, overlay] + ([shift={(0.5em,0.5ex)}]pic cs:#1) circle [radius=8pt];} +\NewDocumentCommand{\pointtoer}{m}{% + \tikz[remember picture] \draw[>->,color=blue,overlay] (0em,0.5ex) to + [bend right] ([shift={(0em,0pt)}]pic cs:#1);% + \tikz[remember picture] \draw[color=gray, overlay] + ([shift={(-0.5em,0.5ex)}]pic cs:#1) ellipse [x radius=45pt, y + radius=6pt];} +\usepackage[breakable, skins, xparse]{tcolorbox} +\tcbset{colback=white, boxrule=0.4pt, colframe=cinnamon, + breakable} +\usepackage[newfloat]{minted} +\labelformat{listing}{listing~#1} +\ifbool{nocolordoc}{\usemintedstyle{bw}}{} +\setminted{bgcolor=ekdcolor,linenos, fontsize=\small} +\newminted[ekdlua]{lua}{bgcolor={}, linenos, fontsize=\relsize{-0.5}, + xleftmargin=12pt, breaklines, numberblanklines=false, numbersep=3pt, + firstnumber=last} +\renewcommand{\theFancyVerbLine}{\rmfamily\smaller\arabic{FancyVerbLine}} +\usepackage[contents]{colordoc} +\newcommand{\pkg}[1]{\textsf{#1}\index{#1=#1 (package)}} +\newcommand{\env}[1]{\texttt{#1}\index{#1=#1 (environment)}} +\backgroundcolor{c}{ekdcolor} +\usepackage{caption} +\captionsetup[listing]{position=above,skip=-1ex} +\usepackage{needspace} +\NewDocumentCommand{\captof}{O{listing} m O{}}{% + \bgroup + \needspace{5\baselineskip}% + \vskip 1ex plus 2pt minus 2pt% + \captionof{#1}{#2}% + #3% + \egroup} +% \usepackage{etoc} +% \etocsettocdepth{paragraph} +% \newcommand{\ekdtableofcontents}{% +% \begingroup +% \etocsetstyle{section}{}{} +% {\etocsavedsectiontocline{% +% \numberline{\etocnumber}\etocname}{\etocpage}}{} +% \etocsetstyle{subsection}{}{} +% {\etocsavedsubsectiontocline{% +% \numberline{\etocnumber}\etocname}{\etocpage}}{}% +% \etocsetstyle{subsubsection}{}{} +% {\etocsavedsubsubsectiontocline{% +% \numberline{\etocnumber}\etocname}{\etocpage}}{}% +% \etocsetstyle{paragraph}{}{\leftskip2cm\rightskip 2.2em \parfillskip +% 0pt plus 1fil\relax \nobreak} +% {\noindent\etocname{} \etocpage{} }{\par}% +% \etocmulticolstyle[2]{\section*{Contents}} +% \pdfbookmark[1]{Contents}{toc} +% \tableofcontents +% \endgroup} +\EnableCrossrefs +\CodelineIndex +\RecordChanges + %\OnlyDescription +\begin{document} + \DocInput{\jobname.dtx} + \PrintChanges + \PrintIndex +\end{document} +%</driver> +% \fi +% +% \CheckSum{1522} +% +% \CharacterTable +% {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z +% Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z +% Digits \0\1\2\3\4\5\6\7\8\9 +% Exclamation \! Double quote \" Hash (number) \# +% Dollar \$ Percent \% Ampersand \& +% Acute accent \' Left paren \( Right paren \) +% Asterisk \* Plus \+ Comma \, +% Minus \- Point \. Solidus \/ +% Colon \: Semicolon \; Less than \< +% Equals \= Greater than \> Question mark \? +% Commercial at \@ Left bracket \[ Backslash \\ +% Right bracket \] Circumflex \^ Underscore \_ +% Grave accent \` Left brace \{ Vertical bar \| +% Right brace \} Tilde \~} +% +% \GetFileInfo{\jobname.dtx} +% \DoNotIndex{\newcommand,\newenvironment,\begin,\begingroup} +% \DoNotIndex{\bgroup,\def,\edef,\egroup,\else,\expandafter,\endgroup} +% \DoNotIndex{\fi,\ifdefined,\luadirect,\luastring,\luastringN} +% \DoNotIndex{\luastringO,\NewDocumentCommand,\space,\unexpanded} +% +% \pdfbookmark[1]{\metaterm{title}}{title} +% \begin{tcolorbox}[ +% colframe=black, +% enhanced, +% drop lifted shadow, +% colback=white, +% boxrule=.25mm, +% halign=center, +% center +% ] +% \metapick[print]{titletext} +% \end{tcolorbox} +% +% \begin{tcolorbox}[title=Notice to the Gentle Reader] +% The current state of this documentation covers the basics of +% \pkg{ekdosis}, namely what should be enough to start a new +% document and see how it works. v1.0 with a full documentation +% should be out by the end of July. Until then, there is a web page +% that can be accessed,\footnote{% +% \url{http://www.robertalessi.net/ekdosis}} with a mailing list +% that one can subscribe to and a section entitled +% \enquote{Literature} where one will find some slides and a paper +% submitted to a journal. +% \end{tcolorbox} +% +% \tableofcontents +% \listoflistings +% +% \changes{v0.99a}{2020/07/08}{First public release (documentation in +% progress)} +% +% \begin{abstract} +% \pkg{ekdosis} is a Lua\LaTeX{} package designed for +% multilingual critical editions. It can be used to typeset texts +% and different layers of critical notes in any direction accepted +% by Lua\TeX. Texts can be arranged in running paragraphs or on +% facing pages, in any number of columns which in turn can be +% synchronized or not. In addition to printed texts, +% \pkg{ekdosis} can convert \texttt{.tex} source files so as to +% produce \texttt{TEI xml} compliant critical +% editions. Database-driven encoding under \LaTeX{} then allows +% extraction of texts entered segment by segment according to +% various criteria: main edited text, variant readings, translations +% or annotated borrowings between texts. It is published under the +% terms of the GNU General Public License (GPL) version 3. +% \end{abstract} +% +% \section*{License and Disclaimer} +% \addcontentsline{toc}{section}{License and disclamer} +% \subsection*{License Applicable to this Document} +% \pdfbookmark[2]{Licence applicable to this document}{copyright-doc} +% \leavevmode\marginpar{\hfill\texttt{fdl1.3}} +% \metapick[print]{rightstext} (See below \vref{sec:fdl}.) +% +% \subsection*{License Applicable to the Software} +% \pdfbookmark[2]{Licence applicable to the software}{copyright-soft} +% \label{sec:license-software} +% +% \pkg{ekdosis} --- \metapick[print]{subtitle} +% \metapick[print]{copyrightstatement} +% +% Please send error reports and suggestions for improvements to Robert +% Alessi: +% \begin{itemize} +% \item email: \mailto[ekdosis package]{alessi@roberalessi.net} +% \item website: \url{http://www.robertalessi.net/ekdosis} +% \item development: \url{http://git.robertalessi.net/ekdosis} +% \item comments, feature requests, bug reports: +% \url{https://gitlab.com/ralessi/eksodis/issues} +% \end{itemize} +% +% \leavevmode\marginpar{\hfill\texttt{gpl3+}} +% 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 +% \href{http://www.gnu.org/licenses}% +% {\texttt{<http://www.gnu.org/licenses/>}}. +% +% This release of \pkg{ekdosis} consists of the following +% source files: +% \begin{itemize} +% \item |ekdosis.ins| +% \item |ekdosis.dtx| +% \item |ekdosis.el| +% \item |Makefile| +% \end{itemize} +% +% \section{Introduction} +% \label{sec:introduction} +% \begin{comment} +% \begin{keyfigure}{l={fig:grid-typesetting},c={Grid Typesetting +% (which never came into existence)}, t={Each square in the grid +% has a side length of \unit[10]{pt}. Therefore, the distance +% between the last line of the text and the first line of the +% apparatus is here approximately \unit[25]{pt}.}} +% \centering +% \begin{tikzpicture} +% \draw[gainsboro,thin] (0.5,0.5) grid [step=10pt] (10,5); % +% \path node [align=justify, text width=8cm] at (5.5,3) {% +% I saw my friend Peter at the station yesterday. We were both +% in a great mood. \enquote{How nice to find you here!} he +% said. I chuckled to myself, recalling the last time we +% met.\par +% \rule{3cm}{0.01cm}\par\footnotesize% +% \textbf{1}~saw A] met B\hskip1em Peter A] John B \hskip1em +% \textbf{2}~great A] good B\hskip1em \textbf{2--3}~How +% nice... said A] \emph{om.} B\hskip1em \textbf{4} \emph{post} +% met \emph{add.} there B.}; \node at (0,3) {\scriptsize +% $\approx$ \unit[25]{pt}}; \draw [->] (0,2.875) -- (0,2.025); +% \end{tikzpicture} +% \end{keyfigure} +% \end{comment} +% +% The reader will find here, by way of introduction, a summarized +% version of the first part of an article that the author submitted +% some weeks ago to the +% \mkbibemph{\citefield{Alessi2020}{journaltitle}} as a contribution +% to a Digital Humanities workshop held at Stanford University +% (\printdate{2019-04-15}).\footcite{Alessi2020} +% +% The name of this package, \pkg{ekdosis}, derives from a Greek +% action noun\---\sg{ἔκδοσις}\---the meaning of which is: +% \enquote{publishing a book}, and also in concrete sense: \enquote{a +% publication, treatise}. For us moderns, this term refers to a long +% tradition of scholarly work consisting in establishing from +% manuscript evidence the texts of Greek and Latin classics that were +% handled down through the Middle Ages to the time of the first +% printed editions. Of course, this definition is extendible to other +% languages as well. The basic premise is that critical editions +% exhibit reconstructed texts from manuscript evidence either under +% the title of the edited text (direct tradition) or from explicit +% citations or parallel passages or translations in other languages +% (indirect tradition). +% +% Whether in print or digital, critical editions come with an +% apparatus criticus in which is mentioned all the evidence that was +% used to build the edited text. Arguably, it is precisely on this +% common point that the two kind of editions part ways for reading a +% traditional, well written apparatus criticus is only meant for +% experienced readers. Getting oneself familiarized with its many +% conventional rules is not unrelated to learning a language, equipped +% with technical terms, grammar rules and style embellishments, which +% came into existence out of over three centuries of scholarly +% attainments. Nevertheless, whereas this language is immediately +% accessible to human mind's ability to use language and interpret +% conventional symbols, it is quite inaccessible to a computer unless +% every item of information has been encoded in the rather dumb format +% that is suited to machines. +% +% On the other hand, editions in print have their own limitations. For +% example, every detail that editors of classical texts decide to +% discard to save space, regardless to its relevance to the purpose of +% the edition, is lost permanently as in the case of dialectal +% coloring of ancient books. Furthermore, passages collected as +% indirect tradition are only available as references in the +% \emph{apparatus testium} and cannot be referred to the original +% text. As a result, the reader is refrained from bestowing attention +% upon major parallel passages to understand better difficult passages. +% +% To conclude on these issues, print publications and digital editions +% are often contrasted as they belonged to two different +% worlds.\footnote{For a good illustration of this point, see +% \cite[\mkbibquote{Content, not Display}]{DLL-TC}.} It is commonly +% said that the content of editions in print is the result of the +% binding of the book itself as an object, whereas digital editions, +% in which format and presentation are by definition separated from +% content, are free from limitations coming from such bindings. To sum +% up from the foregoing considerations, this statement is likely to be +% qualified: as already seen above, the apparatus criticus must be +% looked at as a brilliant production of mind refined by centuries of +% scholarly tradition\---and surely tradition must go on\---arguably +% not as compact paragraphs that require special and painful training +% to be \enquote*{decoded}. On the other hand, what editions in print +% do not provide are what \citename{Mastronarde.Tarrant2017}{author} +% have called \enquote{actionable texts for use in digital +% research},\footcite{Mastronarde.Tarrant2017} namely database-driven +% texts allowing the reader to select annotations and display or +% arrange translations, parallel passages or borrowings in a variety +% of ways. +% +% \pkg{ekdosis} can be seen as an attempt at combining the two +% approaches. +% +% \subsection{Requirements} +% \label{sec:requirements} +% Please refer to \vref{ref:ekdrequirements}. +% +% \subsection{Features} +% \label{sec:features} +% A list of the main features of \pkg{ekdosis} follows:--- +% \begin{enumerate} +% \item \label{it:multicol-feature}\emph{Multilingual critical +% editions\/}: \pkg{ekdosis} can be used to typeset any number of +% texts in any direction accepted by \hologo{LuaTeX}. Running +% paragraphs of text can be arranged in any number of columns, +% either on single or facing pages, which in turn can be +% synchronized or not. \pkg{ekdosis} is also suitable for complex +% layouts as in the case of Arabic poetry or images where three-way +% alignment is required, or diagrams, \emph{\&c}. +% \item \emph{Apparatus criticus\/}: Edited texts can receive multiple +% layers of apparatus, e.g.\ apparatus criticus (to record variant +% readings), apparatus fontium (to collect references to texts quoted +% or cited in the edited text), apparatus testium (to collect +% testimonia or parallel passages), or any kind of short notes to be +% printed on the same page as the edited text, \emph{\&c}. +% \item \texttt{TEI xml} output: \pkg{ekdosis} can be instructed +% to output both PDF and \texttt{TEI xml} files at the same time. +% \item \emph{Database-driven encoding} under \LaTeX{} of texts +% entered segment by segment allows for alignment of parallel texts +% from multilingual corpora. +% \end{enumerate} +% +% Before going into detail, the following simple example will give the +% reader a general idea of the method of encoding with +% \pkg{ekdosis} authoritative texts composed of lemmata, in a way +% that is very close to \texttt{TEI xml} encoding:--- +% +% \captof{The \enquote{Peter/John} basic example}[\label{lst:pj1}] +% \iffalse +%<*example> +% \fi +\begin{minted}{latex} +\begin{ekdosis} + I + \app{ + \lem{saw} + \rdg{met} + } + my friend \app{\lem{Peter}\rdg{John}} at the station yesterday. +\end{ekdosis} +\end{minted} +% \iffalse +%</example> +% \fi +% +% \needspace{4\baselineskip}PDF output:--- +% \medskip +% \begin{alignment}[tcols=1,texts=specimen,apparatus=specimen] +% \begin{specimen} +% I +% \app{ +% \lem{saw} +% \rdg{met} +% } +% my friend +% \app{ +% \lem{Peter} +% \rdg{John} +% } +% at the station yesterday. +% \end{specimen} +% \end{alignment} +% +% \texttt{TEI xml} output:--- +% \iffalse +%<*example> +% \fi +\begin{minted}[linenos=false]{xml} +<p>I +<app> + <lem>saw</lem> + <rdg>met</rdg> +</app>my friend +<app> + <lem>Peter</lem> + <rdg>John</rdg> +</app>at the station yesterday.</p> +\end{minted} +% \iffalse +%</example> +% \fi +% +% As can be seen from \vref{lst:pj1}, the edition text is inserted in +% the \env{ekdosis} environment (l.~1 to 8). Then two +% \cs{app}\marg{apparatus entry} commands (ll.~3 and 7) contain the +% lemma (\cs{lem}\marg{lemma}), namely the reading that is accepted by +% the editor, and at least one variant reading +% (\cs{rdg}\marg{reading}, ll.~5 and 7). As the listing shows, the +% editor is free to lay out the code in a legible manner to the eye: +% the first lemma above spans several lines whereas the second one is +% written in sequence without spaces. +% +% In the PDF ouput, the edition text is printed in the upper part of +% the page, above the line, and naturally shows the accepted +% readings. The margins are used for numeration. In the apparatus +% criticus, below the line, reference to the text is made by +% specifying the number of the line and if several entries refer to +% the same line, numbers are not repeated. Instead, entries are +% separated from one another by a broad horizontal space. Finally, a +% square bracket is used inside entries to distinguish the lemma from +% the variant readings. +% +% Furthermore, as said above, if a \texttt{TEI xml} output be +% required, \pkg{ekdosis} compiles an additional |.xml| file an +% excerpt of which is provided above. +% +% \section{The Basics of \pkg{ekdosis}} +% \label{sec:ekdosis-basics} +% +%\subsection{Loading the Package\---General Options} +%\label{sec:load-general-options} +% +% \pkg{ekdosis} is loaded in the preamble like so:--- +% \iffalse +%<*example> +% \fi +\begin{minted}[linenos=false]{latex} +\usepackage{ekdosis} +\end{minted} +% \iffalse +%</example> +% \fi +% +% \pkg{ekdosis} may be loaded with four optional \enquote*{named +% arguments} either of which is set using the syntax +% \meta{key}$=$\meta{value}. The description of the optional arguments +% follows. +% +% \danger The reader is invited to refer to the relevant sections of +% this documentation for more information on how to use them. +% +% \DescribeOption{layout}\label{ref:layout-opt} +% |layout|$=$\verb+float|footins+\hfill\tcboxverb{Default: float}\\ +% By default, layers of critical notes are inserted as a floating +% environment to be printed at the bottom of pages. |layout=footins| +% can be set to insert critical notes in the default footnote block +% which can be considered to be a special kind of float that is +% printed at the bottom of pages. In this case, the apparatus criticus +% will be inserted between regular numbered footnotes, but will carry +% no footnote mark of its own. +% +% \DescribeOption{divs}\label{ref:divs-opt} +% |divs|$=$\verb+ekdosis|latex+\hfill\tcboxverb{Default: ekdosis}\\ +% In many occasions, \LaTeX{} standard textual divisions do not meet +% the specific requirements of classical and literary texts, the +% divisions of which may depend on many different received +% traditions. \pkg{ekdosis} provides a flexible mechanism in which +% format and presentation have been carefully separated from +% content. It is designed to build un-numbered \texttt{TEI} divisions +% allowed to nest recursively. However, if |divs| be set to |latex|, +% \LaTeX{} standard textual divisions can be used and will be +% translated into \texttt{TEI} numbered |<div>| elements. +% +% \danger It must be noted that the two styles are mutually exclusive. +% \vskip\baselineskip +% +% \DescribeOption{parnotes}\label{ref:parnotes-opt} +% |parnotes|$=$\verb+true|false|roman+% +% \hfill\tcboxverb{Default: not set}\\ +% This named argument does not need a value as it defaults to |true| +% if it is used. Apparatus criticus typeset by \pkg{ekdosis} may +% contain notes and footnotes. The latter can be laid out as +% paragraphed notes below the block of critical notes by means of the +% \pkg{parnotes} package. Additionally, |parnotes=roman| prints these +% footnotes numbered with Roman numerals. +% +% \DescribeOption{teiexport}\label{ref:teiexport-option} +% |teiexport|$=$\verb+true|false|tidy+% +% \hfill\tcboxverb{Default: not set}\\ +% This named argument does not need a value as it defaults to |true| +% if it is used. If |teiexport| be set to |true|, \pkg{ekdosis} is +% instructed to output both PDF and \texttt{TEI xml} files at the same +% time. By default, the \texttt{TEI} file will receive the same +% basename as the |.tex| source file, suffixed with |-tei.xml|. The +% raw |.xml| file that is produced by \pkg{ekdosis} can be further +% processed by the \textsf{tidy} console application.\footnote{See +% \url{http://www.html-tidy.org}.} To make this happen, \textsf{tidy} +% must be installed and the |.tex| source file must be compiled with +% the |--shell-escape| facility so that spawning programs from +% \LaTeX{} can be allowed.\footnote{See +% \url{https://texfaq.org/FAQ-spawnprog} for more information on how +% to do this.} +% +% As an example, the following line loads \pkg{ekdosis} and instructs +% it to output a \texttt{TEI xml} file (in addition to the PDF one) +% and to use \pkg{parnotes} to format with Roman numerals the footnotes +% that are inserted in the apparatus criticus:--- +% \iffalse +%<*example> +% \fi +\begin{minted}[linenos=false]{latex} +\usepackage[teiexport, parnotes=roman]{ekdosis} +\end{minted} +% \iffalse +%</example> +% \fi +% +% \subsection{Witnesses, Hands, Shorthands \& Scholars } +% \label{sec:declarations} +% Any reference that is to be used in the apparatus criticus must be +% \enquote{declared} in the preamble beforehand, namely: manuscript +% sigla (either for single manuscripts or manuscript families, primary +% or later hands, \emph{\&c.}) or abbreviated last names of scholars. +% To that effect, \pkg{ekdosis} provides the following preamble-only +% commands:--- +% \begin{comment} +% \begin{xltabular}[c]{0.4\linewidth}{lXr} +% \caption*{\textbf{Conspectus Siglorum}}\\ +% \SigLine{M}\\ +% \end{xltabular} +% \end{comment} +% +% \paragraph{Witnesses} +% \DescribeMacro{\DeclareWitness} \cs{DeclareWitness}\marg{unique +% id}\marg{rendition}\marg{description}\oarg{options}\\ +% This command requires three mandatory arguments enclosed between +% curly braces used to specify consecutively: +% \begin{enumerate} +% \item The unique identifier of the witness to be used both in the +% |.tex| source file and as an |xml:id| in the \texttt{TEI xml} +% output if any. +% \item The rendition to be used in the printed apparatus criticus, +% which also will be found within the |<sourceDesc>| element of the +% \texttt{TEI} header where the description of the witness occurs, +% within a |<abbr type="siglum">| element. +% \item A basic description of the manuscript to be found in a typical +% printed Conspectus Siglorum, namely: the name of the manuscript +% followed by its call number. +% \end{enumerate} +% Finally, the optional argument of \cs{DeclareWitness} accepts a +% comma-separated list of the following \enquote{name=value} arguments +% that are used to collect items of information to be found within +% the |<msIdentifer>| element in the \texttt{TEI} +% header:---\footnote{See +% \url{https://tei-c.org/release/doc/tei-p5-doc/en/html/MS.html\#msid} +% for detailed information on these elements.}\\ +% \DescribeOption{settlement} |settlement|$=$\meta{name}: The name of +% a city or administrative unit.\\ +% \DescribeOption{institution} |institution|$=$\meta{name}: The name +% of an institution such as a university or library.\\ +% \DescribeOption{repository} |repository|$=$\meta{name}: The name of +% the repository within which the witness is stored.\\ +% \DescribeOption{collection} |collection|$=$\meta{name}: The name of +% a collection of manuscripts.\\ +% \DescribeOption{idno} |idno|$=$\meta{call \#}: Any form of call +% number.\\ +% \DescribeOption{msName} |msName|$=$\meta{name}: The name commonly +% used for the witness.\\ +% \DescribeOption{origDate} |origDate|$=$\meta{date}: Any form of date +% used to identify the date of origin for the witness. +% +% To take here one example, a witness such as the \emph{Marcianus +% Graecus}~269, referred to as manuscript \enquote*{M} in the +% editions, which contains sixty treatises from Hippocrates, could be +% declared as follows:--- \iffalse +%<*example> +% \fi +\begin{minted}[linenos=false]{latex} +\DeclareWitness{M}{M}{\emph{Marcianus Gr.} 269}[ + settlement=Venice, + institution=Marciana Library, + msName=\emph{Marcianus Gr.}, + idno=269, + origDate=s. X] +\end{minted} +% \iffalse +%</example> +% \fi +% +% \paragraph{Hands} +% \DescribeMacro{\DeclareHand} \cs{DeclareHand}\marg{unique +% id}\marg{base ms.}\marg{rendition}\oarg{note}\\ +% This command requires three mandatory arguments enclosed between +% curly braces and one optional argument between square brackets used +% to specify consecutively:--- +% \begin{enumerate} +% \item The unique identifier of the hand to be used both in the +% |.tex| source file and as an |xml:id| in the \texttt{TEI xml} output +% if any. +% \item The unique idendifier of the witness the hand is related +% to. Of course, this witness must have been declared beforehand. +% \item The rendition to be used in the printed apparatus criticus, +% which also will be found within the |<handNote>| element of the +% \texttt{TEI} header where the description of the hand occurs, within +% a |<abbr type="siglum">| element. +% \item Some further information about the hand. +% \end{enumerate} +% +% To continue the preceding example, here is how additions and +% corrections found in the \emph{Marcianus Gr.}~269 could be declared +% after this witness has been declared itself:--- +% \iffalse +%<*example> +% \fi +\begin{minted}[linenos=false]{latex} +\DeclareHand{M1}{M}{M\textsuperscript{1}}[Emendatio scribae ipsius] +\DeclareHand{M2}{M}{M\textsuperscript{2}}[Manus posterior] +\end{minted} +% \iffalse +%</example> +% \fi +% +% As can be seen, values such as |M|, |M1| and |M2| in the |.tex| +% source file will be printed as \getsiglum{M}, \getsiglum{M1} and +% \getsiglum{M2} respectively. Not only the code gains legibility, but +% also flexibility for simply changing any declared rendition will +% update corresponding sigla thoughout the entire edition. +% +% As a final example, here is how \pkg{ekdosis} would encode +% information as declared above for the \emph{Marcianus Gr.}~269 +% should a \texttt{TEI} output be required:--- +% \iffalse +%<*example> +% \fi +\begin{minted}[linenos=false]{xml} +<sourceDesc> + <listWit> + <witness xml:id="M"> + <abbr type="siglum">M</abbr> + <emph>Marcianus Gr.</emph>269 + <msDesc> + <msIdentifier> + <settlement>Venice</settlement> + <institution>Marciana Library</institution> + <idno>269</idno> + <msName> + <emph>Marcianus Gr.</emph> + </msName> + </msIdentifier> + <physDesc> + <handDesc hands="2"> + <handNote xml:id="M1"> + <abbr type="siglum">M + <hi rend="sup">1</hi></abbr> + <p>Emendatio scribae ipius</p> + </handNote> + <handNote xml:id="M2"> + <abbr type="siglum">M + <hi rend="sup">2</hi></abbr> + <p>Manus posterior</p> + </handNote> + </handDesc> + </physDesc> + <history> + <origin> + <origDate>s. X</origDate> + </origin> + </history> + </msDesc></witness> + </listWit> +</sourceDesc> +\end{minted} +% \iffalse +%</example> +% \fi +% +% \paragraph{Shorthands} +% \DescribeMacro{\DeclareShorthand} \cs{DeclareShorthand}\marg{unique +% id}\marg{rendition}\marg{csv list of witnesses}\\ +% This command provides a convenient way to declare \emph{families} of +% witnesses. It takes three mandatory arguments used to specify +% consecutively:--- +% \begin{enumerate} +% \item The unique identifier of the family to be used in the |.tex| +% source file. +% \item The rendition to be used in the printed apparatus criticus. +% \item A comma-separated list of previously declared witnesses. +% \end{enumerate} +% +% As an example, the manuscripts of Caesar's \emph{Gallic War} are +% divided into two families: α, which includes mss.\ A, M, B, R, S, L +% and N, and β, which includes mss.\ T, f, U and l. Therefore, +% provided that all these witnesses have been already declared, here +% is how the two families α and β could be +% declared:---\footnote{These witnesses are used in the example +% provided below in \vref{lst:caesar-bg}.} +% \label{ref:caesar-bg-sigla} +% \iffalse +%<*example> +% \fi +\begin{minted}[linenos=false]{latex} +\DeclareShorthand{a}{α}{A,M,B,R,S,L,N} +\DeclareShorthand{b}{β}{T,f,U,l} +\end{minted} +% \iffalse +%</example> +% \fi +% +% Then, symbols |a| and |b| can be used in the |.tex| source file in +% place of manuscripts that belong to either family. +% +% \paragraph{Scholars} +% \DescribeMacro{\DeclareScholar} \cs{DeclareScholar}\marg{unique +% label}\marg{rendition}\\ +% The \emph{Conspectus Siglorum} that is placed ahead of the edition +% text is traditionally divided into two parts: a)~\emph{Codices}, +% which provides the list of sigla used in the apparatus, +% b)~\emph{Editiones uel Studia}, which provides references to +% scholars whose published or unpublished works contain conjectures +% used in the apparatus criticus. \cs{DeclareScholar} takes two +% mandatory arguments used to specify consecutively:--- +% \begin{enumerate} +% \item A unique label used in the |.tex| source file to refer to the +% work where the conjecture is found. +% \item The rendition to be used in the printed apparatus criticus. +% \end{enumerate} +% +% As \pkg{ekdosis} can include and use \texttt{TEI xml} compliant +% lists of references, it is avisable to use Bib\hologo{(La)TeX} +% labels in the first argument of \cs{DeclareScholar}. Likewise, +% shorthands fields from the bibliographical database can be recalled +% from within the second argument of \cs{DeclareScholar}:--- +% \iffalse +%<*example> +% \fi +\begin{minted}[linenos=false]{latex} +\DeclareScholar{Wil}{Wilamowitz} +% or for example: +\DeclareScholar{Wil}{\citename{Wil}{shorteditor}} +\end{minted} +% \iffalse +%</example> +% \fi +% \label{sec:declarations-end} +% +% \subsection{Editing a Single Text With No Translation} +% \label{sec:single-text-editing} +% \DescribeEnv{ekdosis} +% Running paragraphs of one single text to be edited should be +% inserted in the \env{ekdosis} environment, like so:---\footnote{See +% above \vref{lst:pj1}.} +% \iffalse +%<*example> +% \fi +\begin{minted}[linenos=false]{latex} +\begin{ekdosis} + Edition text goes here. +\end{ekdosis} +\end{minted} +% \iffalse +%</example> +% \fi +% +% \paragraph{Apparatus Entries} +% \DescribeMacro{\app} \cs{app}|[type=|\meta{type}|]|\marg{apparatus +% entries}\\ +% This command takes one mandatory argument and accepts one optional +% argument. Once references to be used as witnesses in the apparatus +% criticus have been declared in the preamble as described in +% \ref{sec:declarations} +% \vpagerefrange{sec:declarations}{sec:declarations-end}, the \cs{app} +% command is used for inserting entries in the apparatus criticus, +% either lemmata, readings or notes, like so:--- +% \iffalse +%<*example> +% \fi +\begin{minted}[linenos=false]{latex} +I saw my friend \app{\lem{Peter}\rdg{John}} yesterday. +or: +I saw my friend + \app{ + \lem{Peter} + \rdg{John} + } +yesterday. +\end{minted} +% \iffalse +%</example> +% \fi +% \cs{app} accepts one further optional argument:---\\ +% \DescribeOption{type} |type|$=$\meta{type}\hfill% +% \tcboxverb{Default: default}\\ +% By default, \pkg{ekdosis} sets one layer of notes\--- the |default| +% layer\---in the apparatus criticus. This layer is fit to receive +% notes related to variant readings from witnesses and sources used by +% the editor to establish the edition text. Additional layers can be +% defined to receive other kinds of notes, such as references to texts +% quoted or cited in the text of the edition (\emph{apparatus +% fontium}), references to testimonia, or quotations of the edited +% text by other authors (\emph{apparatus testium}), explanatory notes, +% and so forth.\footnote{See below, \vref{ref:type-app}.} Once +% additional layers have been defined and assigned to new +% \enquote*{types}, such as \enquote*{testium} and the like, these +% types can be used as values appended to the |type| \enquote*{named +% option}. +% +% \paragraph{Base text and variants} As can be seen in the example +% above, there are two kinds of individual readings: the \emph{lemma}, +% which contains the base text accepted by the editor, and the +% \emph{reading}, which contains deviant readings rejected by the +% editor. +% +% \paragraph{Lemmata} \DescribeMacro{\lem} +% \cs{lem}\oarg{options}\marg{lemma text}\\ +% As \meta{lemma text} is a word or a phrase judged by the editor to +% be authentic or authoritative, \cs{lem} prints it by default both in +% the edition text and as the first part of a new entry in the +% apparatus criticus, preceded by the line number where it occurs or a +% broad space if the entry refers to the same line as the preceding +% entry. \label{ref:lem-opts-b}The optional argument of \cs{lem} +% accepts the following +% comma-separated list of \enquote{name$=$value} arguments:---\\ +% \DescribeOption{wit} |wit|$=$\meta{csv list of witnesses}\\ +% While a single witness may be recorded as in |wit=A|, +% comma-separated lists of multiple witnesses must obviously be +% enclosed in curly braces, like so: +% |wit={A,B,C}|. \label{ref:mss-sep-families}It must be noted +% that witnesses can be grouped by using spaces as separators, like +% so: \verb*|wit={A,B,C, D,E,F}|.\\ +% \DescribeOption{alt} |alt|$=$\meta{alternate lemma}\\ +% While the mandatory argument of \cs{lem}, \meta{lemma text}, is +% always used to print the edition text in the upper part of the page, +% \meta{alternate lemma}, if specified, supersedes what is printed in +% the related entry of the apparatus criticus. This mechanism is useful +% in more than one respect. For instance, it can be used to insert +% abbreviated lemmata in the apparatus criticus, or to introduce an +% alternate way of writing entries with Latin technical terms in the +% apparatus criticus as will be demonstrated below in the example +% provided by \vref{lst:pj2}.\\ +% \DescribeOption{sep} |sep|$=$\meta{separator}\\ +% |sep| allows to change the symbol used to separate the lemma text +% from deviant readings, which is by default the closing square +% bracket (|]|)\\ +% \DescribeOption{nosep} |nosep|$=$\verb+true|false+\\ +% This named argument does not need a value as it defaults to |true| +% if it is used. Obviously, |nosep| removes the separator mentioned +% above.\\ +% \DescribeOption{nolem} |nolem|$=$\verb+true|false+\\ +% This named argument does not need a value as it defaults to |true| +% if it is used. |nolem| completely removes the lemma text from the +% related +% entry in the apparatus criticus.\\ +% \DescribeOption{type} |type|$=$\meta{value}\\ +% This named argument has no effect on the apparatus criticus of the +% edition in print, but it is used in the \texttt{TEI xml} ouput to +% classify the variation recorded in the entry according to some +% convenient typology. Categories such as lexical, morphological, +% orthographical and the like may apply. +% +% Finally, four named arguments can be used to insert words at the +% following specific places in the lemma text:\\ +% \noindent +% \fparbox*{\centered{\textbf{1} \tikzmark{pre}\tred{pre} Peter +% \tikzmark{post}\tred{post} \tikzmark{prewit}\tred{prewit} +% \getsiglum{pjA} +% \tikzmark{postwit}\tred{postwit}] John \getsiglum{pjB}}}\\ +% \DescribeOption{pre} |pre|$=$\meta{words}\pointtol{pre}\\ +% |pre| inserts \meta{words} \emph{before} the lemma text.\\ +% \DescribeOption{post} |post|$=$\meta{words}\pointto{post}\\ +% |post| inserts \meta{words} \emph{after} the lemma text.\\ +% \DescribeOption{prewit} |prewit|$=$\meta{words}\pointto{prewit}\\ +% |prewit| inserts \meta{words} \emph{before} the list of witnesses.\\ +% \DescribeOption{postwit} |postwit|$=$\meta{words}\pointtor{postwit}\\ +% |postwit| inserts \meta{words} \emph{after} the list of witnesses. +% \label{ref:lem-opts-e} +% +% \paragraph{Readings} \DescribeMacro{\rdg} +% \cs{rdg}\oarg{options}\marg{variant reading}\\ +% As \meta{reading} is a word or a phrase judged by the editor to be +% unsatisfactory or corrupted, \cs{rdg} prints it by default in the +% last part of the corresponding entry in the apparatus criticus, +% after the symbol that is used to separate words of the base text +% (the lemma text) from words rejected by the editor. The optional +% argument of \cs{rdg} accepts a comma-separated list of +% \enquote{name$=$value} arguments that is almost identical to +% \cs{app}. Therefore, emphasis will be placed here only on the +% differences. The reader is invited to refer to the description +% provided above \vpagerefrange{ref:lem-opts-b}{ref:lem-opts-e} for +% more detailed information:---\\ +% \DescribeOption{wit} |wit|$=$\meta{csv list of witnesses}\\ +% \DescribeOption{alt} |alt|$=$\meta{alternate reading}\\ +% \DescribeOption{nordg} |nordg|$=$\verb+true|false+\\ +% This named argument does not need a value as it defaults to |true| +% if it is used. |nordg| completely removes the variant reading from +% the related entry in the apparatus criticus.\\ +% \DescribeOption{type} |type|$=$\meta{value}\\ +% \DescribeOption{pre} |pre|$=$\meta{words}\\ +% \DescribeOption{post} |post|$=$\meta{words}\\ +% \DescribeOption{prewit} |prewit|$=$\meta{words}\\ +% \DescribeOption{postwit} |postwit|$=$\meta{words}\\ +% +% \paragraph{Notes} +% \DescribeMacro{\note}\DescribeMacro{\note*} +% \cs{note}\oarg{options}\marg{text} or +% \cs{note*}\oarg{options}\marg{text}\\ +% It may happen that editorial notes be needed to record short +% comments of general nature \emph{between} lemmata and +% readings. \cs{note} inserts inline comments while \cs{note*} places +% comments below the entire apparatus block. Furthermore, if +% \pkg{ekdosis} has been loaded with the |parnotes| option as +% described above \vpageref{ref:parnotes-opt}, \cs{note*} will use the +% \pkg{parnotes} package to lay out the notes as an additional +% paragraph below the apparatus criticus. The optional argument of +% \cs{note}/\cs{note*} accepts the following comma-separated list of +% \enquote{name$=$value} +% arguments:---\\ +% \DescribeOption{pre} |pre|$=$\meta{words}\\ +% |pre| inserts \meta{words} immediately before the note.\\ +% \DescribeOption{post} |post|$=$\meta{words}\\ +% |post| inserts \meta{words} immediately after the note.\\ +% +% \danger Under no circumstances is it permitted to insert the command +% \cs{note} or \cs{note*} inside the argument of \cs{lem} or +% \cs{rdg}. \cs{note}/\cs{note*} must go \emph{between} these +% commands. As a general rule, within \cs{app}|{}| elements, notes +% are inserted immediately \emph{after} the lemma or the variant +% reading they are related to. +% +% \Vref{lst:pj2} provides an illustration of some of the possibilities +% afforded by the commands just described:--- +% +% \captof{The \enquote{Peter/John} full example}[\label{lst:pj2}] +% \iffalse +%<*example> +% \fi +\begin{minted}{latex} +\begin{ekdosis} + I + \app{ + \lem[wit=A]{saw} + \rdg[wit=B]{met}} + my friend + \app{ + \lem{Peter} + \rdg{John} + } + at the station yesterday. We were both in a + \app{ + \lem[wit=A]{great} + \rdg[wit=B]{good}} + mood. + \app{ + \lem[wit=A, alt={How nice... said}]{\enquote{How nice to find + you here!} he said.} + \note*{There are no quotation marks in the mss.} + \rdg[wit=B, alt=\emph{om.}]{}} + I chuckled to myself, recalling the last time we + \app{ + \lem[wit=A,nolem]{met} + \rdg[wit=B, alt={\emph{post} met \emph{add.} there}]{met + there} + \note*{Ms. \getsiglum{B} provides other additions of this kind.}}. +\end{ekdosis} +\end{minted} +% \iffalse +%</example> +% \fi +% \resetlinenumber +% \begin{alignment}[tcols=1,texts=specimen,apparatus=specimen] +% \begin{specimen} +% I \app{\lem[wit=pjA]{saw}\rdg[wit=pjB]{met}} my friend +% \app{ +% \lem{Peter} +% \rdg{John} +% } +% at the station yesterday. We were both in a +% \app{ +% \lem[wit=pjA]{great} +% \rdg[wit=pjB]{good}} +% mood. +% \app{ +% \lem[wit=pjA, alt={\textooquote How nice... said}]{\enquote{How +% nice to find you here!} he said.} +% \note*{There are no quotation marks in the mss.} +% \rdg[wit=pjB, alt=\emph{om.}]{}} +% I chuckled to myself, recalling the last time we +% \app{ +% \lem[wit=pjA,nolem]{met} +% \rdg[wit=pjB, alt={\emph{post} met \emph{add.} there}]{met +% there} +% \note*{Ms. \getsiglum{pjB} provides other additions of this kind.}}. +% \end{specimen} +% \end{alignment} +% +% \begin{remarks} +% \item Close examination of lines~17--8 from \vref{lst:pj2} shows how +% |alt| has been used to insert an abbridged lemma text in the +% apparatus criticus in print while keeping safe what is to be found +% in the \texttt{TEI xml} output. +% \item The same technique has been used at line~24 to insert +% alternate words, including Latin technical terms, in place of the +% variant reading. Hence the use of |nolem| at line~23 to remove the +% lemma text from the apparatus criticus in print. +% \item \cs{note*} has been used to insert short annotations in two +% places (ll.~19 and 26). +% \item For an example of the use of |nordg|, see below +% \vref{lst:caesar-bg}, l.~11. +% \end{remarks} +% +% The corresponding \texttt{TEI xml} output produced by \pkg{ekdosis} +% from the \LaTeX{} source file follows:--- +% +% \captof{The \enquote{Peter/John} full example: \texttt{TEI xml} +% output}[\label{lst:pj2-tei}] +% \iffalse +%<*example> +% \fi +\begin{minted}[linenos=false]{xml} +<p>I +<app> + <lem wit="#A">saw</lem> + <rdg wit="#B">met</rdg> +</app>my friend +<app> + <lem>Peter</lem> + <rdg>John</rdg> +</app>at the station yesterday. We were both in a +<app> + <lem wit="#A">great</lem> + <rdg wit="#B">good</rdg> +</app>mood. +<app> + <lem wit="#A"> + <quote>How nice to find you here!</quote> he said.</lem> + <note>There are no quotation marks in the mss.</note> + <rdg wit="#B" /> +</app>I chuckled to myself, recalling the last time we +<app> + <lem wit="#A">met</lem> + <rdg wit="#B">met there</rdg> + <note>Ms. + <ref target="#B">B</ref>provides other additions of + this kind.</note> +</app>.</p> +\end{minted} +% \iffalse +%</example> +% \fi +% +% \section{Alignment of Parallel Texts} +% \label{sec:alignment-basic} +% As already said above,\footnote{See point +% \vref{it:multicol-feature}.} \pkg{ekdosis} can arrange sundry texts +% in parallel columns\---synchronized or not\---either on the same +% page or on facing pages. Depending on what is needed, any text can +% be equipped with an apparatus criticus. The most common example is +% that of an edition of a classical text with an apparatus criticus +% accompanied by a translation into a modern language on the facing +% page. One can also imagine an edition of two classical texts or two +% different recensions of the same text, each of which provides +% variants recorded in separate apparatus crititus, laid out on the +% left-hand pages, with one or more translations on the corresponding +% right-hand pages, and so forth. +% +% \paragraph{The \env{alignment} Environment} +% \DescribeEnv{alignment} \cs{begin}|{alignment}|\oarg{options}\dots +% \cs{end}|{alignment}|\label{ref:alignment-syntax}\\ +% This environment can be used as it is provided to typeset a standard +% critical edition, namely an edition text, equipped with an apparatus +% criticus and laid out on the left-hand pages, accompanied by a +% translation into a modern language on the facing pages. +% +% \DescribeEnv{edition}\DescribeEnv{translation} Within +% \env{alignment}, two environments are available by default: +% \cs{begin}|{edition}|\allowbreak\dots +% \cs{end}|{ed|\allowbreak|ition}| and \cs{begin}|{translation}|\dots +% \cs{end}|{translation}|. Obviously, the former is used to typeset +% the edition text with an apparatus criticus on the left, while the +% latter is used to typeset the translation on the right, like so:--- +% \iffalse +%<*example> +% \fi +\begin{minted}[linenos=false]{latex} +\begin{alignment} + \begin{edition} + First § of the edition text. + \end{edition} + \begin{translation} + First § of the translation. + \end{translation} + \begin{edition} + Second § of the edition text. + \end{edition} + \begin{translation} + Second § of the translation. + \end{translation} +\end{alignment} +\end{minted} +% \iffalse +%</example> +% \fi +% +% \DescribeEnv{edition*}\DescribeEnv{translation*} Furthermore, +% so-called \enquote{starred} versions of these environments can be +% used at any point to synchronize texts, that is to print them in +% such a way that the tops of all paragraphs are vertically +% aligned. To that effect, it must be noted that merely applying this +% command on a single environment\---for instance the leftmost +% one\---will have all other associated paragraphs printed aligned. +% +% \danger While the whole edition text and the whole translation can +% be inserted in a single \env{edition}/\env{translation} environment +% respectively, it is recommended to enter both texts paragraph by +% paragraph as shown in the example above. Not only this method of +% encoding allows not to lose sight of paragraphs that are meant to be +% read together, but it is also the only way to align paragraphs in +% print, and it is much more suitable to mark up correspondence +% between spans of texts as will be demonstrated below in +% \vref{ref:segmentation}. +% +% As an illustration, a short extract of Caesar's \emph{Gallic War}, +% VI, XIII.1 follows.\footnote{Latin text: \cite{Caesar-BG-v2}; +% English translation: \cite{CaesarTr}.} See the list of sigla for +% manuscripts and manuscript families above +% \vpageref{ref:caesar-bg-sigla}. As this document is not set for +% duplex printing, both texts have been put together on the same +% page. However, the reader will find the full |.tex| source file +% in \vref{sec:caesar-gw-tex} and \texttt{TEI xml} output in +% \vref{sec:caesar-gw-tei}. The corresponding PDF output is available +% in \href{samples/Caesar_BG-6-13-1.pdf}{a separate file}:--- +% +% \captof{Caesar's \emph{Gallic War}, VI, 13.1}[\label{lst:caesar-bg}] +% \iffalse +%<*example> +% \fi +\begin{minted}{latex} +\begin{alignment} + \begin{edition} + \ekddiv{head=XIII, depth=2, n=6.13, type=section} + In omni Gallia eorum hominum qui \app{ + \lem[wit=a]{aliquo} + \rdg[wit=b, alt=in al-]{in aliquo}} + sunt numero atque honore genera sunt duo. Nam plebes paene + seruorum habetur loco, quae \app{ + \lem[wit={A,M}, alt={nihil audet (aut et \getsiglum{A1}) + per se}]{nihil audet per se} + \rdg[wit=A1,nordg]{nihil aut et per se} + \rdg[wit={R,S,L,N}]{nihil habet per se} + \rdg[wit=b]{per se nihil audet}}, \app{ + \lem[wit=a]{nullo} + \rdg[wit=b]{nulli}} adhibetur \app{ + \lem{consilio} + \rdg[wit={T, U}, alt=conc-]{concilio}}. + \end{edition} + \begin{translation} + \ekddiv{head=XIII, depth=2, n=6.13, type=section} + Throughout all Gaul there are two orders of those men who are of + any rank and dignity: for the commonality is held almost in the + condition of slaves, and dares to undertake nothing of itself, + and is admitted to no deliberation. + \end{translation} +\end{alignment} +\end{minted} +% \iffalse +%</example> +% \fi +% +% \resetlinenumber +% \ekdfmtdiv{2}{}{.} +% \begin{alignment}[lcols=2, +% texts=edition[xml:lang="la"]; +% translation[xml:lang="en"]] +% \AtBeginEnvironment{edition}{\selectlanguage{latin}} +% \AtBeginEnvironment{translation}{\selectlanguage{american}} +% \begin{edition} +% \ekddiv{head=XIII, depth=2, n=6.13, type=section} +% In omni Gallia eorum hominum qui \app{ +% \lem[wit=ca]{aliquo} +% \rdg[wit=cb, alt=in al-]{in aliquo}} +% sunt numero atque honore genera sunt duo. Nam plebes paene +% seruorum habetur loco, quae \app{ +% \lem[wit={cA,cM}, alt={nihil audet (aut et \getsiglum{cA1}) +% per se}]{nihil audet per se} +% \rdg[wit=cA1,nordg]{nihil aut et per se} +% \rdg[wit={cR,cS,cL,cN}]{nihil habet per se} +% \rdg[wit=cb]{per se nihil audet}}, \app{ +% \lem[wit=ca]{nullo} +% \rdg[wit=cb]{nulli}} adhibetur \app{ +% \lem{consilio} +% \rdg[wit={cT, cU}, alt=conc-]{concilio}}. +% \end{edition} +% \begin{translation} +% \ekddiv{head=XIII, depth=2, n=6.13, type=section} +% Throughout all Gaul there are two orders of those men who are of +% any rank and dignity: for the commonality is held almost in the +% condition of slaves, and dares to undertake nothing of itself, +% and is admitted to no deliberation. +% \end{translation} +% \end{alignment} +% +% \begin{remarks} +% \item As can be seen from the apparatus entry related to l.~4 above, +% a subvariant has been inserted in the lemma part: \enquote{(aut et +% \getsiglum{cA1})}. This was done by using |alt| in +% \vref{lst:caesar-bg}, ll.~9--10. But as this variant is already +% recorded\---and printed\---in the lemma part, it was necessary to +% remove the entire otherwise redundant variant from the apparatus +% criticus in print. Hence the use of |nordg| at l.~11. +% \item For examples of abbreviations, see ll.~6 and 17. +% \item Line~17 shows how mss.\ T and U (which belong to two distinct +% subfamilies) have been separated from one another: % +% \verb*+wit={T, U}+. See above \vpageref{ref:mss-sep-families} for +% more information on this technique. +% \end{remarks} +% +% Finally, the corresponding \texttt{TEI xml} output follows:--- +% \iffalse +%<*example> +% \fi +\begin{minted}[linenos=false]{xml} +<div xml:id="div-edition_1" xml:lang="la"> + <div type="section" n="6.13"> + <head>XIII</head> + <p>In omni Gallia eorum hominum qui + <app> + <lem wit="#A #M #B #R #S #L #N">aliquo</lem> + <rdg wit="#T #f #U #l">in aliquo</rdg> + </app>sunt numero atque honore genera sunt duo. Nam + plebes paene seruorum habetur loco, quae + <app> + <lem wit="#A #M">nihil audet per se</lem> + <rdg wit="#A1">nihil aut et per se</rdg> + <rdg wit="#R #S #L #N">nihil habet per se</rdg> + <rdg wit="#T #f #U #l">per se nihil audet</rdg> + </app>, + <app> + <lem wit="#A #M #B #R #S #L #N">nullo</lem> + <rdg wit="#T #f #U #l">nulli</rdg> + </app>adhibetur + <app> + <lem>consilio</lem> + <rdg wit="#T #U">concilio</rdg> + </app>.</p> + </div> +</div> +<div xml:id="div-translation_1" xml:lang="en"> + <div type="section" n="6.13"> + <head>XIII</head> + <p>Throughout all Gaul there are two orders of those men + who are of any rank and dignity: for the commonality is + held almost in the condition of slaves, and dares to + undertake nothing of itself, and is admitted to no + deliberation.</p> + </div> +</div> +\end{minted} +% \iffalse +%</example> +% \fi +% +% \subsection{Alignment of Several Texts} +% \label{sec:multiple-alignment} +% As described above \vpageref{ref:alignment-syntax}, the +% \env{alignment} environment may receive an optional argument in which +% the following \enquote{name$=$value} arguments are accepted:---\\ +% \DescribeOption{tcols} +% |tcols|$=$\meta{number}\hfill\tcboxverb{Default: 2}\\ +% |tcols| stores the \underLine{t}otal number of +% \underLine{col}umn\underLine{s} of text to be aligned.\\ +% \DescribeOption{lcols} +% |lcols|$=$\meta{number}\hfill\tcboxverb{Default: 1}\\ +% |lcols| stores the number of \underLine{col}umn\underLine{s} to be +% printed on the \underLine{l}eft-hand page, \emph{out of the total +% number} of columns specified with |tcols|. As can be seen from the +% preceding two default values, \env{alignment} initially sets two +% columns of text on facing pages. Of course, for this setting to work +% properly, one must ensure that the \env{alignment} environment is +% started on a +% left page.\\ +% \DescribeOption{texts} +% |texts|$=$\meta{\underLine{semicolon}-separated +% values}\hfill\tcboxverb{Default: edition;translation}\\ +% Depending on the total number of columns that has been specified +% with |tcols| above, |texts| is then used to define the names of the +% environments that shall receive edition texts, translations, +% \emph{\&c.} Some very important points need to be emphasized in this +% respect:--- +% \begin{enumerate} +% \item Only unaccented letters of the alphabet (whatever the case) +% are allowed to compose the names of \LaTeX{} environments. +% \item These names must be separated from one another by +% \emph{semicolons}, as shown in red in the listing below at the end +% of lines~1 and 2. +% \begin{enumerate} +% \item[\dbend] The colon at the end of line~3 closes the whole +% value of |text| and acts as a higher level separator. +% \end{enumerate} +% \item Each name may be followed by a \enquote*{suboptional} argument +% between square brackets which will then be used to insert +% \texttt{TEI xml} attributes in the corresponding |<div>| +% element. For example, +% \iffalse +%<*example> +% \fi +\begin{minted}[escapeinside=++]{latex} +texts=latin[xml:lang="la"]+\textcolor{red}{;}+ + english[xml:lang="en"]+\textcolor{red}{;}+ + french[xml:lang="fr"]+\textcolor{red}{,}+ +\end{minted} +% \iffalse +%</example> +% \fi +% will be converted into \texttt{TEI xml} as follows:--- +% \iffalse +%<*example> +% \fi +\begin{minted}[linenos=false]{xml} +<div xml:id="div-latin_1" xml:lang="la"> +... +</div> +<div xml:id="div-english_1" xml:lang="en"> +... +</div> +<div xml:id="div-french_1" xml:lang="fr"> +... +</div> +\end{minted} +% \iffalse +%</example> +% \fi +% \begin{enumerate} +% \item[\dbend] As can be seen, \pkg{ekdosis} takes care of +% computing and inserting the |xml:id| attributes which are +% therefore not accepted in the \enquote*{suboptional} arguments +% of |texts|. +% \end{enumerate} +% \item The names of the environments must be specified in exactly the +% same order as they are supposed to appear in the print edition, +% from left to right. +% \end{enumerate} +% \DescribeOption{apparatus} +% |apparatus|$=$\meta{\underLine{semicolon}-separated +% values}\hfill\tcboxverb{Default: edition}\\ +% Then, the |apparatus| option, just as |texts|, takes a +% \underLine{semicolon}-separated list of previously defined +% environments that shall receive at least one layer of apparatus +% criticus.\\ +% \DescribeOption{paired} |paired|$=$\verb+true|false+% +% \hfill\tcboxverb{Default: true (initially not set)}\\ +% This named argument does not need a value as it defaults to |true| +% if it is used. By default, \pkg{ekdosis} follows the \LaTeX{} page +% numbering scheme when multiple texts are arranged on facing +% pages. The |paired| option leaves every right-hand page number +% unchanged, so that both facing pages hold the same page number.\\ +% \DescribeOption{lineation} |lineation|$=$\verb+page|document+ +% \hfill\tcboxverb{Default: document}\\ +% This option applies to edition texts initially set to receive an +% apparatus criticus. By default, lines are continuously numbered +% throughout the document. |lineation=page| sets the numbering to +% start afresh at the top of each page.\\ +% \DescribeOption{flush} |flush|$=$\verb+true|false+ +% \hfill\tcboxverb{Default: false}\\ +% This named argument does not need a value as it defaults to |true| +% if it is used. This option applies on rare occasions only, when two +% or more distinct \env{alignment} environments are started on the same +% page. Should this happen, any subsequent \env{alignment} environment +% must be set with the |flush| option so that every one of them +% carry its own apparatus criticus. +% +% As an example, the alignment of the Latin edition text of Caesar's +% \emph{Gallic War}, printed on left-hand pages, along with two +% translations into English and French, printed on right-hand pages, +% can be set as follows:--- +% \iffalse +%<*example> +% \fi +\begin{minted}[linenos=false]{latex} +\begin{alignment}[tcols=3, + lcols=1, + texts=latin[xml:lang="la"]; + english[xml:lang="en"]; + french[xml:lang="fr"], + apparatus=latin, + lineation=page] + \begin{latin} + Gallia est omnis divisa in partes tres quarum unam incolunt + Belgae, [...] + \end{latin} + \begin{english} + All Gaul is divided into three parts, one of which the Belgae + inhabit, [...] + \end{english} + \begin{french} + L'ensemble de la Gaule est divisé en trois parties: l'une est + habitée par les Belges, [...] + \end{french} +\end{alignment} +\end{minted} +% \iffalse +%</example> +% \fi +% +% \DescribeMacro{\SetEkdosisAlignment} +% \cs{SetEkdosisAlignment}\marg{alignment settings}\\ +% If the same alignment settings are to be shared by several +% \env{alignment} environments, common settings can be collected in +% the argument of \cs{SetEkdosisEnvironment}, like +% so:---\\ +% \iffalse +%<*example> +% \fi +\begin{minted}[linenos=false]{latex} +\SetEkdosisAlignment{ + tcols=3, + lcols=1, + texts=latin[xml:lang="la"]; + english[xml:lang="en"]; + french[xml:lang="fr"], + apparatus=latin, + lineation=page +} +\begin{alignment} + ... +\end{alignment} +\end{minted} +% \iffalse +%</example> +% \fi +% +% \cs{SetEkdosisAlignment} can be used either in the preamble or at +% any point of the document to set or to modify alignment settings. +% +% \section{To Be Continued...} +% v1.0 of \pkg{ekdosis}, which should be available by the end of July +% 2020, will include a full documentation. At the time of writing, the +% author is working on this part of the package. +% +% \begin{comment} +% \section{Multiple-Layer Apparatus Criticus} +% \end{comment} +% \label{sec:multilayer-apparatus} +% +% \label{ref:type-app} +% \begin{comment} +% \section{Correspondence and Alignment} +% \end{comment} +% \label{sec:correspondance-alignment} +% +% \label{ref:segmentation} +% +% \section{GNU Free Documentation License} +% \label{sec:fdl} +% \textbf{Version 1.3, 3 November 2008} +% +% \begin{center} +% Version 1.3, 3 November 2008 +% +% Copyright \copyright{} 2000, 2001, 2002, 2007, 2008 Free +% Software Foundation, Inc. +% +% \bigskip +% +% \url{https://fsf.org/} +% +% \bigskip +% +% Everyone is permitted to copy and distribute verbatim copies +% of this license document, but changing it is not allowed. +% \end{center} +% +% \needspace{3\baselineskip} +% \begin{center} +% {\bf\large Preamble} +% \end{center} +% +% The purpose of this License is to make a manual, textbook, or other +% functional and useful document \enquote{free} in the sense of +% freedom: to assure everyone the effective freedom to copy and +% redistribute it, with or without modifying it, either commercially +% or noncommercially. Secondarily, this License preserves for the +% author and publisher a way to get credit for their work, while not +% being considered responsible for modifications made by others. +% +% This License is a kind of \enquote{copyleft}, which means that +% derivative works of the document must themselves be free in the same +% sense. It complements the GNU General Public License, which is a +% copyleft license designed for free software. +% +% We have designed this License in order to use it for manuals for +% free software, because free software needs free documentation: a +% free program should come with manuals providing the same freedoms +% that the software does. But this License is not limited to software +% manuals; it can be used for any textual work, regardless of subject +% matter or whether it is published as a printed book. We recommend +% this License principally for works whose purpose is instruction or +% reference. +% +% \needspace{3\baselineskip} +% \begin{center} +% {\large\bf 1. APPLICABILITY AND DEFINITIONS\par} +% \end{center} +% +% This License applies to any manual or other work, in any medium, +% that contains a notice placed by the copyright holder saying it can +% be distributed under the terms of this License. Such a notice +% grants a world-wide, royalty-free license, unlimited in duration, to +% use that work under the conditions stated herein. The +% \enquote{\textbf{Document}}, below, refers to any such manual or +% work. Any member of the public is a licensee, and is addressed as +% \enquote{\textbf{you}}. You accept the license if you copy, modify +% or distribute the work in a way requiring permission under copyright +% law. +% +% A \enquote{\textbf{Modified Version}} of the Document means any work +% containing the Document or a portion of it, either copied verbatim, +% or with modifications and/or translated into another language. +% +% A \enquote{\textbf{Secondary Section}} is a named appendix or a +% front-matter section of the Document that deals exclusively with the +% relationship of the publishers or authors of the Document to the +% Document's overall subject (or to related matters) and contains +% nothing that could fall directly within that overall subject. +% (Thus, if the Document is in part a textbook of mathematics, a +% Secondary Section may not explain any mathematics.) The +% relationship could be a matter of historical connection with the +% subject or with related matters, or of legal, commercial, +% philosophical, ethical or political position regarding them. +% +% The \enquote{\textbf{Invariant Sections}} are certain Secondary +% Sections whose titles are designated, as being those of Invariant +% Sections, in the notice that says that the Document is released +% under this License. If a section does not fit the above definition +% of Secondary then it is not allowed to be designated as Invariant. +% The Document may contain zero Invariant Sections. If the Document +% does not identify any Invariant Sections then there are none. +% +% The \enquote{\textbf{Cover Texts}} are certain short passages of +% text that are listed, as Front-Cover Texts or Back-Cover Texts, in +% the notice that says that the Document is released under this +% License. A Front-Cover Text may be at most 5 words, and a +% Back-Cover Text may be at most 25 words. +% +% A \enquote{\textbf{Transparent}} copy of the Document means a +% machine-readable copy, represented in a format whose specification +% is available to the general public, that is suitable for revising +% the document straightforwardly with generic text editors or (for +% images composed of pixels) generic paint programs or (for drawings) +% some widely available drawing editor, and that is suitable for input +% to text formatters or for automatic translation to a variety of +% formats suitable for input to text formatters. A copy made in an +% otherwise Transparent file format whose markup, or absence of +% markup, has been arranged to thwart or discourage subsequent +% modification by readers is not Transparent. An image format is not +% Transparent if used for any substantial amount of text. A copy that +% is not \enquote{Transparent} is called \enquote{\textbf{Opaque}}. +% +% Examples of suitable formats for Transparent copies include plain +% ASCII without markup, Texinfo input format, LaTeX input format, SGML +% or XML using a publicly available DTD, and standard-conforming +% simple HTML, PostScript or PDF designed for human modification. +% Examples of transparent image formats include PNG, XCF and JPG. +% Opaque formats include proprietary formats that can be read and +% edited only by proprietary word processors, SGML or XML for which +% the DTD and/or processing tools are not generally available, and the +% machine-generated HTML, PostScript or PDF produced by some word +% processors for output purposes only. +% +% The \enquote{\textbf{Title Page}} means, for a printed book, the +% title page itself, plus such following pages as are needed to hold, +% legibly, the material this License requires to appear in the title +% page. For works in formats which do not have any title page as +% such, \enquote{Title Page} means the text near the most prominent +% appearance of the work's title, preceding the beginning of the body +% of the text. +% +% The \enquote{\textbf{publisher}} means any person or entity that +% distributes copies of the Document to the public. +% +% A section \enquote{\textbf{Entitled XYZ}} means a named subunit of +% the Document whose title either is precisely XYZ or contains XYZ in +% parentheses following text that translates XYZ in another language. +% (Here XYZ stands for a specific section name mentioned below, such +% as \enquote{\textbf{Acknowledgements}}, +% \enquote{\textbf{Dedications}}, \enquote{\textbf{Endorsements}}, or +% \enquote{\textbf{History}}.) To \enquote{\textbf{Preserve the +% Title}} of such a section when you modify the Document means that it +% remains a section \enquote{Entitled XYZ} according to this +% definition. +% +% The Document may include Warranty Disclaimers next to the notice +% which states that this License applies to the Document. These +% Warranty Disclaimers are considered to be included by reference in +% this License, but only as regards disclaiming warranties: any other +% implication that these Warranty Disclaimers may have is void and has +% no effect on the meaning of this License. +% +% \needspace{3\baselineskip} +% \begin{center} +% {\large\bf 2. VERBATIM COPYING\par} +% \end{center} +% +% You may copy and distribute the Document in any medium, either +% commercially or noncommercially, provided that this License, the +% copyright notices, and the license notice saying this License +% applies to the Document are reproduced in all copies, and that you +% add no other conditions whatsoever to those of this License. You +% may not use technical measures to obstruct or control the reading or +% further copying of the copies you make or distribute. However, you +% may accept compensation in exchange for copies. If you distribute a +% large enough number of copies you must also follow the conditions in +% section~3. +% +% You may also lend copies, under the same conditions stated above, +% and you may publicly display copies. +% +% \needspace{3\baselineskip} +% \begin{center} +% {\large\bf 3. COPYING IN QUANTITY\par} +% \end{center} +% +% If you publish printed copies (or copies in media that commonly have +% printed covers) of the Document, numbering more than 100, and the +% Document's license notice requires Cover Texts, you must enclose the +% copies in covers that carry, clearly and legibly, all these Cover +% Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on +% the back cover. Both covers must also clearly and legibly identify +% you as the publisher of these copies. The front cover must present +% the full title with all words of the title equally prominent and +% visible. You may add other material on the covers in addition. +% Copying with changes limited to the covers, as long as they preserve +% the title of the Document and satisfy these conditions, can be +% treated as verbatim copying in other respects. +% +% If the required texts for either cover are too voluminous to fit +% legibly, you should put the first ones listed (as many as fit +% reasonably) on the actual cover, and continue the rest onto adjacent +% pages. +% +% If you publish or distribute Opaque copies of the Document numbering +% more than 100, you must either include a machine-readable +% Transparent copy along with each Opaque copy, or state in or with +% each Opaque copy a computer-network location from which the general +% network-using public has access to download using public-standard +% network protocols a complete Transparent copy of the Document, free +% of added material. If you use the latter option, you must take +% reasonably prudent steps, when you begin distribution of Opaque +% copies in quantity, to ensure that this Transparent copy will remain +% thus accessible at the stated location until at least one year after +% the last time you distribute an Opaque copy (directly or through +% your agents or retailers) of that edition to the public. +% +% It is requested, but not required, that you contact the authors of +% the Document well before redistributing any large number of copies, +% to give them a chance to provide you with an updated version of the +% Document. +% +% \needspace{3\baselineskip} +% \begin{center} +% {\large\bf 4. MODIFICATIONS\par} +% \end{center} +% +% You may copy and distribute a Modified Version of the Document under +% the conditions of sections 2 and 3 above, provided that you release +% the Modified Version under precisely this License, with the Modified +% Version filling the role of the Document, thus licensing +% distribution and modification of the Modified Version to whoever +% possesses a copy of it. In addition, you must do these things in +% the Modified Version: +% +% \begin{itemize} +% \item[A.] Use in the Title Page (and on the covers, if any) a title +% distinct from that of the Document, and from those of previous +% versions (which should, if there were any, be listed in the +% History section of the Document). You may use the same title as a +% previous version if the original publisher of that version gives +% permission. +% +% \item[B.] List on the Title Page, as authors, one or more persons +% or entities responsible for authorship of the modifications in +% the Modified Version, together with at least five of the +% principal authors of the Document (all of its principal authors, +% if it has fewer than five), unless they release you from this +% requirement. +% +% \item[C.] State on the Title page the name of the publisher of the +% Modified Version, as the publisher. +% +% \item[D.] Preserve all the copyright notices of the Document. +% +% \item[E.] Add an appropriate copyright notice for your +% modifications adjacent to the other copyright notices. +% +% \item[F.] Include, immediately after the copyright notices, a +% license notice giving the public permission to use the Modified +% Version under the terms of this License, in the form shown in the +% Addendum below. +% +% \item[G.] Preserve in that license notice the full lists of +% Invariant Sections and required Cover Texts given in the +% Document's license notice. +% +% \item[H.] Include an unaltered copy of this License. +% +% \item[I.] Preserve the section Entitled \enquote{History}, +% Preserve its Title, and add to it an item stating at least the +% title, year, new authors, and publisher of the Modified Version +% as given on the Title Page. If there is no section Entitled +% \enquote{History} in the Document, create one stating the title, +% year, authors, and publisher of the Document as given on its +% Title Page, then add an item describing the Modified Version as +% stated in the previous sentence. +% +% \item[J.] Preserve the network location, if any, given in the +% Document for public access to a Transparent copy of the Document, +% and likewise the network locations given in the Document for +% previous versions it was based on. These may be placed in the +% \enquote{History} section. You may omit a network location for a +% work that was published at least four years before the Document +% itself, or if the original publisher of the version it refers to +% gives permission. +% +% \item[K.] For any section Entitled \enquote{Acknowledgements} or +% \enquote{Dedications}, Preserve the Title of the section, and +% preserve in the section all the substance and tone of each of the +% contributor acknowledgements and/or dedications given therein. +% +% \item[L.] Preserve all the Invariant Sections of the Document, +% unaltered in their text and in their titles. Section numbers or +% the equivalent are not considered part of the section titles. +% +% \item[M.] Delete any section Entitled \enquote{Endorsements}. +% Such a section may not be included in the Modified Version. +% +% \item[N.] Do not retitle any existing section to be Entitled +% \enquote{Endorsements} or to conflict in title with any Invariant +% Section. +% +% \item[O.] Preserve any Warranty Disclaimers. +% \end{itemize} +% +% If the Modified Version includes new front-matter sections or +% appendices that qualify as Secondary Sections and contain no +% material copied from the Document, you may at your option designate +% some or all of these sections as invariant. To do this, add their +% titles to the list of Invariant Sections in the Modified Version's +% license notice. These titles must be distinct from any other +% section titles. +% +% You may add a section Entitled \enquote{Endorsements}, provided it +% contains nothing but endorsements of your Modified Version by +% various parties---for example, statements of peer review or that the +% text has been approved by an organization as the authoritative +% definition of a standard. +% +% You may add a passage of up to five words as a Front-Cover Text, and +% a passage of up to 25 words as a Back-Cover Text, to the end of the +% list of Cover Texts in the Modified Version. Only one passage of +% Front-Cover Text and one of Back-Cover Text may be added by (or +% through arrangements made by) any one entity. If the Document +% already includes a cover text for the same cover, previously added +% by you or by arrangement made by the same entity you are acting on +% behalf of, you may not add another; but you may replace the old one, +% on explicit permission from the previous publisher that added the +% old one. +% +% The author(s) and publisher(s) of the Document do not by this +% License give permission to use their names for publicity for or to +% assert or imply endorsement of any Modified Version. +% +% \needspace{3\baselineskip} +% \begin{center} +% {\large\bf 5. COMBINING DOCUMENTS\par} +% \end{center} +% +% You may combine the Document with other documents released under +% this License, under the terms defined in section~4 above for +% modified versions, provided that you include in the combination all +% of the Invariant Sections of all of the original documents, +% unmodified, and list them all as Invariant Sections of your combined +% work in its license notice, and that you preserve all their Warranty +% Disclaimers. +% +% The combined work need only contain one copy of this License, and +% multiple identical Invariant Sections may be replaced with a single +% copy. If there are multiple Invariant Sections with the same name +% but different contents, make the title of each such section unique +% by adding at the end of it, in parentheses, the name of the original +% author or publisher of that section if known, or else a unique +% number. Make the same adjustment to the section titles in the list +% of Invariant Sections in the license notice of the combined work. +% +% In the combination, you must combine any sections Entitled +% \enquote{History} in the various original documents, forming one +% section Entitled \enquote{History}; likewise combine any sections +% Entitled \enquote{Acknowledgements}, and any sections Entitled +% \enquote{Dedications}. You must delete all sections Entitled +% \enquote{Endorsements}. +% +% \needspace{3\baselineskip} +% \begin{center} +% {\large\bf 6. COLLECTIONS OF DOCUMENTS\par} +% \end{center} +% +% You may make a collection consisting of the Document and other +% documents released under this License, and replace the individual +% copies of this License in the various documents with a single copy +% that is included in the collection, provided that you follow the +% rules of this License for verbatim copying of each of the documents +% in all other respects. +% +% You may extract a single document from such a collection, and +% distribute it individually under this License, provided you insert a +% copy of this License into the extracted document, and follow this +% License in all other respects regarding verbatim copying of that +% document. +% +% \needspace{3\baselineskip} +% \begin{center} +% {\large\bf 7. AGGREGATION WITH INDEPENDENT WORKS\par} +% \end{center} +% +% A compilation of the Document or its derivatives with other separate +% and independent documents or works, in or on a volume of a storage +% or distribution medium, is called an \enquote{aggregate} if the +% copyright resulting from the compilation is not used to limit the +% legal rights of the compilation's users beyond what the individual +% works permit. When the Document is included in an aggregate, this +% License does not apply to the other works in the aggregate which are +% not themselves derivative works of the Document. +% +% If the Cover Text requirement of section~3 is applicable to these +% copies of the Document, then if the Document is less than one half +% of the entire aggregate, the Document's Cover Texts may be placed on +% covers that bracket the Document within the aggregate, or the +% electronic equivalent of covers if the Document is in electronic +% form. Otherwise they must appear on printed covers that bracket the +% whole aggregate. +% +% \needspace{3\baselineskip} +% \begin{center} +% {\large\bf 8. TRANSLATION\par} +% \end{center} +% +% Translation is considered a kind of modification, so you may +% distribute translations of the Document under the terms of +% section~4. Replacing Invariant Sections with translations requires +% special permission from their copyright holders, but you may include +% translations of some or all Invariant Sections in addition to the +% original versions of these Invariant Sections. You may include a +% translation of this License, and all the license notices in the +% Document, and any Warranty Disclaimers, provided that you also +% include the original English version of this License and the +% original versions of those notices and disclaimers. In case of a +% disagreement between the translation and the original version of +% this License or a notice or disclaimer, the original version will +% prevail. +% +% If a section in the Document is Entitled \enquote{Acknowledgements}, +% \enquote{Dedications}, or \enquote{History}, the requirement +% (section~4) to Preserve its Title (section~1) will typically require +% changing the actual title. +% +% \needspace{3\baselineskip} +% \begin{center} +% {\large\bf 9. TERMINATION\par} +% \end{center} +% +% You may not copy, modify, sublicense, or distribute the Document +% except as expressly provided under this License. Any attempt +% otherwise to copy, modify, sublicense, or distribute it is void, and +% will automatically terminate your rights under this License. +% +% However, if you cease all violation of this License, then your +% license from a particular copyright holder is reinstated (a) +% provisionally, unless and until the copyright holder explicitly and +% finally terminates your license, and (b) permanently, if the +% copyright holder fails to notify you of the violation by some +% reasonable means prior to 60 days after the cessation. +% +% Moreover, your license from a particular copyright holder is +% reinstated permanently if the copyright holder notifies you of the +% violation by some reasonable means, this is the first time you have +% received notice of violation of this License (for any work) from +% that copyright holder, and you cure the violation prior to 30 days +% after your receipt of the notice. +% +% Termination of your rights under this section does not terminate the +% licenses of parties who have received copies or rights from you +% under this License. If your rights have been terminated and not +% permanently reinstated, receipt of a copy of some or all of the same +% material does not give you any rights to use it. +% +% \needspace{3\baselineskip} +% \begin{center} +% {\large\bf 10. FUTURE REVISIONS OF THIS LICENSE\par} +% \end{center} +% +% The Free Software Foundation may publish new, revised versions of +% the GNU Free Documentation License from time to time. Such new +% versions will be similar in spirit to the present version, but may +% differ in detail to address new problems or concerns. See +% \url{https://www.gnu.org/licenses/}. +% +% Each version of the License is given a distinguishing version +% number. If the Document specifies that a particular numbered +% version of this License \enquote{or any later version} applies to +% it, you have the option of following the terms and conditions either +% of that specified version or of any later version that has been +% published (not as a draft) by the Free Software Foundation. If the +% Document does not specify a version number of this License, you may +% choose any version ever published (not as a draft) by the Free +% Software Foundation. If the Document specifies that a proxy can +% decide which future versions of this License can be used, that +% proxy's public statement of acceptance of a version permanently +% authorizes you to choose that version for the Document. +% +% \needspace{3\baselineskip} +% \begin{center} +% {\large\bf 11. RELICENSING\par} +% \end{center} +% +% \enquote{Massive Multiauthor Collaboration Site} (or \enquote{MMC +% Site}) means any World Wide Web server that publishes copyrightable +% works and also provides prominent facilities for anybody to edit +% those works. A public wiki that anybody can edit is an example of +% such a server. A \enquote{Massive Multiauthor Collaboration} (or +% \enquote{MMC}) contained in the site means any set of copyrightable +% works thus published on the MMC site. +% +% \enquote{CC-BY-SA} means the Creative Commons Attribution-Share +% Alike 3.0 license published by Creative Commons Corporation, a +% not-for-profit corporation with a principal place of business in San +% Francisco, California, as well as future copyleft versions of that +% license published by that same organization. +% +% \enquote{Incorporate} means to publish or republish a Document, in +% whole or in part, as part of another Document. +% +% An MMC is \enquote{eligible for relicensing} if it is licensed under +% this License, and if all works that were first published under this +% License somewhere other than this MMC, and subsequently incorporated +% in whole or in part into the MMC, (1) had no cover texts or +% invariant sections, and (2) were thus incorporated prior to November +% 1, 2008. +% +% The operator of an MMC Site may republish an MMC contained in the +% site under CC-BY-SA on the same site at any time before August 1, +% 2009, provided the MMC is eligible for relicensing. +% +% \needspace{3\baselineskip} +% \begin{center} +% {\large\bf ADDENDUM: How to use this License for your documents\par} +% \end{center} +% +% To use this License in a document you have written, include a copy +% of the License in the document and put the following copyright and +% license notices just after the title page: +% +% \bigskip +% \begin{quote} +% Copyright \copyright{} YEAR YOUR NAME. Permission is granted to +% copy, distribute and/or modify this document under the terms of +% the GNU Free Documentation License, Version 1.3 or any later +% version published by the Free Software Foundation; with no +% Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. +% A copy of the license is included in the section entitled +% \enquote{GNU Free Documentation License}. +% \end{quote} +% \bigskip +% +% If you have Invariant Sections, Front-Cover Texts and Back-Cover +% Texts, replace the \enquote{with \dots\ Texts.}\ line with this: +% +% \bigskip +% \begin{quote} +% with the Invariant Sections being LIST THEIR TITLES, with the +% Front-Cover Texts being LIST, and with the Back-Cover Texts being LIST. +% \end{quote} +% \bigskip +% +% If you have Invariant Sections without Cover Texts, or some other +% combination of the three, merge those two alternatives to suit the +% situation. +% +% If your document contains nontrivial examples of program code, we +% recommend releasing these examples in parallel under your choice of +% free software license, such as the GNU General Public License, +% to permit their use in free software. +% +% \printbibliography[heading=bibintoc] +% +% \StopEventually{} +% +% \section{Implementation} +% \label{sec:implementation} +% +% \iffalse +%<*package> +% \fi +% +% \pkg{ekdosis} relies on Lua functions and tables. Read the +% |.lua| files that accompany \pkg{ekdosis} for more +% information. +% \begin{macrocode} +\RequirePackage{iftex} +% \end{macrocode} +% Of course, \pkg{ekdosis} requires {\LuaLaTeX}. Issue an error +% if the document is processed with another engine. +% \begin{macrocode} +\RequireLuaTeX +% \end{macrocode} +% Set global options:--- +% \begin{macrocode} +\RequirePackage{expkv-opt} +\RequirePackage{expkv-def} +\newif\if@pkg@float +\newif\if@pkg@footins +\newif\if@pkg@ekddivs +\newif\if@parnotesroman +\newif\if@pkg@parnotes +\newif\iftei@export +\ekvdefinekeys{ekdosis}{ + choice layout = {float = {\@pkg@floattrue}, + footins = {\@pkg@footinstrue}}, + initial layout = float, + unknown-choice layout = \PackageError{ekdosis}{unknown + layout=#1}{`layout' must be either `float' or `footins'.}, + choice divs = {ekdosis = {\@pkg@ekddivstrue}, + latex = {\@pkg@ekddivsfalse + \AtBeginDocument{\luadirect{ekdosis.setekddivsfalse()}}}}, + initial divs = ekdosis, + unknown-choice divs = \PackageError{ekdosis}{unknown divs=#1}{`divs' + must be either `ekdosis' or `latex'.}, + choice parnotes = {false = {}, + true = {\@pkg@parnotestrue}, + roman = {\@pkg@parnotestrue\@parnotesromantrue}}, + default parnotes = true, + unknown-choice parnotes = \PackageError{ekdosis}{unknown + parnotes=#1}{`parnotes' must be either `true', or `false' or + `roman'.}, + choice teiexport = {false = {}, + true = {\tei@exporttrue + \AtBeginDocument{\luadirect{ekdosis.openteistream()}}% + \AtEndDocument{\luadirect{ekdosis.closeteistream()}}}, + tidy = {\tei@exporttrue + \AtBeginDocument{\luadirect{ekdosis.openteistream()}}% + \AtEndDocument{\luadirect{ekdosis.closeteistream("tidy")}}}}, + default teiexport = true, + unknown-choice teiexport = \PackageError{ekdosis}{unknown + teiexport=#1}{`teiexport' must be either `true', `false' or + `tidy'.} +} +\ekvoProcessLocalOptions{ekdosis} +% \end{macrocode} +% \paragraph{Required Packages} \label{ref:ekdrequirements} In +% addition to \pkg{iftex}, \pkg{expkv-opt} and \pkg{expkv-def}, a list +% of the packages that are required by \pkg{ekdosis} follows:--- +% \begin{macrocode} +% \RequirePackage{iftex} % already loaded above +% \RequirePackage{expkv-opt} % already loaded above +% \RequirePackage{expkv-def} % already loaded above +\RequirePackage{luacode} +\RequirePackage{paracol} +\RequirePackage{xparse} +\RequirePackage{etoolbox} +\RequirePackage{lineno} +\RequirePackage{keyfloat} +\RequirePackage{refcount} +\RequirePackage[user,abspage]{zref} +\RequirePackage{ltxcmds} +\if@pkg@parnotes + \RequirePackage{parnotes} +\fi +% \end{macrocode} +% \paragraph{Lua} Here begins the real work: load |ekdosis.lua|:--- +% \begin{macrocode} +\luadirect{dofile(kpse.find_file("ekdosis.lua"))} +% \end{macrocode} +% \begin{macrocode} +\AtEndDocument{ + \luadirect{ekdosis.closestream()} +} +% \end{macrocode} +% Use |\normalfont| for line numbers:--- +% \begin{macrocode} +\renewcommand\linenumberfont{\normalfont\footnotesize} +% \end{macrocode} +% \begin{macro}{\SetEkdosisHooks} \cs{SetEkdosisHooks} is used to set +% hooks meant to be shared by all declared apparatuses, such as the +% font size, the format of numerals, \emph{\&c.} This command can be +% used in the preamble or at any point of the document. +% \begin{macrocode} +\ekvdefinekeys{ekd@hooks}{ + store appfontsize = \ekd@appfontsize, + store refnumstyle = \ekd@refnumstyle, + store postrefnum = \ekd@postrefnum, + initial appfontsize = \footnotesize, + initial refnumstyle = \bfseries, + initial postrefnum = ~ +} +\NewDocumentCommand{\SetEkdosisHooks}{m}{\ekvset{ekd@hooks}{#1}} +% \end{macrocode} +% \end{macro} +% Build and process the list of witnesses and hands:--- +% \begin{macrocode} +\ekvdefinekeys{ekd@witness}{ + store settlement = \settlement@value, + store institution = \institution@value, + store repository = \repository@value, + store collection = \collection@value, + store idno = \idno@value, + store msName = \msName@value, + store origDate = \origDate@value +} +% \end{macrocode} +% \begin{macro}{\DeclareWitness} \cs{DeclareWitness} is a +% preamble-only command. It takes three mandatory arguments and one +% optional argument. It is meant to collect data related to +% witnesses to be used in the edition text. Data are stored in |Lua| +% tables and are used to encode the |<listWit>| part of the |TEI| +% header as well as the Conspectus Siglorum in the edition in print. +% \begin{macrocode} +\NewDocumentCommand{\DeclareWitness}{m m m O{}}{% + \bgroup + \ekvset{ekd@witness}{#4} + \luadirect{ekdosis.newwitness( + \luastringN{#1}, + \luastringN{#2}, + \luastringN{#3}, + \luastringO{\settlement@value}, + \luastringO{\institution@value}, + \luastringO{\repository@value}, + \luastringO{\collection@value}, + \luastringO{\idno@value}, + \luastringO{\msName@value}, + \luastringO{\origDate@value})} + \egroup + } +\@onlypreamble\DeclareWitness +% \end{macrocode} +% \end{macro} +% \begin{macro}{\DeclareHand} As \cs{DeclareWitness}, \cs{DeclareHand} +% is a preamble-only command meant to collect data and store them in +% |Lua| tables. It takes three mandatory arguments and one optional +% argument. The second argument is used to connect the hand to a +% declared witness it is related to. Then the table in which this +% witness is recorded can be fed with new data. +% \begin{macrocode} +\NewDocumentCommand{\DeclareHand}{m m m +O{}}{ + \luadirect{ekdosis.newhand(\luastringN{#1}, + \luastringN{#2}, + \luastringN{#3}, + \luastringN{#4})} +} +\@onlypreamble\DeclareHand +% \end{macrocode} +% \end{macro} +% \begin{macro}{\DeclareScholar} There is also a table in which are +% collected data related to scholars' names to be used in the +% apparatus criticus. \cs{DeclareScholar} is a preamble-only command +% and takes two mandatory arguments: a unique id and a shorthand to +% be used in the apparatus criticus which can be extracted from a +% bibliographic database. +% \begin{macrocode} +\NewDocumentCommand{\DeclareScholar}{m m}{ + \luadirect{ekdosis.newscholar(\luastringN{#1}, + \luastringN{#2})} +} +\@onlypreamble\DeclareScholar +% \end{macrocode} +% \end{macro} +% \begin{macro}{\DeclareShorthand} \cs{DeclareShorthand} is a +% preamble-only command that can be used to record manuscript +% families or any kind of shorthand to be used to refer to +% previously declared ids, for example the shorthand |codd| can be +% used to point to all declared witnesses. This command takes three +% mandatory arguments: a unique id, its rendition in print and a +% csv-list of previously declared ids. +% \begin{macrocode} +\NewDocumentCommand{\DeclareShorthand}{m m m}{ + \luadirect{ekdosis.newshorthand(\luastringN{#1}, + \luastringN{#2}, + \luastringN{#3})} +} +\@onlypreamble\DeclareShorthand +% \end{macrocode} +% \end{macro} +% \begin{macrocode} +\NewDocumentCommand{\getsiglum}{m}{% + \luadirect{tex.sprint(ekdosis.getsiglum(\luastringN{#1}))}% +} +\NewDocumentCommand{\SigLine}{m}{% + \luadirect{tex.sprint(ekdosis.basic_cs(\luastringN{#1}))} +} +% \end{macrocode} +% \paragraph{\TeX\ to \texttt{TEI xml}} +% The following three commands can be used to instruct \pkg{ekdosis} +% how to convert unknown or unusual \hologo{(La)TeX} commands into +% \texttt{TEI xml} equivalents. +% \begin{macro}{\TeXtoTEI} +% \cs{TeXtoTEI}\marg{csname}\marg{TEI element}\oarg{TEI attribute(s)} +% takes two mandatory arguments and one optional argument, namely: the +% control sequence name to be converted, the \texttt{TEI} element it +% is to be converted into and any additional \texttt{xml} attributes +% to be appended to the opening \texttt{TEI} element:--- +% \begin{macrocode} +\NewDocumentCommand{\TeXtoTEI}{m m O{}}{% + \luadirect{ekdosis.newcmdtotag(\luastringN{#1}, + \luastringN{#2}, + \luastringN{#3})} +} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\EnvtoTEI} +% \begin{macro}{\EnvtoTEI*} +% \cs{EnvtoTEI}\meta{*}\marg{env name}\marg{TEI element}\oarg{TEI +% attribute(s)} instructs how to convert \LaTeX{} environments into +% \texttt{TEI xml} equivalents. It takes two mandatory arguments and +% one optional argument, namely the name of the \LaTeX{} environment +% to be converted, the \texttt{TEI} element it is to be converted into +% and any additional attributes to be appended to the \texttt{TEI} +% opening element. \cs{EnvtoTEI*} is restricted to \texttt{TEI} +% elements that must never appear within |<p>| elements, such as +% |<div>|, |<lg>| and the like. +% \begin{macrocode} +\NewDocumentCommand{\EnvtoTEI}{s m m O{}}{% + \IfBooleanTF{#1}{% + \luadirect{ekdosis.newenvtotag(\luastringN{#2}, + \luastringN{#3}, + \luastringN{#4}, + "yes")} + }{% + \luadirect{ekdosis.newenvtotag(\luastringN{#2}, + \luastringN{#3}, + \luastringN{#4})} + } +} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \begin{macro}{\TeXtoTEIPatt} +% Finally, the more flexible\---and more delicate to +% handle\---\cs{TeXtoTEIPatt}\marg{\TeX\ +% pattern}\allowbreak\marg{\texttt{TEI} pattern} uses pattern matching +% to instruct \pkg{ekdosis} how to convert \hologo{(La)TeX} commands +% into \texttt{TEI} equivalents. +% \begin{macrocode} +\NewDocumentCommand{\TeXtoTEIPatt}{m m}{% + \luadirect{ekdosis.newpatttotag(\luastringN{#1}, \luastringN{#2})} +} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\SetTEIFilename} \cs{SetTEIFilename}\marg{basename} is +% a preamble-only command. It is used to set the base name of the +% |TEI xml| output file, to which the suffix |.xml| is appended. By +% default, the base name is |\jobname-tei|:--- +% \begin{macrocode} +\NewDocumentCommand{\SetTEIFileName}{m}{ + \luadirect{ekdosis.setteifilename(\luastringN{#1})} +} +\@onlypreamble\SetTEIFileName +% \end{macrocode} +% \end{macro} +% \begin{macro}{\SetxmlBibResource} This is a preamble-only command. +% If a base name for a \texttt{TEI xml} compliant bibliographical +% database file is provided with +% \cs{SetxmlBibResource}\marg{basename}, \pkg{ekdosis} will use +% insert formatted data in the back matter section of its own +% \texttt{TEI xml} output file, as |<biblStruct>| elements within a +% |<listBibl>| section. +% \begin{macrocode} +\NewDocumentCommand{\SetxmlBibResource}{m}{ + \luadirect{ekdosis.setxmlbibresource(\luastringN{#1})} +} +\@onlypreamble\SetxmlBibResource +% \end{macrocode} +% \end{macro} +% +%\paragraph{Multi-layer apparatuses} +% \pkg{ekdosis} must know is an entry is to be processed in a single- +% or multiple-layer context:--- +% \begin{macrocode} +\newif\ifekd@mapps +% \end{macrocode} +% Now the key-value options can be defined:--- +% \begin{macrocode} +\ekvdefinekeys{ekd@newapp}{ + choice direction = {LR = \def\direction@val{LR}, + RL = \def\direction@val{RL}}, + unknown-choice direction = \PackageError{ekdosis}{unknown + direction=#1}{`direction' must be either `LR' or `RL'.}, + store rule = \rule@val, + store delim = \delim@val, + store sep = \sep@val, + store bhook = \bhook@val, + store ehook = \ehook@val, + initial direction = LR, + initial ehook = {\csname ekd@end@apparatus\endcsname} +} +% \end{macrocode} +% \begin{macro}{\DeclareApparatus} +% \cs{DeclareApparatus}\marg{apparatus name}\oarg{options} is a +% preamble-only command. As a mandatory argument, it takes the name of +% the new layer of notes to be inserted in the apparatus block. Then, +% the following six key-value options can be used to lay out the +% layer: \verb+direction=LR|RL+, |rule|, |delim| (the delimiter between +% entries), |sep| (the separator between lemma part and readings or +% notes), |bhook| (\LaTeX{} code inserted as the layer begins), +% |ehook| (\LaTeX{} code inserted as the layer ends):--- +% \begin{macrocode} +\NewDocumentCommand{\DeclareApparatus}{m O{}}{ + \newbool{subsq@unit@#1} + \booltrue{subsq@unit@#1} + \unless\ifekd@mapps\global\ekd@mappstrue\fi + \bgroup + \ekvset{ekd@newapp}{#2} + \luadirect{ekdosis.newapparatus( + \luastringN{#1}, + \luastring{\direction@val}, + \luastringO{\rule@val}, + \luastringO{\delim@val}, + \luastringO{\sep@val}, + \luastringO{\bhook@val}, + \luastringO{\ehook@val} + )} + \egroup +} +\@onlypreamble\DeclareApparatus +% \end{macrocode} +% \end{macro} +% Apparatus-related settings and functions. Some booleans to check if +% an apparatus should be inserted and what is the current environment. +% \begin{macrocode} +\newbool{do@app} +\newif\ifekd@state +\newif\ifekd@isinapp +\newif\ifekd@isinlem +% \end{macrocode} +% The next boolean is shared with \pkg{arabluatex}. \cs{LRnum} is used +% internally to ensure that numerals referring to line spans are +% displayed in the right order. +% \begin{macrocode} +\providebool{al@rlmode} +\@ifpackageloaded{arabluatex}{}{% + \def\setRL{\booltrue{al@rlmode}\pardir TRT\textdir TRT} + \def\setLR{\boolfalse{al@rlmode}\pardir TLT \textdir TLT} +} +\protected\def\LRnum#1{\bgroup\textdir TLT#1\egroup} +% \end{macrocode} +% Set counter referring to line numbers and make it global. +% \begin{macrocode} +\newcounter{ekd@lab} +\globalcounter{ekd@lab} +% \end{macrocode} +% This command inserts words in the apparatus criticus without +% checking if both |ekd@isinapp| and |ekd@state| are set to |true|. +% \begin{macrocode} +\NewDocumentCommand{\unconditional@appin}{o m}{% + \IfNoValueTF{#1} + {\luadirect{ekdosis.appin(\luastringO{#2})}} + {\luadirect{ekdosis.appin(\luastringO{#2}, \luastringO{#1})}}% +} +% \end{macrocode} +% \begin{macro}{\blfootnote} \cs{blfootnote}\marg{footnote} is used +% internally to insert the apparatus in the footnote block should the +% global optional argument |layout| be set to |footins|. Therefore, it +% is not documented. +% \begin{macrocode} + % \def\blfootnote{\gdef\@thefnmark{\relax}\@footnotetext} +\def\blfootnote{\gdef\@thefnmark{}\@blfootnotetext} +\long\def\@blfootnotetext#1{\insert\footins{% + \reset@font\footnotesize + \interlinepenalty\interfootnotelinepenalty + \splittopskip\footnotesep + \splitmaxdepth \dp\strutbox \floatingpenalty \@MM + \hsize\columnwidth \@parboxrestore + \protected@edef\@currentlabel{% + \csname p@footnote\endcsname\@thefnmark + }% + \color@begingroup + \@makeblfntext{% + \rule\z@\footnotesep\ignorespaces#1\@finalstrut\strutbox}% + \color@endgroup}}% +\newcommand\@makeblfntext[1]{% + \parindent 1em% + \noindent + \hb@xt@0em{\hss\@makefnmark}#1} +% \end{macrocode} +% \end{macro} +% \paragraph{Single-layer apparatus} The following commands are for +% general settings. All of them can be used in the preamble or at any +% point of the document:--- +% \begin{macro}{\SetLTRapp} +% \begin{macro}{\SetRTLapp} +% \cs{SetLTRapp} and \cs{SetRTLapp} are two argument-less commands to +% set the direction of single-layer apparatus criticus, either LTR or +% RTL:--- +% \begin{macrocode} +\newif\ifrtl@app +\NewDocumentCommand{\SetRTLapp}{}{\rtl@apptrue} +\NewDocumentCommand{\SetLTRapp}{}{\rtl@appfalse} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \begin{macro}{\SetSeparator} +% \cs{SetSeparator}\marg{separator} allows to change the separator +% between lemma texts and variant readings, which is by default +% a closing square bracket followed by a space (\verb*+] +):--- +% \begin{macrocode} +\edef\ekdsep{] } +\NewDocumentCommand{\SetSeparator}{m}{\edef\ekdsep{#1}} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\SetEndApparatus} +% \cs{SetEndApparatus}\marg{characters} can be used to append +% characters at the end of the apparatus block\---such as a full stop, +% as it is customary in some editions. By default, nothing is +% appended:--- +% \begin{macrocode} +\edef\ekd@end@apparatus{} +\NewDocumentCommand{\SetEndApparatus}{m}{\edef\ekd@end@apparatus{#1}} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\SetUnitDelimiter} +% \cs{SetUnitDelimiter}\marg{delimiter} can be used to set the +% delimiter between entries in the apparatus criticus. By default, +% there is no delimiter except a simple space. \cs{SetUnitDelimiter} +% can be used to insert a broad space (with |\hskip| for instance, as +% in the OCT series) or the divider-sign (‖, as in the Budé series):--- +% \begin{macrocode} +\def\ekd@unit@delim{} +\NewDocumentCommand{\SetUnitDelimiter}{m}{\def\ekd@unit@delim{#1}} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\footnoteruletrue} +% \begin{macro}{\footnoterulefalse} +% As \pkg{ekdosis} takes care of drawing a rule separating the main +% text from the apparatus block as well as layers of notes from each +% other inside this block, it may not be desirable to have +% the standard \LaTeX{} \enquote{footnoterule} printed on every page +% of the edition text. \cs{footnoterulefalse} removes it while +% \cs{footnoteruletrue} leaves it untouched. The latter is set by +% default. +% \begin{macrocode} +\def\ekd@default@rule{\rule{2truein}{0.5pt}} +\newif\iffootnoterule +\footnoteruletrue +\let\dflt@footnoterule\footnoterule +\let\dflt@pcol@footnoterule\pcol@footnoterule +\renewcommand\footnoterule{% + \iffootnoterule + \dflt@footnoterule% + \fi +} +\renewcommand\pcol@footnoterule{% + \iffootnoterule + \dflt@pcol@footnoterule% + \fi +} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \begin{macro}{\SetDefaultRule} +% By default, \pkg{ekdosis} draws separating rules the definition of +% which is |\rule{2truein}{0.5pt}|. This can be changed in the +% preamble or at any point of the document with +% \cs{SetDefaultRule}\marg{\allowbreak{}rule definition}. Leaving this +% argument empty as in \cs{SetDefaultRule}|{}| removes the rule. +% \begin{macrocode} +\NewDocumentCommand{\SetDefaultRule}{m}{% + \def\@tempa{#1} + \ifx\@tempa\empty\def\ekd@default@rule{\mbox{}}% + \else% + \def\ekd@default@rule{#1}% + \fi} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\NLS} +% \cs{NLS} is adapted from a snippet written by Heiko Oberdiek. It is +% used by \pkg{ekdosis} internally to prevent page breaks between +% separating rules and subsequent notes. Therefore, it is not +% documented. +% \begin{macrocode} +\newcommand*{\NLS}{% + \par% + \nobreak% + \vspace{-\parskip}% + \noindent% + \ignorespaces} +% \end{macrocode} +% \end{macro} +% This boolean is used to test if a given entry is to be preceded by a +% numeral referring to the line of the edition text. +% \begin{macrocode} +\newif\ifsubsq@unit +\subsq@unittrue +% \end{macrocode} +% \cs{add@@apparatus} inserts the apparatus block on a given page +% either in the footnote floating block or in a float of its own, +% depending on the value set in the |layout| global option. +% \begin{macrocode} +\def\add@@apparatus{% + \if@pkg@parnotes\parnotes\else\fi% + \if@pkg@footins% + \bgroup% + \ifrtl@app\setRL\else\setLR\fi% + \blfootnote{% + \if@pkg@parnotes% + \if@parnotesroman% + \renewcommand*{\theparnotemark}{\roman{parnotemark}}\else\fi% + \parnoteclear\else\fi% + \footnotesize\apparatus\unless\ifekd@mapps\ekd@end@apparatus\fi% + \if@pkg@parnotes\parnotes\parnotereset\else\fi% + }% + \egroup% + \fi% + \if@pkg@float% + \keyparbox[!b]{}{\ifrtl@app\setRL\else\setLR\fi% + \if@pkg@parnotes% + \if@parnotesroman% + \renewcommand*{\theparnotemark}{\roman{parnotemark}}\else\fi% + \parnoteclear\else\fi% + \ekd@appfontsize\apparatus\unless\ifekd@mapps\ekd@end@apparatus\fi% + \if@pkg@parnotes\parnotes\parnotereset\else\fi% + }% + \fi% +} +% \end{macrocode} +% Before inserting any new entry, \cs{add@apparatus} is called +% \cs{test@apparatus} to decide whether a new apparatus block must be +% created on a given page. +% \begin{macrocode} +\def\add@apparatus{% + \test@apparatus% + \ifbool{do@app}{\subsq@unitfalse\add@@apparatus}{}% +} +% \end{macrocode} +% \cs{append@app} inserts a bare (sub)entry in the apparatus... +% \begin{macrocode} +\NewDocumentCommand{\append@app}{o +m}{% + \ifekd@isinapp% + \ifekd@state% + \IfNoValueTF{#1}% + {\luadirect{ekdosis.appin(\luastringO{#2})}}% + {\luadirect{ekdosis.appin(\luastringO{#2}, \luastringO{#1})}}% + \fi% + \fi} +% \end{macrocode} +% while \cs{append@ln@app} inserts a (sub)entry possibly preceded by a +% line number. +% \begin{macrocode} +\NewDocumentCommand{\append@ln@app}{o +m}{% + \IfNoValueTF{#1} + {\luadirect{tex.sprint(ekdosis.mdvappend(\luastringO{#2}))}} + {\luadirect{tex.sprint(ekdosis.mdvappend(\luastringO{#2}, + \luastringO{#1}))}}} +% \end{macrocode} +% \begin{macro}{\EkdosisDefaultApparatus} +% By default, \pkg{ekdosis} defines one layer of critical notes which +% is called |default|. This name can be changed at any point of the +% document with \cs{EkdosisDefaultApparatus}\marg{name}. +% \begin{macrocode} +\ekvdefinekeys{appnote}{ + store type = \ekdan@type, + initial type = default + } +\NewDocumentCommand{\EkdosisDefaultApparatus}{m}{% + \ekvset{appnote}{type=#1}} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\app} +% \cs{app}|[type=|\meta{type}|]|\marg{apparatus entries} takes one +% mandatory argument and accepts one optional argument. |type=| refers +% to the layer the note must go into and \meta{apparatus entries} +% contains command used to insert the entries, either \cs{lem}, +% \cs{rdg} or \cs{note}\meta{*}:--- +% \begin{macrocode} +\NewDocumentCommand{\app}{O{} > { \TrimSpaces } +m}{% + \begingroup + \ekvset{appnote}{#1}% + \ekd@isinapptrue% + \stepcounter{ekd@lab}% + \zlabel{ekd:\theekd@lab}% + \luadirect{ekdosis.storeabspg( + \luastring{\zref@extract{ekd:\theekd@lab}{abspage}})}% + \ifekd@state\add@apparatus\fi% + \luadirect{tex.sprint(ekdosis.removesp(\luastringN{#2}))}% + \ekd@isinappfalse% + \endgroup} +% \end{macrocode} +% \end{macro} +% \cs{current@ref@arg} is used outside \cs{app} by \cs{note}. It takes +% two mandatory arguments: the beginning line label and the ending +% line label\---which are manually inserted---and returns the formatted +% reference to be inserted in the apparatus criticus. +% \begin{macrocode} +\def\current@ref@arg#1#2{{%\textdir TLT% + \unexpanded\expandafter{\ekd@refnumstyle}% + \ifnum% + \getpagerefnumber{#1} + = + \getpagerefnumber{#2} + \ifnum% + \getrefnumber{#1} + = + \getrefnumber{#2} + % + \ifekd@mapps% + \ifbool{subsq@unit@\ekdan@type}{% + \ifnum% + \getrefnumber{#1} + = + \getrefnumber{\luadirect{tex.sprint(ekdosis.getprevnotelab())}} + \else + \LRnum{\getrefnumber{#1}}% issue the no + \fi% + }% + {\LRnum{\getrefnumber{#1}}}% issue the no + \else + \ifsubsq@unit% + % + \ifnum% + \getrefnumber{#1} + = + \getrefnumber{\luadirect{tex.sprint(ekdosis.getprevnotelab())}} + \else + \LRnum{\getrefnumber{#1}}% issue the no + \fi + % + \else + \LRnum{\getrefnumber{#1}}% issue the no + \fi + \fi + % + \else + \LRnum{\getrefnumber{#1}}--% + \LRnum{\getrefnumber{#2}}% issue the nos + \fi% + \else + \LRnum{\getrefnumber{#1}}--% + \LRnum{\getpagerefnumber{#2}}.% + \LRnum{\getrefnumber{#2}}% issue pg and ln nos + \fi% + }\unexpanded\expandafter{\ekd@postrefnum}% +} +% \end{macrocode} +% \cs{current@ref} is pretty much the same as \cs{current@reg@arg}, +% but takes no argument. It is used by commands such as \cs{lem} when +% references to page and line numbers can be returned by \textsf{Lua}. +% \begin{macrocode} +\def\current@ref{{%\textdir TLT% + \unexpanded\expandafter{\ekd@refnumstyle}% + \ifnum% + \getpagerefnumber{\luadirect{tex.sprint(ekdosis.getlnlab())}-b} + = + \getpagerefnumber{\luadirect{tex.sprint(ekdosis.getlnlab())}-e} + \ifnum% + \getrefnumber{\luadirect{tex.sprint(ekdosis.getlnlab())}-b} + = + \getrefnumber{\luadirect{tex.sprint(ekdosis.getlnlab())}-e} + % + \ifekd@mapps% + \ifbool{subsq@unit@\ekdan@type}{% + \ifnum% + \getrefnumber{\luadirect{tex.sprint(ekdosis.getlnlab())}-b} + = + \getrefnumber{\luadirect{tex.sprint(ekdosis.getprevlnlab())}-b} + \else + \LRnum{\getrefnumber{\luadirect{tex.sprint(ekdosis.getlnlab())}-b}}% issue the no + \fi% + }{\LRnum{\getrefnumber{\luadirect{tex.sprint(ekdosis.getlnlab())}-b}}}% issue the no + \else + \ifsubsq@unit% + % + \ifnum% + \getrefnumber{\luadirect{tex.sprint(ekdosis.getlnlab())}-b} + = + \getrefnumber{\luadirect{tex.sprint(ekdosis.getprevlnlab())}-b} + \else + \LRnum{\getrefnumber{\luadirect{tex.sprint(ekdosis.getlnlab())}-b}}% issue the no + \fi + % + \else + \LRnum{\getrefnumber{\luadirect{tex.sprint(ekdosis.getlnlab())}-b}}% issue the no + \fi + \fi + % + \else + \LRnum{\getrefnumber{\luadirect{tex.sprint(ekdosis.getlnlab())}-b}}--% + \LRnum{\getrefnumber{\luadirect{tex.sprint(ekdosis.getlnlab())}-e}}% issue the nos + \fi% + \else + \LRnum{\getrefnumber{\luadirect{tex.sprint(ekdosis.getlnlab())}-b}}--% + \LRnum{\getpagerefnumber{\luadirect{tex.sprint(ekdosis.getlnlab())}-e}}.% + \LRnum{\getrefnumber{\luadirect{tex.sprint(ekdosis.getlnlab())}-e}}% issue pg and ln nos + \fi% + }\unexpanded\expandafter{\ekd@postrefnum}% +} +% \end{macrocode} +% Define keys to be used by the optional arguments of \cs{lem} and +% \cs{rdg}:--- +% \begin{macrocode} +\ekvdefinekeys{lem}{ + code wit = \def\ekdlr@wit{#1}, + code alt = \def\ekdlr@alt{#1}, + code pre = \def\ekdlr@pre{#1}, + code post = \def\ekdlr@post{#1}, + code prewit = \def\ekdlr@prewit{#1}, + code postwit = \def\ekdlr@postwit{#1}, + store type = \ekdlr@type, + store sep = \ekdl@sep, + bool nolem = \ifekdl@nolem, + bool nosep = \ifekdl@nosep, + initial sep = \ekdsep +} +\ekvdefinekeys{rdg}{ + code wit = \def\ekdlr@wit{#1}, + code alt = \def\ekdlr@alt{#1}, + code pre = \def\ekdlr@pre{#1}, + code post = \def\ekdlr@post{#1}, + code prewit = \def\ekdlr@prewit{#1}, + code postwit = \def\ekdlr@postwit{#1}, + store type = \ekdlr@type, + bool nordg = \ifekdr@nordg +} +% \end{macrocode} +% \begin{macro}{\lem} +% \cs{lem}\oarg{options}\marg{lemma text} inserts \meta{lemma text} +% both in the edition text and in the apparatus criticus by default, +% preceded by the reference to the line number or a space if it is the +% same number as the one of the previous entry. This command accepts +% the optional key-value arguments just defined above. +% \begin{macrocode} +\NewDocumentCommand{\lem}{O{} m}{% + \ekd@isinlemtrue% + \luadirect{ekdosis.dolnlab(\luastringN{#2})}% + \bgroup% + \ekvset{lem}{#1}% + \ifekd@mapps% + \ifnum% + \luadirect{tex.sprint(ekdosis.get_bagunits(\luastringO{\ekdan@type}))} + = 1 + \boolfalse{subsq@unit@\ekdan@type}% + \fi% + \luadirect{ekdosis.increment_bagunits(\luastringO{\ekdan@type})}% + \def\ekd@munit@delim{% + \luadirect{tex.sprint(ekdosis.getappdelim(\luastringO{\ekdan@type}))}}% + \fi% + \ifekdl@nolem\edef\lem@app{% + % \hskip .75em + \ifekd@mapps + \ifbool{subsq@unit@\ekdan@type}% + {\ekd@munit@delim}{}% + \else% + \ifsubsq@unit\unexpanded\expandafter{\ekd@unit@delim}\fi% + \fi% + \current@ref}%\hskip .25em}% + \else% + \ifbool{al@rlmode}{% + \edef\lem@app{% + % \hskip .75em + \ifekd@mapps + \ifbool{subsq@unit@\ekdan@type}% + {\ekd@munit@delim}{}% + \else% + \ifsubsq@unit\unexpanded\expandafter{\ekd@unit@delim}\fi% + \fi% + \current@ref%\hskip .25em + \ifdefined\ekdlr@alt% + \ifdefined\ekdlr@post% + \space\unexpanded\expandafter{\ekdlr@post}\space\else\fi + {\textdir TRT\unexpanded\expandafter{\ekdlr@alt}}% + \ifdefined\ekdlr@pre% + \space\unexpanded\expandafter{\ekdlr@pre}\space\else\fi + \else + \ifdefined\ekdlr@post% + \space\unexpanded\expandafter{\ekdlr@post}\space\else\fi + {\textdir TRT\unexpanded{#2}}% + \ifdefined\ekdlr@pre% + \space\unexpanded\expandafter{\ekdlr@pre}\space\else\fi + \fi + \ifdefined\ekdlr@postwit% + \space\unexpanded\expandafter{\ekdlr@postwit}\else\fi + \ifdefined\ekdlr@wit\space\getsiglum{\ekdlr@wit}\else\fi + \ifdefined\ekdlr@prewit% + \space\unexpanded\expandafter{\ekdlr@prewit}\space\else\fi + \ifekdl@nosep\else\unexpanded\expandafter{\ekdl@sep}\fi + }% + }% + {% + \edef\lem@app{% + % \hskip .75em + \ifekd@mapps + \ifbool{subsq@unit@\ekdan@type}% + {\ekd@munit@delim}{}% + \else% + \ifsubsq@unit\unexpanded\expandafter{\ekd@unit@delim}\fi% + \fi% + \current@ref%\hskip .25em + \ifdefined\ekdlr@alt% + \ifdefined\ekdlr@pre% + \space\unexpanded\expandafter{\ekdlr@pre}\space\else\fi + \ltx@ifpackageloaded{babel}% + {\noexpand\selectlanguage{\languagename}% + \unexpanded\expandafter{\ekdlr@alt}}% + {\unexpanded\expandafter{\ekdlr@alt}}% + \ifdefined\ekdlr@post% + \space\unexpanded\expandafter{\ekdlr@post}\space\else\fi + \else + \ifdefined\ekdlr@pre% + \space\unexpanded\expandafter{\ekdlr@pre}\space\else\fi + \ltx@ifpackageloaded{babel}% + {\noexpand\selectlanguage{\languagename}\unexpanded{#2}}{% + \unexpanded{#2}}% + \ifdefined\ekdlr@post% + \space\unexpanded\expandafter{\ekdlr@post}\space\else\fi + \fi + \ifdefined\ekdlr@prewit% + \space\unexpanded\expandafter{\ekdlr@prewit}\space\else\fi + \ifdefined\ekdlr@wit\space\getsiglum{\ekdlr@wit}\else\fi + \ifdefined\ekdlr@postwit% + \space\unexpanded\expandafter{\ekdlr@postwit}\else\fi + \ifekdl@nosep\else\unexpanded\expandafter{\ekdl@sep}\fi + }% + }% + \fi% + \ifekd@mapps% + \append@ln@app[\ekdan@type]{\lem@app}% + \else% + \append@ln@app{\lem@app}% + \fi% + \egroup% + \ekd@isinlemfalse% + \subsq@unittrue% +} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\rdg} +% \cs{rdg}\oarg{options}\marg{variant reading} inserts \meta{variant +% reading} in the second part of the entry, after the lemma text and +% the separator, in the apparatus criticus. This command accepts the +% optional key-value arguments defined above. +% \begin{macrocode} +\NewDocumentCommand{\rdg}{O{} m}{% + \bgroup% + \ekvset{rdg}{#1}% + % \ifekdr@nordg\append@app{}\else% do we need \append@app{} here? If + % % so, keep in mind \ifekd@mapps, + % like so: + \ifekdr@nordg% + \ifekd@mapps% + \append@app[\ekdan@type]{}% + \else% + \append@app{}% + \fi% + \else% + \ifbool{al@rlmode}{% + \edef\rdg@app{% + \ifdefined\ekdlr@alt% + \ifdefined\ekdlr@post% + \space\unexpanded\expandafter{\ekdlr@post}\space\else\fi + {\textdir TRT\unexpanded\expandafter{\ekdlr@alt}}% + \ifdefined\ekdlr@pre% + \space\unexpanded\expandafter{\ekdlr@pre}\space\else\fi + \else + \ifdefined\ekdlr@post% + \space\unexpanded\expandafter{\ekdlr@post}\space\else\fi + {\textdir TRT\unexpanded{#2}}% + \ifdefined\ekdlr@pre% + \space\unexpanded\expandafter{\ekdlr@pre}\space\else\fi + \fi + \ifdefined\ekdlr@postwit% + \space\unexpanded\expandafter{\ekdlr@postwit}\else\fi + \ifdefined\ekdlr@wit\space\getsiglum{\ekdlr@wit}\else\fi + \ifdefined\ekdlr@prewit% + \space\unexpanded\expandafter{\ekdlr@prewit}\space\else\fi + }% + }% + {% + \edef\rdg@app{% + \ifdefined\ekdlr@alt% + \ifdefined\ekdlr@pre% + \space\unexpanded\expandafter{\ekdlr@pre}\space\else\fi + \ltx@ifpackageloaded{babel}% + {\noexpand\selectlanguage{\languagename}% + \unexpanded\expandafter{\ekdlr@alt}}% + {\unexpanded\expandafter{\ekdlr@alt}}% + \ifdefined\ekdlr@post% + \space\unexpanded\expandafter{\ekdlr@post}\space\else\fi + \else + \ifdefined\ekdlr@pre% + \space\unexpanded\expandafter{\ekdlr@pre}\space\else\fi + \ltx@ifpackageloaded{babel}% + {\noexpand\selectlanguage{\languagename}\unexpanded{#2}}{% + \unexpanded{#2}}% + \ifdefined\ekdlr@post% + \space\unexpanded\expandafter{\ekdlr@post}\space\else\fi + \fi + \ifdefined\ekdlr@prewit% + \space\unexpanded\expandafter{\ekdlr@prewit}\space\else\fi + \ifdefined\ekdlr@wit\space\getsiglum{\ekdlr@wit}\else\fi + \ifdefined\ekdlr@postwit% + \space\unexpanded\expandafter{\ekdlr@postwit}\else\fi + }% + }% + \ifekd@mapps% + \append@app[\ekdan@type]{\rdg@app}% + \else% + \append@app{\rdg@app}% + \fi% + \fi% + \egroup% +} +% \end{macrocode} +% \end{macro} +% Define keys to be used by the optional argument of \cs{note} when +% this command is found outside \cs{app}:--- +% \begin{macrocode} +\ekvdefinekeys{note}{ + store type = \ekdan@type, + store lem = \ekdn@lem, + code labelb = \def\ekdn@labelb{#1}, + code labele = \def\ekdn@labele{#1}, + store sep = \ekdn@sep, + initial type = default, + initial sep = \ekdsep +} +% \end{macrocode} +% \cs{note@noapp} is used internally when a \cs{note} command is found +% outside \cs{app}. This command is mostly used to insert short +% comments or references to texts quoted or cited in the edition text +% to go into additional layers of the apparatus criticus, e.g.\ the +% \emph{apparatus testium}. It accepts the optional key-value +% arguments just defined above. It must be noted that |labelb| must be +% specified; otherwise \pkg{ekdosis} will issue an error message. +% \begin{macrocode} +\NewDocumentCommand{\note@noapp}{O{} +m}{% + \bgroup% + \ekvset{note}{#1}% + \stepcounter{ekd@lab}% + \zlabel{ekd:\theekd@lab}% + \luadirect{ekdosis.storeabspg( + \luastring{\zref@extract{ekd:\theekd@lab}{abspage}})}% + \ifekd@state\add@apparatus\fi% + \ifekd@mapps% + \ifnum% + \luadirect{tex.sprint(ekdosis.get_bagunits(\luastringO{\ekdan@type}))} + = 1 + \boolfalse{subsq@unit@\ekdan@type}% + \fi% + \luadirect{ekdosis.increment_bagunits(\luastringO{\ekdan@type})}% + \def\ekd@munit@delim{% + \luadirect{tex.sprint(ekdosis.getappdelim(\luastringO{\ekdan@type}))}}% + \fi% + \ifdefined\ekdn@labelb% + \luadirect{tex.sprint(ekdosis.setnotelab(\luastringO{\ekdn@labelb}))}% + \ifdefined\ekdn@labele\else\def\ekdn@labele{\ekdn@labelb}\fi% + \else\PackageError{ekdosis}{missing labelb}{`labelb' must be + set.}\fi% + \ifbool{al@rlmode}% + {\edef\note@contents{% + % \hskip .75em + \ifekd@mapps + \ifbool{subsq@unit@\ekdan@type}% + {\ekd@munit@delim}{}% + \else% + \ifsubsq@unit\unexpanded\expandafter{\ekd@unit@delim}\fi% + \fi% + \current@ref@arg{\ekdn@labelb}{\ekdn@labele}%\hskip .25em + \ifdefined\ekdn@lem% + {\textdir TRT\unexpanded\expandafter{\ekdn@lem}}% + \unexpanded\expandafter{\ekdn@sep}\else\fi% + {\textdir TRT\unexpanded{#2}}}}% + {\edef\note@contents{% + % \hskip .75em + \ifekd@mapps + \ifbool{subsq@unit@\ekdan@type}% + {\ekd@munit@delim}{}% + \else% + \ifsubsq@unit\unexpanded\expandafter{\ekd@unit@delim}\fi% + \fi% + \current@ref@arg{\ekdn@labelb}{\ekdn@labele}%\hskip .25em + \ifdefined\ekdn@lem + \ltx@ifpackageloaded{babel}% + {\noexpand\selectlanguage{\languagename}% + \unexpanded\expandafter{\ekdn@lem}}% + {\unexpanded\expandafter{\ekdn@lem}}% + \unexpanded\expandafter{\ekdn@sep}\else\fi% + \ltx@ifpackageloaded{babel}% + {\noexpand\selectlanguage{\languagename}\unexpanded{#2}}{% + \unexpanded{#2}}}}% + \ifekd@mapps% + \unconditional@appin[\ekdan@type]{\note@contents}% + \else% + \unconditional@appin{\note@contents}% + \fi% + \luadirect{ekdosis.setprevnotelab(\luastringO{\ekdn@labelb})}% + \egroup% + \subsq@unittrue% +} +% \end{macrocode} +% Define keys to be used by the optional argument of \cs{note} when +% this command is found inside \cs{app}:--- +% \begin{macrocode} +\ekvdefinekeys{ekd@note}{ + store pre = \pre@value, + store post = \post@value +} +% \end{macrocode} +% The following three commands, \cs{note@app}, \cs{ekd@note} and +% \cs{ekd@note@star} are used internally when a \cs{note} command is +% found inside \cs{app}. These commands are used to insert short +% comments after the lemma text or after any variant reading in the +% apparatus criticus. \cs{note@app} and subsequently \cs{ekd@note} and +% \cs{ekd@note@star} accept the optional key-value arguments just +% defined above. +% \begin{macrocode} +\NewDocumentCommand{\ekd@note}{O{} m}{% + \bgroup% + \ekvset{ekd@note}{#1}% + \edef\note@contents{% + \ekvifdefinedNoVal{note}{pre}{}{% + \unexpanded\expandafter{\pre@value}}% + \unexpanded{#2}% + \ekvifdefinedNoVal{note}{post}{}{% + \unexpanded\expandafter{\post@value}}% + }% + \append@app{\note@contents}% + \egroup% +} +\NewDocumentCommand{\ekd@note@star}{O{} m}{% + \if@pkg@parnotes + \bgroup% + \ekvset{ekd@note}{#1}% + \edef\note@contents{% + \ekvifdefinedNoVal{note}{pre}{}{% + \unexpanded\expandafter{\pre@value}}% + \unskip\noexpand\parnote{#2}% + \ekvifdefinedNoVal{note}{post}{}{% + \unexpanded\expandafter{\post@value}}% + }% + \append@app{\note@contents}% + \egroup% + \else + \append@app{\unskip\footnote{#2}}% + \fi% +} +\NewDocumentCommand{\note@app}{s O{} +m}{% + \ifbool{al@rlmode}{% + \IfBooleanTF{#1}{\ekd@note@star[#2]{% + {\textdir TRT#3}}} + {\ekd@note[#2]{{\textdir TRT#3}}}% + }{% + \IfBooleanTF{#1}{\ekd@note@star[#2]{#3}} + {\ekd@note[#2]{#3}}% + }% +} +% \end{macrocode} +% \begin{macro}{\note} +% Finally, \cs{note} is a simple command designed to check whether +% \cs{note} itself is called inside or outside \cs{app}. Then, unless +% it is found inside \cs{lem}, it calls \cs{note@app} in the former +% case and \cs{note@noapp} in the latter case:--- +% \begin{macrocode} +\NewDocumentCommand{\note}{s O{} +m}{% + \ifekd@state% + \ifekd@isinapp% + \ifekd@isinlem% + \note@noapp[#2]{#3}% + \else% + \IfBooleanTF{#1}{\note@app*[#2]{#3}}{\note@app[#2]{#3}}% + \fi% + \else% + \note@noapp[#2]{#3}% + \fi% + \fi% +} +% \end{macrocode} +% \end{macro} +% \cs{apparatus} is used internally by \pkg{ekdosis} to print the +% apparatus at the bottom of pages. Therefore, it is not documented, +% but this may change in the future for it will be possible to have +% apparatuses printed at other places. +% \begin{macrocode} +\NewDocumentCommand{\apparatus}{}{% + \luadirect{tex.sprint(ekdosis.appout())}} +% \end{macrocode} +% The following two commands call \textsf{Lua} functions to check +% whether an apparatus should be printed on a given page and to store +% the current column id. +% \begin{macrocode} +\NewDocumentCommand{\test@apparatus}{}{% + \luadirect{tex.sprint(ekdosis.testapparatus())}} +\NewDocumentCommand{\ekd@storecol}{}{% + \luadirect{ekdosis.storecurcol(\luastring{\thecolumn})}% +} +% \end{macrocode} +% Start and stop |ekdosis|: +% \begin{macrocode} +\NewDocumentCommand{\EkdosisOn}{}{% + \ekd@statetrue} +\NewDocumentCommand{\EkdosisOff}{}{% + \ekd@statefalse% +} +% \end{macrocode} +% Neutralize unwanted commands provided by \pkg{lineno} within the +% \env{ekdosis} environment:--- +% \begin{macrocode} +\def\ekd@setlineno{% + \let\setpagewiselinenumbers\relax% + \let\pagewiselinenumbers\relax% + \let\endpagewiselinenumbers\relax% + \let\runningpagewiselinenumbers\relax% + \let\realpagewiselinenumbers\relax% +} +% \end{macrocode} +% \begin{environment}{ekdosis} +% Finally comes the \env{ekdosis} environment meant to receive the +% edition text equipped with an apparatus criticus. This environment +% collects its contents and delivers it to \textsf{Lua} functions if a +% \texttt{TEI xml} output file be desired. +% \begin{macrocode} +\NewDocumentEnvironment{ekdosis}{+b}{% + \ekd@setlineno% + \runninglinenumbers + \EkdosisOn#1}{% + \EkdosisOff + \endrunninglinenumbers% + \iftei@export + \luadirect{ekdosis.exporttei(\luastringN{\par #1\par })}\fi} +% \end{macrocode} +% \end{environment} +% \paragraph{Alignment} What follows isto arrange texts in parallel +% columns either on single pages or on facing pages. +% +% Define keys to be used by the \env{alignment} environment:--- +% \begin{macrocode} +\newif\ifekd@pagelineation +\ekvdefinekeys{ekd@align}{ + store tcols = \tcols@num, + store lcols = \lcols@num, + store texts = \texts@value, + store apparatus = \apparatus@value, + bool paired = \ifekd@paired, + choice lineation = {page = \ekd@pagelineationtrue, + document = \ekd@pagelineationfalse}, + unknown-choice lineation = \PackageError{ekdosis}{unknown + lineation=#1}{`lineation' must be either `page' or `document'.}, + choice segmentation = {auto = \def\segmentation@val{auto}, + noauto = \def\segmentation@val{noauto}}, + unknown-choice segmentation = \PackageError{ekdosis}{unknown + segmentation=#1}{`segmentation' must be either `auto' or + `noauto'.}, + bool flush = \ifekd@flushapp, + initial tcols = 2, + initial lcols = 1, + initial texts = edition;translation, + initial apparatus = edition, + default segmentation = auto +} +% \end{macrocode} +% \begin{macro}{\SetEkdosisAlignment} +% \cs{SetEkdosisAlignment}\marg{settings} can be used either in the +% preamble or at any point of the document to set or modify the +% keys-value settings just defined above. +% \begin{macrocode} +\NewDocumentCommand{\SetEkdosisAlignment}{m}{ + \ekvset{ekd@align}{#1} +} +% \end{macrocode} +% \end{macro} +% Patch \pkg{paracol} to insert a hook in \cs{pcol@nextpage}. This +% hook is used to reset line numbers on new pages. +% \begin{macrocode} +\patchcmd{\pcol@nextpage}{% + \endgroup}{% + \ifekd@pagelineation\resetlinenumber\fi + \endgroup}{}{} +% \end{macrocode} +% \cs{EkdosisColStart} and \cs{EkdosisColStop} initialize columns +% meant to receive edition texts. These commands are used internally +% by \pkg{ekdosis}. +% \begin{macrocode} +\NewDocumentCommand{\EkdosisColStart}{}{% + \ekd@setlineno% + \runninglinenumbers + \ekd@storecol% + \stepcounter{ekd@lab}% + \zlabel{ekd:\theekd@lab}% + \luadirect{% + ekdosis.storeabspg(\luastring{\zref@extract{ekd:\theekd@lab}{abspage}}, + "pg_i")}% + \ifekd@pagelineation + \luadirect{tex.sprint(ekdosis.checkresetlineno())} + \fi +} +\NewDocumentCommand{\EkdosisColStop}{}{% + \stepcounter{ekd@lab}% + \zlabel{ekd:\theekd@lab}% + \luadirect{% + ekdosis.storeabspg(\luastring{\zref@extract{ekd:\theekd@lab}{abspage}}, + "pg_ii")}% + \endrunninglinenumbers% +} +% \end{macrocode} +% \begin{environment}{alignment} +% \cs{begin}|{alignment}|\oarg{options}\dots\cs{end}|{alignment}| can +% be used as it is provided to typeset a standard critical edition +% text on the left-hand pages accompanied with a translation on the +% right-hand pages. To that effect, it provides by default two new +% environments, \env{edition} and \env{translation}, to be used to +% typeset both texts. (Either whole texts or texts entered by +% paragraphs alternately.) The optional argument of \env{aligment} +% accepts the exact same key-value options as \cs{SetEkdosisAlignment} +% described above. One may contrast these options with those accepted +% by \cs{SetEkdosisAlignment} as \enquote{local settings}. +% \begin{macrocode} +\NewDocumentEnvironment{alignment}{O{}} +{% + \ekvset{ekd@align}{#1}% + \luadirect{ekdosis.mkenvdata( + \luastring{\texts@value}, + "texts" + )} + \ifekd@flushapp + \luadirect{ekdosis.newalignment("set")} + \fi + \luadirect{ekdosis.mkenvdata( + \luastring{\apparatus@value}, "apparatus" + )} + \setrunninglinenumbers + \luadirect{tex.sprint(ekdosis.mkenv())} + \ifekd@paired + \begin{paracol}[\lcols@num]{\tcols@num} + \else + \begin{paracol}[\lcols@num]*{\tcols@num} + \fi + } + {\end{paracol} + \iftei@export\luadirect{ekdosis.export_coldata_totei()}\fi + \ifekd@flushapp + \luadirect{ekdosis.newalignment("reset")} + \fi + \luadirect{ekdosis.flushenvdata()} + \luadirect{ekdosis.flushcolnums()} + } +% \end{macrocode} +% \end{environment} +% \paragraph{Divisions of the Body} +% \pkg{ekdosis} can convert \cs{book}, \cs{part}, \cs{chapter}, +% \cs{section}, \cs{subsec{\allowbreak}tion} and \cs{subsubsection} +% into corresponding \texttt{TEI} \enquote*{numbered} +% |<div|\textsubscript{\emph{n}}|>| elements, where $1\leq n\leq 6$. +% \begin{macro}{\MkBodyDivs} +% \cs{MkBodyDivs} is used to let \pkg{ekdosis} know which sectional +% commands are actually being used in an edition text. This command +% takes six mandatory arguments. For example, if \cs{section} and +% \cs{subsection} are the only sectional commands being used, +% |\MkBodyDivs{section}{subsection}{}{}{}{}| will have \cs{section} +% and \cs{subsection} converted into |<div1>| and |<div2>| +% respectively. +% \begin{macrocode} +\NewDocumentCommand{\MkBodyDivs}{mmmmmm}{ + \luadirect{ekdosis.mkdivdepths( + \luastringN{#1}, + \luastringN{#2}, + \luastringN{#3}, + \luastringN{#4}, + \luastringN{#5}, + \luastringN{#6} + ) + } +} +% \end{macrocode} +% \end{macro} +% Divisions specific to \pkg{ekdosis}. Define keys to be used by +% \cs{ekddiv}:--- +% \begin{macrocode} +\ekvdefinekeys{ekd@div}{ + code type = \def\type@value{#1}, + code n = \def\n@value{#1}, + code head = \def\head@value{#1}, + code barehead = \def\barehead@value{#1}, + store depth = \depth@value, + choice toc = {book = \def\toc@value{book}, + part = \def\toc@value{part}, + chapter = \def\toc@value{chapter}, + section = \def\toc@value{section}, + subsection = \def\toc@value{subsection}, + subsubsection = \def\toc@value{subsubsection}, + paragraph = \def\toc@value{paragraph}, + subparagraph = \def\toc@value{subparagraph}}, + unknown-choice toc = \PackageError{ekdosis}{unknown toc=#1}{`toc' + must be either `book', `part', `chapter', `section', `subsection', + \MessageBreak `subsubsection', `paragraph' or `subparagraph'.}, + initial depth = 1 +} +% \end{macrocode} +% \begin{macro}{\ekdfmtdiv} +% \cs{ekdfmtdiv}\marg{n}\marg{code before}\marg{code after} is +% used to lay out the heading of the title. It takes three mandatory +% arguments: \emph{n}, namely the number referring to the particular +% depth of the division, and then some \LaTeX{} formatting commands +% to go before and after the heading itself:--- +% \begin{macrocode} +\NewDocumentCommand{\ekdfmtdiv}{m m m}{ + \luadirect{ekdosis.fmtdiv(\luastring{#1}, + \luastringN{#2}, + \luastringN{#3})} +} +% \end{macrocode} +% \end{macro} +% \cs{ekd@getfmtdiv} gets the formatting commands that have been +% stored by \cs{ekdfmtdiv}. +% \begin{macrocode} +\NewDocumentCommand{\ekd@getfmtdiv}{m m}{% + \luadirect{tex.sprint(ekdosis.getfmtdiv(\luastringO{#1}, + \luastringN{#2}))}% +} +% \end{macrocode} +% \begin{macro}{\ekddiv} +% \cs{ekddiv}\marg{key-value arguments} is the standard command +% provided by \pkg{ekdosis} to meet the requirements of classical and +% literary texts the divisions of which depend on many different +% received traditions. It takes one optional argument in which the +% key-value arguments defined above are accepted, and converts the +% divisions into \texttt{TEI} \enquote*{un-numbered} |<div>| +% elements. +% \begin{macrocode} +\NewDocumentCommand{\ekddiv}{m}{ + \begingroup + \ekvset{ekd@div}{#1}% + \ifdefined\head@value + \bgroup + \ekd@getfmtdiv{\depth@value}{b}% + \head@value + \ekd@getfmtdiv{\depth@value}{e}% + \egroup + \ifdefined\toc@value + \ltx@ifpackageloaded{hyperref}{\phantomsection}{}% + \ifdefined\barehead@value + \addcontentsline{toc}{\toc@value}{\barehead@value}% + \else + \addcontentsline{toc}{\toc@value}{\head@value}% + \fi + \fi + \fi + \endgroup +} +% \end{macrocode} +% \end{macro} +% A very basic and provisional implementation of poetry lines +% follows:--- +% \begin{macrocode} +\newlength{\ekdverseindentlength} +\setlength{\ekdverseindentlength}{\parindent} +\newenvironment*{ekdverse}[1][\ekdverseindentlength]{ + \begin{list}{}{% + \setlength{\leftmargin}{#1} + \setlength{\itemsep}{0pt} + \setlength{\topsep}{0pt} + \setlength{\partopsep}{0pt} + } + \item[] + }{\end{list}} +% \end{macrocode} +% +% \iffalse +%</package> +% \fi +% +% \Finale +% \iffalse +%<*lua> +% \fi +% \begin{comment} +% \begin{ekdlua} +-- `' +-- This table will hold the functions: +ekdosis = {} + +-- lpeg equivalent for string.gsub() +local function gsub(s, patt, repl) + patt = lpeg.P(patt) + patt = lpeg.Cs((patt / repl + 1)^0) + return lpeg.match(patt, s) +end + +-- some basic patterns: +local letters = lpeg.R("az", "AZ") +local ascii = lpeg.R("az", "AZ", "@@") +local dblbkslash = lpeg.Cs("\\") +local bsqbrackets = lpeg.Cs{ "[" * ((1 - lpeg.S"[]") + lpeg.V(1))^0 * "]" } +local bcbraces = lpeg.Cs{ "{" * ((1 - lpeg.S"{}") + lpeg.V(1))^0 * "}" } +local spce = lpeg.Cs(" ") +local spcenc = lpeg.P(" ") +local cmdstar = lpeg.Cs(spce * lpeg.P("*")) +local bsqbracketsii = lpeg.Cs(bsqbrackets^-2) +local bcbracesii = lpeg.Cs(bcbraces^-2) +local cmd = lpeg.Cs(dblbkslash * ascii^1 * cmdstar^-1) +local rawcmd = lpeg.Cs(dblbkslash * ascii^1) +local aftercmd = lpeg.Cs(lpeg.S("*[{,.?;:'`\"") + dblbkslash) +local cmdargs = lpeg.Cs(spce^-1 * bsqbracketsii * bcbracesii * bsqbrackets^-1) +local app = lpeg.Cs("app") +local lemrdg = lpeg.Cs(lpeg.Cs("lem") + lpeg.Cs("rdg")) +local note = lpeg.Cs("note") +local lnbrk = lpeg.Cs("\\\\") +local poemline = lpeg.Cs(lnbrk * bsqbrackets^-1) +local endpoem = lpeg.Cs(lnbrk * lpeg.S("*!") * bsqbrackets^-1) +local sections = lpeg.Cs(lpeg.P("book") + lpeg.P("part") + lpeg.P("chapter") + + lpeg.P("section") + lpeg.P("subsection") + + lpeg.P("subsubsection")) +local par = lpeg.P(lpeg.P("\\par") * spce^1) +local parb = lpeg.P(lpeg.Cs("\\p@rb") * spce^1) +local para = lpeg.P(lpeg.Cs("\\p@ra") * spce^1) + +-- Bind to local variables +local next = next + +-- General +xmlids = {} + +local function xmlidfound(element) + for i = 1,#xmlids do + if xmlids[i].xmlid == element then + return true + end + end + return false +end + +-- Witnesses +listWit = {} +idsRend = {} +shorthands = {} + +local function isfound(table, value) + for i = 1,#table do + if table[i] == value then + return true + end + end + return false +end + +local function isintable(table, value) + for i = 1,#table do + if table[i].a == value then + return true + end + end + return false +end + +local function get_a_index(id, table) + local idfound = nil + for i = 1,#table + do + if table[i].a == id then + idfound = i + break + end + end + return idfound +end + +local function getindex(id, table) + local idfound = nil + for i = 1,#table + do + if table[i].xmlid == id then + idfound = i + break + end + end + return idfound +end + +function ekdosis.newwitness(id, + siglum, + description, + Settlement, + Institution, + Repository, + Collection, + Idno, + MsName, + OrigDate) + if xmlidfound(id) + then + tex.print("\\unexpanded{\\PackageWarning{ekdosis}{\"" + ..id.. + "\" already exists as a xml:id. " + .. + "Please pick another id.}}") + else + table.insert(xmlids, {xmlid = id}) + table.sort(xmlids, function(a ,b) return(#a.xmlid > #b.xmlid) end) + table.insert(idsRend, {xmlid = id, abbr = siglum}) + table.sort(idsRend, function(a ,b) return(#a.xmlid > #b.xmlid) end) + table.insert(listWit, {xmlid = id, + abbr = siglum, + detailsDesc = description, + msIdentifier = { + settlement = Settlement, + institution = Institution, + repository = Repository, + collection = Collection, + idno = Idno, + msName = MsName} + }) + local indexwit = getindex(id, listWit) + if OrigDate ~= "" then + listWit[indexwit].history = {} + listWit[indexwit].history.origin = {origDate = OrigDate} + end + end + return true +end + +function ekdosis.newhand(id, witid, siglum, description) + if xmlidfound(id) or not xmlidfound(witid) + then + tex.print("\\unexpanded{\\PackageWarning{ekdosis}{\"" + ..id.. + "\" already exists as a xml:id. " + .. + "Please pick another id.}}") + else + table.insert(xmlids, {xmlid = id}) + table.sort(xmlids, function(a ,b) return(#a.xmlid > #b.xmlid) end) + table.insert(idsRend, {xmlid = id, abbr = siglum}) + table.sort(idsRend, function(a ,b) return(#a.xmlid > #b.xmlid) end) + local indexwit = getindex(witid, listWit) + -- listWit[indexwit].handDesc = {xmlid = id, abbr = siglum, handNote = description} + if listWit[indexwit].handDesc == nil + then + listWit[indexwit].handDesc = {} + else + end + table.insert(listWit[indexwit].handDesc, + {xmlid = id, abbr = siglum, detailsDesc = description}) + end + return true +end + +function ekdosis.newshorthand(id, rend, xmlids) + if isintable(shorthands, id) + then + tex.print("\\unexpanded{\\PackageWarning{ekdosis}{\"" + ..id.. + "\" already exists as a shorthand. " + .. + "Please pick another shorthand.}}") + else + table.insert(shorthands, { a = id, b = rend, c = xmlids }) + table.sort(shorthands, function(a ,b) return(#a.a > #b.a) end) + table.insert(idsRend, {xmlid = id, abbr = rend}) + table.sort(idsRend, function(a ,b) return(#a.xmlid > #b.xmlid) end) + end + return true +end + +local xmlbibresource = nil + +function ekdosis.setxmlbibresource(str) + xmlbibresource = str..".xml" + return true +end + +function ekdosis.newscholar(id, siglum) + if xmlidfound(id) + then + tex.print("\\unexpanded{\\PackageWarning{ekdosis}{\"" + ..id.. + "\" already exists as a xml:id. " + .. + "Please pick another id.}}") + else + table.insert(xmlids, {xmlid = id}) + table.sort(xmlids, function(a ,b) return(#a.xmlid > #b.xmlid) end) + table.insert(idsRend, {xmlid = id, abbr = siglum}) + table.sort(idsRend, function(a ,b) return(#a.xmlid > #b.xmlid) end) + end + return true +end + +function ekdosis.getsiglum(str, opt) + str = str.."," + str = string.gsub(str, "%s-(%,)", "%1") + ctrl = str + if opt == "tei" then + for i = 1,#shorthands do + str = string.gsub(str, shorthands[i].a, shorthands[i].c) + end + for i = 1,#idsRend do + str = string.gsub(str, "(%f[%w])"..idsRend[i].xmlid.."(%,)", + "%1#"..idsRend[i].xmlid.."%2") + ctrl = string.gsub(ctrl, idsRend[i].xmlid.."%,", "") + end + str = string.gsub(str, "%,(%s-)([%#])", " %2") + str = string.gsub(str, "%,$", "") + else + for i = 1,#idsRend do + str = string.gsub(str, idsRend[i].xmlid.."%,", idsRend[i].abbr) + ctrl = string.gsub(ctrl, idsRend[i].xmlid.."%,", "") + end + end + -- if string.find(ctrl, "[A-Za-z0-9]") + if string.find(ctrl, "%S") + then + return "<??>" + else + return str + end +end + +-- begin totei functions + +local cmdtotags = { + {a="textsuperscript", b="hi", c=" rend=\"sup\""}, + {a="textsubscript", b="hi", c=" rend=\"sub\""}, + {a="LRfootnote", b="note", c=" place=\"bottom\""}, + {a="RLfootnote", b="note", c=" place=\"bottom\""}, + {a="enquote *", b="quote", c=""}, + {a="footnote", b="note", c=" place=\"bottom\""}, + {a="enquote", b="quote", c=""}, + {a="txtrans", b="s", c=" xml:lang=\"ar-Latn\" type=\"transliterated\""}, + {a="textbf", b="hi", c=" rend=\"bold\""}, + {a="textit", b="hi", c=" rend=\"italic\""}, + {a="textsc", b="hi", c=" rend=\"smallcaps\""}, + {a="textsf", b="hi", c=" rend=\"sf\""}, + {a="arbup", b="hi", c=" rend=\"sup\""}, + {a="txarb", b="s", c=" xml:lang=\"arb\""}, + {a="arb", b="foreign", + c=" xml:lang=\"ar-Latn\" type=\"transliterated\" subtype=\"arabtex\""} +} + +local texpatttotags = { + {a="\\icite%s?%[(.-)%]%[(.-)%]{(.-)}", b="%1 <ref target=\"#%3\">%2</ref>"}, + {a="\\icite%s?%[(.-)%]{(.-)}", b="<ref target=\"#%2\">%1</ref>"}, + {a="\\icite%s?{(.-)}", b="<ptr target=\"#%1\"/>"}, + {a="\\linelabel%s?{(.-)}", b="<anchor xml:id=\"%1\"/>"}, + {a="\\label%s?{(.-)}", b="<anchor xml:id=\"%1\"/>"}, + {a="\\v?pageref%s?{(.-)}", b="<ptr target=\"#%1\"/>"}, + {a="\\v?ref%s?{(.-)}", b="<ptr target=\"#%1\"/>"} +} + +local envtotags = { + {a="flushright", b="p", c=" rend=\"align(right)\""}, + {a="flushleft", b="p", c=" rend=\"align(left)\""}, + {a="quotation", b="quote", c=""}, + {a="ekdverse", b="lg", c=""}, + {a="txarabtr", b="p", c=" xml:lang=\"ar-Latn\" type=\"transliterated\""}, + {a="txarab", b="p", c=" xml:lang=\"arb\""}, + {a="center", b="p", c=" rend=\"align(center)\""}, + {a="verse", b="lg", c=""}, + {a="arab", b="p", + c=" xml:lang=\"ar-Latn\" type=\"transliterated\" subtype=\"arabtex\""} +} + +local close_p = { + "p", + "lg" +} + +local forbid_xmlid = true + +function ekdosis.newcmdtotag(cmd, tag, attr) + if forbid_xmlid + then + attr = string.gsub(attr, "xml:id", "n") -- xml:id is not allowed here + else + end + if isintable(cmdtotags, cmd) + then + local index = get_a_index(cmd, cmdtotags) + table.remove(cmdtotags, index) + table.insert(cmdtotags, {a = cmd, b = tag, c = " "..attr}) + table.sort(cmdtotags, function(a ,b) return(#a.a > #b.a) end) + else + table.insert(cmdtotags, {a = cmd, b = tag, c = " "..attr}) + table.sort(cmdtotags, function(a ,b) return(#a.a > #b.a) end) + end + return true +end + +function ekdosis.newpatttotag(pat, repl) + pat = string.gsub(pat, "([%[%]])", "%%%1") + pat = string.gsub(pat, "%#[1-9]", "(.-)") + repl = string.gsub(repl, "%#([1-9])", "%%%1") + table.insert(texpatttotags, { a = pat, b = repl }) + table.sort(texpatttotags, function(a ,b) return(#a.a > #b.a) end) + return true +end + +function ekdosis.newenvtotag(env, tag, attr, closep) + if forbid_xmlid + then + attr = string.gsub(attr, "xml:id", "n") -- xml:id is not allowed here + else + end + if isintable(envtotags, env) + then + local index = get_a_index(env, envtotags) + table.remove(envtotags, index) + table.insert(envtotags, {a = env, b = tag, c = " "..attr, d = closep}) + table.sort(envtotags, function(a ,b) return(#a.a > #b.a) end) + else + table.insert(envtotags, {a = env, b = tag, c = " "..attr, d = closep}) + table.sort(envtotags, function(a ,b) return(#a.a > #b.a) end) + end + return true +end + +-- Get values of attributes +local function get_attr_value(str, attr) + str = str.."," + local attrval = string.match(str, "%f[%w]"..attr.."%s?%=%s?%b{}") + or string.match(str, "%f[%w]"..attr.."%s?%=%s?.-%,") + or "" + attrval = string.gsub(attrval, attr.."%s?%=%s?(%b{})", function(bbraces) + bbraces = string.sub(bbraces, 2, -2) + return string.format("%s", bbraces) + end) + attrval = string.gsub(attrval, attr.."%s?%=%s?(.-)%s?%,", "%1") + return attrval +end + +local function xml_entities(str) + str = string.gsub(str, "%<", "<") + str = string.gsub(str, "%>", ">") + return str +end + +local function note_totei(str) + str = gsub(str, + dblbkslash * + note * + spcenc^-1 * + bsqbrackets * + bcbraces * + spcenc^-1, + function(bkslash, cmd, opt, arg) + opt = string.sub(opt, 2, -2) + arg = string.sub(arg, 2, -2) + teitype = get_attr_value(opt, "type") + if teitype ~= "" then teitype = " type=\""..teitype.."\"" else end + right = get_attr_value(opt, "labelb") + left = get_attr_value(opt, "labele") + if left ~= "" + then + return string.format( + "<%s%s target=\"#range(right(%s),left(%s))\">%s</%s><anchor xml:id=\"%s\"/>", + cmd, teitype, right, left, arg, cmd, right) + elseif left == "" + then + return string.format( + "<%s%s target=\"#right(%s)\">%s</%s><anchor xml:id=\"%s\"/>", + cmd, teitype, right, arg, cmd, right) + end + end) + return str +end + +local function app_totei(str) + str = gsub(str, + dblbkslash * + app * + spcenc^-1 * + bsqbrackets * + bcbraces * + spcenc^-1, + function(bkslash, cmd, opt, arg) + opt = string.sub(opt, 2, -2) + arg = string.sub(arg, 2, -2) + opt = get_attr_value(opt, "type") + if opt ~= "" then opt = " type=\""..opt.."\"" else end + return app_totei(string.format("<%s%s>%s</%s>", + cmd, opt, arg, cmd)) + end) + return str +end + +local function lem_rdg_totei(str) + str = gsub(str, + spcenc^-1 * + dblbkslash * + lemrdg * + spcenc^-1 * + bsqbrackets * + bcbraces * + spcenc^-1, + function(bkslash, cmd, opt, arg) + opt = string.sub(opt, 2, -2) + arg = string.sub(arg, 2, -2) + -- opt = get_attr_value(opt, "wit") + -- + teiwit = get_attr_value(opt, "wit") + if teiwit ~= "" then teiwit = " wit=\""..ekdosis.getsiglum(teiwit, "tei").."\"" else end + teitype = get_attr_value(opt, "type") + if teitype ~= "" then teitype = " type=\""..teitype.."\"" else end + -- + if opt == "" + then + return lem_rdg_totei(string.format("<%s>%s</%s>", + cmd, arg, cmd)) + else + -- opt = ekdosis.getsiglum(opt, "tei") + return lem_rdg_totei(string.format("<%s%s%s>%s</%s>", + cmd, teiwit, teitype, arg, cmd)) + end + end) + str = gsub(str, spcenc^-0 * dblbkslash * lemrdg * spcenc^-1 * bcbraces * spcenc^-1, + function(bkslash, cmd, arg) + arg = string.sub(arg, 2, -2) + return lem_rdg_totei(string.format("<%s>%s</%s>", cmd, arg, cmd)) + end) + return str +end + +local function relocate_notes(str) + str = string.gsub(str, "(%<lem.-%>.-)(%<note.->.-%<%/note%>)(.-%<%/lem%>)", "%1%3%2") + return str +end + +local function linestotei(str) +-- str = "\n<l>"..str + str = string.gsub(str, "^%s?(.-)%s?$", "\n<l>%1</l>\n") +-- str = gsub(str, endpoem, "</l>\n") + str = gsub(str, poemline * spcenc^-1 * lpeg.P(">"), "\n<lb/>") + str = gsub(str, poemline * spcenc^-1, "</l>\n<l>") +-- str = str.."</l>\n" + return str +end + +-- better use lpeg: look into this later +local function versetotei(str) + str = string.gsub(str, "(\\begin%s?%{ekdverse%})(%b[])(.-)(\\end%s?%{ekdverse%})", function(benv, opt, arg, eenv) + arg = linestotei(arg) + return string.format("%s%s%s%s", benv, opt, arg, eenv) + end) + str = string.gsub(str, "(\\begin%s?%{ekdverse%})(.-)(\\end%s?%{ekdverse%})", function(benv, arg, eenv) + arg = linestotei(arg) + return string.format("%s%s%s", benv, arg, eenv) + end) + str = string.gsub(str, "(\\begin%s?%{verse%})(%b[])(.-)(\\end%s?%{verse%})", function(benv, opt, arg, eenv) + arg = linestotei(arg) + return string.format("%s%s%s%s", benv, opt, arg, eenv) + end) + str = string.gsub(str, "(\\begin%s?%{verse%})(.-)(\\end%s?%{verse%})", function(benv, arg, eenv) + arg = linestotei(arg) + return string.format("%s%s%s", benv, arg, eenv) + end) + return str +end + +local function envtotei(str) + for i = 1,#envtotags + do + if envtotags[i].b ~= "" + then + if isfound(close_p, envtotags[i].b) or envtotags[i].d == "yes" + then + str = gsub(str, lpeg.P("\\begin") * spcenc^-1 * lpeg.P("{") + * lpeg.Cs(envtotags[i].a) * lpeg.P("}") + * bsqbracketsii * bcbracesii * spcenc^-1, + "\\p@rb <"..envtotags[i].b..envtotags[i].c..">") + str = gsub(str, spcenc^-1 * lpeg.P("\\end") * spcenc^-1 * lpeg.P("{") + * lpeg.Cs(envtotags[i].a) * lpeg.P("}"), + "</"..envtotags[i].b..">\\p@ra ") + else + str = gsub(str, lpeg.P("\\begin") * spcenc^-1 * lpeg.P("{") + * lpeg.Cs(envtotags[i].a) * lpeg.P("}") + * bsqbracketsii * bcbracesii * spcenc^-1, + "<"..envtotags[i].b..envtotags[i].c..">") + str = gsub(str, spcenc^-1 * lpeg.P("\\end") * spcenc^-1 * lpeg.P("{") + * lpeg.Cs(envtotags[i].a) * lpeg.P("}"), + "</"..envtotags[i].b..">") + end + else + str = gsub(str, lpeg.P("\\begin") * spcenc^-1 * lpeg.P("{") + * lpeg.Cs(envtotags[i].a) * lpeg.P("}") + * bsqbracketsii * bcbracesii * spcenc^-1, + "") + str = gsub(str, spcenc^-1 * lpeg.P("\\end") * spcenc^-1 * lpeg.P("{") + * lpeg.Cs(envtotags[i].a) * lpeg.P("}"), + "") + end + end + str = gsub(str, lpeg.P("\\begin") * spcenc^-1 * lpeg.P("{") + * lpeg.Cs(ascii^1) * lpeg.P("}") * bsqbracketsii + * bcbracesii * spcenc^-1, + "<%1>") + str = gsub(str, spcenc^-1 * lpeg.P("\\end") * spcenc^-1 * lpeg.P("{") + * lpeg.Cs(ascii^1) * lpeg.P("}") * bsqbracketsii + * bcbracesii, + "</%1>") + return str +end + +local function texpatttotei(str) + for i = 1,#texpatttotags do + str = string.gsub(str, texpatttotags[i].a, texpatttotags[i].b) + end + return str +end + +local function cmdtotei(str) + for i = 1,#cmdtotags + do + str = gsub(str, lpeg.P("\\") * lpeg.Cs(cmdtotags[i].a) * spcenc^-1 * bsqbrackets * -bcbraces, "\\%1%2{}") + str = gsub(str, lpeg.P("\\") * lpeg.Cs(cmdtotags[i].a) * spcenc^-1 * -(bsqbrackets + bcbraces), "\\%1[]{}") + str = string.gsub(str, "(\\"..cmdtotags[i].a..")%s?%*?(%b{})", "%1[]%2") + str = string.gsub(str, "(\\"..cmdtotags[i].a..")%s?%*?(%b[])(%b{})", + function(cmd, arg, body) + body = string.sub(body, 2, -2) + arg = string.sub(arg, 2, -2) + arg = string.gsub(arg, "(%b{})", function(braces) + braces = string.sub(braces, 2, -2) + return string.format("\"%s\"", braces) + end) + body = cmdtotei(body) + -- return string.format("<"..cmdtotags[i].b..cmdtotags[i].c.." %s>%s</"..cmdtotags[i].b..">", arg, body) + if cmdtotags[i].b ~= "" + then + return string.format("<"..cmdtotags[i].b..cmdtotags[i].c..">%s</" .. + cmdtotags[i].b..">", body) + else + return "" + end + end) + end + -- temporarily: + str = string.gsub(str, "\\(getsiglum)%s?(%b{})", + function(cmd, body) + body = string.sub(body, 2, -2) + teisiglum = ekdosis.getsiglum(body, "tei") + printsiglum = ekdosis.getsiglum(body) + -- body = cmdtotei(body) + return string.format("<ref target=\"%s\">%s</ref>", + teisiglum, printsiglum) + end) + str = string.gsub(str, "\\(%a+)%s?%*?(%b[])(%b{})", + function(cmd, opt, body) + body = string.sub(body, 2, -2) + body = cmdtotei(body) + return string.format("<%s>%s</%s>", cmd, body, cmd) + end) + str = string.gsub(str, "\\(%a+)%s?%*?(%b{})", + function(cmd, body) + body = string.sub(body, 2, -2) + body = cmdtotei(body) + return string.format("<%s>%s</%s>", cmd, body, cmd) + end) + str = string.gsub(str, "(%s)(%>)", "%2") + return str +end + +local function partotei(str) + str = gsub(str, lpeg.P(lpeg.P("\\par") * spcenc^1)^1, "\\par ") + str = gsub(str, ((para + parb) * par^-1)^2, "\\p@r ") + str = string.gsub(str, "\\p@ra%s+", "<p>") + str = string.gsub(str, "\\p@rb%s+", "</p>") + str = string.gsub(str, "\\p@r%s+", "") + str = string.gsub(str, "%s?\\par%s?", "<p>", 1) + str = string.gsub(str, "(%<p%>)(%s-)(%<%/?div%d?)", "%3") + str = string.gsub(str, "%s?\\par%s?", "</p><p>") + str = string.gsub(str, "<p>%s?</p>", "") + str = string.gsub(str, "(%<p%>)%s?(%</div%>)$", "%2") + str = string.gsub(str, "(%<p%>)%s?$", "") + str = string.gsub(str, "(<p>)%s?(<div.->)", "%2%1") + return str +end + +local function self_close_tags(str) + str = gsub(str, lpeg.P("<" * -lpeg.S("/")) + * lpeg.Cs(letters^1) + * lpeg.Cs((1 - lpeg.S"<>")^0) + * lpeg.P(">") + * lpeg.P("</") + * lpeg.Cs(letters^1) + * lpeg.P(">"), function(ftag, arg, ltag) + if ftag == ltag + then + return string.format("<%s%s/>", ftag, arg) + else + end + end) + return str +end + +local divdepth = { + book = 1, + part = 2, + chapter = 3, + section = 4, + subsection = 5, + subsubsection = 6 +} + +function ekdosis.mkdivdepths(...) + divdepth = {} + local num = 1 + for _, y in ipairs{...} + do + if y == "book" or "part" or "chapter" + or "section" or "subsection" or "subsubsection" + then + divdepth[y] = num + num = num + 1 + else + end + end + return true +end + +-- LaTeX side: format the divisions +local fmtdiv = {} + +function ekdosis.fmtdiv(n, fmtb, fmte) + if isintable(fmtdiv, n) + then + local index = get_a_index(n, fmtdiv) + table.remove(fmtdiv, index) + else + end + table.insert(fmtdiv, { a = n, formatb = fmtb, formate = fmte} ) + return true +end + +function ekdosis.getfmtdiv(n, pos) + local index = get_a_index(n, fmtdiv) + if index ~= nil + then + if pos == "b" + then + return fmtdiv[index].formatb + elseif pos == "e" + then + return fmtdiv[index].formate + end + else + return "" + end +end + +local ekddivs = true + +function ekdosis.setekddivsfalse() + ekddivs = false +end + +local function ekddivs_totei(str) + str = gsub(str, dblbkslash * lpeg.Cs("ekddiv") * spce^-1 * bcbraces, + function(bkslash, cmd, space, arg) + if ekddivs + then + arg = string.sub(arg, 2, -2) + teitype = get_attr_value(arg, "type") + tein = get_attr_value(arg, "n") + teihead = get_attr_value(arg, "head") + teidepth = get_attr_value(arg, "depth") + if teitype ~= "" then teitype = " type=\""..teitype.."\"" else end + if tein ~= "" then tein = " n=\""..tein.."\"" else end + if teidepth ~= "" + then + teidepth = " depth=\""..teidepth.."\"" + else + teidepth = " depth=\"1\"" + end + return string.format("\\p@rb <div%s%s%s><head>%s</head>\\p@ra ", + teitype, tein, teidepth, teihead) + else + return "" + end + end) + return str +end + +local function section_totei(str) + str = gsub(str, dblbkslash * sections * spce^-1 * bcbraces, "%1%2%3[]%4") + str = gsub(str, dblbkslash * sections * spce^-1 * bsqbrackets * bcbraces, + function(bkslash, secname, space, opt, arg) + if ekddivs + then + return "" + else + ctr = divdepth[secname] + arg = string.sub(arg, 2, -2) + return string.format("\\p@rb <div%s type=\"%s\"><head>%s</head>\\p@ra ", + ctr, secname, arg) + end + end) + return str +end + +local used_ndivs = {} + +local function close_ekddivs_at_end(str) + local isdiv = false + if string.find(str, "</div>$") + then + isdiv = true + str = string.gsub(str, "(.*)(</div>)$", "%1") + else + end + -- collect used depth numbers + for i in string.gmatch(str, "<div .-depth%=\"%d\".->") + do + i = string.match(i, "depth=\"%d\"") + i = string.match(i, "%d") + if isintable(used_ndivs, i) + then + else + table.insert(used_ndivs, {a = i} ) + end + end + if next(used_ndivs) ~= nil + then + table.sort(used_ndivs, function(a ,b) return(#a.a > #b.a) end) + else + end + local firstdiv = string.match(str, "<div .-depth%=\"%d\".->") or "" + firstdiv = string.match(firstdiv, "depth%=\"%d\"") or "" + firstdiv = string.match(firstdiv, "%d") or "" + local lastdiv = string.match(string.reverse(str), ">.-\"%d\"%=htped.- vid<") or "" + lastdiv = string.match(lastdiv, "\"%d\"%=htped") or "" + lastdiv = string.match(lastdiv, "%d") or "" + local firstdivindex = get_a_index(firstdiv, used_ndivs) + local lastdivindex = get_a_index(lastdiv, used_ndivs) + firstdivindex = tonumber(firstdivindex) + lastdivindex = tonumber(lastdivindex) + local closedivs = "" + if isintable(used_ndivs, firstdiv) + then + while lastdivindex >= firstdivindex + do + closedivs = closedivs.."</div>" + lastdivindex = lastdivindex - 1 + end + end + if isdiv + then + return str..closedivs.."</div>" + else + return str..closedivs + end +end + +local function close_ndivs_at_end(str) + local isdiv = false + if string.find(str, "</div>$") + then + isdiv = true + str = string.gsub(str, "(.*)(</div>)$", "%1") + else + end + -- collect used div numbers + for i in string.gmatch(str, "<div[1-6]") + do + i = string.match(i, "[1-6]") + if isintable(used_ndivs, i) + then + else + table.insert(used_ndivs, {a = i} ) + end + end + if next(used_ndivs) ~= nil + then + table.sort(used_ndivs, function(a ,b) return(#a.a > #b.a) end) + else + end + local firstdiv = string.match(str, "<div[1-6]") or "" + firstdiv = string.match(firstdiv, "[1-6]") or "" + local lastdiv = string.match(string.reverse(str), "[1-6]vid<") or "" + lastdiv = string.match(lastdiv, "[1-6]") or "" + local firstdivindex = get_a_index(firstdiv, used_ndivs) + local lastdivindex = get_a_index(lastdiv, used_ndivs) + firstdivindex = tonumber(firstdivindex) + lastdivindex = tonumber(lastdivindex) + local closedivs = "" + if isintable(used_ndivs, firstdiv) + then + while lastdivindex >= firstdivindex + do + closedivs = closedivs.."</div"..used_ndivs[lastdivindex].a..">" + lastdivindex = lastdivindex - 1 + end + end + if isdiv + then + return str..closedivs.."</div>" + else + return str..closedivs + end +end + +local function close_ekddivs_in_between(str) + local maxdepth = 1 + for i in string.gmatch(str, "<div.-depth=\"(%d)\".->", "%1") + do + if tonumber(i) > tonumber(maxdepth) + then + maxdepth = i + else + end + end + for ndivi = 1, maxdepth + do + str = string.gsub(str, "(<div .-depth%=\")("..ndivi..")(\".->)(.-)(<div .-depth%=\")(%d)(\".->)", + function(bdivi, ndivi, edivi, between, bdivii, ndivii, edivii) + local firstdiv = ndivi + local lastdiv = ndivii + local firstdivindex = get_a_index(firstdiv, used_ndivs) + local lastdivindex = get_a_index(lastdiv, used_ndivs) + firstdivindex = tonumber(firstdivindex) + lastdivindex = tonumber(lastdivindex) + local closedivs = "" + if firstdivindex >= lastdivindex + then + while firstdivindex >= lastdivindex + do + closedivs = closedivs.."</div>" + firstdivindex = firstdivindex - 1 + end + end + return string.format("%s%s%s%s%s%s%s%s", + bdivi, ndivi, edivi, between, closedivs, bdivii, ndivii, edivii) + end) + end + str = string.gsub(str, "(<div.-)(%sdepth%=\"%d\")(.->)", "%1%3") + used_ndivs = {} + return str +end + +local function close_ndivs_in_between(str) + for ndivi = 1, 6 + do + str = string.gsub(str, "(<div)("..ndivi..")(.->)(.-)(<div)([1-6])(.->)", + function(bdivi, ndivi, edivi, between, bdivii, ndivii, edivii) + local firstdiv = ndivi + local lastdiv = ndivii + local firstdivindex = get_a_index(firstdiv, used_ndivs) + local lastdivindex = get_a_index(lastdiv, used_ndivs) + firstdivindex = tonumber(firstdivindex) + lastdivindex = tonumber(lastdivindex) + local closedivs = "" + if firstdivindex >= lastdivindex + then + while firstdivindex >= lastdivindex + do + closedivs = closedivs.."</div"..used_ndivs[firstdivindex].a..">" + firstdivindex = firstdivindex - 1 + end + end + return string.format("%s%s%s%s%s%s%s%s", + bdivi, ndivi, edivi, between, closedivs, bdivii, ndivii, edivii) + + end) + end + used_ndivs = {} + return str +end + +local function textotei(str) + str = xml_entities(str) + str = texpatttotei(str) + str = note_totei(str) + str = app_totei(str) + str = lem_rdg_totei(str) + str = relocate_notes(str) + str = versetotei(str) + str = envtotei(str) + str = ekddivs_totei(str) + str = section_totei(str) + str = cmdtotei(str) + str = self_close_tags(str) + str = partotei(str) + if ekddivs + then + str = close_ekddivs_at_end(str) + str = close_ekddivs_in_between(str) + else + str = close_ndivs_at_end(str) + str = close_ndivs_in_between(str) + end + return str +end + +local teifilename = tex.jobname.."-tei" + +function ekdosis.setteifilename(str) + teifilename = str + return true +end + +function ekdosis.openteistream() + local f = io.open(teifilename.."_tmp.xml", "a+") + f:write('<?xml version="1.0" encoding="utf-8"?>', "\n") + f:write("<TEI xmlns=\"http://www.tei-c.org/ns/1.0\">", "\n") + f:write("<teiHeader>", "\n") + f:write("<fileDesc>", "\n") + f:write("<titleStmt>", "\n") + f:write("<title><!-- Title --></title>", "\n") + f:write("<respStmt>", "\n") + f:write("<resp><!-- Edited by --></resp>", "\n") + f:write("<name><!-- Name --></name>", "\n") + f:write("</respStmt>", "\n") + f:write("</titleStmt>", "\n") + f:write("<publicationStmt>", "\n") + f:write("<distributor><!-- Distributor name --></distributor>", "\n") + f:write("</publicationStmt>", "\n") + f:write("<sourceDesc>", "\n") + f:write("<listWit>", "\n") + for i = 1,#listWit do + f:write('<witness xml:id=\"', listWit[i].xmlid, "\">", "\n") + f:write('<abbr type="siglum">', textotei(listWit[i].abbr), "</abbr>", "\n") + f:write(textotei(listWit[i].detailsDesc), "\n") + f:write("<msDesc>", "\n") + if listWit[i].msIdentifier.settlement == "" + and listWit[i].msIdentifier.institution == "" + and listWit[i].msIdentifier.repository == "" + and listWit[i].msIdentifier.collection == "" + and listWit[i].msIdentifier.idno == "" + and listWit[i].msIdentifier.msName == "" + then + f:write("<msIdentifier/>", "\n") + else + f:write("<msIdentifier>", "\n") + if listWit[i].msIdentifier.settlement ~= "" then + f:write("<settlement>", textotei(listWit[i].msIdentifier.settlement), "</settlement>", "\n") + else end + if listWit[i].msIdentifier.institution ~= "" then + f:write("<institution>", textotei(listWit[i].msIdentifier.institution), "</institution>", "\n") + else end + if listWit[i].msIdentifier.repository ~= "" then + f:write("<repository>", textotei(listWit[i].msIdentifier.repository), "</repository>", "\n") + else end + if listWit[i].msIdentifier.collection ~= "" then + f:write("<collection>", textotei(listWit[i].msIdentifier.collection), "</collection>", "\n") + else end + if listWit[i].msIdentifier.idno ~= "" then + f:write("<idno>", textotei(listWit[i].msIdentifier.idno), "</idno>", "\n") + else end + if listWit[i].msIdentifier.msName ~= "" then + f:write("<msName>", textotei(listWit[i].msIdentifier.msName), "</msName>", "\n") + else end + f:write("</msIdentifier>", "\n") + end + if listWit[i].handDesc ~= nil then + f:write("<physDesc>", "\n") + f:write("<handDesc hands=\"", #listWit[i].handDesc, "\">", "\n") + local j = 1 + while listWit[i].handDesc[j] + do + f:write("<handNote xml:id=\"", listWit[i].handDesc[j].xmlid, "\">", "\n") + f:write('<abbr type="siglum">', textotei(listWit[i].handDesc[j].abbr), "</abbr>", "\n") + f:write("<p>", textotei(listWit[i].handDesc[j].detailsDesc), "</p>", "\n") + f:write("</handNote>", "\n") + j = j + 1 + end + f:write("</handDesc>", "\n") + f:write("</physDesc>", "\n") + else end + if listWit[i].history ~= nil then + f:write("<history>", "\n") + f:write("<origin>", "\n") + f:write("<origDate>", textotei(listWit[i].history.origin.origDate), "</origDate>", "\n") + f:write("</origin>", "\n") + f:write("</history>", "\n") + end + f:write("</msDesc>", "\n") + f:write("</witness>", "\n") + end + f:write("</listWit>", "\n") + f:write("</sourceDesc>", "\n") + f:write("</fileDesc>", "\n") + f:write("<encodingDesc>", "\n") + f:write('<variantEncoding method="parallel-segmentation" location="internal"/>', "\n") + f:write("</encodingDesc>", "\n") + f:write("</teiHeader>", "\n") + f:write("<text>", "\n") + f:write("<body>", "\n") + f:close() + return true +end + +local tidy = nil + +local function cleanup_tei() + local f = assert(io.open(teifilename.."_tmp.xml", "r")) + t = f:read("*a") + t = string.gsub(t, "%<p%>%s?%</p%>", "") + t = string.gsub(t, "^\n", "") + f:close() + local fw = assert(io.open(teifilename.."_tmp.xml", "w")) + fw:write(t) + fw:close() + return true +end + +function ekdosis.closeteistream(opt) + local f = io.open(teifilename.."_tmp.xml", "a+") + f:write("\n", "</body>", "\n") + if xmlbibresource ~= nil then + bibf = assert(io.open(xmlbibresource, "r")) + t = bibf:read("*a") + t = string.gsub(t, "%s+corresp%=%b\"\"", "") + t = string.gsub(t, "\n\n", "\n") + f:write("<back>", "\n") + f:write("<listBibl>", "\n") + for i in string.gmatch(t, "<biblStruct.->.-</biblStruct>") + do + f:write(i, "\n") + end + f:write("</listBibl>", "\n") + f:write("</back>", "\n") + bibf:close() + else + end + f:write("</text>", "\n") + f:write("</TEI>", "\n") + f:close() + cleanup_tei() + os.remove(teifilename..".xml") + os.rename(teifilename.."_tmp.xml", teifilename..".xml") + if opt == "tidy" then + os.execute("tidy -qmi -xml --output-xml yes "..teifilename..".xml") + else + end + return true +end + +function ekdosis.exporttei(str) + local f = io.open(teifilename.."_tmp.xml", "a+") + -- f:write("\n<p>") + str = textotei(str) + f:write(str) + f:close() + return true +end +-- end totei functions + +-- begin basic TeX Conspectus siglorum +function ekdosis.basic_cs(msid) + local indexwit = getindex(msid, listWit) + siglum = listWit[indexwit].abbr + -- if listWit[indexwit].detailsDesc == "" + -- then + -- name = listWit[indexwit].msIdentifier.msName + -- else + -- name = listWit[indexwit].msIdentifier.msName + -- .."\\thinspace\\newline\\bgroup\\footnotesize{}".. + -- listWit[indexwit].detailsDesc + -- .."\\egroup{}" + -- end + name = listWit[indexwit].detailsDesc + if listWit[indexwit].history ~= nil + and + listWit[indexwit].history.origin ~= nil + then + date = listWit[indexwit].history.origin.origDate + else + date = "" + end + return siglum.."&"..name.."&"..date +end +-- end basic TeX Conspectus siglorum + +function ekdosis.removesp(str) + str = gsub(str, cmd * cmdargs * spcenc^-1, "%1%2") + return str +end + +function ekdosis.closestream() + os.remove(tex.jobname..".ekd") + os.rename(tex.jobname.."_tmp.ekd", tex.jobname..".ekd") + return true +end + +local cur_abs_pg = 0 +local pg_i = nil +local pg_ii = nil +local prevcol = nil +local curcol = "x" + +local check_resetlineno = {} + +function ekdosis.update_abspg(n) -- not used + cur_abs_pg = n + return true +end + +function ekdosis.storeabspg(n, pg) + if pg == "pg_i" then + pg_i = n + elseif pg == "pg_ii" then + pg_ii = n + table.insert(check_resetlineno, curcol.."-"..pg_ii) + end + cur_abs_pg = n + return true +end + +function ekdosis.checkresetlineno() + if isfound(check_resetlineno, curcol.."-"..pg_i) + then + return "" + else + return "\\resetlinenumber" + end +end + +-- +-- Build environments to be aligned +-- + +local cur_alignment = "-" +local cur_alignment_patt = "%-" +local cur_alignment_cnt = 1 + +local newalignment = false +function ekdosis.newalignment(str) + if str == "set" + then + newalignment = true + cur_alignment = "-"..cur_alignment_cnt.."-" + cur_alignment_patt = "%-"..cur_alignment_cnt.."%-" + cur_alignment_cnt = cur_alignment_cnt + 1 + elseif str == "reset" + then + newalignment = false + cur_alignment = "-" + cur_alignment_patt = "-" + end + return true +end + +local aligned_texts = {} +local texts_w_apparatus = {} +local coldata_totei = {} + +local function sanitize_envdata(str) -- look for a better way to achieve this + str = string.gsub(str, "(%a+)%s+(%b[])", "%1%2") + str = string.gsub(str, "(%a+)(%b[])%s+", "%1%2") + str = string.gsub(str, "%s+(%a+)(%b[])", "%1%2") + str = gsub(str, lpeg.Cs(letters^1) + * spcenc^-1 + * -bsqbrackets + * lpeg.Cs(";"), "%1[]%2") + str = string.gsub(str, "%s+(%a+)(%b[])", "%1%2") + return str +end + +function ekdosis.mkenvdata(str, opt) + if not string.find(str, "%;", -1) then str = str .. ";" else end + -- str = str ..";" + -- str = string.gsub(str, "%s+", "") + local fieldstart = 1 + local col = 0 + if opt == "texts" then + str = sanitize_envdata(str) + repeat + local _s, nexti = string.find(str, "%b[]%s-%;", fieldstart) + local namediv = string.gsub(string.sub(str, fieldstart, nexti-1), "(%a+)%s-(%b[])", "%1") + local attr = string.gsub(string.sub(str, fieldstart, nexti-1), "(%a+)%s-(%b[])", "%2") + attr = string.sub(attr, 2, -2) + if forbid_xmlid + then + attr = string.gsub(attr, "xml:id", "n") -- xml:id is not allowed here + else + end + table.insert(aligned_texts, { text = namediv, + attribute = attr, + column = col }) + table.insert(coldata_totei, { environment = namediv, + data = {} }) + col = col + 1 + fieldstart = nexti + 1 + until fieldstart > string.len(str) + return aligned_texts + elseif opt == "apparatus" then + repeat + local nexti = string.find(str, "%;", fieldstart) + table.insert(texts_w_apparatus, string.sub(str, fieldstart, nexti-1)) + fieldstart = nexti +1 + until fieldstart > string.len(str) + return texts_w_apparatus + end +end + +-- Reminder: the following two variables are already set above +-- local prevcol = nil +-- local curcol = "x" + +function ekdosis.storecurcol(n) + curcol = n + return true +end + +function ekdosis.flushcolnums() + prevcol = nil + curcol = "x" + return true +end + +function ekdosis.flushenvdata() + aligned_texts = {} + texts_w_apparatus = {} + coldata_totei = {} + return true +end + +function ekdosis.storecoldata(nthcol, chunk) + local tindex = tonumber(nthcol) + 1 + table.insert(coldata_totei[tindex].data, chunk) + return true +end + +local environment_div = {} + +function ekdosis.newscholar(id, siglum) + if xmlidfound(id) + then + tex.print("\\unexpanded{\\PackageWarning{ekdosis}{\"" + ..id.. + "\" already exists as a xml:id. " + .. + "Please pick another id.}}") + else + table.insert(xmlids, {xmlid = id}) + table.sort(xmlids, function(a ,b) return(#a.xmlid > #b.xmlid) end) + table.insert(idsRend, {xmlid = id, abbr = siglum}) + table.sort(idsRend, function(a ,b) return(#a.xmlid > #b.xmlid) end) + end + return true +end + + +local function build_envdiv(str) + if not environment_div[str] + then + environment_div[str] = 1 + else + environment_div[str] = environment_div[str] + 1 + end + local div = "div-"..str.."_"..environment_div[str] + if xmlidfound(div) + then + tex.print("\\unexpanded{\\PackageWarning{ekdosis}{\"" + ..div.. + "\" already exists as a xml:id. " + .. + "ekdosis has generated some random id.}}") + return "div-"..math.random(1000,9999) + else + table.insert(xmlids, {xmlid = div}) + table.sort(xmlids, function(a ,b) return(#a.xmlid > #b.xmlid) end) + return div + end +end + +function ekdosis.mkenv() + local environments = {} + for i = 1,#aligned_texts + do + if isfound(texts_w_apparatus, aligned_texts[i].text) + then + table.insert(environments, "\\NewDocumentEnvironment{".. aligned_texts[i].text.."}{+b}" + .."{\\begin{nthcolumn}{".. aligned_texts[i].column.."}" + .."\\par" + .."\\EkdosisColStart" + .."\\EkdosisOn#1" + .."}{\\EkdosisOff" + .."\\EkdosisColStop" + .."\\end{nthcolumn}" + .."\\csname iftei@export\\endcsname\\luadirect{ekdosis.storecoldata(" + .. aligned_texts[i].column + ..", \\luastringN{\\par#1\\par})}\\fi" + .."}") + table.insert(environments, "\\NewDocumentEnvironment{".. aligned_texts[i].text.."*}{+b}" + .."{\\begin{nthcolumn*}{".. aligned_texts[i].column.."}[]" + .."\\par" + .."\\EkdosisColStart" + .."\\EkdosisOn#1" + .."}{\\EkdosisOff" + .."\\EkdosisColStop" + .."\\end{nthcolumn*}" + .."\\csname iftei@export\\endcsname\\luadirect{ekdosis.storecoldata(" + .. aligned_texts[i].column + ..", \\luastringN{\\par#1\\par})}\\fi" + .."}") + else + table.insert(environments, "\\NewDocumentEnvironment{".. aligned_texts[i].text.."}{+b}" + .."{\\begin{nthcolumn}{".. aligned_texts[i].column.."}" + .."\\par" + .."#1" + .."}{\\end{nthcolumn}" + .."\\csname iftei@export\\endcsname\\luadirect{ekdosis.storecoldata(" + .. aligned_texts[i].column + ..", \\luastringN{\\par#1\\par})}\\fi" + .."}") + table.insert(environments, "\\NewDocumentEnvironment{".. aligned_texts[i].text.."*}{+b}" + .."{\\begin{nthcolumn*}{"..aligned_texts[i].column.."}[]" + .."\\par" + .."#1" + .."}{" + .."\\end{nthcolumn*}" + .."\\csname iftei@export\\endcsname\\luadirect{ekdosis.storecoldata(" + .. aligned_texts[i].column + ..", \\luastringN{\\par#1\\par})}\\fi" + .."}") + end + forbid_xmlid = false + if aligned_texts[i].attribute ~= "" + then + ekdosis.newenvtotag(aligned_texts[i].text, "div", + "xml:id=\"" + ..build_envdiv(aligned_texts[i].text) + .."\" " + ..aligned_texts[i].attribute) + else + ekdosis.newenvtotag(aligned_texts[i].text, "div", + "xml:id=\"" + ..build_envdiv(aligned_texts[i].text) + .."\"") + end + forbid_xmlid = true + end + str = table.concat(environments) + return str +end + +function ekdosis.export_coldata_totei() + for i = 1,#coldata_totei + do + ekdosis.exporttei("\\begin{".. coldata_totei[i].environment .."}" + .. table.concat(coldata_totei[i].data) + .. "\\end{".. coldata_totei[i].environment .."}") + end +end + +-- handle multiple layers in apparatuses +-- +local apparatuses = {} +local bagunits = {} + +function ekdosis.newapparatus(teitype, + appdir, + apprule, + appdelim, + appsep, + appbhook, + appehook) + if isintable(apparatuses, teitype) + then + tex.print("\\unexpanded{\\PackageWarning{ekdosis}{\"" + ..teitype.. + "\" already exists.}}") + else + table.insert(apparatuses, {a = teitype, + direction = appdir, + rule = apprule, + delim = appdelim, + sep = appsep, + bhook = appbhook, + ehook = appehook}) + end + bagunits[teitype] = 1 + return true +end + +function ekdosis.getappdelim(str) + for i = 1,#apparatuses + do + if apparatuses[i].a == str then + delimfound = apparatuses[i].delim + break + end + end + return delimfound +end + +function ekdosis.get_bagunits(teitype) + return bagunits[teitype] +end + +function ekdosis.increment_bagunits(teitype) + bagunits[teitype] = (bagunits[teitype] or 0) + 1 +end + +local function reset_bagunits() + for i = 1,#apparatuses + do + bagunits[apparatuses[i].a] = 1 + end +end + +function ekdosis.appin(str, teitype) + local f = io.open(tex.jobname.."_tmp.ekd", "a+") + if next(apparatuses) == nil + then + f:write("<", cur_abs_pg, cur_alignment, curcol, "-0>", str, "</", + cur_abs_pg, cur_alignment, curcol, "-0>\n") + else + for i = 1,#apparatuses + do + if apparatuses[i].a == teitype then + appno = i + break + end + end + f:write("<", cur_abs_pg, cur_alignment, curcol, "-", + appno, ">", str, "</", cur_abs_pg, cur_alignment, curcol, "-", appno, ">\n") + end + f:close() + return true +end + +function ekdosis.appout() + local file = io.open(tex.jobname..".ekd", "r") + if file ~= nil then io.close(file) + f = assert(io.open(tex.jobname..".ekd", "r")) + t = f:read("*a") + local output = {} + if next(apparatuses) == nil then + -- table.insert(output, "BEGIN") + table.insert(output, "\\noindent\\csname ekd@default@rule\\endcsname\\NLS{}") +-- table.insert(output, "\\noindent ") + for i in string.gmatch(t, + "<"..cur_abs_pg + ..cur_alignment_patt + ..curcol.."%-0>.-</" + ..cur_abs_pg + ..cur_alignment_patt + ..curcol.."%-0>") + do + table.insert(output, i) + end + -- table.insert(output, "END") + else + local n = 1 + while apparatuses[n] + do + if string.match(t, "<"..cur_abs_pg.. + cur_alignment_patt + ..curcol.."%-"..n..">.-</" + ..cur_abs_pg + ..cur_alignment_patt + ..curcol.."%-"..n..">") + then + -- table.insert(output, "BEGIN") + table.insert(output, "\\bgroup{}") + if apparatuses[n].direction == "LR" + then + table.insert(output, "\\pardir TLT\\textdir TLT{}") + elseif apparatuses[n].direction == "RL" + then + table.insert(output, "\\pardir TRT\\textdir TRT{}") + end + if apparatuses[n].rule == "none" + then + if n > 1 + then + table.insert(output, "\\NLS{}") + else + table.insert(output, "\\noindent ") + end + elseif apparatuses[n].rule ~= "" + then + if n > 1 + then + table.insert(output, "\\NLS{}" .. apparatuses[n].rule .. "\\NLS{}") + else +-- table.insert(output, "\\noindent ") + table.insert(output, apparatuses[n].rule .. "\\NLS{}") + end + else + if n > 1 + then + table.insert(output, "\\NLS\\csname ekd@default@rule\\endcsname\\NLS{}") + else +-- table.insert(output, "\\noindent ") + table.insert(output, "\\csname ekd@default@rule\\endcsname\\NLS{}") + end + end + if apparatuses[n].sep ~= "" + then + table.insert(output, "\\edef\\ekdsep{" .. apparatuses[n].sep .. "}") + else + end + if apparatuses[n].bhook ~= "" + then + table.insert(output, apparatuses[n].bhook) + else + table.insert(output, "\\relax") + end + for i in string.gmatch(t, + "<"..cur_abs_pg + ..cur_alignment_patt + ..curcol.."%-"..n..">.-</" + ..cur_abs_pg + ..cur_alignment_patt + ..curcol.."%-"..n..">") + do + table.insert(output, i) + end + if apparatuses[n].ehook ~= "" + then + table.insert(output, apparatuses[n].ehook) + else + end + table.insert(output, "\\egroup{}") + -- table.insert(output, "END") + end + n = n + 1 + end + end + f:close() + str = table.concat(output) + str = string.gsub(str, "</"..cur_abs_pg..cur_alignment_patt..curcol.."%-[0-9]>", "") + str = string.gsub(str, "<"..cur_abs_pg..cur_alignment_patt..curcol.."%-[0-9]>", " ") + return str + else + end +end + +function ekdosis.appin_out(str, nl) + local f = io.open(tex.jobname.."_tmp.ekd", "a+") + if nl == "yes" then + f:write(str, "\n") + else + f:write(str) + end + f:close() + return true +end + +local curcol_curabspg = {} + +function ekdosis.testapparatus() + if isfound(curcol_curabspg, curcol.."-"..cur_abs_pg) + then + if newalignment + then + if next(apparatuses) ~= nil then + reset_bagunits() + end + newalignment = false + return "\\booltrue{do@app}" + else + return "\\boolfalse{do@app}" + end + else + table.insert(curcol_curabspg, curcol.."-"..cur_abs_pg) + if next(apparatuses) ~= nil then + reset_bagunits() + end + return "\\booltrue{do@app}" + end +end + +local lnlabs = {} +local lnlab_salt = 0 +local current_lnlab = nil +local prev_lnlab = nil +local current_notelab = nil +local prev_notelab = nil +local current_lemma = nil +local salt = 0 + +local function mdvisintable(table, value) + for _, v in pairs(table) do + if v == value then return true end + end + return false +end + +function ekdosis.dolnlab(str) + prev_lnlab = current_lnlab + current_lemma = str + i = md5.sumhexa(str) + if not mdvisintable(lnlabs, i) then + table.insert(lnlabs, i) + else + i = i..salt + table.insert(lnlabs, i) + salt = salt + 1 + end + current_lnlab = i + return true +end + +function ekdosis.getlnlab() + return current_lnlab +end + +function ekdosis.getprevlnlab() + return prev_lnlab +end + +function ekdosis.setnotelab(str) + current_notelab = str + return "\\linelabel{" .. current_notelab .. "}" +end + +function ekdosis.getnotelab() + return current_notelab +end + +function ekdosis.setprevnotelab(str) + prev_notelab = str + return true +end + +function ekdosis.getprevnotelab() + return prev_notelab +end + +local function remove_note(str) + str = gsub(str, dblbkslash * lpeg.P("note") * cmdargs, "") + return str +end + +function ekdosis.mdvappend(str, teitype) + if teitype == nil + then + return "\\linelabel{" .. current_lnlab .. "-b}\\wordboundary{}" + .. + current_lemma + .. + "\\linelabel{" .. current_lnlab .. "-e}" + .. + "\\csname append@app\\endcsname{" + .. remove_note(str) .. "}" + else + return "\\linelabel{" .. current_lnlab .. "-b}\\wordboundary{}" + .. + current_lemma + .. + "\\linelabel{" .. current_lnlab .. "-e}" + .. + "\\csname append@app\\endcsname" .. "[" .. teitype .. "]{" + .. remove_note(str) .. "}" + end +end + +% \end{ekdlua} +% \end{comment} +% \iffalse +%</lua> +% \fi +% +% \section{Sample: C. J. Caesar, \emph{Gallic War}, +% VI, XIII.1} +% \label{sec:caesar-gw-6-1-13} +% \subsection{\texttt{.tex} Source File} +% \label{sec:caesar-gw-tex} +% \inputminted[linenos=false]{latex}{samples/Caesar_BG-6-13-1.tex} +% \subsection{\texttt{TEI xml} Output} +% \label{sec:caesar-gw-tei} +% \inputminted[linenos=false]{xml}{samples/Caesar_BG-6-13-1-tei.xml} +% +\endinput diff --git a/Master/texmf-dist/source/lualatex/ekdosis/ekdosis.ins b/Master/texmf-dist/source/lualatex/ekdosis/ekdosis.ins new file mode 100644 index 00000000000..6427d379690 --- /dev/null +++ b/Master/texmf-dist/source/lualatex/ekdosis/ekdosis.ins @@ -0,0 +1,62 @@ +\input docstrip.tex +\keepsilent +\askforoverwritefalse +\preamble +-------:| ----------------------------------------------------------------- +ekdosis:| Typesetting TEI xml compliant critical editions + Author:| Robert Alessi + E-mail:| alessi@robertalessi.net +License:| Released under the GNU General Public License v3 or later + See:| http://www.gnu.org/licenses/ + +This file is part of the `ekdosis' package + +ekdosis -- Typesetting TEI xml compliant critical editions +Copyright (C) 2020 Robert Alessi + +Please send error reports and suggestions for improvements to Robert +Alessi <alessi@robertalessi.net> + +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 +<http://www.gnu.org/licenses/>. + +This work consists of the files ekdosis.dtx, ekdosis.el, this file and +a Makefile. +Running "make" generates the derived files README, ekdosis.pdf and +ekdosis.sty. +Running "make inst" installs the files in the user's TeX tree. +\endpreamble + +\usedir{tex/lualatex/ekdosis} +\generate{ + \file{\jobname.sty}{\from{\jobname.dtx}{package}} +} +\nopreamble\nopostamble +\usedir{tex/lualatex/ekdosis} +\bgroup +\catcode9=12 +\generate{ + \file{\jobname.lua}{ + \from{\jobname.dtx}{luapre} + \from{\jobname.dtx}{lua} + } +} +\egroup +% \usedir{doc/lualatex/ekdosis} +% \generate{ +% \file{ekdosis-ex01.tex}{ +% \from{\jobname.dtx}{example01} +% } +% } +\endbatchfile diff --git a/Master/texmf-dist/tex/lualatex/ekdosis/ekdosis.lua b/Master/texmf-dist/tex/lualatex/ekdosis/ekdosis.lua new file mode 100644 index 00000000000..cab5b029694 --- /dev/null +++ b/Master/texmf-dist/tex/lualatex/ekdosis/ekdosis.lua @@ -0,0 +1,1694 @@ +--[[ +This file is part of the `ekdosis' package + +ekdosis -- Typesetting TEI xml compliant critical editions +Copyright (C) 2020 Robert Alessi + +Please send error reports and suggestions for improvements to Robert +Alessi <alessi@robertalessi.net> + +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 +<http://www.gnu.org/licenses/>. +--]] + +-- `' +-- This table will hold the functions: +ekdosis = {} + +-- lpeg equivalent for string.gsub() +local function gsub(s, patt, repl) + patt = lpeg.P(patt) + patt = lpeg.Cs((patt / repl + 1)^0) + return lpeg.match(patt, s) +end + +-- some basic patterns: +local letters = lpeg.R("az", "AZ") +local ascii = lpeg.R("az", "AZ", "@@") +local dblbkslash = lpeg.Cs("\\") +local bsqbrackets = lpeg.Cs{ "[" * ((1 - lpeg.S"[]") + lpeg.V(1))^0 * "]" } +local bcbraces = lpeg.Cs{ "{" * ((1 - lpeg.S"{}") + lpeg.V(1))^0 * "}" } +local spce = lpeg.Cs(" ") +local spcenc = lpeg.P(" ") +local cmdstar = lpeg.Cs(spce * lpeg.P("*")) +local bsqbracketsii = lpeg.Cs(bsqbrackets^-2) +local bcbracesii = lpeg.Cs(bcbraces^-2) +local cmd = lpeg.Cs(dblbkslash * ascii^1 * cmdstar^-1) +local rawcmd = lpeg.Cs(dblbkslash * ascii^1) +local aftercmd = lpeg.Cs(lpeg.S("*[{,.?;:'`\"") + dblbkslash) +local cmdargs = lpeg.Cs(spce^-1 * bsqbracketsii * bcbracesii * bsqbrackets^-1) +local app = lpeg.Cs("app") +local lemrdg = lpeg.Cs(lpeg.Cs("lem") + lpeg.Cs("rdg")) +local note = lpeg.Cs("note") +local lnbrk = lpeg.Cs("\\\\") +local poemline = lpeg.Cs(lnbrk * bsqbrackets^-1) +local endpoem = lpeg.Cs(lnbrk * lpeg.S("*!") * bsqbrackets^-1) +local sections = lpeg.Cs(lpeg.P("book") + lpeg.P("part") + lpeg.P("chapter") + + lpeg.P("section") + lpeg.P("subsection") + + lpeg.P("subsubsection")) +local par = lpeg.P(lpeg.P("\\par") * spce^1) +local parb = lpeg.P(lpeg.Cs("\\p@rb") * spce^1) +local para = lpeg.P(lpeg.Cs("\\p@ra") * spce^1) + +-- Bind to local variables +local next = next + +-- General +xmlids = {} + +local function xmlidfound(element) + for i = 1,#xmlids do + if xmlids[i].xmlid == element then + return true + end + end + return false +end + +-- Witnesses +listWit = {} +idsRend = {} +shorthands = {} + +local function isfound(table, value) + for i = 1,#table do + if table[i] == value then + return true + end + end + return false +end + +local function isintable(table, value) + for i = 1,#table do + if table[i].a == value then + return true + end + end + return false +end + +local function get_a_index(id, table) + local idfound = nil + for i = 1,#table + do + if table[i].a == id then + idfound = i + break + end + end + return idfound +end + +local function getindex(id, table) + local idfound = nil + for i = 1,#table + do + if table[i].xmlid == id then + idfound = i + break + end + end + return idfound +end + +function ekdosis.newwitness(id, + siglum, + description, + Settlement, + Institution, + Repository, + Collection, + Idno, + MsName, + OrigDate) + if xmlidfound(id) + then + tex.print("\\unexpanded{\\PackageWarning{ekdosis}{\"" + ..id.. + "\" already exists as a xml:id. " + .. + "Please pick another id.}}") + else + table.insert(xmlids, {xmlid = id}) + table.sort(xmlids, function(a ,b) return(#a.xmlid > #b.xmlid) end) + table.insert(idsRend, {xmlid = id, abbr = siglum}) + table.sort(idsRend, function(a ,b) return(#a.xmlid > #b.xmlid) end) + table.insert(listWit, {xmlid = id, + abbr = siglum, + detailsDesc = description, + msIdentifier = { + settlement = Settlement, + institution = Institution, + repository = Repository, + collection = Collection, + idno = Idno, + msName = MsName} + }) + local indexwit = getindex(id, listWit) + if OrigDate ~= "" then + listWit[indexwit].history = {} + listWit[indexwit].history.origin = {origDate = OrigDate} + end + end + return true +end + +function ekdosis.newhand(id, witid, siglum, description) + if xmlidfound(id) or not xmlidfound(witid) + then + tex.print("\\unexpanded{\\PackageWarning{ekdosis}{\"" + ..id.. + "\" already exists as a xml:id. " + .. + "Please pick another id.}}") + else + table.insert(xmlids, {xmlid = id}) + table.sort(xmlids, function(a ,b) return(#a.xmlid > #b.xmlid) end) + table.insert(idsRend, {xmlid = id, abbr = siglum}) + table.sort(idsRend, function(a ,b) return(#a.xmlid > #b.xmlid) end) + local indexwit = getindex(witid, listWit) + -- listWit[indexwit].handDesc = {xmlid = id, abbr = siglum, handNote = description} + if listWit[indexwit].handDesc == nil + then + listWit[indexwit].handDesc = {} + else + end + table.insert(listWit[indexwit].handDesc, + {xmlid = id, abbr = siglum, detailsDesc = description}) + end + return true +end + +function ekdosis.newshorthand(id, rend, xmlids) + if isintable(shorthands, id) + then + tex.print("\\unexpanded{\\PackageWarning{ekdosis}{\"" + ..id.. + "\" already exists as a shorthand. " + .. + "Please pick another shorthand.}}") + else + table.insert(shorthands, { a = id, b = rend, c = xmlids }) + table.sort(shorthands, function(a ,b) return(#a.a > #b.a) end) + table.insert(idsRend, {xmlid = id, abbr = rend}) + table.sort(idsRend, function(a ,b) return(#a.xmlid > #b.xmlid) end) + end + return true +end + +local xmlbibresource = nil + +function ekdosis.setxmlbibresource(str) + xmlbibresource = str..".xml" + return true +end + +function ekdosis.newscholar(id, siglum) + if xmlidfound(id) + then + tex.print("\\unexpanded{\\PackageWarning{ekdosis}{\"" + ..id.. + "\" already exists as a xml:id. " + .. + "Please pick another id.}}") + else + table.insert(xmlids, {xmlid = id}) + table.sort(xmlids, function(a ,b) return(#a.xmlid > #b.xmlid) end) + table.insert(idsRend, {xmlid = id, abbr = siglum}) + table.sort(idsRend, function(a ,b) return(#a.xmlid > #b.xmlid) end) + end + return true +end + +function ekdosis.getsiglum(str, opt) + str = str.."," + str = string.gsub(str, "%s-(%,)", "%1") + ctrl = str + if opt == "tei" then + for i = 1,#shorthands do + str = string.gsub(str, shorthands[i].a, shorthands[i].c) + end + for i = 1,#idsRend do + str = string.gsub(str, "(%f[%w])"..idsRend[i].xmlid.."(%,)", + "%1#"..idsRend[i].xmlid.."%2") + ctrl = string.gsub(ctrl, idsRend[i].xmlid.."%,", "") + end + str = string.gsub(str, "%,(%s-)([%#])", " %2") + str = string.gsub(str, "%,$", "") + else + for i = 1,#idsRend do + str = string.gsub(str, idsRend[i].xmlid.."%,", idsRend[i].abbr) + ctrl = string.gsub(ctrl, idsRend[i].xmlid.."%,", "") + end + end + -- if string.find(ctrl, "[A-Za-z0-9]") + if string.find(ctrl, "%S") + then + return "<??>" + else + return str + end +end + +-- begin totei functions + +local cmdtotags = { + {a="textsuperscript", b="hi", c=" rend=\"sup\""}, + {a="textsubscript", b="hi", c=" rend=\"sub\""}, + {a="LRfootnote", b="note", c=" place=\"bottom\""}, + {a="RLfootnote", b="note", c=" place=\"bottom\""}, + {a="enquote *", b="quote", c=""}, + {a="footnote", b="note", c=" place=\"bottom\""}, + {a="enquote", b="quote", c=""}, + {a="txtrans", b="s", c=" xml:lang=\"ar-Latn\" type=\"transliterated\""}, + {a="textbf", b="hi", c=" rend=\"bold\""}, + {a="textit", b="hi", c=" rend=\"italic\""}, + {a="textsc", b="hi", c=" rend=\"smallcaps\""}, + {a="textsf", b="hi", c=" rend=\"sf\""}, + {a="arbup", b="hi", c=" rend=\"sup\""}, + {a="txarb", b="s", c=" xml:lang=\"arb\""}, + {a="arb", b="foreign", + c=" xml:lang=\"ar-Latn\" type=\"transliterated\" subtype=\"arabtex\""} +} + +local texpatttotags = { + {a="\\icite%s?%[(.-)%]%[(.-)%]{(.-)}", b="%1 <ref target=\"#%3\">%2</ref>"}, + {a="\\icite%s?%[(.-)%]{(.-)}", b="<ref target=\"#%2\">%1</ref>"}, + {a="\\icite%s?{(.-)}", b="<ptr target=\"#%1\"/>"}, + {a="\\linelabel%s?{(.-)}", b="<anchor xml:id=\"%1\"/>"}, + {a="\\label%s?{(.-)}", b="<anchor xml:id=\"%1\"/>"}, + {a="\\v?pageref%s?{(.-)}", b="<ptr target=\"#%1\"/>"}, + {a="\\v?ref%s?{(.-)}", b="<ptr target=\"#%1\"/>"} +} + +local envtotags = { + {a="flushright", b="p", c=" rend=\"align(right)\""}, + {a="flushleft", b="p", c=" rend=\"align(left)\""}, + {a="quotation", b="quote", c=""}, + {a="ekdverse", b="lg", c=""}, + {a="txarabtr", b="p", c=" xml:lang=\"ar-Latn\" type=\"transliterated\""}, + {a="txarab", b="p", c=" xml:lang=\"arb\""}, + {a="center", b="p", c=" rend=\"align(center)\""}, + {a="verse", b="lg", c=""}, + {a="arab", b="p", + c=" xml:lang=\"ar-Latn\" type=\"transliterated\" subtype=\"arabtex\""} +} + +local close_p = { + "p", + "lg" +} + +local forbid_xmlid = true + +function ekdosis.newcmdtotag(cmd, tag, attr) + if forbid_xmlid + then + attr = string.gsub(attr, "xml:id", "n") -- xml:id is not allowed here + else + end + if isintable(cmdtotags, cmd) + then + local index = get_a_index(cmd, cmdtotags) + table.remove(cmdtotags, index) + table.insert(cmdtotags, {a = cmd, b = tag, c = " "..attr}) + table.sort(cmdtotags, function(a ,b) return(#a.a > #b.a) end) + else + table.insert(cmdtotags, {a = cmd, b = tag, c = " "..attr}) + table.sort(cmdtotags, function(a ,b) return(#a.a > #b.a) end) + end + return true +end + +function ekdosis.newpatttotag(pat, repl) + pat = string.gsub(pat, "([%[%]])", "%%%1") + pat = string.gsub(pat, "%#[1-9]", "(.-)") + repl = string.gsub(repl, "%#([1-9])", "%%%1") + table.insert(texpatttotags, { a = pat, b = repl }) + table.sort(texpatttotags, function(a ,b) return(#a.a > #b.a) end) + return true +end + +function ekdosis.newenvtotag(env, tag, attr, closep) + if forbid_xmlid + then + attr = string.gsub(attr, "xml:id", "n") -- xml:id is not allowed here + else + end + if isintable(envtotags, env) + then + local index = get_a_index(env, envtotags) + table.remove(envtotags, index) + table.insert(envtotags, {a = env, b = tag, c = " "..attr, d = closep}) + table.sort(envtotags, function(a ,b) return(#a.a > #b.a) end) + else + table.insert(envtotags, {a = env, b = tag, c = " "..attr, d = closep}) + table.sort(envtotags, function(a ,b) return(#a.a > #b.a) end) + end + return true +end + +-- Get values of attributes +local function get_attr_value(str, attr) + str = str.."," + local attrval = string.match(str, "%f[%w]"..attr.."%s?%=%s?%b{}") + or string.match(str, "%f[%w]"..attr.."%s?%=%s?.-%,") + or "" + attrval = string.gsub(attrval, attr.."%s?%=%s?(%b{})", function(bbraces) + bbraces = string.sub(bbraces, 2, -2) + return string.format("%s", bbraces) + end) + attrval = string.gsub(attrval, attr.."%s?%=%s?(.-)%s?%,", "%1") + return attrval +end + +local function xml_entities(str) + str = string.gsub(str, "%<", "<") + str = string.gsub(str, "%>", ">") + return str +end + +local function note_totei(str) + str = gsub(str, + dblbkslash * + note * + spcenc^-1 * + bsqbrackets * + bcbraces * + spcenc^-1, + function(bkslash, cmd, opt, arg) + opt = string.sub(opt, 2, -2) + arg = string.sub(arg, 2, -2) + teitype = get_attr_value(opt, "type") + if teitype ~= "" then teitype = " type=\""..teitype.."\"" else end + right = get_attr_value(opt, "labelb") + left = get_attr_value(opt, "labele") + if left ~= "" + then + return string.format( + "<%s%s target=\"#range(right(%s),left(%s))\">%s</%s><anchor xml:id=\"%s\"/>", + cmd, teitype, right, left, arg, cmd, right) + elseif left == "" + then + return string.format( + "<%s%s target=\"#right(%s)\">%s</%s><anchor xml:id=\"%s\"/>", + cmd, teitype, right, arg, cmd, right) + end + end) + return str +end + +local function app_totei(str) + str = gsub(str, + dblbkslash * + app * + spcenc^-1 * + bsqbrackets * + bcbraces * + spcenc^-1, + function(bkslash, cmd, opt, arg) + opt = string.sub(opt, 2, -2) + arg = string.sub(arg, 2, -2) + opt = get_attr_value(opt, "type") + if opt ~= "" then opt = " type=\""..opt.."\"" else end + return app_totei(string.format("<%s%s>%s</%s>", + cmd, opt, arg, cmd)) + end) + return str +end + +local function lem_rdg_totei(str) + str = gsub(str, + spcenc^-1 * + dblbkslash * + lemrdg * + spcenc^-1 * + bsqbrackets * + bcbraces * + spcenc^-1, + function(bkslash, cmd, opt, arg) + opt = string.sub(opt, 2, -2) + arg = string.sub(arg, 2, -2) + -- opt = get_attr_value(opt, "wit") + -- + teiwit = get_attr_value(opt, "wit") + if teiwit ~= "" then teiwit = " wit=\""..ekdosis.getsiglum(teiwit, "tei").."\"" else end + teitype = get_attr_value(opt, "type") + if teitype ~= "" then teitype = " type=\""..teitype.."\"" else end + -- + if opt == "" + then + return lem_rdg_totei(string.format("<%s>%s</%s>", + cmd, arg, cmd)) + else + -- opt = ekdosis.getsiglum(opt, "tei") + return lem_rdg_totei(string.format("<%s%s%s>%s</%s>", + cmd, teiwit, teitype, arg, cmd)) + end + end) + str = gsub(str, spcenc^-0 * dblbkslash * lemrdg * spcenc^-1 * bcbraces * spcenc^-1, + function(bkslash, cmd, arg) + arg = string.sub(arg, 2, -2) + return lem_rdg_totei(string.format("<%s>%s</%s>", cmd, arg, cmd)) + end) + return str +end + +local function relocate_notes(str) + str = string.gsub(str, "(%<lem.-%>.-)(%<note.->.-%<%/note%>)(.-%<%/lem%>)", "%1%3%2") + return str +end + +local function linestotei(str) +-- str = "\n<l>"..str + str = string.gsub(str, "^%s?(.-)%s?$", "\n<l>%1</l>\n") +-- str = gsub(str, endpoem, "</l>\n") + str = gsub(str, poemline * spcenc^-1 * lpeg.P(">"), "\n<lb/>") + str = gsub(str, poemline * spcenc^-1, "</l>\n<l>") +-- str = str.."</l>\n" + return str +end + +-- better use lpeg: look into this later +local function versetotei(str) + str = string.gsub(str, "(\\begin%s?%{ekdverse%})(%b[])(.-)(\\end%s?%{ekdverse%})", function(benv, opt, arg, eenv) + arg = linestotei(arg) + return string.format("%s%s%s%s", benv, opt, arg, eenv) + end) + str = string.gsub(str, "(\\begin%s?%{ekdverse%})(.-)(\\end%s?%{ekdverse%})", function(benv, arg, eenv) + arg = linestotei(arg) + return string.format("%s%s%s", benv, arg, eenv) + end) + str = string.gsub(str, "(\\begin%s?%{verse%})(%b[])(.-)(\\end%s?%{verse%})", function(benv, opt, arg, eenv) + arg = linestotei(arg) + return string.format("%s%s%s%s", benv, opt, arg, eenv) + end) + str = string.gsub(str, "(\\begin%s?%{verse%})(.-)(\\end%s?%{verse%})", function(benv, arg, eenv) + arg = linestotei(arg) + return string.format("%s%s%s", benv, arg, eenv) + end) + return str +end + +local function envtotei(str) + for i = 1,#envtotags + do + if envtotags[i].b ~= "" + then + if isfound(close_p, envtotags[i].b) or envtotags[i].d == "yes" + then + str = gsub(str, lpeg.P("\\begin") * spcenc^-1 * lpeg.P("{") + * lpeg.Cs(envtotags[i].a) * lpeg.P("}") + * bsqbracketsii * bcbracesii * spcenc^-1, + "\\p@rb <"..envtotags[i].b..envtotags[i].c..">") + str = gsub(str, spcenc^-1 * lpeg.P("\\end") * spcenc^-1 * lpeg.P("{") + * lpeg.Cs(envtotags[i].a) * lpeg.P("}"), + "</"..envtotags[i].b..">\\p@ra ") + else + str = gsub(str, lpeg.P("\\begin") * spcenc^-1 * lpeg.P("{") + * lpeg.Cs(envtotags[i].a) * lpeg.P("}") + * bsqbracketsii * bcbracesii * spcenc^-1, + "<"..envtotags[i].b..envtotags[i].c..">") + str = gsub(str, spcenc^-1 * lpeg.P("\\end") * spcenc^-1 * lpeg.P("{") + * lpeg.Cs(envtotags[i].a) * lpeg.P("}"), + "</"..envtotags[i].b..">") + end + else + str = gsub(str, lpeg.P("\\begin") * spcenc^-1 * lpeg.P("{") + * lpeg.Cs(envtotags[i].a) * lpeg.P("}") + * bsqbracketsii * bcbracesii * spcenc^-1, + "") + str = gsub(str, spcenc^-1 * lpeg.P("\\end") * spcenc^-1 * lpeg.P("{") + * lpeg.Cs(envtotags[i].a) * lpeg.P("}"), + "") + end + end + str = gsub(str, lpeg.P("\\begin") * spcenc^-1 * lpeg.P("{") + * lpeg.Cs(ascii^1) * lpeg.P("}") * bsqbracketsii + * bcbracesii * spcenc^-1, + "<%1>") + str = gsub(str, spcenc^-1 * lpeg.P("\\end") * spcenc^-1 * lpeg.P("{") + * lpeg.Cs(ascii^1) * lpeg.P("}") * bsqbracketsii + * bcbracesii, + "</%1>") + return str +end + +local function texpatttotei(str) + for i = 1,#texpatttotags do + str = string.gsub(str, texpatttotags[i].a, texpatttotags[i].b) + end + return str +end + +local function cmdtotei(str) + for i = 1,#cmdtotags + do + str = gsub(str, lpeg.P("\\") * lpeg.Cs(cmdtotags[i].a) * spcenc^-1 * bsqbrackets * -bcbraces, "\\%1%2{}") + str = gsub(str, lpeg.P("\\") * lpeg.Cs(cmdtotags[i].a) * spcenc^-1 * -(bsqbrackets + bcbraces), "\\%1[]{}") + str = string.gsub(str, "(\\"..cmdtotags[i].a..")%s?%*?(%b{})", "%1[]%2") + str = string.gsub(str, "(\\"..cmdtotags[i].a..")%s?%*?(%b[])(%b{})", + function(cmd, arg, body) + body = string.sub(body, 2, -2) + arg = string.sub(arg, 2, -2) + arg = string.gsub(arg, "(%b{})", function(braces) + braces = string.sub(braces, 2, -2) + return string.format("\"%s\"", braces) + end) + body = cmdtotei(body) + -- return string.format("<"..cmdtotags[i].b..cmdtotags[i].c.." %s>%s</"..cmdtotags[i].b..">", arg, body) + if cmdtotags[i].b ~= "" + then + return string.format("<"..cmdtotags[i].b..cmdtotags[i].c..">%s</" .. + cmdtotags[i].b..">", body) + else + return "" + end + end) + end + -- temporarily: + str = string.gsub(str, "\\(getsiglum)%s?(%b{})", + function(cmd, body) + body = string.sub(body, 2, -2) + teisiglum = ekdosis.getsiglum(body, "tei") + printsiglum = ekdosis.getsiglum(body) + -- body = cmdtotei(body) + return string.format("<ref target=\"%s\">%s</ref>", + teisiglum, printsiglum) + end) + str = string.gsub(str, "\\(%a+)%s?%*?(%b[])(%b{})", + function(cmd, opt, body) + body = string.sub(body, 2, -2) + body = cmdtotei(body) + return string.format("<%s>%s</%s>", cmd, body, cmd) + end) + str = string.gsub(str, "\\(%a+)%s?%*?(%b{})", + function(cmd, body) + body = string.sub(body, 2, -2) + body = cmdtotei(body) + return string.format("<%s>%s</%s>", cmd, body, cmd) + end) + str = string.gsub(str, "(%s)(%>)", "%2") + return str +end + +local function partotei(str) + str = gsub(str, lpeg.P(lpeg.P("\\par") * spcenc^1)^1, "\\par ") + str = gsub(str, ((para + parb) * par^-1)^2, "\\p@r ") + str = string.gsub(str, "\\p@ra%s+", "<p>") + str = string.gsub(str, "\\p@rb%s+", "</p>") + str = string.gsub(str, "\\p@r%s+", "") + str = string.gsub(str, "%s?\\par%s?", "<p>", 1) + str = string.gsub(str, "(%<p%>)(%s-)(%<%/?div%d?)", "%3") + str = string.gsub(str, "%s?\\par%s?", "</p><p>") + str = string.gsub(str, "<p>%s?</p>", "") + str = string.gsub(str, "(%<p%>)%s?(%</div%>)$", "%2") + str = string.gsub(str, "(%<p%>)%s?$", "") + str = string.gsub(str, "(<p>)%s?(<div.->)", "%2%1") + return str +end + +local function self_close_tags(str) + str = gsub(str, lpeg.P("<" * -lpeg.S("/")) + * lpeg.Cs(letters^1) + * lpeg.Cs((1 - lpeg.S"<>")^0) + * lpeg.P(">") + * lpeg.P("</") + * lpeg.Cs(letters^1) + * lpeg.P(">"), function(ftag, arg, ltag) + if ftag == ltag + then + return string.format("<%s%s/>", ftag, arg) + else + end + end) + return str +end + +local divdepth = { + book = 1, + part = 2, + chapter = 3, + section = 4, + subsection = 5, + subsubsection = 6 +} + +function ekdosis.mkdivdepths(...) + divdepth = {} + local num = 1 + for _, y in ipairs{...} + do + if y == "book" or "part" or "chapter" + or "section" or "subsection" or "subsubsection" + then + divdepth[y] = num + num = num + 1 + else + end + end + return true +end + +-- LaTeX side: format the divisions +local fmtdiv = {} + +function ekdosis.fmtdiv(n, fmtb, fmte) + if isintable(fmtdiv, n) + then + local index = get_a_index(n, fmtdiv) + table.remove(fmtdiv, index) + else + end + table.insert(fmtdiv, { a = n, formatb = fmtb, formate = fmte} ) + return true +end + +function ekdosis.getfmtdiv(n, pos) + local index = get_a_index(n, fmtdiv) + if index ~= nil + then + if pos == "b" + then + return fmtdiv[index].formatb + elseif pos == "e" + then + return fmtdiv[index].formate + end + else + return "" + end +end + +local ekddivs = true + +function ekdosis.setekddivsfalse() + ekddivs = false +end + +local function ekddivs_totei(str) + str = gsub(str, dblbkslash * lpeg.Cs("ekddiv") * spce^-1 * bcbraces, + function(bkslash, cmd, space, arg) + if ekddivs + then + arg = string.sub(arg, 2, -2) + teitype = get_attr_value(arg, "type") + tein = get_attr_value(arg, "n") + teihead = get_attr_value(arg, "head") + teidepth = get_attr_value(arg, "depth") + if teitype ~= "" then teitype = " type=\""..teitype.."\"" else end + if tein ~= "" then tein = " n=\""..tein.."\"" else end + if teidepth ~= "" + then + teidepth = " depth=\""..teidepth.."\"" + else + teidepth = " depth=\"1\"" + end + return string.format("\\p@rb <div%s%s%s><head>%s</head>\\p@ra ", + teitype, tein, teidepth, teihead) + else + return "" + end + end) + return str +end + +local function section_totei(str) + str = gsub(str, dblbkslash * sections * spce^-1 * bcbraces, "%1%2%3[]%4") + str = gsub(str, dblbkslash * sections * spce^-1 * bsqbrackets * bcbraces, + function(bkslash, secname, space, opt, arg) + if ekddivs + then + return "" + else + ctr = divdepth[secname] + arg = string.sub(arg, 2, -2) + return string.format("\\p@rb <div%s type=\"%s\"><head>%s</head>\\p@ra ", + ctr, secname, arg) + end + end) + return str +end + +local used_ndivs = {} + +local function close_ekddivs_at_end(str) + local isdiv = false + if string.find(str, "</div>$") + then + isdiv = true + str = string.gsub(str, "(.*)(</div>)$", "%1") + else + end + -- collect used depth numbers + for i in string.gmatch(str, "<div .-depth%=\"%d\".->") + do + i = string.match(i, "depth=\"%d\"") + i = string.match(i, "%d") + if isintable(used_ndivs, i) + then + else + table.insert(used_ndivs, {a = i} ) + end + end + if next(used_ndivs) ~= nil + then + table.sort(used_ndivs, function(a ,b) return(#a.a > #b.a) end) + else + end + local firstdiv = string.match(str, "<div .-depth%=\"%d\".->") or "" + firstdiv = string.match(firstdiv, "depth%=\"%d\"") or "" + firstdiv = string.match(firstdiv, "%d") or "" + local lastdiv = string.match(string.reverse(str), ">.-\"%d\"%=htped.- vid<") or "" + lastdiv = string.match(lastdiv, "\"%d\"%=htped") or "" + lastdiv = string.match(lastdiv, "%d") or "" + local firstdivindex = get_a_index(firstdiv, used_ndivs) + local lastdivindex = get_a_index(lastdiv, used_ndivs) + firstdivindex = tonumber(firstdivindex) + lastdivindex = tonumber(lastdivindex) + local closedivs = "" + if isintable(used_ndivs, firstdiv) + then + while lastdivindex >= firstdivindex + do + closedivs = closedivs.."</div>" + lastdivindex = lastdivindex - 1 + end + end + if isdiv + then + return str..closedivs.."</div>" + else + return str..closedivs + end +end + +local function close_ndivs_at_end(str) + local isdiv = false + if string.find(str, "</div>$") + then + isdiv = true + str = string.gsub(str, "(.*)(</div>)$", "%1") + else + end + -- collect used div numbers + for i in string.gmatch(str, "<div[1-6]") + do + i = string.match(i, "[1-6]") + if isintable(used_ndivs, i) + then + else + table.insert(used_ndivs, {a = i} ) + end + end + if next(used_ndivs) ~= nil + then + table.sort(used_ndivs, function(a ,b) return(#a.a > #b.a) end) + else + end + local firstdiv = string.match(str, "<div[1-6]") or "" + firstdiv = string.match(firstdiv, "[1-6]") or "" + local lastdiv = string.match(string.reverse(str), "[1-6]vid<") or "" + lastdiv = string.match(lastdiv, "[1-6]") or "" + local firstdivindex = get_a_index(firstdiv, used_ndivs) + local lastdivindex = get_a_index(lastdiv, used_ndivs) + firstdivindex = tonumber(firstdivindex) + lastdivindex = tonumber(lastdivindex) + local closedivs = "" + if isintable(used_ndivs, firstdiv) + then + while lastdivindex >= firstdivindex + do + closedivs = closedivs.."</div"..used_ndivs[lastdivindex].a..">" + lastdivindex = lastdivindex - 1 + end + end + if isdiv + then + return str..closedivs.."</div>" + else + return str..closedivs + end +end + +local function close_ekddivs_in_between(str) + local maxdepth = 1 + for i in string.gmatch(str, "<div.-depth=\"(%d)\".->", "%1") + do + if tonumber(i) > tonumber(maxdepth) + then + maxdepth = i + else + end + end + for ndivi = 1, maxdepth + do + str = string.gsub(str, "(<div .-depth%=\")("..ndivi..")(\".->)(.-)(<div .-depth%=\")(%d)(\".->)", + function(bdivi, ndivi, edivi, between, bdivii, ndivii, edivii) + local firstdiv = ndivi + local lastdiv = ndivii + local firstdivindex = get_a_index(firstdiv, used_ndivs) + local lastdivindex = get_a_index(lastdiv, used_ndivs) + firstdivindex = tonumber(firstdivindex) + lastdivindex = tonumber(lastdivindex) + local closedivs = "" + if firstdivindex >= lastdivindex + then + while firstdivindex >= lastdivindex + do + closedivs = closedivs.."</div>" + firstdivindex = firstdivindex - 1 + end + end + return string.format("%s%s%s%s%s%s%s%s", + bdivi, ndivi, edivi, between, closedivs, bdivii, ndivii, edivii) + end) + end + str = string.gsub(str, "(<div.-)(%sdepth%=\"%d\")(.->)", "%1%3") + used_ndivs = {} + return str +end + +local function close_ndivs_in_between(str) + for ndivi = 1, 6 + do + str = string.gsub(str, "(<div)("..ndivi..")(.->)(.-)(<div)([1-6])(.->)", + function(bdivi, ndivi, edivi, between, bdivii, ndivii, edivii) + local firstdiv = ndivi + local lastdiv = ndivii + local firstdivindex = get_a_index(firstdiv, used_ndivs) + local lastdivindex = get_a_index(lastdiv, used_ndivs) + firstdivindex = tonumber(firstdivindex) + lastdivindex = tonumber(lastdivindex) + local closedivs = "" + if firstdivindex >= lastdivindex + then + while firstdivindex >= lastdivindex + do + closedivs = closedivs.."</div"..used_ndivs[firstdivindex].a..">" + firstdivindex = firstdivindex - 1 + end + end + return string.format("%s%s%s%s%s%s%s%s", + bdivi, ndivi, edivi, between, closedivs, bdivii, ndivii, edivii) + + end) + end + used_ndivs = {} + return str +end + +local function textotei(str) + str = xml_entities(str) + str = texpatttotei(str) + str = note_totei(str) + str = app_totei(str) + str = lem_rdg_totei(str) + str = relocate_notes(str) + str = versetotei(str) + str = envtotei(str) + str = ekddivs_totei(str) + str = section_totei(str) + str = cmdtotei(str) + str = self_close_tags(str) + str = partotei(str) + if ekddivs + then + str = close_ekddivs_at_end(str) + str = close_ekddivs_in_between(str) + else + str = close_ndivs_at_end(str) + str = close_ndivs_in_between(str) + end + return str +end + +local teifilename = tex.jobname.."-tei" + +function ekdosis.setteifilename(str) + teifilename = str + return true +end + +function ekdosis.openteistream() + local f = io.open(teifilename.."_tmp.xml", "a+") + f:write('<?xml version="1.0" encoding="utf-8"?>', "\n") + f:write("<TEI xmlns=\"http://www.tei-c.org/ns/1.0\">", "\n") + f:write("<teiHeader>", "\n") + f:write("<fileDesc>", "\n") + f:write("<titleStmt>", "\n") + f:write("<title><!-- Title --></title>", "\n") + f:write("<respStmt>", "\n") + f:write("<resp><!-- Edited by --></resp>", "\n") + f:write("<name><!-- Name --></name>", "\n") + f:write("</respStmt>", "\n") + f:write("</titleStmt>", "\n") + f:write("<publicationStmt>", "\n") + f:write("<distributor><!-- Distributor name --></distributor>", "\n") + f:write("</publicationStmt>", "\n") + f:write("<sourceDesc>", "\n") + f:write("<listWit>", "\n") + for i = 1,#listWit do + f:write('<witness xml:id=\"', listWit[i].xmlid, "\">", "\n") + f:write('<abbr type="siglum">', textotei(listWit[i].abbr), "</abbr>", "\n") + f:write(textotei(listWit[i].detailsDesc), "\n") + f:write("<msDesc>", "\n") + if listWit[i].msIdentifier.settlement == "" + and listWit[i].msIdentifier.institution == "" + and listWit[i].msIdentifier.repository == "" + and listWit[i].msIdentifier.collection == "" + and listWit[i].msIdentifier.idno == "" + and listWit[i].msIdentifier.msName == "" + then + f:write("<msIdentifier/>", "\n") + else + f:write("<msIdentifier>", "\n") + if listWit[i].msIdentifier.settlement ~= "" then + f:write("<settlement>", textotei(listWit[i].msIdentifier.settlement), "</settlement>", "\n") + else end + if listWit[i].msIdentifier.institution ~= "" then + f:write("<institution>", textotei(listWit[i].msIdentifier.institution), "</institution>", "\n") + else end + if listWit[i].msIdentifier.repository ~= "" then + f:write("<repository>", textotei(listWit[i].msIdentifier.repository), "</repository>", "\n") + else end + if listWit[i].msIdentifier.collection ~= "" then + f:write("<collection>", textotei(listWit[i].msIdentifier.collection), "</collection>", "\n") + else end + if listWit[i].msIdentifier.idno ~= "" then + f:write("<idno>", textotei(listWit[i].msIdentifier.idno), "</idno>", "\n") + else end + if listWit[i].msIdentifier.msName ~= "" then + f:write("<msName>", textotei(listWit[i].msIdentifier.msName), "</msName>", "\n") + else end + f:write("</msIdentifier>", "\n") + end + if listWit[i].handDesc ~= nil then + f:write("<physDesc>", "\n") + f:write("<handDesc hands=\"", #listWit[i].handDesc, "\">", "\n") + local j = 1 + while listWit[i].handDesc[j] + do + f:write("<handNote xml:id=\"", listWit[i].handDesc[j].xmlid, "\">", "\n") + f:write('<abbr type="siglum">', textotei(listWit[i].handDesc[j].abbr), "</abbr>", "\n") + f:write("<p>", textotei(listWit[i].handDesc[j].detailsDesc), "</p>", "\n") + f:write("</handNote>", "\n") + j = j + 1 + end + f:write("</handDesc>", "\n") + f:write("</physDesc>", "\n") + else end + if listWit[i].history ~= nil then + f:write("<history>", "\n") + f:write("<origin>", "\n") + f:write("<origDate>", textotei(listWit[i].history.origin.origDate), "</origDate>", "\n") + f:write("</origin>", "\n") + f:write("</history>", "\n") + end + f:write("</msDesc>", "\n") + f:write("</witness>", "\n") + end + f:write("</listWit>", "\n") + f:write("</sourceDesc>", "\n") + f:write("</fileDesc>", "\n") + f:write("<encodingDesc>", "\n") + f:write('<variantEncoding method="parallel-segmentation" location="internal"/>', "\n") + f:write("</encodingDesc>", "\n") + f:write("</teiHeader>", "\n") + f:write("<text>", "\n") + f:write("<body>", "\n") + f:close() + return true +end + +local tidy = nil + +local function cleanup_tei() + local f = assert(io.open(teifilename.."_tmp.xml", "r")) + t = f:read("*a") + t = string.gsub(t, "%<p%>%s?%</p%>", "") + t = string.gsub(t, "^\n", "") + f:close() + local fw = assert(io.open(teifilename.."_tmp.xml", "w")) + fw:write(t) + fw:close() + return true +end + +function ekdosis.closeteistream(opt) + local f = io.open(teifilename.."_tmp.xml", "a+") + f:write("\n", "</body>", "\n") + if xmlbibresource ~= nil then + bibf = assert(io.open(xmlbibresource, "r")) + t = bibf:read("*a") + t = string.gsub(t, "%s+corresp%=%b\"\"", "") + t = string.gsub(t, "\n\n", "\n") + f:write("<back>", "\n") + f:write("<listBibl>", "\n") + for i in string.gmatch(t, "<biblStruct.->.-</biblStruct>") + do + f:write(i, "\n") + end + f:write("</listBibl>", "\n") + f:write("</back>", "\n") + bibf:close() + else + end + f:write("</text>", "\n") + f:write("</TEI>", "\n") + f:close() + cleanup_tei() + os.remove(teifilename..".xml") + os.rename(teifilename.."_tmp.xml", teifilename..".xml") + if opt == "tidy" then + os.execute("tidy -qmi -xml --output-xml yes "..teifilename..".xml") + else + end + return true +end + +function ekdosis.exporttei(str) + local f = io.open(teifilename.."_tmp.xml", "a+") + -- f:write("\n<p>") + str = textotei(str) + f:write(str) + f:close() + return true +end +-- end totei functions + +-- begin basic TeX Conspectus siglorum +function ekdosis.basic_cs(msid) + local indexwit = getindex(msid, listWit) + siglum = listWit[indexwit].abbr + -- if listWit[indexwit].detailsDesc == "" + -- then + -- name = listWit[indexwit].msIdentifier.msName + -- else + -- name = listWit[indexwit].msIdentifier.msName + -- .."\\thinspace\\newline\\bgroup\\footnotesize{}".. + -- listWit[indexwit].detailsDesc + -- .."\\egroup{}" + -- end + name = listWit[indexwit].detailsDesc + if listWit[indexwit].history ~= nil + and + listWit[indexwit].history.origin ~= nil + then + date = listWit[indexwit].history.origin.origDate + else + date = "" + end + return siglum.."&"..name.."&"..date +end +-- end basic TeX Conspectus siglorum + +function ekdosis.removesp(str) + str = gsub(str, cmd * cmdargs * spcenc^-1, "%1%2") + return str +end + +function ekdosis.closestream() + os.remove(tex.jobname..".ekd") + os.rename(tex.jobname.."_tmp.ekd", tex.jobname..".ekd") + return true +end + +local cur_abs_pg = 0 +local pg_i = nil +local pg_ii = nil +local prevcol = nil +local curcol = "x" + +local check_resetlineno = {} + +function ekdosis.update_abspg(n) -- not used + cur_abs_pg = n + return true +end + +function ekdosis.storeabspg(n, pg) + if pg == "pg_i" then + pg_i = n + elseif pg == "pg_ii" then + pg_ii = n + table.insert(check_resetlineno, curcol.."-"..pg_ii) + end + cur_abs_pg = n + return true +end + +function ekdosis.checkresetlineno() + if isfound(check_resetlineno, curcol.."-"..pg_i) + then + return "" + else + return "\\resetlinenumber" + end +end + +-- +-- Build environments to be aligned +-- + +local cur_alignment = "-" +local cur_alignment_patt = "%-" +local cur_alignment_cnt = 1 + +local newalignment = false +function ekdosis.newalignment(str) + if str == "set" + then + newalignment = true + cur_alignment = "-"..cur_alignment_cnt.."-" + cur_alignment_patt = "%-"..cur_alignment_cnt.."%-" + cur_alignment_cnt = cur_alignment_cnt + 1 + elseif str == "reset" + then + newalignment = false + cur_alignment = "-" + cur_alignment_patt = "-" + end + return true +end + +local aligned_texts = {} +local texts_w_apparatus = {} +local coldata_totei = {} + +local function sanitize_envdata(str) -- look for a better way to achieve this + str = string.gsub(str, "(%a+)%s+(%b[])", "%1%2") + str = string.gsub(str, "(%a+)(%b[])%s+", "%1%2") + str = string.gsub(str, "%s+(%a+)(%b[])", "%1%2") + str = gsub(str, lpeg.Cs(letters^1) + * spcenc^-1 + * -bsqbrackets + * lpeg.Cs(";"), "%1[]%2") + str = string.gsub(str, "%s+(%a+)(%b[])", "%1%2") + return str +end + +function ekdosis.mkenvdata(str, opt) + if not string.find(str, "%;", -1) then str = str .. ";" else end + -- str = str ..";" + -- str = string.gsub(str, "%s+", "") + local fieldstart = 1 + local col = 0 + if opt == "texts" then + str = sanitize_envdata(str) + repeat + local _s, nexti = string.find(str, "%b[]%s-%;", fieldstart) + local namediv = string.gsub(string.sub(str, fieldstart, nexti-1), "(%a+)%s-(%b[])", "%1") + local attr = string.gsub(string.sub(str, fieldstart, nexti-1), "(%a+)%s-(%b[])", "%2") + attr = string.sub(attr, 2, -2) + if forbid_xmlid + then + attr = string.gsub(attr, "xml:id", "n") -- xml:id is not allowed here + else + end + table.insert(aligned_texts, { text = namediv, + attribute = attr, + column = col }) + table.insert(coldata_totei, { environment = namediv, + data = {} }) + col = col + 1 + fieldstart = nexti + 1 + until fieldstart > string.len(str) + return aligned_texts + elseif opt == "apparatus" then + repeat + local nexti = string.find(str, "%;", fieldstart) + table.insert(texts_w_apparatus, string.sub(str, fieldstart, nexti-1)) + fieldstart = nexti +1 + until fieldstart > string.len(str) + return texts_w_apparatus + end +end + +-- Reminder: the following two variables are already set above +-- local prevcol = nil +-- local curcol = "x" + +function ekdosis.storecurcol(n) + curcol = n + return true +end + +function ekdosis.flushcolnums() + prevcol = nil + curcol = "x" + return true +end + +function ekdosis.flushenvdata() + aligned_texts = {} + texts_w_apparatus = {} + coldata_totei = {} + return true +end + +function ekdosis.storecoldata(nthcol, chunk) + local tindex = tonumber(nthcol) + 1 + table.insert(coldata_totei[tindex].data, chunk) + return true +end + +local environment_div = {} + +function ekdosis.newscholar(id, siglum) + if xmlidfound(id) + then + tex.print("\\unexpanded{\\PackageWarning{ekdosis}{\"" + ..id.. + "\" already exists as a xml:id. " + .. + "Please pick another id.}}") + else + table.insert(xmlids, {xmlid = id}) + table.sort(xmlids, function(a ,b) return(#a.xmlid > #b.xmlid) end) + table.insert(idsRend, {xmlid = id, abbr = siglum}) + table.sort(idsRend, function(a ,b) return(#a.xmlid > #b.xmlid) end) + end + return true +end + +local function build_envdiv(str) + if not environment_div[str] + then + environment_div[str] = 1 + else + environment_div[str] = environment_div[str] + 1 + end + local div = "div-"..str.."_"..environment_div[str] + if xmlidfound(div) + then + tex.print("\\unexpanded{\\PackageWarning{ekdosis}{\"" + ..div.. + "\" already exists as a xml:id. " + .. + "ekdosis has generated some random id.}}") + return "div-"..math.random(1000,9999) + else + table.insert(xmlids, {xmlid = div}) + table.sort(xmlids, function(a ,b) return(#a.xmlid > #b.xmlid) end) + return div + end +end + +function ekdosis.mkenv() + local environments = {} + for i = 1,#aligned_texts + do + if isfound(texts_w_apparatus, aligned_texts[i].text) + then + table.insert(environments, "\\NewDocumentEnvironment{".. aligned_texts[i].text.."}{+b}" + .."{\\begin{nthcolumn}{".. aligned_texts[i].column.."}" + .."\\par" + .."\\EkdosisColStart" + .."\\EkdosisOn#1" + .."}{\\EkdosisOff" + .."\\EkdosisColStop" + .."\\end{nthcolumn}" + .."\\csname iftei@export\\endcsname\\luadirect{ekdosis.storecoldata(" + .. aligned_texts[i].column + ..", \\luastringN{\\par#1\\par})}\\fi" + .."}") + table.insert(environments, "\\NewDocumentEnvironment{".. aligned_texts[i].text.."*}{+b}" + .."{\\begin{nthcolumn*}{".. aligned_texts[i].column.."}[]" + .."\\par" + .."\\EkdosisColStart" + .."\\EkdosisOn#1" + .."}{\\EkdosisOff" + .."\\EkdosisColStop" + .."\\end{nthcolumn*}" + .."\\csname iftei@export\\endcsname\\luadirect{ekdosis.storecoldata(" + .. aligned_texts[i].column + ..", \\luastringN{\\par#1\\par})}\\fi" + .."}") + else + table.insert(environments, "\\NewDocumentEnvironment{".. aligned_texts[i].text.."}{+b}" + .."{\\begin{nthcolumn}{".. aligned_texts[i].column.."}" + .."\\par" + .."#1" + .."}{\\end{nthcolumn}" + .."\\csname iftei@export\\endcsname\\luadirect{ekdosis.storecoldata(" + .. aligned_texts[i].column + ..", \\luastringN{\\par#1\\par})}\\fi" + .."}") + table.insert(environments, "\\NewDocumentEnvironment{".. aligned_texts[i].text.."*}{+b}" + .."{\\begin{nthcolumn*}{"..aligned_texts[i].column.."}[]" + .."\\par" + .."#1" + .."}{" + .."\\end{nthcolumn*}" + .."\\csname iftei@export\\endcsname\\luadirect{ekdosis.storecoldata(" + .. aligned_texts[i].column + ..", \\luastringN{\\par#1\\par})}\\fi" + .."}") + end + forbid_xmlid = false + if aligned_texts[i].attribute ~= "" + then + ekdosis.newenvtotag(aligned_texts[i].text, "div", + "xml:id=\"" + ..build_envdiv(aligned_texts[i].text) + .."\" " + ..aligned_texts[i].attribute) + else + ekdosis.newenvtotag(aligned_texts[i].text, "div", + "xml:id=\"" + ..build_envdiv(aligned_texts[i].text) + .."\"") + end + forbid_xmlid = true + end + str = table.concat(environments) + return str +end + +function ekdosis.export_coldata_totei() + for i = 1,#coldata_totei + do + ekdosis.exporttei("\\begin{".. coldata_totei[i].environment .."}" + .. table.concat(coldata_totei[i].data) + .. "\\end{".. coldata_totei[i].environment .."}") + end +end + +-- handle multiple layers in apparatuses +-- +local apparatuses = {} +local bagunits = {} + +function ekdosis.newapparatus(teitype, + appdir, + apprule, + appdelim, + appsep, + appbhook, + appehook) + if isintable(apparatuses, teitype) + then + tex.print("\\unexpanded{\\PackageWarning{ekdosis}{\"" + ..teitype.. + "\" already exists.}}") + else + table.insert(apparatuses, {a = teitype, + direction = appdir, + rule = apprule, + delim = appdelim, + sep = appsep, + bhook = appbhook, + ehook = appehook}) + end + bagunits[teitype] = 1 + return true +end + +function ekdosis.getappdelim(str) + for i = 1,#apparatuses + do + if apparatuses[i].a == str then + delimfound = apparatuses[i].delim + break + end + end + return delimfound +end + +function ekdosis.get_bagunits(teitype) + return bagunits[teitype] +end + +function ekdosis.increment_bagunits(teitype) + bagunits[teitype] = (bagunits[teitype] or 0) + 1 +end + +local function reset_bagunits() + for i = 1,#apparatuses + do + bagunits[apparatuses[i].a] = 1 + end +end + +function ekdosis.appin(str, teitype) + local f = io.open(tex.jobname.."_tmp.ekd", "a+") + if next(apparatuses) == nil + then + f:write("<", cur_abs_pg, cur_alignment, curcol, "-0>", str, "</", + cur_abs_pg, cur_alignment, curcol, "-0>\n") + else + for i = 1,#apparatuses + do + if apparatuses[i].a == teitype then + appno = i + break + end + end + f:write("<", cur_abs_pg, cur_alignment, curcol, "-", + appno, ">", str, "</", cur_abs_pg, cur_alignment, curcol, "-", appno, ">\n") + end + f:close() + return true +end + +function ekdosis.appout() + local file = io.open(tex.jobname..".ekd", "r") + if file ~= nil then io.close(file) + f = assert(io.open(tex.jobname..".ekd", "r")) + t = f:read("*a") + local output = {} + if next(apparatuses) == nil then + -- table.insert(output, "BEGIN") + table.insert(output, "\\noindent\\csname ekd@default@rule\\endcsname\\NLS{}") +-- table.insert(output, "\\noindent ") + for i in string.gmatch(t, + "<"..cur_abs_pg + ..cur_alignment_patt + ..curcol.."%-0>.-</" + ..cur_abs_pg + ..cur_alignment_patt + ..curcol.."%-0>") + do + table.insert(output, i) + end + -- table.insert(output, "END") + else + local n = 1 + while apparatuses[n] + do + if string.match(t, "<"..cur_abs_pg.. + cur_alignment_patt + ..curcol.."%-"..n..">.-</" + ..cur_abs_pg + ..cur_alignment_patt + ..curcol.."%-"..n..">") + then + -- table.insert(output, "BEGIN") + table.insert(output, "\\bgroup{}") + if apparatuses[n].direction == "LR" + then + table.insert(output, "\\pardir TLT\\textdir TLT{}") + elseif apparatuses[n].direction == "RL" + then + table.insert(output, "\\pardir TRT\\textdir TRT{}") + end + if apparatuses[n].rule == "none" + then + if n > 1 + then + table.insert(output, "\\NLS{}") + else + table.insert(output, "\\noindent ") + end + elseif apparatuses[n].rule ~= "" + then + if n > 1 + then + table.insert(output, "\\NLS{}" .. apparatuses[n].rule .. "\\NLS{}") + else +-- table.insert(output, "\\noindent ") + table.insert(output, apparatuses[n].rule .. "\\NLS{}") + end + else + if n > 1 + then + table.insert(output, "\\NLS\\csname ekd@default@rule\\endcsname\\NLS{}") + else +-- table.insert(output, "\\noindent ") + table.insert(output, "\\csname ekd@default@rule\\endcsname\\NLS{}") + end + end + if apparatuses[n].sep ~= "" + then + table.insert(output, "\\edef\\ekdsep{" .. apparatuses[n].sep .. "}") + else + end + if apparatuses[n].bhook ~= "" + then + table.insert(output, apparatuses[n].bhook) + else + table.insert(output, "\\relax") + end + for i in string.gmatch(t, + "<"..cur_abs_pg + ..cur_alignment_patt + ..curcol.."%-"..n..">.-</" + ..cur_abs_pg + ..cur_alignment_patt + ..curcol.."%-"..n..">") + do + table.insert(output, i) + end + if apparatuses[n].ehook ~= "" + then + table.insert(output, apparatuses[n].ehook) + else + end + table.insert(output, "\\egroup{}") + -- table.insert(output, "END") + end + n = n + 1 + end + end + f:close() + str = table.concat(output) + str = string.gsub(str, "</"..cur_abs_pg..cur_alignment_patt..curcol.."%-[0-9]>", "") + str = string.gsub(str, "<"..cur_abs_pg..cur_alignment_patt..curcol.."%-[0-9]>", " ") + return str + else + end +end + +function ekdosis.appin_out(str, nl) + local f = io.open(tex.jobname.."_tmp.ekd", "a+") + if nl == "yes" then + f:write(str, "\n") + else + f:write(str) + end + f:close() + return true +end + +local curcol_curabspg = {} + +function ekdosis.testapparatus() + if isfound(curcol_curabspg, curcol.."-"..cur_abs_pg) + then + if newalignment + then + if next(apparatuses) ~= nil then + reset_bagunits() + end + newalignment = false + return "\\booltrue{do@app}" + else + return "\\boolfalse{do@app}" + end + else + table.insert(curcol_curabspg, curcol.."-"..cur_abs_pg) + if next(apparatuses) ~= nil then + reset_bagunits() + end + return "\\booltrue{do@app}" + end +end + +local lnlabs = {} +local lnlab_salt = 0 +local current_lnlab = nil +local prev_lnlab = nil +local current_notelab = nil +local prev_notelab = nil +local current_lemma = nil +local salt = 0 + +local function mdvisintable(table, value) + for _, v in pairs(table) do + if v == value then return true end + end + return false +end + +function ekdosis.dolnlab(str) + prev_lnlab = current_lnlab + current_lemma = str + i = md5.sumhexa(str) + if not mdvisintable(lnlabs, i) then + table.insert(lnlabs, i) + else + i = i..salt + table.insert(lnlabs, i) + salt = salt + 1 + end + current_lnlab = i + return true +end + +function ekdosis.getlnlab() + return current_lnlab +end + +function ekdosis.getprevlnlab() + return prev_lnlab +end + +function ekdosis.setnotelab(str) + current_notelab = str + return "\\linelabel{" .. current_notelab .. "}" +end + +function ekdosis.getnotelab() + return current_notelab +end + +function ekdosis.setprevnotelab(str) + prev_notelab = str + return true +end + +function ekdosis.getprevnotelab() + return prev_notelab +end + +local function remove_note(str) + str = gsub(str, dblbkslash * lpeg.P("note") * cmdargs, "") + return str +end + +function ekdosis.mdvappend(str, teitype) + if teitype == nil + then + return "\\linelabel{" .. current_lnlab .. "-b}\\wordboundary{}" + .. + current_lemma + .. + "\\linelabel{" .. current_lnlab .. "-e}" + .. + "\\csname append@app\\endcsname{" + .. remove_note(str) .. "}" + else + return "\\linelabel{" .. current_lnlab .. "-b}\\wordboundary{}" + .. + current_lemma + .. + "\\linelabel{" .. current_lnlab .. "-e}" + .. + "\\csname append@app\\endcsname" .. "[" .. teitype .. "]{" + .. remove_note(str) .. "}" + end +end + diff --git a/Master/texmf-dist/tex/lualatex/ekdosis/ekdosis.sty b/Master/texmf-dist/tex/lualatex/ekdosis/ekdosis.sty new file mode 100644 index 00000000000..ae7abb0f8dc --- /dev/null +++ b/Master/texmf-dist/tex/lualatex/ekdosis/ekdosis.sty @@ -0,0 +1,959 @@ +%% +%% This is file `ekdosis.sty', +%% generated with the docstrip utility. +%% +%% The original source files were: +%% +%% ekdosis.dtx (with options: `package') +%% -------:| ----------------------------------------------------------------- +%% ekdosis:| Typesetting TEI xml compliant critical editions +%% Author:| Robert Alessi +%% E-mail:| alessi@robertalessi.net +%% License:| Released under the GNU General Public License v3 or later +%% See:| http://www.gnu.org/licenses/ +%% +%% This file is part of the `ekdosis' package +%% +%% ekdosis -- Typesetting TEI xml compliant critical editions +%% Copyright (C) 2020 Robert Alessi +%% +%% Please send error reports and suggestions for improvements to Robert +%% Alessi <alessi@robertalessi.net> +%% +%% 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 +%% <http://www.gnu.org/licenses/>. +%% +%% This work consists of the files ekdosis.dtx, ekdosis.el, this file and +%% a Makefile. +%% Running "make" generates the derived files README, ekdosis.pdf and +%% ekdosis.sty. +%% Running "make inst" installs the files in the user's TeX tree. +\NeedsTeXFormat{LaTeX2e}[1999/12/01] +\ProvidesPackage{ekdosis} + [2020/07/08 v0.99a Typesetting TEI xml compliant critical editions] +\RequirePackage{iftex} +\RequireLuaTeX +\RequirePackage{expkv-opt} +\RequirePackage{expkv-def} +\newif\if@pkg@float +\newif\if@pkg@footins +\newif\if@pkg@ekddivs +\newif\if@parnotesroman +\newif\if@pkg@parnotes +\newif\iftei@export +\ekvdefinekeys{ekdosis}{ + choice layout = {float = {\@pkg@floattrue}, + footins = {\@pkg@footinstrue}}, + initial layout = float, + unknown-choice layout = \PackageError{ekdosis}{unknown + layout=#1}{`layout' must be either `float' or `footins'.}, + choice divs = {ekdosis = {\@pkg@ekddivstrue}, + latex = {\@pkg@ekddivsfalse + \AtBeginDocument{\luadirect{ekdosis.setekddivsfalse()}}}}, + initial divs = ekdosis, + unknown-choice divs = \PackageError{ekdosis}{unknown divs=#1}{`divs' + must be either `ekdosis' or `latex'.}, + choice parnotes = {false = {}, + true = {\@pkg@parnotestrue}, + roman = {\@pkg@parnotestrue\@parnotesromantrue}}, + default parnotes = true, + unknown-choice parnotes = \PackageError{ekdosis}{unknown + parnotes=#1}{`parnotes' must be either `true', or `false' or + `roman'.}, + choice teiexport = {false = {}, + true = {\tei@exporttrue + \AtBeginDocument{\luadirect{ekdosis.openteistream()}}% + \AtEndDocument{\luadirect{ekdosis.closeteistream()}}}, + tidy = {\tei@exporttrue + \AtBeginDocument{\luadirect{ekdosis.openteistream()}}% + \AtEndDocument{\luadirect{ekdosis.closeteistream("tidy")}}}}, + default teiexport = true, + unknown-choice teiexport = \PackageError{ekdosis}{unknown + teiexport=#1}{`teiexport' must be either `true', `false' or + `tidy'.} +} +\ekvoProcessLocalOptions{ekdosis} +\RequirePackage{luacode} +\RequirePackage{paracol} +\RequirePackage{xparse} +\RequirePackage{etoolbox} +\RequirePackage{lineno} +\RequirePackage{keyfloat} +\RequirePackage{refcount} +\RequirePackage[user,abspage]{zref} +\RequirePackage{ltxcmds} +\if@pkg@parnotes + \RequirePackage{parnotes} +\fi +\luadirect{dofile(kpse.find_file("ekdosis.lua"))} +\AtEndDocument{ + \luadirect{ekdosis.closestream()} +} +\renewcommand\linenumberfont{\normalfont\footnotesize} +\ekvdefinekeys{ekd@hooks}{ + store appfontsize = \ekd@appfontsize, + store refnumstyle = \ekd@refnumstyle, + store postrefnum = \ekd@postrefnum, + initial appfontsize = \footnotesize, + initial refnumstyle = \bfseries, + initial postrefnum = ~ +} +\NewDocumentCommand{\SetEkdosisHooks}{m}{\ekvset{ekd@hooks}{#1}} +\ekvdefinekeys{ekd@witness}{ + store settlement = \settlement@value, + store institution = \institution@value, + store repository = \repository@value, + store collection = \collection@value, + store idno = \idno@value, + store msName = \msName@value, + store origDate = \origDate@value +} +\NewDocumentCommand{\DeclareWitness}{m m m O{}}{% + \bgroup + \ekvset{ekd@witness}{#4} + \luadirect{ekdosis.newwitness( + \luastringN{#1}, + \luastringN{#2}, + \luastringN{#3}, + \luastringO{\settlement@value}, + \luastringO{\institution@value}, + \luastringO{\repository@value}, + \luastringO{\collection@value}, + \luastringO{\idno@value}, + \luastringO{\msName@value}, + \luastringO{\origDate@value})} + \egroup + } +\@onlypreamble\DeclareWitness +\NewDocumentCommand{\DeclareHand}{m m m +O{}}{ + \luadirect{ekdosis.newhand(\luastringN{#1}, + \luastringN{#2}, + \luastringN{#3}, + \luastringN{#4})} +} +\@onlypreamble\DeclareHand +\NewDocumentCommand{\DeclareScholar}{m m}{ + \luadirect{ekdosis.newscholar(\luastringN{#1}, + \luastringN{#2})} +} +\@onlypreamble\DeclareScholar +\NewDocumentCommand{\DeclareShorthand}{m m m}{ + \luadirect{ekdosis.newshorthand(\luastringN{#1}, + \luastringN{#2}, + \luastringN{#3})} +} +\@onlypreamble\DeclareShorthand +\NewDocumentCommand{\getsiglum}{m}{% + \luadirect{tex.sprint(ekdosis.getsiglum(\luastringN{#1}))}% +} +\NewDocumentCommand{\SigLine}{m}{% + \luadirect{tex.sprint(ekdosis.basic_cs(\luastringN{#1}))} +} +\NewDocumentCommand{\TeXtoTEI}{m m O{}}{% + \luadirect{ekdosis.newcmdtotag(\luastringN{#1}, + \luastringN{#2}, + \luastringN{#3})} +} +\NewDocumentCommand{\EnvtoTEI}{s m m O{}}{% + \IfBooleanTF{#1}{% + \luadirect{ekdosis.newenvtotag(\luastringN{#2}, + \luastringN{#3}, + \luastringN{#4}, + "yes")} + }{% + \luadirect{ekdosis.newenvtotag(\luastringN{#2}, + \luastringN{#3}, + \luastringN{#4})} + } +} +\NewDocumentCommand{\TeXtoTEIPatt}{m m}{% + \luadirect{ekdosis.newpatttotag(\luastringN{#1}, \luastringN{#2})} +} +\NewDocumentCommand{\SetTEIFileName}{m}{ + \luadirect{ekdosis.setteifilename(\luastringN{#1})} +} +\@onlypreamble\SetTEIFileName +\NewDocumentCommand{\SetxmlBibResource}{m}{ + \luadirect{ekdosis.setxmlbibresource(\luastringN{#1})} +} +\@onlypreamble\SetxmlBibResource +\newif\ifekd@mapps +\ekvdefinekeys{ekd@newapp}{ + choice direction = {LR = \def\direction@val{LR}, + RL = \def\direction@val{RL}}, + unknown-choice direction = \PackageError{ekdosis}{unknown + direction=#1}{`direction' must be either `LR' or `RL'.}, + store rule = \rule@val, + store delim = \delim@val, + store sep = \sep@val, + store bhook = \bhook@val, + store ehook = \ehook@val, + initial direction = LR, + initial ehook = {\csname ekd@end@apparatus\endcsname} +} +\NewDocumentCommand{\DeclareApparatus}{m O{}}{ + \newbool{subsq@unit@#1} + \booltrue{subsq@unit@#1} + \unless\ifekd@mapps\global\ekd@mappstrue\fi + \bgroup + \ekvset{ekd@newapp}{#2} + \luadirect{ekdosis.newapparatus( + \luastringN{#1}, + \luastring{\direction@val}, + \luastringO{\rule@val}, + \luastringO{\delim@val}, + \luastringO{\sep@val}, + \luastringO{\bhook@val}, + \luastringO{\ehook@val} + )} + \egroup +} +\@onlypreamble\DeclareApparatus +\newbool{do@app} +\newif\ifekd@state +\newif\ifekd@isinapp +\newif\ifekd@isinlem +\providebool{al@rlmode} +\@ifpackageloaded{arabluatex}{}{% + \def\setRL{\booltrue{al@rlmode}\pardir TRT\textdir TRT} + \def\setLR{\boolfalse{al@rlmode}\pardir TLT \textdir TLT} +} +\protected\def\LRnum#1{\bgroup\textdir TLT#1\egroup} +\newcounter{ekd@lab} +\globalcounter{ekd@lab} +\NewDocumentCommand{\unconditional@appin}{o m}{% + \IfNoValueTF{#1} + {\luadirect{ekdosis.appin(\luastringO{#2})}} + {\luadirect{ekdosis.appin(\luastringO{#2}, \luastringO{#1})}}% +} + % \def\blfootnote{\gdef\@thefnmark{\relax}\@footnotetext} +\def\blfootnote{\gdef\@thefnmark{}\@blfootnotetext} +\long\def\@blfootnotetext#1{\insert\footins{% + \reset@font\footnotesize + \interlinepenalty\interfootnotelinepenalty + \splittopskip\footnotesep + \splitmaxdepth \dp\strutbox \floatingpenalty \@MM + \hsize\columnwidth \@parboxrestore + \protected@edef\@currentlabel{% + \csname p@footnote\endcsname\@thefnmark + }% + \color@begingroup + \@makeblfntext{% + \rule\z@\footnotesep\ignorespaces#1\@finalstrut\strutbox}% + \color@endgroup}}% +\newcommand\@makeblfntext[1]{% + \parindent 1em% + \noindent + \hb@xt@0em{\hss\@makefnmark}#1} +\newif\ifrtl@app +\NewDocumentCommand{\SetRTLapp}{}{\rtl@apptrue} +\NewDocumentCommand{\SetLTRapp}{}{\rtl@appfalse} +\edef\ekdsep{] } +\NewDocumentCommand{\SetSeparator}{m}{\edef\ekdsep{#1}} +\edef\ekd@end@apparatus{} +\NewDocumentCommand{\SetEndApparatus}{m}{\edef\ekd@end@apparatus{#1}} +\def\ekd@unit@delim{} +\NewDocumentCommand{\SetUnitDelimiter}{m}{\def\ekd@unit@delim{#1}} +\def\ekd@default@rule{\rule{2truein}{0.5pt}} +\newif\iffootnoterule +\footnoteruletrue +\let\dflt@footnoterule\footnoterule +\let\dflt@pcol@footnoterule\pcol@footnoterule +\renewcommand\footnoterule{% + \iffootnoterule + \dflt@footnoterule% + \fi +} +\renewcommand\pcol@footnoterule{% + \iffootnoterule + \dflt@pcol@footnoterule% + \fi +} +\NewDocumentCommand{\SetDefaultRule}{m}{% + \def\@tempa{#1} + \ifx\@tempa\empty\def\ekd@default@rule{\mbox{}}% + \else% + \def\ekd@default@rule{#1}% + \fi} +\newcommand*{\NLS}{% + \par% + \nobreak% + \vspace{-\parskip}% + \noindent% + \ignorespaces} +\newif\ifsubsq@unit +\subsq@unittrue +\def\add@@apparatus{% + \if@pkg@parnotes\parnotes\else\fi% + \if@pkg@footins% + \bgroup% + \ifrtl@app\setRL\else\setLR\fi% + \blfootnote{% + \if@pkg@parnotes% + \if@parnotesroman% + \renewcommand*{\theparnotemark}{\roman{parnotemark}}\else\fi% + \parnoteclear\else\fi% + \footnotesize\apparatus\unless\ifekd@mapps\ekd@end@apparatus\fi% + \if@pkg@parnotes\parnotes\parnotereset\else\fi% + }% + \egroup% + \fi% + \if@pkg@float% + \keyparbox[!b]{}{\ifrtl@app\setRL\else\setLR\fi% + \if@pkg@parnotes% + \if@parnotesroman% + \renewcommand*{\theparnotemark}{\roman{parnotemark}}\else\fi% + \parnoteclear\else\fi% + \ekd@appfontsize\apparatus\unless\ifekd@mapps\ekd@end@apparatus\fi% + \if@pkg@parnotes\parnotes\parnotereset\else\fi% + }% + \fi% +} +\def\add@apparatus{% + \test@apparatus% + \ifbool{do@app}{\subsq@unitfalse\add@@apparatus}{}% +} +\NewDocumentCommand{\append@app}{o +m}{% + \ifekd@isinapp% + \ifekd@state% + \IfNoValueTF{#1}% + {\luadirect{ekdosis.appin(\luastringO{#2})}}% + {\luadirect{ekdosis.appin(\luastringO{#2}, \luastringO{#1})}}% + \fi% + \fi} +\NewDocumentCommand{\append@ln@app}{o +m}{% + \IfNoValueTF{#1} + {\luadirect{tex.sprint(ekdosis.mdvappend(\luastringO{#2}))}} + {\luadirect{tex.sprint(ekdosis.mdvappend(\luastringO{#2}, + \luastringO{#1}))}}} +\ekvdefinekeys{appnote}{ + store type = \ekdan@type, + initial type = default + } +\NewDocumentCommand{\EkdosisDefaultApparatus}{m}{% + \ekvset{appnote}{type=#1}} +\NewDocumentCommand{\app}{O{} > { \TrimSpaces } +m}{% + \begingroup + \ekvset{appnote}{#1}% + \ekd@isinapptrue% + \stepcounter{ekd@lab}% + \zlabel{ekd:\theekd@lab}% + \luadirect{ekdosis.storeabspg( + \luastring{\zref@extract{ekd:\theekd@lab}{abspage}})}% + \ifekd@state\add@apparatus\fi% + \luadirect{tex.sprint(ekdosis.removesp(\luastringN{#2}))}% + \ekd@isinappfalse% + \endgroup} +\def\current@ref@arg#1#2{{%\textdir TLT% + \unexpanded\expandafter{\ekd@refnumstyle}% + \ifnum% + \getpagerefnumber{#1} + = + \getpagerefnumber{#2} + \ifnum% + \getrefnumber{#1} + = + \getrefnumber{#2} + % + \ifekd@mapps% + \ifbool{subsq@unit@\ekdan@type}{% + \ifnum% + \getrefnumber{#1} + = + \getrefnumber{\luadirect{tex.sprint(ekdosis.getprevnotelab())}} + \else + \LRnum{\getrefnumber{#1}}% issue the no + \fi% + }% + {\LRnum{\getrefnumber{#1}}}% issue the no + \else + \ifsubsq@unit% + % + \ifnum% + \getrefnumber{#1} + = + \getrefnumber{\luadirect{tex.sprint(ekdosis.getprevnotelab())}} + \else + \LRnum{\getrefnumber{#1}}% issue the no + \fi + % + \else + \LRnum{\getrefnumber{#1}}% issue the no + \fi + \fi + % + \else + \LRnum{\getrefnumber{#1}}--% + \LRnum{\getrefnumber{#2}}% issue the nos + \fi% + \else + \LRnum{\getrefnumber{#1}}--% + \LRnum{\getpagerefnumber{#2}}.% + \LRnum{\getrefnumber{#2}}% issue pg and ln nos + \fi% + }\unexpanded\expandafter{\ekd@postrefnum}% +} +\def\current@ref{{%\textdir TLT% + \unexpanded\expandafter{\ekd@refnumstyle}% + \ifnum% + \getpagerefnumber{\luadirect{tex.sprint(ekdosis.getlnlab())}-b} + = + \getpagerefnumber{\luadirect{tex.sprint(ekdosis.getlnlab())}-e} + \ifnum% + \getrefnumber{\luadirect{tex.sprint(ekdosis.getlnlab())}-b} + = + \getrefnumber{\luadirect{tex.sprint(ekdosis.getlnlab())}-e} + % + \ifekd@mapps% + \ifbool{subsq@unit@\ekdan@type}{% + \ifnum% + \getrefnumber{\luadirect{tex.sprint(ekdosis.getlnlab())}-b} + = + \getrefnumber{\luadirect{tex.sprint(ekdosis.getprevlnlab())}-b} + \else + \LRnum{\getrefnumber{\luadirect{tex.sprint(ekdosis.getlnlab())}-b}}% issue the no + \fi% + }{\LRnum{\getrefnumber{\luadirect{tex.sprint(ekdosis.getlnlab())}-b}}}% issue the no + \else + \ifsubsq@unit% + % + \ifnum% + \getrefnumber{\luadirect{tex.sprint(ekdosis.getlnlab())}-b} + = + \getrefnumber{\luadirect{tex.sprint(ekdosis.getprevlnlab())}-b} + \else + \LRnum{\getrefnumber{\luadirect{tex.sprint(ekdosis.getlnlab())}-b}}% issue the no + \fi + % + \else + \LRnum{\getrefnumber{\luadirect{tex.sprint(ekdosis.getlnlab())}-b}}% issue the no + \fi + \fi + % + \else + \LRnum{\getrefnumber{\luadirect{tex.sprint(ekdosis.getlnlab())}-b}}--% + \LRnum{\getrefnumber{\luadirect{tex.sprint(ekdosis.getlnlab())}-e}}% issue the nos + \fi% + \else + \LRnum{\getrefnumber{\luadirect{tex.sprint(ekdosis.getlnlab())}-b}}--% + \LRnum{\getpagerefnumber{\luadirect{tex.sprint(ekdosis.getlnlab())}-e}}.% + \LRnum{\getrefnumber{\luadirect{tex.sprint(ekdosis.getlnlab())}-e}}% issue pg and ln nos + \fi% + }\unexpanded\expandafter{\ekd@postrefnum}% +} +\ekvdefinekeys{lem}{ + code wit = \def\ekdlr@wit{#1}, + code alt = \def\ekdlr@alt{#1}, + code pre = \def\ekdlr@pre{#1}, + code post = \def\ekdlr@post{#1}, + code prewit = \def\ekdlr@prewit{#1}, + code postwit = \def\ekdlr@postwit{#1}, + store type = \ekdlr@type, + store sep = \ekdl@sep, + bool nolem = \ifekdl@nolem, + bool nosep = \ifekdl@nosep, + initial sep = \ekdsep +} +\ekvdefinekeys{rdg}{ + code wit = \def\ekdlr@wit{#1}, + code alt = \def\ekdlr@alt{#1}, + code pre = \def\ekdlr@pre{#1}, + code post = \def\ekdlr@post{#1}, + code prewit = \def\ekdlr@prewit{#1}, + code postwit = \def\ekdlr@postwit{#1}, + store type = \ekdlr@type, + bool nordg = \ifekdr@nordg +} +\NewDocumentCommand{\lem}{O{} m}{% + \ekd@isinlemtrue% + \luadirect{ekdosis.dolnlab(\luastringN{#2})}% + \bgroup% + \ekvset{lem}{#1}% + \ifekd@mapps% + \ifnum% + \luadirect{tex.sprint(ekdosis.get_bagunits(\luastringO{\ekdan@type}))} + = 1 + \boolfalse{subsq@unit@\ekdan@type}% + \fi% + \luadirect{ekdosis.increment_bagunits(\luastringO{\ekdan@type})}% + \def\ekd@munit@delim{% + \luadirect{tex.sprint(ekdosis.getappdelim(\luastringO{\ekdan@type}))}}% + \fi% + \ifekdl@nolem\edef\lem@app{% + % \hskip .75em + \ifekd@mapps + \ifbool{subsq@unit@\ekdan@type}% + {\ekd@munit@delim}{}% + \else% + \ifsubsq@unit\unexpanded\expandafter{\ekd@unit@delim}\fi% + \fi% + \current@ref}%\hskip .25em}% + \else% + \ifbool{al@rlmode}{% + \edef\lem@app{% + % \hskip .75em + \ifekd@mapps + \ifbool{subsq@unit@\ekdan@type}% + {\ekd@munit@delim}{}% + \else% + \ifsubsq@unit\unexpanded\expandafter{\ekd@unit@delim}\fi% + \fi% + \current@ref%\hskip .25em + \ifdefined\ekdlr@alt% + \ifdefined\ekdlr@post% + \space\unexpanded\expandafter{\ekdlr@post}\space\else\fi + {\textdir TRT\unexpanded\expandafter{\ekdlr@alt}}% + \ifdefined\ekdlr@pre% + \space\unexpanded\expandafter{\ekdlr@pre}\space\else\fi + \else + \ifdefined\ekdlr@post% + \space\unexpanded\expandafter{\ekdlr@post}\space\else\fi + {\textdir TRT\unexpanded{#2}}% + \ifdefined\ekdlr@pre% + \space\unexpanded\expandafter{\ekdlr@pre}\space\else\fi + \fi + \ifdefined\ekdlr@postwit% + \space\unexpanded\expandafter{\ekdlr@postwit}\else\fi + \ifdefined\ekdlr@wit\space\getsiglum{\ekdlr@wit}\else\fi + \ifdefined\ekdlr@prewit% + \space\unexpanded\expandafter{\ekdlr@prewit}\space\else\fi + \ifekdl@nosep\else\unexpanded\expandafter{\ekdl@sep}\fi + }% + }% + {% + \edef\lem@app{% + % \hskip .75em + \ifekd@mapps + \ifbool{subsq@unit@\ekdan@type}% + {\ekd@munit@delim}{}% + \else% + \ifsubsq@unit\unexpanded\expandafter{\ekd@unit@delim}\fi% + \fi% + \current@ref%\hskip .25em + \ifdefined\ekdlr@alt% + \ifdefined\ekdlr@pre% + \space\unexpanded\expandafter{\ekdlr@pre}\space\else\fi + \ltx@ifpackageloaded{babel}% + {\noexpand\selectlanguage{\languagename}% + \unexpanded\expandafter{\ekdlr@alt}}% + {\unexpanded\expandafter{\ekdlr@alt}}% + \ifdefined\ekdlr@post% + \space\unexpanded\expandafter{\ekdlr@post}\space\else\fi + \else + \ifdefined\ekdlr@pre% + \space\unexpanded\expandafter{\ekdlr@pre}\space\else\fi + \ltx@ifpackageloaded{babel}% + {\noexpand\selectlanguage{\languagename}\unexpanded{#2}}{% + \unexpanded{#2}}% + \ifdefined\ekdlr@post% + \space\unexpanded\expandafter{\ekdlr@post}\space\else\fi + \fi + \ifdefined\ekdlr@prewit% + \space\unexpanded\expandafter{\ekdlr@prewit}\space\else\fi + \ifdefined\ekdlr@wit\space\getsiglum{\ekdlr@wit}\else\fi + \ifdefined\ekdlr@postwit% + \space\unexpanded\expandafter{\ekdlr@postwit}\else\fi + \ifekdl@nosep\else\unexpanded\expandafter{\ekdl@sep}\fi + }% + }% + \fi% + \ifekd@mapps% + \append@ln@app[\ekdan@type]{\lem@app}% + \else% + \append@ln@app{\lem@app}% + \fi% + \egroup% + \ekd@isinlemfalse% + \subsq@unittrue% +} +\NewDocumentCommand{\rdg}{O{} m}{% + \bgroup% + \ekvset{rdg}{#1}% + % \ifekdr@nordg\append@app{}\else% do we need \append@app{} here? If + % % so, keep in mind \ifekd@mapps, + % like so: + \ifekdr@nordg% + \ifekd@mapps% + \append@app[\ekdan@type]{}% + \else% + \append@app{}% + \fi% + \else% + \ifbool{al@rlmode}{% + \edef\rdg@app{% + \ifdefined\ekdlr@alt% + \ifdefined\ekdlr@post% + \space\unexpanded\expandafter{\ekdlr@post}\space\else\fi + {\textdir TRT\unexpanded\expandafter{\ekdlr@alt}}% + \ifdefined\ekdlr@pre% + \space\unexpanded\expandafter{\ekdlr@pre}\space\else\fi + \else + \ifdefined\ekdlr@post% + \space\unexpanded\expandafter{\ekdlr@post}\space\else\fi + {\textdir TRT\unexpanded{#2}}% + \ifdefined\ekdlr@pre% + \space\unexpanded\expandafter{\ekdlr@pre}\space\else\fi + \fi + \ifdefined\ekdlr@postwit% + \space\unexpanded\expandafter{\ekdlr@postwit}\else\fi + \ifdefined\ekdlr@wit\space\getsiglum{\ekdlr@wit}\else\fi + \ifdefined\ekdlr@prewit% + \space\unexpanded\expandafter{\ekdlr@prewit}\space\else\fi + }% + }% + {% + \edef\rdg@app{% + \ifdefined\ekdlr@alt% + \ifdefined\ekdlr@pre% + \space\unexpanded\expandafter{\ekdlr@pre}\space\else\fi + \ltx@ifpackageloaded{babel}% + {\noexpand\selectlanguage{\languagename}% + \unexpanded\expandafter{\ekdlr@alt}}% + {\unexpanded\expandafter{\ekdlr@alt}}% + \ifdefined\ekdlr@post% + \space\unexpanded\expandafter{\ekdlr@post}\space\else\fi + \else + \ifdefined\ekdlr@pre% + \space\unexpanded\expandafter{\ekdlr@pre}\space\else\fi + \ltx@ifpackageloaded{babel}% + {\noexpand\selectlanguage{\languagename}\unexpanded{#2}}{% + \unexpanded{#2}}% + \ifdefined\ekdlr@post% + \space\unexpanded\expandafter{\ekdlr@post}\space\else\fi + \fi + \ifdefined\ekdlr@prewit% + \space\unexpanded\expandafter{\ekdlr@prewit}\space\else\fi + \ifdefined\ekdlr@wit\space\getsiglum{\ekdlr@wit}\else\fi + \ifdefined\ekdlr@postwit% + \space\unexpanded\expandafter{\ekdlr@postwit}\else\fi + }% + }% + \ifekd@mapps% + \append@app[\ekdan@type]{\rdg@app}% + \else% + \append@app{\rdg@app}% + \fi% + \fi% + \egroup% +} +\ekvdefinekeys{note}{ + store type = \ekdan@type, + store lem = \ekdn@lem, + code labelb = \def\ekdn@labelb{#1}, + code labele = \def\ekdn@labele{#1}, + store sep = \ekdn@sep, + initial type = default, + initial sep = \ekdsep +} +\NewDocumentCommand{\note@noapp}{O{} +m}{% + \bgroup% + \ekvset{note}{#1}% + \stepcounter{ekd@lab}% + \zlabel{ekd:\theekd@lab}% + \luadirect{ekdosis.storeabspg( + \luastring{\zref@extract{ekd:\theekd@lab}{abspage}})}% + \ifekd@state\add@apparatus\fi% + \ifekd@mapps% + \ifnum% + \luadirect{tex.sprint(ekdosis.get_bagunits(\luastringO{\ekdan@type}))} + = 1 + \boolfalse{subsq@unit@\ekdan@type}% + \fi% + \luadirect{ekdosis.increment_bagunits(\luastringO{\ekdan@type})}% + \def\ekd@munit@delim{% + \luadirect{tex.sprint(ekdosis.getappdelim(\luastringO{\ekdan@type}))}}% + \fi% + \ifdefined\ekdn@labelb% + \luadirect{tex.sprint(ekdosis.setnotelab(\luastringO{\ekdn@labelb}))}% + \ifdefined\ekdn@labele\else\def\ekdn@labele{\ekdn@labelb}\fi% + \else\PackageError{ekdosis}{missing labelb}{`labelb' must be + set.}\fi% + \ifbool{al@rlmode}% + {\edef\note@contents{% + % \hskip .75em + \ifekd@mapps + \ifbool{subsq@unit@\ekdan@type}% + {\ekd@munit@delim}{}% + \else% + \ifsubsq@unit\unexpanded\expandafter{\ekd@unit@delim}\fi% + \fi% + \current@ref@arg{\ekdn@labelb}{\ekdn@labele}%\hskip .25em + \ifdefined\ekdn@lem% + {\textdir TRT\unexpanded\expandafter{\ekdn@lem}}% + \unexpanded\expandafter{\ekdn@sep}\else\fi% + {\textdir TRT\unexpanded{#2}}}}% + {\edef\note@contents{% + % \hskip .75em + \ifekd@mapps + \ifbool{subsq@unit@\ekdan@type}% + {\ekd@munit@delim}{}% + \else% + \ifsubsq@unit\unexpanded\expandafter{\ekd@unit@delim}\fi% + \fi% + \current@ref@arg{\ekdn@labelb}{\ekdn@labele}%\hskip .25em + \ifdefined\ekdn@lem + \ltx@ifpackageloaded{babel}% + {\noexpand\selectlanguage{\languagename}% + \unexpanded\expandafter{\ekdn@lem}}% + {\unexpanded\expandafter{\ekdn@lem}}% + \unexpanded\expandafter{\ekdn@sep}\else\fi% + \ltx@ifpackageloaded{babel}% + {\noexpand\selectlanguage{\languagename}\unexpanded{#2}}{% + \unexpanded{#2}}}}% + \ifekd@mapps% + \unconditional@appin[\ekdan@type]{\note@contents}% + \else% + \unconditional@appin{\note@contents}% + \fi% + \luadirect{ekdosis.setprevnotelab(\luastringO{\ekdn@labelb})}% + \egroup% + \subsq@unittrue% +} +\ekvdefinekeys{ekd@note}{ + store pre = \pre@value, + store post = \post@value +} +\NewDocumentCommand{\ekd@note}{O{} m}{% + \bgroup% + \ekvset{ekd@note}{#1}% + \edef\note@contents{% + \ekvifdefinedNoVal{note}{pre}{}{% + \unexpanded\expandafter{\pre@value}}% + \unexpanded{#2}% + \ekvifdefinedNoVal{note}{post}{}{% + \unexpanded\expandafter{\post@value}}% + }% + \append@app{\note@contents}% + \egroup% +} +\NewDocumentCommand{\ekd@note@star}{O{} m}{% + \if@pkg@parnotes + \bgroup% + \ekvset{ekd@note}{#1}% + \edef\note@contents{% + \ekvifdefinedNoVal{note}{pre}{}{% + \unexpanded\expandafter{\pre@value}}% + \unskip\noexpand\parnote{#2}% + \ekvifdefinedNoVal{note}{post}{}{% + \unexpanded\expandafter{\post@value}}% + }% + \append@app{\note@contents}% + \egroup% + \else + \append@app{\unskip\footnote{#2}}% + \fi% +} +\NewDocumentCommand{\note@app}{s O{} +m}{% + \ifbool{al@rlmode}{% + \IfBooleanTF{#1}{\ekd@note@star[#2]{% + {\textdir TRT#3}}} + {\ekd@note[#2]{{\textdir TRT#3}}}% + }{% + \IfBooleanTF{#1}{\ekd@note@star[#2]{#3}} + {\ekd@note[#2]{#3}}% + }% +} +\NewDocumentCommand{\note}{s O{} +m}{% + \ifekd@state% + \ifekd@isinapp% + \ifekd@isinlem% + \note@noapp[#2]{#3}% + \else% + \IfBooleanTF{#1}{\note@app*[#2]{#3}}{\note@app[#2]{#3}}% + \fi% + \else% + \note@noapp[#2]{#3}% + \fi% + \fi% +} +\NewDocumentCommand{\apparatus}{}{% + \luadirect{tex.sprint(ekdosis.appout())}} +\NewDocumentCommand{\test@apparatus}{}{% + \luadirect{tex.sprint(ekdosis.testapparatus())}} +\NewDocumentCommand{\ekd@storecol}{}{% + \luadirect{ekdosis.storecurcol(\luastring{\thecolumn})}% +} +\NewDocumentCommand{\EkdosisOn}{}{% + \ekd@statetrue} +\NewDocumentCommand{\EkdosisOff}{}{% + \ekd@statefalse% +} +\def\ekd@setlineno{% + \let\setpagewiselinenumbers\relax% + \let\pagewiselinenumbers\relax% + \let\endpagewiselinenumbers\relax% + \let\runningpagewiselinenumbers\relax% + \let\realpagewiselinenumbers\relax% +} +\NewDocumentEnvironment{ekdosis}{+b}{% + \ekd@setlineno% + \runninglinenumbers + \EkdosisOn#1}{% + \EkdosisOff + \endrunninglinenumbers% + \iftei@export + \luadirect{ekdosis.exporttei(\luastringN{\par #1\par })}\fi} +\newif\ifekd@pagelineation +\ekvdefinekeys{ekd@align}{ + store tcols = \tcols@num, + store lcols = \lcols@num, + store texts = \texts@value, + store apparatus = \apparatus@value, + bool paired = \ifekd@paired, + choice lineation = {page = \ekd@pagelineationtrue, + document = \ekd@pagelineationfalse}, + unknown-choice lineation = \PackageError{ekdosis}{unknown + lineation=#1}{`lineation' must be either `page' or `document'.}, + choice segmentation = {auto = \def\segmentation@val{auto}, + noauto = \def\segmentation@val{noauto}}, + unknown-choice segmentation = \PackageError{ekdosis}{unknown + segmentation=#1}{`segmentation' must be either `auto' or + `noauto'.}, + bool flush = \ifekd@flushapp, + initial tcols = 2, + initial lcols = 1, + initial texts = edition;translation, + initial apparatus = edition, + default segmentation = auto +} +\NewDocumentCommand{\SetEkdosisAlignment}{m}{ + \ekvset{ekd@align}{#1} +} +\patchcmd{\pcol@nextpage}{% + \endgroup}{% + \ifekd@pagelineation\resetlinenumber\fi + \endgroup}{}{} +\NewDocumentCommand{\EkdosisColStart}{}{% + \ekd@setlineno% + \runninglinenumbers + \ekd@storecol% + \stepcounter{ekd@lab}% + \zlabel{ekd:\theekd@lab}% + \luadirect{% + ekdosis.storeabspg(\luastring{\zref@extract{ekd:\theekd@lab}{abspage}}, + "pg_i")}% + \ifekd@pagelineation + \luadirect{tex.sprint(ekdosis.checkresetlineno())} + \fi +} +\NewDocumentCommand{\EkdosisColStop}{}{% + \stepcounter{ekd@lab}% + \zlabel{ekd:\theekd@lab}% + \luadirect{% + ekdosis.storeabspg(\luastring{\zref@extract{ekd:\theekd@lab}{abspage}}, + "pg_ii")}% + \endrunninglinenumbers% +} +\NewDocumentEnvironment{alignment}{O{}} +{% + \ekvset{ekd@align}{#1}% + \luadirect{ekdosis.mkenvdata( + \luastring{\texts@value}, + "texts" + )} + \ifekd@flushapp + \luadirect{ekdosis.newalignment("set")} + \fi + \luadirect{ekdosis.mkenvdata( + \luastring{\apparatus@value}, "apparatus" + )} + \setrunninglinenumbers + \luadirect{tex.sprint(ekdosis.mkenv())} + \ifekd@paired + \begin{paracol}[\lcols@num]{\tcols@num} + \else + \begin{paracol}[\lcols@num]*{\tcols@num} + \fi + } + {\end{paracol} + \iftei@export\luadirect{ekdosis.export_coldata_totei()}\fi + \ifekd@flushapp + \luadirect{ekdosis.newalignment("reset")} + \fi + \luadirect{ekdosis.flushenvdata()} + \luadirect{ekdosis.flushcolnums()} + } +\NewDocumentCommand{\MkBodyDivs}{mmmmmm}{ + \luadirect{ekdosis.mkdivdepths( + \luastringN{#1}, + \luastringN{#2}, + \luastringN{#3}, + \luastringN{#4}, + \luastringN{#5}, + \luastringN{#6} + ) + } +} +\ekvdefinekeys{ekd@div}{ + code type = \def\type@value{#1}, + code n = \def\n@value{#1}, + code head = \def\head@value{#1}, + code barehead = \def\barehead@value{#1}, + store depth = \depth@value, + choice toc = {book = \def\toc@value{book}, + part = \def\toc@value{part}, + chapter = \def\toc@value{chapter}, + section = \def\toc@value{section}, + subsection = \def\toc@value{subsection}, + subsubsection = \def\toc@value{subsubsection}, + paragraph = \def\toc@value{paragraph}, + subparagraph = \def\toc@value{subparagraph}}, + unknown-choice toc = \PackageError{ekdosis}{unknown toc=#1}{`toc' + must be either `book', `part', `chapter', `section', `subsection', + \MessageBreak `subsubsection', `paragraph' or `subparagraph'.}, + initial depth = 1 +} +\NewDocumentCommand{\ekdfmtdiv}{m m m}{ + \luadirect{ekdosis.fmtdiv(\luastring{#1}, + \luastringN{#2}, + \luastringN{#3})} +} +\NewDocumentCommand{\ekd@getfmtdiv}{m m}{% + \luadirect{tex.sprint(ekdosis.getfmtdiv(\luastringO{#1}, + \luastringN{#2}))}% +} +\NewDocumentCommand{\ekddiv}{m}{ + \begingroup + \ekvset{ekd@div}{#1}% + \ifdefined\head@value + \bgroup + \ekd@getfmtdiv{\depth@value}{b}% + \head@value + \ekd@getfmtdiv{\depth@value}{e}% + \egroup + \ifdefined\toc@value + \ltx@ifpackageloaded{hyperref}{\phantomsection}{}% + \ifdefined\barehead@value + \addcontentsline{toc}{\toc@value}{\barehead@value}% + \else + \addcontentsline{toc}{\toc@value}{\head@value}% + \fi + \fi + \fi + \endgroup +} +\newlength{\ekdverseindentlength} +\setlength{\ekdverseindentlength}{\parindent} +\newenvironment*{ekdverse}[1][\ekdverseindentlength]{ + \begin{list}{}{% + \setlength{\leftmargin}{#1} + \setlength{\itemsep}{0pt} + \setlength{\topsep}{0pt} + \setlength{\partopsep}{0pt} + } + \item[] + }{\end{list}} +\endinput +%% +%% End of file `ekdosis.sty'. diff --git a/Master/tlpkg/bin/tlpkg-ctan-check b/Master/tlpkg/bin/tlpkg-ctan-check index dbc0e51ae29..ce84deb74da 100755 --- a/Master/tlpkg/bin/tlpkg-ctan-check +++ b/Master/tlpkg/bin/tlpkg-ctan-check @@ -260,7 +260,7 @@ my @TLP_working = qw( ec ecc ecclesiastic ecltree eco ecobiblatex econ-bst econometrics economic ecothesis ecv ed edfnotes edmac edmargin ednotes eemeir eepic efbox egameps - egplot ehhline eiad eiad-ltx eijkhout ejpecp ekaia ektype-tanka + egplot ehhline eiad eiad-ltx eijkhout ejpecp ekaia ekdosis ektype-tanka elbioimp electrum eledform eledmac elegantbook elegantnote elegantpaper elements ellipse ellipsis diff --git a/Master/tlpkg/tlpsrc/collection-luatex.tlpsrc b/Master/tlpkg/tlpsrc/collection-luatex.tlpsrc index ab2cb569d28..7f11c396ee9 100644 --- a/Master/tlpkg/tlpsrc/collection-luatex.tlpsrc +++ b/Master/tlpkg/tlpsrc/collection-luatex.tlpsrc @@ -15,6 +15,7 @@ depend cloze depend combofont depend cstypo depend ctablestack +depend ekdosis depend emoji depend emojicite depend enigma diff --git a/Master/tlpkg/tlpsrc/ekdosis.tlpsrc b/Master/tlpkg/tlpsrc/ekdosis.tlpsrc new file mode 100644 index 00000000000..e69de29bb2d --- /dev/null +++ b/Master/tlpkg/tlpsrc/ekdosis.tlpsrc |