summaryrefslogtreecommitdiff
path: root/Master
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2020-07-08 21:18:08 +0000
committerKarl Berry <karl@freefriends.org>2020-07-08 21:18:08 +0000
commit637224a93d20e487f3ba4cdc5040a68c86fb6617 (patch)
tree73e4ed9dd1fcd4a3762e2367457f3a69cd70ecaf /Master
parentc226379cc4863e82904bd636c705d73c20670015 (diff)
ekdosis (8jul20)
git-svn-id: svn://tug.org/texlive/trunk@55786 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master')
-rw-r--r--Master/texmf-dist/doc/lualatex/ekdosis/README.md130
-rw-r--r--Master/texmf-dist/doc/lualatex/ekdosis/ekdosis.el150
-rw-r--r--Master/texmf-dist/doc/lualatex/ekdosis/ekdosis.pdfbin0 -> 362094 bytes
-rw-r--r--Master/texmf-dist/doc/lualatex/ekdosis/samples/Caesar_BG-6-13-1-tei.xml225
-rw-r--r--Master/texmf-dist/doc/lualatex/ekdosis/samples/Caesar_BG-6-13-1.pdfbin0 -> 17989 bytes
-rw-r--r--Master/texmf-dist/doc/lualatex/ekdosis/samples/Caesar_BG-6-13-1.tex118
-rw-r--r--Master/texmf-dist/source/lualatex/ekdosis/Makefile109
-rw-r--r--Master/texmf-dist/source/lualatex/ekdosis/ekdosis.dtx5388
-rw-r--r--Master/texmf-dist/source/lualatex/ekdosis/ekdosis.ins62
-rw-r--r--Master/texmf-dist/tex/lualatex/ekdosis/ekdosis.lua1694
-rw-r--r--Master/texmf-dist/tex/lualatex/ekdosis/ekdosis.sty959
-rwxr-xr-xMaster/tlpkg/bin/tlpkg-ctan-check2
-rw-r--r--Master/tlpkg/tlpsrc/collection-luatex.tlpsrc1
-rw-r--r--Master/tlpkg/tlpsrc/ekdosis.tlpsrc0
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
new file mode 100644
index 00000000000..ef69e146fa5
--- /dev/null
+++ b/Master/texmf-dist/doc/lualatex/ekdosis/ekdosis.pdf
Binary files differ
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
new file mode 100644
index 00000000000..4f80ccc1372
--- /dev/null
+++ b/Master/texmf-dist/doc/lualatex/ekdosis/samples/Caesar_BG-6-13-1.pdf
Binary files differ
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, "%<", "&lt;")
+ str = string.gsub(str, "%>", "&gt;")
+ 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("&gt;"), "\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, "%<", "&lt;")
+ str = string.gsub(str, "%>", "&gt;")
+ 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("&gt;"), "\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