texlive[55786] Master: ekdosis (8jul20)

commits+karl at tug.org commits+karl at tug.org
Wed Jul 8 23:18:08 CEST 2020


Revision: 55786
          http://tug.org/svn/texlive?view=revision&revision=55786
Author:   karl
Date:     2020-07-08 23:18:08 +0200 (Wed, 08 Jul 2020)
Log Message:
-----------
ekdosis (8jul20)

Modified Paths:
--------------
    trunk/Master/tlpkg/bin/tlpkg-ctan-check
    trunk/Master/tlpkg/tlpsrc/collection-luatex.tlpsrc

Added Paths:
-----------
    trunk/Master/texmf-dist/doc/lualatex/ekdosis/
    trunk/Master/texmf-dist/doc/lualatex/ekdosis/README.md
    trunk/Master/texmf-dist/doc/lualatex/ekdosis/ekdosis.el
    trunk/Master/texmf-dist/doc/lualatex/ekdosis/ekdosis.pdf
    trunk/Master/texmf-dist/doc/lualatex/ekdosis/samples/
    trunk/Master/texmf-dist/doc/lualatex/ekdosis/samples/Caesar_BG-6-13-1-tei.xml
    trunk/Master/texmf-dist/doc/lualatex/ekdosis/samples/Caesar_BG-6-13-1.pdf
    trunk/Master/texmf-dist/doc/lualatex/ekdosis/samples/Caesar_BG-6-13-1.tex
    trunk/Master/texmf-dist/source/lualatex/ekdosis/
    trunk/Master/texmf-dist/source/lualatex/ekdosis/Makefile
    trunk/Master/texmf-dist/source/lualatex/ekdosis/ekdosis.dtx
    trunk/Master/texmf-dist/source/lualatex/ekdosis/ekdosis.ins
    trunk/Master/texmf-dist/tex/lualatex/ekdosis/
    trunk/Master/texmf-dist/tex/lualatex/ekdosis/ekdosis.lua
    trunk/Master/texmf-dist/tex/lualatex/ekdosis/ekdosis.sty
    trunk/Master/tlpkg/tlpsrc/ekdosis.tlpsrc

Added: trunk/Master/texmf-dist/doc/lualatex/ekdosis/README.md
===================================================================
--- trunk/Master/texmf-dist/doc/lualatex/ekdosis/README.md	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/lualatex/ekdosis/README.md	2020-07-08 21:18:08 UTC (rev 55786)
@@ -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 at 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.


Property changes on: trunk/Master/texmf-dist/doc/lualatex/ekdosis/README.md
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/lualatex/ekdosis/ekdosis.el
===================================================================
--- trunk/Master/texmf-dist/doc/lualatex/ekdosis/ekdosis.el	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/lualatex/ekdosis/ekdosis.el	2020-07-08 21:18:08 UTC (rev 55786)
@@ -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 at 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


Property changes on: trunk/Master/texmf-dist/doc/lualatex/ekdosis/ekdosis.el
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/lualatex/ekdosis/ekdosis.pdf
===================================================================
(Binary files differ)

Index: trunk/Master/texmf-dist/doc/lualatex/ekdosis/ekdosis.pdf
===================================================================
--- trunk/Master/texmf-dist/doc/lualatex/ekdosis/ekdosis.pdf	2020-07-08 21:17:27 UTC (rev 55785)
+++ trunk/Master/texmf-dist/doc/lualatex/ekdosis/ekdosis.pdf	2020-07-08 21:18:08 UTC (rev 55786)

Property changes on: trunk/Master/texmf-dist/doc/lualatex/ekdosis/ekdosis.pdf
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/pdf
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/lualatex/ekdosis/samples/Caesar_BG-6-13-1-tei.xml
===================================================================
--- trunk/Master/texmf-dist/doc/lualatex/ekdosis/samples/Caesar_BG-6-13-1-tei.xml	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/lualatex/ekdosis/samples/Caesar_BG-6-13-1-tei.xml	2020-07-08 21:18:08 UTC (rev 55786)
@@ -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>

Added: trunk/Master/texmf-dist/doc/lualatex/ekdosis/samples/Caesar_BG-6-13-1.pdf
===================================================================
(Binary files differ)

Index: trunk/Master/texmf-dist/doc/lualatex/ekdosis/samples/Caesar_BG-6-13-1.pdf
===================================================================
--- trunk/Master/texmf-dist/doc/lualatex/ekdosis/samples/Caesar_BG-6-13-1.pdf	2020-07-08 21:17:27 UTC (rev 55785)
+++ trunk/Master/texmf-dist/doc/lualatex/ekdosis/samples/Caesar_BG-6-13-1.pdf	2020-07-08 21:18:08 UTC (rev 55786)

Property changes on: trunk/Master/texmf-dist/doc/lualatex/ekdosis/samples/Caesar_BG-6-13-1.pdf
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/pdf
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/lualatex/ekdosis/samples/Caesar_BG-6-13-1.tex
===================================================================
--- trunk/Master/texmf-dist/doc/lualatex/ekdosis/samples/Caesar_BG-6-13-1.tex	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/lualatex/ekdosis/samples/Caesar_BG-6-13-1.tex	2020-07-08 21:18:08 UTC (rev 55786)
@@ -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}


Property changes on: trunk/Master/texmf-dist/doc/lualatex/ekdosis/samples/Caesar_BG-6-13-1.tex
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/source/lualatex/ekdosis/Makefile
===================================================================
--- trunk/Master/texmf-dist/source/lualatex/ekdosis/Makefile	                        (rev 0)
+++ trunk/Master/texmf-dist/source/lualatex/ekdosis/Makefile	2020-07-08 21:18:08 UTC (rev 55786)
@@ -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


Property changes on: trunk/Master/texmf-dist/source/lualatex/ekdosis/Makefile
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/source/lualatex/ekdosis/ekdosis.dtx
===================================================================
--- trunk/Master/texmf-dist/source/lualatex/ekdosis/ekdosis.dtx	                        (rev 0)
+++ trunk/Master/texmf-dist/source/lualatex/ekdosis/ekdosis.dtx	2020-07-08 21:18:08 UTC (rev 55786)
@@ -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 at 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 at 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}
+ at 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}
+}
+
+ at 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}
+}
+
+ at 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}}
+
+ at Online{DLL-TC,
+  author =	 {{Digital Latin Library}},
+  title =	 {Textual Criticism},
+  url =
+  {https://digitallatin.org/library-digital-latin-texts/textual-criticism},
+  urldate =	 {2020-05-24}
+}
+
+ at 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 at roberalessi.net}
+\metaset[print]{contactemail}{\mailto[ekdosis]{alessi at 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 at 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 at pkg@float
+\newif\if at pkg@footins
+\newif\if at pkg@ekddivs
+\newif\if at parnotesroman
+\newif\if at pkg@parnotes
+\newif\iftei at export
+\ekvdefinekeys{ekdosis}{
+  choice layout = {float = {\@pkg at floattrue},
+    footins = {\@pkg at footinstrue}},
+  initial layout = float,
+  unknown-choice layout = \PackageError{ekdosis}{unknown
+    layout=#1}{`layout' must be either `float' or `footins'.},
+  choice divs = {ekdosis = {\@pkg at ekddivstrue},
+    latex = {\@pkg at 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 at parnotestrue},
+    roman = {\@pkg at 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 at exporttrue
+      \AtBeginDocument{\luadirect{ekdosis.openteistream()}}%
+      \AtEndDocument{\luadirect{ekdosis.closeteistream()}}},
+    tidy = {\tei at 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 at 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 at hooks}{
+  store appfontsize = \ekd at appfontsize,
+  store refnumstyle = \ekd at refnumstyle,
+  store postrefnum = \ekd at postrefnum,
+  initial appfontsize = \footnotesize,
+  initial refnumstyle = \bfseries,
+  initial postrefnum = ~
+}
+\NewDocumentCommand{\SetEkdosisHooks}{m}{\ekvset{ekd at hooks}{#1}}
+%    \end{macrocode}
+% \end{macro}
+% Build and process the list of witnesses and hands:---
+%    \begin{macrocode}
+\ekvdefinekeys{ekd at witness}{
+  store settlement = \settlement at value,
+  store institution = \institution at value,
+  store repository = \repository at value,
+  store collection = \collection at value,
+  store idno = \idno at value,
+  store msName = \msName at value,
+  store origDate = \origDate at 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 at witness}{#4}
+    \luadirect{ekdosis.newwitness(
+      \luastringN{#1},
+      \luastringN{#2},
+      \luastringN{#3},
+      \luastringO{\settlement at value},
+      \luastringO{\institution at value},
+      \luastringO{\repository at value},
+      \luastringO{\collection at value},
+      \luastringO{\idno at value},
+      \luastringO{\msName at value},
+      \luastringO{\origDate at 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 at mapps
+%    \end{macrocode}
+% Now the key-value options can be defined:---
+%    \begin{macrocode}
+\ekvdefinekeys{ekd at newapp}{
+  choice direction = {LR = \def\direction at val{LR},
+                      RL = \def\direction at val{RL}},
+  unknown-choice direction = \PackageError{ekdosis}{unknown
+    direction=#1}{`direction' must be either `LR' or `RL'.},
+  store rule = \rule at val,
+  store delim = \delim at val,
+  store sep = \sep at val,
+  store bhook = \bhook at val,
+  store ehook = \ehook at val,
+  initial direction = LR,
+  initial ehook = {\csname ekd at 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 at unit@#1}
+  \booltrue{subsq at unit@#1}
+  \unless\ifekd at mapps\global\ekd at mappstrue\fi
+  \bgroup
+  \ekvset{ekd at newapp}{#2}
+  \luadirect{ekdosis.newapparatus(
+    \luastringN{#1},
+    \luastring{\direction at val},
+    \luastringO{\rule at val},
+    \luastringO{\delim at val},
+    \luastringO{\sep at val},
+    \luastringO{\bhook at val},
+    \luastringO{\ehook at 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 at app}
+\newif\ifekd at state
+\newif\ifekd at isinapp
+\newif\ifekd at 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 at rlmode}
+\@ifpackageloaded{arabluatex}{}{%
+  \def\setRL{\booltrue{al at rlmode}\pardir TRT\textdir TRT}
+  \def\setLR{\boolfalse{al at 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 at lab}
+\globalcounter{ekd at lab}
+%    \end{macrocode}
+% This command inserts words in the apparatus criticus without
+% checking if both |ekd at isinapp| and |ekd at state| are set to |true|.
+%    \begin{macrocode}
+\NewDocumentCommand{\unconditional at 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 at font\footnotesize
+    \interlinepenalty\interfootnotelinepenalty
+    \splittopskip\footnotesep
+    \splitmaxdepth \dp\strutbox \floatingpenalty \@MM
+    \hsize\columnwidth \@parboxrestore
+    \protected at edef\@currentlabel{%
+       \csname p at footnote\endcsname\@thefnmark
+    }%
+    \color at begingroup
+      \@makeblfntext{%
+        \rule\z@\footnotesep\ignorespaces#1\@finalstrut\strutbox}%
+    \color at endgroup}}%
+\newcommand\@makeblfntext[1]{%
+    \parindent 1em%
+    \noindent
+    \hb at 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 at app
+\NewDocumentCommand{\SetRTLapp}{}{\rtl at apptrue}
+\NewDocumentCommand{\SetLTRapp}{}{\rtl at 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 at end@apparatus{}
+\NewDocumentCommand{\SetEndApparatus}{m}{\edef\ekd at 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 at unit@delim{}
+\NewDocumentCommand{\SetUnitDelimiter}{m}{\def\ekd at 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 at default@rule{\rule{2truein}{0.5pt}}
+\newif\iffootnoterule
+\footnoteruletrue
+\let\dflt at footnoterule\footnoterule
+\let\dflt at pcol@footnoterule\pcol at footnoterule
+\renewcommand\footnoterule{%
+  \iffootnoterule
+  \dflt at footnoterule%
+  \fi
+}
+\renewcommand\pcol at footnoterule{%
+  \iffootnoterule
+  \dflt at 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 at default@rule{\mbox{}}%
+  \else%
+  \def\ekd at 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 at unit
+\subsq at 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 at pkg@parnotes\parnotes\else\fi%
+  \if at pkg@footins%
+  \bgroup%
+  \ifrtl at app\setRL\else\setLR\fi%
+  \blfootnote{%
+    \if at pkg@parnotes%
+    \if at parnotesroman%
+    \renewcommand*{\theparnotemark}{\roman{parnotemark}}\else\fi%
+    \parnoteclear\else\fi%
+    \footnotesize\apparatus\unless\ifekd at mapps\ekd at end@apparatus\fi%
+    \if at pkg@parnotes\parnotes\parnotereset\else\fi%
+  }%
+  \egroup%
+  \fi%
+  \if at pkg@float%
+  \keyparbox[!b]{}{\ifrtl at app\setRL\else\setLR\fi%
+    \if at pkg@parnotes%
+    \if at parnotesroman%
+    \renewcommand*{\theparnotemark}{\roman{parnotemark}}\else\fi%
+    \parnoteclear\else\fi%
+    \ekd at appfontsize\apparatus\unless\ifekd at mapps\ekd at end@apparatus\fi%
+    \if at pkg@parnotes\parnotes\parnotereset\else\fi%
+  }%
+  \fi%
+}
+%    \end{macrocode}
+% Before inserting any new entry, \cs{add at apparatus} is called
+% \cs{test at apparatus} to decide whether a new apparatus block must be
+% created on a given page.
+%    \begin{macrocode}
+\def\add at apparatus{%
+  \test at apparatus%
+  \ifbool{do at app}{\subsq at unitfalse\add@@apparatus}{}%
+}
+%    \end{macrocode}
+% \cs{append at app} inserts a bare (sub)entry in the apparatus...
+%    \begin{macrocode}
+\NewDocumentCommand{\append at app}{o +m}{%
+  \ifekd at isinapp%
+    \ifekd at state%
+    \IfNoValueTF{#1}%
+      {\luadirect{ekdosis.appin(\luastringO{#2})}}%
+      {\luadirect{ekdosis.appin(\luastringO{#2}, \luastringO{#1})}}%
+    \fi%
+  \fi}
+%    \end{macrocode}
+% while \cs{append at ln@app} inserts a (sub)entry possibly preceded by a
+% line number.
+%    \begin{macrocode}
+\NewDocumentCommand{\append at 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 at 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 at isinapptrue%
+  \stepcounter{ekd at lab}%
+  \zlabel{ekd:\theekd at lab}%
+  \luadirect{ekdosis.storeabspg(
+    \luastring{\zref at extract{ekd:\theekd at lab}{abspage}})}%
+  \ifekd at state\add at apparatus\fi%
+  \luadirect{tex.sprint(ekdosis.removesp(\luastringN{#2}))}%
+  \ekd at isinappfalse%
+  \endgroup}
+%    \end{macrocode}
+% \end{macro}
+% \cs{current at 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 at ref@arg#1#2{{%\textdir TLT%
+    \unexpanded\expandafter{\ekd at refnumstyle}%
+    \ifnum%
+    \getpagerefnumber{#1}
+    =
+    \getpagerefnumber{#2}
+    \ifnum%
+    \getrefnumber{#1}
+    =
+    \getrefnumber{#2}
+    % 
+    \ifekd at mapps%
+    \ifbool{subsq at unit@\ekdan at 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 at 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 at postrefnum}%
+}
+%    \end{macrocode}
+% \cs{current at ref} is pretty much the same as \cs{current at 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 at ref{{%\textdir TLT%
+    \unexpanded\expandafter{\ekd at 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 at mapps%
+    \ifbool{subsq at unit@\ekdan at 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 at 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 at 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 at wit{#1},
+  code alt  = \def\ekdlr at alt{#1},
+  code pre = \def\ekdlr at pre{#1},
+  code post = \def\ekdlr at post{#1},
+  code prewit = \def\ekdlr at prewit{#1},
+  code postwit = \def\ekdlr at postwit{#1},
+  store type = \ekdlr at type,
+  store sep = \ekdl at sep,
+  bool nolem = \ifekdl at nolem,
+  bool nosep = \ifekdl at nosep,
+  initial sep = \ekdsep
+}
+\ekvdefinekeys{rdg}{
+  code wit = \def\ekdlr at wit{#1},
+  code alt  = \def\ekdlr at alt{#1},
+  code pre = \def\ekdlr at pre{#1},
+  code post = \def\ekdlr at post{#1},
+  code prewit = \def\ekdlr at prewit{#1},
+  code postwit = \def\ekdlr at postwit{#1},
+  store type = \ekdlr at type,
+  bool nordg = \ifekdr at 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 at isinlemtrue%
+  \luadirect{ekdosis.dolnlab(\luastringN{#2})}%
+  \bgroup%
+  \ekvset{lem}{#1}%
+  \ifekd at mapps%
+    \ifnum%
+    \luadirect{tex.sprint(ekdosis.get_bagunits(\luastringO{\ekdan at type}))}
+    = 1
+    \boolfalse{subsq at unit@\ekdan at type}%
+    \fi%
+    \luadirect{ekdosis.increment_bagunits(\luastringO{\ekdan at type})}%
+    \def\ekd at munit@delim{%
+      \luadirect{tex.sprint(ekdosis.getappdelim(\luastringO{\ekdan at type}))}}%
+  \fi%
+  \ifekdl at nolem\edef\lem at app{%
+    % \hskip .75em
+    \ifekd at mapps
+    \ifbool{subsq at unit@\ekdan at type}%
+    {\ekd at munit@delim}{}%
+    \else%
+    \ifsubsq at unit\unexpanded\expandafter{\ekd at unit@delim}\fi%
+    \fi%
+    \current at ref}%\hskip .25em}%
+  \else%
+  \ifbool{al at rlmode}{%
+    \edef\lem at app{%
+      % \hskip .75em
+      \ifekd at mapps
+      \ifbool{subsq at unit@\ekdan at type}%
+      {\ekd at munit@delim}{}%
+      \else%
+      \ifsubsq at unit\unexpanded\expandafter{\ekd at unit@delim}\fi%
+      \fi%
+      \current at ref%\hskip .25em
+      \ifdefined\ekdlr at alt%
+        \ifdefined\ekdlr at post%
+          \space\unexpanded\expandafter{\ekdlr at post}\space\else\fi
+        {\textdir TRT\unexpanded\expandafter{\ekdlr at alt}}%
+        \ifdefined\ekdlr at pre%
+          \space\unexpanded\expandafter{\ekdlr at pre}\space\else\fi
+      \else
+        \ifdefined\ekdlr at post%
+          \space\unexpanded\expandafter{\ekdlr at post}\space\else\fi
+        {\textdir TRT\unexpanded{#2}}%
+        \ifdefined\ekdlr at pre%
+          \space\unexpanded\expandafter{\ekdlr at pre}\space\else\fi
+      \fi
+      \ifdefined\ekdlr at postwit%
+        \space\unexpanded\expandafter{\ekdlr at postwit}\else\fi
+      \ifdefined\ekdlr at wit\space\getsiglum{\ekdlr at wit}\else\fi
+      \ifdefined\ekdlr at prewit%
+        \space\unexpanded\expandafter{\ekdlr at prewit}\space\else\fi
+      \ifekdl at nosep\else\unexpanded\expandafter{\ekdl at sep}\fi
+    }%
+  }%
+  {%
+    \edef\lem at app{%
+      % \hskip .75em
+      \ifekd at mapps
+      \ifbool{subsq at unit@\ekdan at type}%
+      {\ekd at munit@delim}{}%
+      \else%
+      \ifsubsq at unit\unexpanded\expandafter{\ekd at unit@delim}\fi%
+      \fi%
+      \current at ref%\hskip .25em
+      \ifdefined\ekdlr at alt%
+        \ifdefined\ekdlr at pre%
+          \space\unexpanded\expandafter{\ekdlr at pre}\space\else\fi
+        \ltx at ifpackageloaded{babel}%
+          {\noexpand\selectlanguage{\languagename}%
+            \unexpanded\expandafter{\ekdlr at alt}}%
+          {\unexpanded\expandafter{\ekdlr at alt}}%
+        \ifdefined\ekdlr at post%
+          \space\unexpanded\expandafter{\ekdlr at post}\space\else\fi
+      \else
+        \ifdefined\ekdlr at pre%
+          \space\unexpanded\expandafter{\ekdlr at pre}\space\else\fi
+          \ltx at ifpackageloaded{babel}%
+          {\noexpand\selectlanguage{\languagename}\unexpanded{#2}}{%
+            \unexpanded{#2}}%
+        \ifdefined\ekdlr at post%
+          \space\unexpanded\expandafter{\ekdlr at post}\space\else\fi
+      \fi
+      \ifdefined\ekdlr at prewit%
+        \space\unexpanded\expandafter{\ekdlr at prewit}\space\else\fi
+      \ifdefined\ekdlr at wit\space\getsiglum{\ekdlr at wit}\else\fi
+      \ifdefined\ekdlr at postwit%
+        \space\unexpanded\expandafter{\ekdlr at postwit}\else\fi
+      \ifekdl at nosep\else\unexpanded\expandafter{\ekdl at sep}\fi
+    }%
+  }%
+  \fi%
+  \ifekd at mapps%
+  \append at ln@app[\ekdan at type]{\lem at app}%
+  \else%
+  \append at ln@app{\lem at app}%
+  \fi%
+  \egroup%
+  \ekd at isinlemfalse%
+  \subsq at 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 at nordg\append at app{}\else% do we need \append at app{} here? If
+  %                               % so, keep in mind \ifekd at mapps,
+  %                               like so:
+  \ifekdr at nordg%
+    \ifekd at mapps%
+      \append at app[\ekdan at type]{}%
+    \else%
+    \append at app{}%
+    \fi%
+  \else%
+  \ifbool{al at rlmode}{%
+    \edef\rdg at app{%
+      \ifdefined\ekdlr at alt%
+        \ifdefined\ekdlr at post%
+          \space\unexpanded\expandafter{\ekdlr at post}\space\else\fi
+        {\textdir TRT\unexpanded\expandafter{\ekdlr at alt}}%
+        \ifdefined\ekdlr at pre%
+          \space\unexpanded\expandafter{\ekdlr at pre}\space\else\fi
+      \else
+        \ifdefined\ekdlr at post%
+          \space\unexpanded\expandafter{\ekdlr at post}\space\else\fi
+        {\textdir TRT\unexpanded{#2}}%
+        \ifdefined\ekdlr at pre%
+          \space\unexpanded\expandafter{\ekdlr at pre}\space\else\fi
+      \fi
+      \ifdefined\ekdlr at postwit%
+        \space\unexpanded\expandafter{\ekdlr at postwit}\else\fi
+      \ifdefined\ekdlr at wit\space\getsiglum{\ekdlr at wit}\else\fi
+      \ifdefined\ekdlr at prewit%
+        \space\unexpanded\expandafter{\ekdlr at prewit}\space\else\fi
+    }%
+  }%
+  {%
+    \edef\rdg at app{%
+      \ifdefined\ekdlr at alt%
+        \ifdefined\ekdlr at pre%
+          \space\unexpanded\expandafter{\ekdlr at pre}\space\else\fi
+        \ltx at ifpackageloaded{babel}%
+          {\noexpand\selectlanguage{\languagename}%
+            \unexpanded\expandafter{\ekdlr at alt}}%
+          {\unexpanded\expandafter{\ekdlr at alt}}%
+        \ifdefined\ekdlr at post%
+          \space\unexpanded\expandafter{\ekdlr at post}\space\else\fi
+      \else
+        \ifdefined\ekdlr at pre%
+          \space\unexpanded\expandafter{\ekdlr at pre}\space\else\fi
+          \ltx at ifpackageloaded{babel}%
+          {\noexpand\selectlanguage{\languagename}\unexpanded{#2}}{%
+            \unexpanded{#2}}%
+        \ifdefined\ekdlr at post%
+          \space\unexpanded\expandafter{\ekdlr at post}\space\else\fi
+      \fi
+      \ifdefined\ekdlr at prewit%
+        \space\unexpanded\expandafter{\ekdlr at prewit}\space\else\fi
+      \ifdefined\ekdlr at wit\space\getsiglum{\ekdlr at wit}\else\fi
+      \ifdefined\ekdlr at postwit%
+        \space\unexpanded\expandafter{\ekdlr at postwit}\else\fi
+    }%
+  }%
+  \ifekd at mapps%
+      \append at app[\ekdan at type]{\rdg at app}%
+  \else%
+  \append at app{\rdg at 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 at type,
+  store lem = \ekdn at lem,
+  code labelb = \def\ekdn at labelb{#1},
+  code labele = \def\ekdn at labele{#1},
+  store sep = \ekdn at sep,
+  initial type = default,
+  initial sep = \ekdsep
+}
+%    \end{macrocode}
+% \cs{note at 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 at noapp}{O{} +m}{%
+  \bgroup%
+  \ekvset{note}{#1}%
+  \stepcounter{ekd at lab}%
+  \zlabel{ekd:\theekd at lab}%
+  \luadirect{ekdosis.storeabspg(
+    \luastring{\zref at extract{ekd:\theekd at lab}{abspage}})}%
+  \ifekd at state\add at apparatus\fi%
+  \ifekd at mapps%
+    \ifnum%
+      \luadirect{tex.sprint(ekdosis.get_bagunits(\luastringO{\ekdan at type}))}
+      = 1
+      \boolfalse{subsq at unit@\ekdan at type}%
+    \fi%
+  \luadirect{ekdosis.increment_bagunits(\luastringO{\ekdan at type})}%
+    \def\ekd at munit@delim{%
+      \luadirect{tex.sprint(ekdosis.getappdelim(\luastringO{\ekdan at type}))}}%
+  \fi%  
+  \ifdefined\ekdn at labelb%
+    \luadirect{tex.sprint(ekdosis.setnotelab(\luastringO{\ekdn at labelb}))}%
+    \ifdefined\ekdn at labele\else\def\ekdn at labele{\ekdn at labelb}\fi%
+  \else\PackageError{ekdosis}{missing labelb}{`labelb' must be
+    set.}\fi%
+  \ifbool{al at rlmode}%
+  {\edef\note at contents{%
+      % \hskip .75em
+      \ifekd at mapps
+        \ifbool{subsq at unit@\ekdan at type}%
+        {\ekd at munit@delim}{}%
+      \else%
+        \ifsubsq at unit\unexpanded\expandafter{\ekd at unit@delim}\fi%
+      \fi%
+      \current at ref@arg{\ekdn at labelb}{\ekdn at labele}%\hskip .25em
+      \ifdefined\ekdn at lem%
+          {\textdir TRT\unexpanded\expandafter{\ekdn at lem}}%
+          \unexpanded\expandafter{\ekdn at sep}\else\fi%
+            {\textdir TRT\unexpanded{#2}}}}%
+  {\edef\note at contents{%
+      % \hskip .75em
+      \ifekd at mapps
+        \ifbool{subsq at unit@\ekdan at type}%
+        {\ekd at munit@delim}{}%
+      \else%
+        \ifsubsq at unit\unexpanded\expandafter{\ekd at unit@delim}\fi%
+      \fi%
+      \current at ref@arg{\ekdn at labelb}{\ekdn at labele}%\hskip .25em
+      \ifdefined\ekdn at lem
+        \ltx at ifpackageloaded{babel}%
+          {\noexpand\selectlanguage{\languagename}%
+            \unexpanded\expandafter{\ekdn at lem}}%
+          {\unexpanded\expandafter{\ekdn at lem}}%
+          \unexpanded\expandafter{\ekdn at sep}\else\fi%
+          \ltx at ifpackageloaded{babel}%
+          {\noexpand\selectlanguage{\languagename}\unexpanded{#2}}{%
+            \unexpanded{#2}}}}%
+  \ifekd at mapps%
+  \unconditional at appin[\ekdan at type]{\note at contents}%
+  \else%
+  \unconditional at appin{\note at contents}%
+  \fi%
+    \luadirect{ekdosis.setprevnotelab(\luastringO{\ekdn at labelb})}%
+  \egroup%
+  \subsq at 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 at note}{
+  store pre = \pre at value,
+  store post = \post at value
+}
+%    \end{macrocode}
+% The following three commands, \cs{note at app}, \cs{ekd at note} and
+% \cs{ekd at 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 at app} and subsequently \cs{ekd at note} and
+% \cs{ekd at note@star} accept the optional key-value arguments just
+% defined above.
+%    \begin{macrocode}
+\NewDocumentCommand{\ekd at note}{O{} m}{%
+  \bgroup%
+  \ekvset{ekd at note}{#1}%
+  \edef\note at contents{%
+    \ekvifdefinedNoVal{note}{pre}{}{%
+      \unexpanded\expandafter{\pre at value}}%
+    \unexpanded{#2}%
+    \ekvifdefinedNoVal{note}{post}{}{%
+      \unexpanded\expandafter{\post at value}}%
+  }%
+  \append at app{\note at contents}%
+  \egroup%
+}
+\NewDocumentCommand{\ekd at note@star}{O{} m}{%
+  \if at pkg@parnotes
+    \bgroup%
+      \ekvset{ekd at note}{#1}%
+      \edef\note at contents{%
+        \ekvifdefinedNoVal{note}{pre}{}{%
+          \unexpanded\expandafter{\pre at value}}%
+        \unskip\noexpand\parnote{#2}%
+        \ekvifdefinedNoVal{note}{post}{}{%
+          \unexpanded\expandafter{\post at value}}%
+      }%
+      \append at app{\note at contents}%
+    \egroup%
+  \else
+    \append at app{\unskip\footnote{#2}}%
+  \fi%
+}
+\NewDocumentCommand{\note at app}{s O{} +m}{%
+  \ifbool{al at rlmode}{%
+    \IfBooleanTF{#1}{\ekd at note@star[#2]{%
+          {\textdir TRT#3}}}
+    {\ekd at note[#2]{{\textdir TRT#3}}}%
+  }{%
+    \IfBooleanTF{#1}{\ekd at note@star[#2]{#3}}
+    {\ekd at 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 at app} in the former
+% case and \cs{note at noapp} in the latter case:---
+%    \begin{macrocode}
+\NewDocumentCommand{\note}{s O{} +m}{%
+  \ifekd at state%
+    \ifekd at isinapp%
+      \ifekd at isinlem%
+        \note at noapp[#2]{#3}%
+      \else%
+        \IfBooleanTF{#1}{\note at app*[#2]{#3}}{\note at app[#2]{#3}}%
+      \fi%
+    \else%
+      \note at 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 at apparatus}{}{%
+  \luadirect{tex.sprint(ekdosis.testapparatus())}}
+\NewDocumentCommand{\ekd at storecol}{}{%
+  \luadirect{ekdosis.storecurcol(\luastring{\thecolumn})}%
+}
+%    \end{macrocode}
+% Start and stop |ekdosis|:
+%    \begin{macrocode}
+\NewDocumentCommand{\EkdosisOn}{}{%
+  \ekd at statetrue}
+\NewDocumentCommand{\EkdosisOff}{}{%
+  \ekd at statefalse%
+}
+%    \end{macrocode}
+% Neutralize unwanted commands provided by \pkg{lineno} within the
+% \env{ekdosis} environment:---
+%    \begin{macrocode}
+\def\ekd at 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 at setlineno%
+  \runninglinenumbers
+    \EkdosisOn#1}{%
+    \EkdosisOff
+  \endrunninglinenumbers%
+  \iftei at 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 at pagelineation
+\ekvdefinekeys{ekd at align}{
+  store tcols = \tcols at num,
+  store lcols = \lcols at num,
+  store texts = \texts at value,
+  store apparatus = \apparatus at value,
+  bool paired = \ifekd at paired,
+  choice lineation = {page = \ekd at pagelineationtrue,
+                      document = \ekd at pagelineationfalse},
+  unknown-choice lineation = \PackageError{ekdosis}{unknown
+    lineation=#1}{`lineation' must be either `page' or `document'.},
+  choice segmentation = {auto = \def\segmentation at val{auto},
+                         noauto = \def\segmentation at val{noauto}},
+  unknown-choice segmentation = \PackageError{ekdosis}{unknown
+    segmentation=#1}{`segmentation' must be either `auto' or
+    `noauto'.},
+  bool flush = \ifekd at 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 at align}{#1}
+}
+%    \end{macrocode}
+% \end{macro}
+% Patch \pkg{paracol} to insert a hook in \cs{pcol at nextpage}. This
+% hook is used to reset line numbers on new pages.
+%    \begin{macrocode}
+\patchcmd{\pcol at nextpage}{%
+  \endgroup}{%
+  \ifekd at 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 at setlineno%
+  \runninglinenumbers
+  \ekd at storecol%
+  \stepcounter{ekd at lab}%
+  \zlabel{ekd:\theekd at lab}%
+  \luadirect{%
+    ekdosis.storeabspg(\luastring{\zref at extract{ekd:\theekd at lab}{abspage}},
+    "pg_i")}%
+  \ifekd at pagelineation
+    \luadirect{tex.sprint(ekdosis.checkresetlineno())}
+  \fi
+}
+\NewDocumentCommand{\EkdosisColStop}{}{%
+  \stepcounter{ekd at lab}%
+  \zlabel{ekd:\theekd at lab}%
+  \luadirect{%
+    ekdosis.storeabspg(\luastring{\zref at extract{ekd:\theekd at 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 at align}{#1}%
+  \luadirect{ekdosis.mkenvdata(
+    \luastring{\texts at value},
+    "texts"
+    )}
+  \ifekd at flushapp
+    \luadirect{ekdosis.newalignment("set")}
+  \fi
+  \luadirect{ekdosis.mkenvdata(
+    \luastring{\apparatus at value}, "apparatus"
+    )}
+  \setrunninglinenumbers
+  \luadirect{tex.sprint(ekdosis.mkenv())}
+  \ifekd at paired
+  \begin{paracol}[\lcols at num]{\tcols at num}
+  \else
+  \begin{paracol}[\lcols at num]*{\tcols at num}
+  \fi
+  }
+  {\end{paracol}
+  \iftei at export\luadirect{ekdosis.export_coldata_totei()}\fi
+  \ifekd at 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 at div}{
+  code type = \def\type at value{#1},
+  code n = \def\n at value{#1},
+  code head = \def\head at value{#1},
+  code barehead = \def\barehead at value{#1},
+  store depth = \depth at value,
+  choice toc = {book = \def\toc at value{book},
+                part = \def\toc at value{part},
+                chapter = \def\toc at value{chapter},
+                section = \def\toc at value{section},
+                subsection = \def\toc at value{subsection},
+                subsubsection = \def\toc at value{subsubsection},
+                paragraph = \def\toc at value{paragraph},
+                subparagraph = \def\toc at 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 at getfmtdiv} gets the formatting commands that have been
+% stored by \cs{ekdfmtdiv}.
+%    \begin{macrocode}
+\NewDocumentCommand{\ekd at 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 at div}{#1}%
+  \ifdefined\head at value
+    \bgroup
+      \ekd at getfmtdiv{\depth at value}{b}%
+      \head at value
+      \ekd at getfmtdiv{\depth at value}{e}%
+    \egroup
+      \ifdefined\toc at value
+        \ltx at ifpackageloaded{hyperref}{\phantomsection}{}%
+          \ifdefined\barehead at value
+            \addcontentsline{toc}{\toc at value}{\barehead at value}%
+          \else
+            \addcontentsline{toc}{\toc at value}{\head at 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 at rb") * spce^1)
+local para = lpeg.P(lpeg.Cs("\\p at ra") * spce^1)
+
+-- Bind to local variables
+local next = next
+
+-- General
+xmlids = {}
+
+local function xmlidfound(element)
+   for i = 1,#xmlids do
+      if xmlids[i].xmlid == element then
+	 return true
+      end
+   end
+   return false
+end
+
+-- Witnesses
+listWit = {}
+idsRend = {}
+shorthands = {}
+
+local function isfound(table, value)
+   for i = 1,#table do
+      if table[i] == value then
+	 return true
+      end
+   end
+   return false
+end
+
+local function isintable(table, value)
+   for i = 1,#table do
+      if table[i].a == value then
+	 return true
+      end
+   end
+   return false
+end
+
+local function get_a_index(id, table)
+   local idfound = nil
+   for i = 1,#table
+   do
+      if table[i].a == id then
+	 idfound = i
+	 break
+      end
+   end
+   return idfound
+end
+
+local function getindex(id, table)
+   local idfound = nil
+   for i = 1,#table
+   do
+      if table[i].xmlid == id then
+	 idfound = i
+	 break
+      end
+   end
+   return idfound
+end
+
+function ekdosis.newwitness(id,
+			    siglum,
+			    description,
+			    Settlement,
+			    Institution,
+			    Repository,
+			    Collection,
+			    Idno,
+			    MsName,
+			    OrigDate)
+   if xmlidfound(id)
+   then
+      tex.print("\\unexpanded{\\PackageWarning{ekdosis}{\""
+      	 ..id..
+      	 "\" already exists as a xml:id. "
+      	 ..
+      	 "Please pick another id.}}")
+   else
+      table.insert(xmlids, {xmlid = id})
+      table.sort(xmlids, function(a ,b) return(#a.xmlid > #b.xmlid) end)
+      table.insert(idsRend, {xmlid = id, abbr = siglum})
+      table.sort(idsRend, function(a ,b) return(#a.xmlid > #b.xmlid) end)
+      table.insert(listWit, {xmlid = id,
+			     abbr = siglum,
+			     detailsDesc = description,
+			     msIdentifier = {
+				settlement = Settlement,
+				institution = Institution,
+				repository = Repository,
+				collection = Collection,
+				idno = Idno,
+				msName = MsName}
+                             })
+      local indexwit = getindex(id, listWit)
+      if OrigDate ~= "" then
+	 listWit[indexwit].history = {}
+	 listWit[indexwit].history.origin = {origDate = OrigDate}
+      end
+   end
+   return true
+end
+
+function ekdosis.newhand(id, witid, siglum, description)
+   if xmlidfound(id) or not xmlidfound(witid)
+   then
+      tex.print("\\unexpanded{\\PackageWarning{ekdosis}{\""
+      	 ..id..
+      	 "\" already exists as a xml:id. "
+      	 ..
+      	 "Please pick another id.}}")
+   else
+      table.insert(xmlids, {xmlid = id})
+      table.sort(xmlids, function(a ,b) return(#a.xmlid > #b.xmlid) end)
+      table.insert(idsRend, {xmlid = id, abbr = siglum})
+      table.sort(idsRend, function(a ,b) return(#a.xmlid > #b.xmlid) end)
+      local indexwit = getindex(witid, listWit)
+      -- listWit[indexwit].handDesc = {xmlid = id, abbr = siglum, handNote = description}
+      if listWit[indexwit].handDesc == nil
+      then
+	 listWit[indexwit].handDesc = {}
+      else
+      end
+      table.insert(listWit[indexwit].handDesc,
+		   {xmlid = id, abbr = siglum, detailsDesc = description})
+   end
+   return true
+end
+
+function ekdosis.newshorthand(id, rend, xmlids)
+   if isintable(shorthands, id)
+   then
+      tex.print("\\unexpanded{\\PackageWarning{ekdosis}{\""
+      	 ..id..
+      	 "\" already exists as a shorthand. "
+      	 ..
+      	 "Please pick another shorthand.}}")
+   else
+      table.insert(shorthands, { a = id, b = rend, c = xmlids })
+      table.sort(shorthands, function(a ,b) return(#a.a > #b.a) end)
+      table.insert(idsRend, {xmlid = id, abbr = rend})
+      table.sort(idsRend, function(a ,b) return(#a.xmlid > #b.xmlid) end)
+   end
+   return true
+end
+
+local xmlbibresource = nil
+
+function ekdosis.setxmlbibresource(str)
+   xmlbibresource = str..".xml"
+   return true
+end
+
+function ekdosis.newscholar(id, siglum)
+   if xmlidfound(id)
+   then
+      tex.print("\\unexpanded{\\PackageWarning{ekdosis}{\""
+	    ..id..
+	    "\" already exists as a xml:id. " 
+	    ..
+	    "Please pick another id.}}")
+   else
+      table.insert(xmlids, {xmlid = id})
+      table.sort(xmlids, function(a ,b) return(#a.xmlid > #b.xmlid) end)
+      table.insert(idsRend, {xmlid = id, abbr = siglum})
+      table.sort(idsRend, function(a ,b) return(#a.xmlid > #b.xmlid) end)
+   end
+   return true
+end
+
+function ekdosis.getsiglum(str, opt)
+   str = str..","
+   str = string.gsub(str, "%s-(%,)", "%1")
+   ctrl = str
+   if opt == "tei" then
+      for i = 1,#shorthands do
+	 str = string.gsub(str, shorthands[i].a, shorthands[i].c)
+      end
+      for i = 1,#idsRend do
+	 str  = string.gsub(str, "(%f[%w])"..idsRend[i].xmlid.."(%,)",
+			    "%1#"..idsRend[i].xmlid.."%2")
+	 ctrl = string.gsub(ctrl, idsRend[i].xmlid.."%,", "")
+      end
+      str = string.gsub(str, "%,(%s-)([%#])", " %2")
+      str = string.gsub(str, "%,$", "")
+   else
+      for i = 1,#idsRend do
+	 str  = string.gsub(str, idsRend[i].xmlid.."%,", idsRend[i].abbr)
+	 ctrl = string.gsub(ctrl, idsRend[i].xmlid.."%,", "")
+      end
+   end
+   -- if string.find(ctrl, "[A-Za-z0-9]")
+   if string.find(ctrl, "%S")
+   then
+      return "<??>"
+   else
+      return str
+   end
+end
+
+-- begin totei functions
+
+local cmdtotags = {
+   {a="textsuperscript", b="hi", c=" rend=\"sup\""},
+   {a="textsubscript", b="hi", c=" rend=\"sub\""},
+   {a="LRfootnote", b="note", c=" place=\"bottom\""},
+   {a="RLfootnote", b="note", c=" place=\"bottom\""},
+   {a="enquote *", b="quote", c=""},
+   {a="footnote", b="note", c=" place=\"bottom\""},
+   {a="enquote", b="quote", c=""},
+   {a="txtrans", b="s", c=" xml:lang=\"ar-Latn\" type=\"transliterated\""},
+   {a="textbf", b="hi", c=" rend=\"bold\""},
+   {a="textit", b="hi", c=" rend=\"italic\""},
+   {a="textsc", b="hi", c=" rend=\"smallcaps\""},
+   {a="textsf", b="hi", c=" rend=\"sf\""},
+   {a="arbup", b="hi", c=" rend=\"sup\""},
+   {a="txarb", b="s", c=" xml:lang=\"arb\""},
+   {a="arb", b="foreign",
+    c=" xml:lang=\"ar-Latn\" type=\"transliterated\" subtype=\"arabtex\""}
+}
+
+local texpatttotags = {
+   {a="\\icite%s?%[(.-)%]%[(.-)%]{(.-)}", b="%1 <ref target=\"#%3\">%2</ref>"},
+   {a="\\icite%s?%[(.-)%]{(.-)}", b="<ref target=\"#%2\">%1</ref>"},
+   {a="\\icite%s?{(.-)}", b="<ptr target=\"#%1\"/>"},
+   {a="\\linelabel%s?{(.-)}", b="<anchor xml:id=\"%1\"/>"},
+   {a="\\label%s?{(.-)}", b="<anchor xml:id=\"%1\"/>"},
+   {a="\\v?pageref%s?{(.-)}", b="<ptr target=\"#%1\"/>"},
+   {a="\\v?ref%s?{(.-)}", b="<ptr target=\"#%1\"/>"}
+}
+
+local envtotags = {
+   {a="flushright", b="p", c=" rend=\"align(right)\""},
+   {a="flushleft", b="p", c=" rend=\"align(left)\""},
+   {a="quotation", b="quote", c=""},
+   {a="ekdverse", b="lg", c=""},
+   {a="txarabtr", b="p", c=" xml:lang=\"ar-Latn\" type=\"transliterated\""},
+   {a="txarab", b="p", c=" xml:lang=\"arb\""},
+   {a="center", b="p", c=" rend=\"align(center)\""},
+   {a="verse", b="lg", c=""},
+   {a="arab", b="p",
+    c=" xml:lang=\"ar-Latn\" type=\"transliterated\" subtype=\"arabtex\""}
+}
+
+local close_p = {
+   "p",
+   "lg"
+}
+
+local forbid_xmlid = true
+
+function ekdosis.newcmdtotag(cmd, tag, attr)
+   if forbid_xmlid
+   then
+      attr = string.gsub(attr, "xml:id", "n") -- xml:id is not allowed here
+   else
+   end
+   if isintable(cmdtotags, cmd)
+   then
+      local index = get_a_index(cmd, cmdtotags)
+      table.remove(cmdtotags, index)
+      table.insert(cmdtotags, {a = cmd, b = tag, c = " "..attr})
+      table.sort(cmdtotags, function(a ,b) return(#a.a > #b.a) end)
+   else
+      table.insert(cmdtotags, {a = cmd, b = tag, c = " "..attr})
+      table.sort(cmdtotags, function(a ,b) return(#a.a > #b.a) end)
+   end
+   return true
+end
+
+function ekdosis.newpatttotag(pat, repl)
+   pat = string.gsub(pat, "([%[%]])", "%%%1")
+   pat = string.gsub(pat, "%#[1-9]", "(.-)")
+   repl = string.gsub(repl, "%#([1-9])", "%%%1")
+   table.insert(texpatttotags, { a = pat, b = repl })
+   table.sort(texpatttotags, function(a ,b) return(#a.a > #b.a) end)
+   return true
+end
+
+function ekdosis.newenvtotag(env, tag, attr, closep)
+   if forbid_xmlid
+   then
+      attr = string.gsub(attr, "xml:id", "n") -- xml:id is not allowed here
+   else
+   end
+   if isintable(envtotags, env)
+   then
+      local index = get_a_index(env, envtotags)
+      table.remove(envtotags, index)
+      table.insert(envtotags, {a = env, b = tag, c = " "..attr, d = closep})
+      table.sort(envtotags, function(a ,b) return(#a.a > #b.a) end)
+   else
+      table.insert(envtotags, {a = env, b = tag, c = " "..attr, d = closep})
+      table.sort(envtotags, function(a ,b) return(#a.a > #b.a) end)
+   end
+   return true
+end
+
+-- Get values of attributes
+local function get_attr_value(str, attr)
+   str = str..","
+   local attrval = string.match(str, "%f[%w]"..attr.."%s?%=%s?%b{}")
+      or string.match(str, "%f[%w]"..attr.."%s?%=%s?.-%,")
+      or ""
+   attrval = string.gsub(attrval, attr.."%s?%=%s?(%b{})", function(bbraces)
+			    bbraces = string.sub(bbraces, 2, -2)
+			    return string.format("%s", bbraces)
+   end)
+   attrval = string.gsub(attrval, attr.."%s?%=%s?(.-)%s?%,", "%1")
+   return attrval
+end
+
+local function xml_entities(str)
+   str = string.gsub(str, "%<", "<")
+   str = string.gsub(str, "%>", ">")
+   return str
+end
+
+local function note_totei(str)
+   str = gsub(str,
+	      dblbkslash *
+		 note *
+		 spcenc^-1 *
+		 bsqbrackets *
+		 bcbraces *
+		 spcenc^-1,
+	      function(bkslash, cmd, opt, arg)
+		 opt = string.sub(opt, 2, -2)
+		 arg = string.sub(arg, 2, -2)
+		 teitype = get_attr_value(opt, "type")
+		 if teitype ~= "" then teitype = " type=\""..teitype.."\"" else end
+		 right = get_attr_value(opt, "labelb")
+		 left = get_attr_value(opt, "labele")
+		 if left ~= ""
+		 then
+		    return string.format(
+		       "<%s%s target=\"#range(right(%s),left(%s))\">%s</%s><anchor xml:id=\"%s\"/>",
+		       cmd, teitype, right, left, arg, cmd, right)
+		 elseif left == ""
+		 then
+		    return string.format(
+		       "<%s%s target=\"#right(%s)\">%s</%s><anchor xml:id=\"%s\"/>",
+		       cmd, teitype, right, arg, cmd, right)
+		 end
+   end)
+   return str
+end
+
+local function app_totei(str)
+   str = gsub(str,
+	      dblbkslash *
+		 app *
+		 spcenc^-1 *
+		 bsqbrackets *
+		 bcbraces *
+		 spcenc^-1,
+	      function(bkslash, cmd, opt, arg)
+		 opt = string.sub(opt, 2, -2)
+		 arg = string.sub(arg, 2, -2)
+		 opt = get_attr_value(opt, "type")
+		 if opt ~= "" then opt = " type=\""..opt.."\"" else end
+		 return app_totei(string.format("<%s%s>%s</%s>",
+						cmd, opt, arg, cmd))
+   end)
+   return str
+end
+
+local function lem_rdg_totei(str)
+   str = gsub(str,
+	      spcenc^-1 *
+		 dblbkslash *
+		 lemrdg *
+		 spcenc^-1 *
+		 bsqbrackets *
+		 bcbraces *
+		 spcenc^-1,
+	      function(bkslash, cmd, opt, arg)
+		 opt = string.sub(opt, 2, -2)
+		 arg = string.sub(arg, 2, -2)
+		 -- opt = get_attr_value(opt, "wit")
+		 --
+		 teiwit = get_attr_value(opt, "wit")
+		 if teiwit ~= "" then teiwit = " wit=\""..ekdosis.getsiglum(teiwit, "tei").."\"" else end
+		 teitype = get_attr_value(opt, "type")
+		 if teitype ~= "" then teitype = " type=\""..teitype.."\"" else end
+		 --
+		 if opt == ""
+		 then
+		    return lem_rdg_totei(string.format("<%s>%s</%s>",
+						       cmd, arg, cmd))
+		 else
+		    -- opt = ekdosis.getsiglum(opt, "tei")
+		    return lem_rdg_totei(string.format("<%s%s%s>%s</%s>",
+						       cmd, teiwit, teitype, arg, cmd))
+		 end
+   end)
+   str = gsub(str, spcenc^-0 * dblbkslash * lemrdg * spcenc^-1 * bcbraces * spcenc^-1,
+	      function(bkslash, cmd, arg)
+		 arg = string.sub(arg, 2, -2)
+		 return lem_rdg_totei(string.format("<%s>%s</%s>", cmd, arg, cmd))
+   end)
+   return str
+end
+
+local function relocate_notes(str)
+   str = string.gsub(str, "(%<lem.-%>.-)(%<note.->.-%<%/note%>)(.-%<%/lem%>)", "%1%3%2")
+   return str
+end
+
+local function linestotei(str)
+--   str = "\n<l>"..str
+   str = string.gsub(str, "^%s?(.-)%s?$", "\n<l>%1</l>\n")
+--   str = gsub(str, endpoem, "</l>\n")
+   str = gsub(str, poemline * spcenc^-1 * lpeg.P(">"), "\n<lb/>")
+   str = gsub(str, poemline * spcenc^-1, "</l>\n<l>")
+--   str = str.."</l>\n"
+   return str
+end
+
+-- better use lpeg: look into this later
+local function versetotei(str)
+   str = string.gsub(str, "(\\begin%s?%{ekdverse%})(%b[])(.-)(\\end%s?%{ekdverse%})", function(benv, opt, arg, eenv)
+			arg = linestotei(arg)
+			return string.format("%s%s%s%s", benv, opt, arg, eenv)
+   end)
+   str = string.gsub(str, "(\\begin%s?%{ekdverse%})(.-)(\\end%s?%{ekdverse%})", function(benv, arg, eenv)
+			arg = linestotei(arg)
+			return string.format("%s%s%s", benv, arg, eenv)
+   end)
+   str = string.gsub(str, "(\\begin%s?%{verse%})(%b[])(.-)(\\end%s?%{verse%})", function(benv, opt, arg, eenv)
+			arg = linestotei(arg)
+			return string.format("%s%s%s%s", benv, opt, arg, eenv)
+   end)
+   str = string.gsub(str, "(\\begin%s?%{verse%})(.-)(\\end%s?%{verse%})", function(benv, arg, eenv)
+			arg = linestotei(arg)
+			return string.format("%s%s%s", benv, arg, eenv)
+   end)
+   return str
+end
+
+local function envtotei(str)
+   for i = 1,#envtotags
+   do
+      if envtotags[i].b ~= ""
+      then
+	 if isfound(close_p, envtotags[i].b) or envtotags[i].d == "yes"
+	 then
+	    str = gsub(str, lpeg.P("\\begin") * spcenc^-1 * lpeg.P("{")
+			  * lpeg.Cs(envtotags[i].a) * lpeg.P("}")
+			  * bsqbracketsii * bcbracesii * spcenc^-1,
+		       "\\p at 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 at 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 at r ")
+   str = string.gsub(str, "\\p at ra%s+", "<p>")
+   str = string.gsub(str, "\\p at rb%s+", "</p>")
+   str = string.gsub(str, "\\p at 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 at rb <div%s%s%s><head>%s</head>\\p at 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 at rb <div%s type=\"%s\"><head>%s</head>\\p at 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 at 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 at 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 at 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 at 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 at 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 at default@rule\\endcsname\\NLS{}")
+		  else
+--		     table.insert(output, "\\noindent ")
+		     table.insert(output, "\\csname ekd at 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 at app}"
+      else
+	 return "\\boolfalse{do at app}"
+      end
+   else
+      table.insert(curcol_curabspg, curcol.."-"..cur_abs_pg)
+      if next(apparatuses) ~= nil then
+	 reset_bagunits()
+      end
+      return "\\booltrue{do at 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 at app\\endcsname{"
+      .. remove_note(str) .. "}"
+   else
+   return "\\linelabel{" .. current_lnlab .. "-b}\\wordboundary{}"
+      ..
+      current_lemma
+      ..
+      "\\linelabel{" .. current_lnlab .. "-e}"
+      ..
+      "\\csname append at 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


Property changes on: trunk/Master/texmf-dist/source/lualatex/ekdosis/ekdosis.dtx
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/source/lualatex/ekdosis/ekdosis.ins
===================================================================
--- trunk/Master/texmf-dist/source/lualatex/ekdosis/ekdosis.ins	                        (rev 0)
+++ trunk/Master/texmf-dist/source/lualatex/ekdosis/ekdosis.ins	2020-07-08 21:18:08 UTC (rev 55786)
@@ -0,0 +1,62 @@
+\input docstrip.tex
+\keepsilent
+\askforoverwritefalse
+\preamble
+-------:| -----------------------------------------------------------------
+ekdosis:| Typesetting TEI xml compliant critical editions
+ Author:| Robert Alessi
+ E-mail:| alessi at 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 at 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

Added: trunk/Master/texmf-dist/tex/lualatex/ekdosis/ekdosis.lua
===================================================================
--- trunk/Master/texmf-dist/tex/lualatex/ekdosis/ekdosis.lua	                        (rev 0)
+++ trunk/Master/texmf-dist/tex/lualatex/ekdosis/ekdosis.lua	2020-07-08 21:18:08 UTC (rev 55786)
@@ -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 at 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 at rb") * spce^1)
+local para = lpeg.P(lpeg.Cs("\\p at ra") * spce^1)
+
+-- Bind to local variables
+local next = next
+
+-- General
+xmlids = {}
+
+local function xmlidfound(element)
+   for i = 1,#xmlids do
+      if xmlids[i].xmlid == element then
+	 return true
+      end
+   end
+   return false
+end
+
+-- Witnesses
+listWit = {}
+idsRend = {}
+shorthands = {}
+
+local function isfound(table, value)
+   for i = 1,#table do
+      if table[i] == value then
+	 return true
+      end
+   end
+   return false
+end
+
+local function isintable(table, value)
+   for i = 1,#table do
+      if table[i].a == value then
+	 return true
+      end
+   end
+   return false
+end
+
+local function get_a_index(id, table)
+   local idfound = nil
+   for i = 1,#table
+   do
+      if table[i].a == id then
+	 idfound = i
+	 break
+      end
+   end
+   return idfound
+end
+
+local function getindex(id, table)
+   local idfound = nil
+   for i = 1,#table
+   do
+      if table[i].xmlid == id then
+	 idfound = i
+	 break
+      end
+   end
+   return idfound
+end
+
+function ekdosis.newwitness(id,
+			    siglum,
+			    description,
+			    Settlement,
+			    Institution,
+			    Repository,
+			    Collection,
+			    Idno,
+			    MsName,
+			    OrigDate)
+   if xmlidfound(id)
+   then
+      tex.print("\\unexpanded{\\PackageWarning{ekdosis}{\""
+      	 ..id..
+      	 "\" already exists as a xml:id. "
+      	 ..
+      	 "Please pick another id.}}")
+   else
+      table.insert(xmlids, {xmlid = id})
+      table.sort(xmlids, function(a ,b) return(#a.xmlid > #b.xmlid) end)
+      table.insert(idsRend, {xmlid = id, abbr = siglum})
+      table.sort(idsRend, function(a ,b) return(#a.xmlid > #b.xmlid) end)
+      table.insert(listWit, {xmlid = id,
+			     abbr = siglum,
+			     detailsDesc = description,
+			     msIdentifier = {
+				settlement = Settlement,
+				institution = Institution,
+				repository = Repository,
+				collection = Collection,
+				idno = Idno,
+				msName = MsName}
+                             })
+      local indexwit = getindex(id, listWit)
+      if OrigDate ~= "" then
+	 listWit[indexwit].history = {}
+	 listWit[indexwit].history.origin = {origDate = OrigDate}
+      end
+   end
+   return true
+end
+
+function ekdosis.newhand(id, witid, siglum, description)
+   if xmlidfound(id) or not xmlidfound(witid)
+   then
+      tex.print("\\unexpanded{\\PackageWarning{ekdosis}{\""
+      	 ..id..
+      	 "\" already exists as a xml:id. "
+      	 ..
+      	 "Please pick another id.}}")
+   else
+      table.insert(xmlids, {xmlid = id})
+      table.sort(xmlids, function(a ,b) return(#a.xmlid > #b.xmlid) end)
+      table.insert(idsRend, {xmlid = id, abbr = siglum})
+      table.sort(idsRend, function(a ,b) return(#a.xmlid > #b.xmlid) end)
+      local indexwit = getindex(witid, listWit)
+      -- listWit[indexwit].handDesc = {xmlid = id, abbr = siglum, handNote = description}
+      if listWit[indexwit].handDesc == nil
+      then
+	 listWit[indexwit].handDesc = {}
+      else
+      end
+      table.insert(listWit[indexwit].handDesc,
+		   {xmlid = id, abbr = siglum, detailsDesc = description})
+   end
+   return true
+end
+
+function ekdosis.newshorthand(id, rend, xmlids)
+   if isintable(shorthands, id)
+   then
+      tex.print("\\unexpanded{\\PackageWarning{ekdosis}{\""
+      	 ..id..
+      	 "\" already exists as a shorthand. "
+      	 ..
+      	 "Please pick another shorthand.}}")
+   else
+      table.insert(shorthands, { a = id, b = rend, c = xmlids })
+      table.sort(shorthands, function(a ,b) return(#a.a > #b.a) end)
+      table.insert(idsRend, {xmlid = id, abbr = rend})
+      table.sort(idsRend, function(a ,b) return(#a.xmlid > #b.xmlid) end)
+   end
+   return true
+end
+
+local xmlbibresource = nil
+
+function ekdosis.setxmlbibresource(str)
+   xmlbibresource = str..".xml"
+   return true
+end
+
+function ekdosis.newscholar(id, siglum)
+   if xmlidfound(id)
+   then
+      tex.print("\\unexpanded{\\PackageWarning{ekdosis}{\""
+	    ..id..
+	    "\" already exists as a xml:id. "
+	    ..
+	    "Please pick another id.}}")
+   else
+      table.insert(xmlids, {xmlid = id})
+      table.sort(xmlids, function(a ,b) return(#a.xmlid > #b.xmlid) end)
+      table.insert(idsRend, {xmlid = id, abbr = siglum})
+      table.sort(idsRend, function(a ,b) return(#a.xmlid > #b.xmlid) end)
+   end
+   return true
+end
+
+function ekdosis.getsiglum(str, opt)
+   str = str..","
+   str = string.gsub(str, "%s-(%,)", "%1")
+   ctrl = str
+   if opt == "tei" then
+      for i = 1,#shorthands do
+	 str = string.gsub(str, shorthands[i].a, shorthands[i].c)
+      end
+      for i = 1,#idsRend do
+	 str  = string.gsub(str, "(%f[%w])"..idsRend[i].xmlid.."(%,)",
+			    "%1#"..idsRend[i].xmlid.."%2")
+	 ctrl = string.gsub(ctrl, idsRend[i].xmlid.."%,", "")
+      end
+      str = string.gsub(str, "%,(%s-)([%#])", " %2")
+      str = string.gsub(str, "%,$", "")
+   else
+      for i = 1,#idsRend do
+	 str  = string.gsub(str, idsRend[i].xmlid.."%,", idsRend[i].abbr)
+	 ctrl = string.gsub(ctrl, idsRend[i].xmlid.."%,", "")
+      end
+   end
+   -- if string.find(ctrl, "[A-Za-z0-9]")
+   if string.find(ctrl, "%S")
+   then
+      return "<??>"
+   else
+      return str
+   end
+end
+
+-- begin totei functions
+
+local cmdtotags = {
+   {a="textsuperscript", b="hi", c=" rend=\"sup\""},
+   {a="textsubscript", b="hi", c=" rend=\"sub\""},
+   {a="LRfootnote", b="note", c=" place=\"bottom\""},
+   {a="RLfootnote", b="note", c=" place=\"bottom\""},
+   {a="enquote *", b="quote", c=""},
+   {a="footnote", b="note", c=" place=\"bottom\""},
+   {a="enquote", b="quote", c=""},
+   {a="txtrans", b="s", c=" xml:lang=\"ar-Latn\" type=\"transliterated\""},
+   {a="textbf", b="hi", c=" rend=\"bold\""},
+   {a="textit", b="hi", c=" rend=\"italic\""},
+   {a="textsc", b="hi", c=" rend=\"smallcaps\""},
+   {a="textsf", b="hi", c=" rend=\"sf\""},
+   {a="arbup", b="hi", c=" rend=\"sup\""},
+   {a="txarb", b="s", c=" xml:lang=\"arb\""},
+   {a="arb", b="foreign",
+    c=" xml:lang=\"ar-Latn\" type=\"transliterated\" subtype=\"arabtex\""}
+}
+
+local texpatttotags = {
+   {a="\\icite%s?%[(.-)%]%[(.-)%]{(.-)}", b="%1 <ref target=\"#%3\">%2</ref>"},
+   {a="\\icite%s?%[(.-)%]{(.-)}", b="<ref target=\"#%2\">%1</ref>"},
+   {a="\\icite%s?{(.-)}", b="<ptr target=\"#%1\"/>"},
+   {a="\\linelabel%s?{(.-)}", b="<anchor xml:id=\"%1\"/>"},
+   {a="\\label%s?{(.-)}", b="<anchor xml:id=\"%1\"/>"},
+   {a="\\v?pageref%s?{(.-)}", b="<ptr target=\"#%1\"/>"},
+   {a="\\v?ref%s?{(.-)}", b="<ptr target=\"#%1\"/>"}
+}
+
+local envtotags = {
+   {a="flushright", b="p", c=" rend=\"align(right)\""},
+   {a="flushleft", b="p", c=" rend=\"align(left)\""},
+   {a="quotation", b="quote", c=""},
+   {a="ekdverse", b="lg", c=""},
+   {a="txarabtr", b="p", c=" xml:lang=\"ar-Latn\" type=\"transliterated\""},
+   {a="txarab", b="p", c=" xml:lang=\"arb\""},
+   {a="center", b="p", c=" rend=\"align(center)\""},
+   {a="verse", b="lg", c=""},
+   {a="arab", b="p",
+    c=" xml:lang=\"ar-Latn\" type=\"transliterated\" subtype=\"arabtex\""}
+}
+
+local close_p = {
+   "p",
+   "lg"
+}
+
+local forbid_xmlid = true
+
+function ekdosis.newcmdtotag(cmd, tag, attr)
+   if forbid_xmlid
+   then
+      attr = string.gsub(attr, "xml:id", "n") -- xml:id is not allowed here
+   else
+   end
+   if isintable(cmdtotags, cmd)
+   then
+      local index = get_a_index(cmd, cmdtotags)
+      table.remove(cmdtotags, index)
+      table.insert(cmdtotags, {a = cmd, b = tag, c = " "..attr})
+      table.sort(cmdtotags, function(a ,b) return(#a.a > #b.a) end)
+   else
+      table.insert(cmdtotags, {a = cmd, b = tag, c = " "..attr})
+      table.sort(cmdtotags, function(a ,b) return(#a.a > #b.a) end)
+   end
+   return true
+end
+
+function ekdosis.newpatttotag(pat, repl)
+   pat = string.gsub(pat, "([%[%]])", "%%%1")
+   pat = string.gsub(pat, "%#[1-9]", "(.-)")
+   repl = string.gsub(repl, "%#([1-9])", "%%%1")
+   table.insert(texpatttotags, { a = pat, b = repl })
+   table.sort(texpatttotags, function(a ,b) return(#a.a > #b.a) end)
+   return true
+end
+
+function ekdosis.newenvtotag(env, tag, attr, closep)
+   if forbid_xmlid
+   then
+      attr = string.gsub(attr, "xml:id", "n") -- xml:id is not allowed here
+   else
+   end
+   if isintable(envtotags, env)
+   then
+      local index = get_a_index(env, envtotags)
+      table.remove(envtotags, index)
+      table.insert(envtotags, {a = env, b = tag, c = " "..attr, d = closep})
+      table.sort(envtotags, function(a ,b) return(#a.a > #b.a) end)
+   else
+      table.insert(envtotags, {a = env, b = tag, c = " "..attr, d = closep})
+      table.sort(envtotags, function(a ,b) return(#a.a > #b.a) end)
+   end
+   return true
+end
+
+-- Get values of attributes
+local function get_attr_value(str, attr)
+   str = str..","
+   local attrval = string.match(str, "%f[%w]"..attr.."%s?%=%s?%b{}")
+      or string.match(str, "%f[%w]"..attr.."%s?%=%s?.-%,")
+      or ""
+   attrval = string.gsub(attrval, attr.."%s?%=%s?(%b{})", function(bbraces)
+			    bbraces = string.sub(bbraces, 2, -2)
+			    return string.format("%s", bbraces)
+   end)
+   attrval = string.gsub(attrval, attr.."%s?%=%s?(.-)%s?%,", "%1")
+   return attrval
+end
+
+local function xml_entities(str)
+   str = string.gsub(str, "%<", "<")
+   str = string.gsub(str, "%>", ">")
+   return str
+end
+
+local function note_totei(str)
+   str = gsub(str,
+	      dblbkslash *
+		 note *
+		 spcenc^-1 *
+		 bsqbrackets *
+		 bcbraces *
+		 spcenc^-1,
+	      function(bkslash, cmd, opt, arg)
+		 opt = string.sub(opt, 2, -2)
+		 arg = string.sub(arg, 2, -2)
+		 teitype = get_attr_value(opt, "type")
+		 if teitype ~= "" then teitype = " type=\""..teitype.."\"" else end
+		 right = get_attr_value(opt, "labelb")
+		 left = get_attr_value(opt, "labele")
+		 if left ~= ""
+		 then
+		    return string.format(
+		       "<%s%s target=\"#range(right(%s),left(%s))\">%s</%s><anchor xml:id=\"%s\"/>",
+		       cmd, teitype, right, left, arg, cmd, right)
+		 elseif left == ""
+		 then
+		    return string.format(
+		       "<%s%s target=\"#right(%s)\">%s</%s><anchor xml:id=\"%s\"/>",
+		       cmd, teitype, right, arg, cmd, right)
+		 end
+   end)
+   return str
+end
+
+local function app_totei(str)
+   str = gsub(str,
+	      dblbkslash *
+		 app *
+		 spcenc^-1 *
+		 bsqbrackets *
+		 bcbraces *
+		 spcenc^-1,
+	      function(bkslash, cmd, opt, arg)
+		 opt = string.sub(opt, 2, -2)
+		 arg = string.sub(arg, 2, -2)
+		 opt = get_attr_value(opt, "type")
+		 if opt ~= "" then opt = " type=\""..opt.."\"" else end
+		 return app_totei(string.format("<%s%s>%s</%s>",
+						cmd, opt, arg, cmd))
+   end)
+   return str
+end
+
+local function lem_rdg_totei(str)
+   str = gsub(str,
+	      spcenc^-1 *
+		 dblbkslash *
+		 lemrdg *
+		 spcenc^-1 *
+		 bsqbrackets *
+		 bcbraces *
+		 spcenc^-1,
+	      function(bkslash, cmd, opt, arg)
+		 opt = string.sub(opt, 2, -2)
+		 arg = string.sub(arg, 2, -2)
+		 -- opt = get_attr_value(opt, "wit")
+		 --
+		 teiwit = get_attr_value(opt, "wit")
+		 if teiwit ~= "" then teiwit = " wit=\""..ekdosis.getsiglum(teiwit, "tei").."\"" else end
+		 teitype = get_attr_value(opt, "type")
+		 if teitype ~= "" then teitype = " type=\""..teitype.."\"" else end
+		 --
+		 if opt == ""
+		 then
+		    return lem_rdg_totei(string.format("<%s>%s</%s>",
+						       cmd, arg, cmd))
+		 else
+		    -- opt = ekdosis.getsiglum(opt, "tei")
+		    return lem_rdg_totei(string.format("<%s%s%s>%s</%s>",
+						       cmd, teiwit, teitype, arg, cmd))
+		 end
+   end)
+   str = gsub(str, spcenc^-0 * dblbkslash * lemrdg * spcenc^-1 * bcbraces * spcenc^-1,
+	      function(bkslash, cmd, arg)
+		 arg = string.sub(arg, 2, -2)
+		 return lem_rdg_totei(string.format("<%s>%s</%s>", cmd, arg, cmd))
+   end)
+   return str
+end
+
+local function relocate_notes(str)
+   str = string.gsub(str, "(%<lem.-%>.-)(%<note.->.-%<%/note%>)(.-%<%/lem%>)", "%1%3%2")
+   return str
+end
+
+local function linestotei(str)
+--   str = "\n<l>"..str
+   str = string.gsub(str, "^%s?(.-)%s?$", "\n<l>%1</l>\n")
+--   str = gsub(str, endpoem, "</l>\n")
+   str = gsub(str, poemline * spcenc^-1 * lpeg.P(">"), "\n<lb/>")
+   str = gsub(str, poemline * spcenc^-1, "</l>\n<l>")
+--   str = str.."</l>\n"
+   return str
+end
+
+-- better use lpeg: look into this later
+local function versetotei(str)
+   str = string.gsub(str, "(\\begin%s?%{ekdverse%})(%b[])(.-)(\\end%s?%{ekdverse%})", function(benv, opt, arg, eenv)
+			arg = linestotei(arg)
+			return string.format("%s%s%s%s", benv, opt, arg, eenv)
+   end)
+   str = string.gsub(str, "(\\begin%s?%{ekdverse%})(.-)(\\end%s?%{ekdverse%})", function(benv, arg, eenv)
+			arg = linestotei(arg)
+			return string.format("%s%s%s", benv, arg, eenv)
+   end)
+   str = string.gsub(str, "(\\begin%s?%{verse%})(%b[])(.-)(\\end%s?%{verse%})", function(benv, opt, arg, eenv)
+			arg = linestotei(arg)
+			return string.format("%s%s%s%s", benv, opt, arg, eenv)
+   end)
+   str = string.gsub(str, "(\\begin%s?%{verse%})(.-)(\\end%s?%{verse%})", function(benv, arg, eenv)
+			arg = linestotei(arg)
+			return string.format("%s%s%s", benv, arg, eenv)
+   end)
+   return str
+end
+
+local function envtotei(str)
+   for i = 1,#envtotags
+   do
+      if envtotags[i].b ~= ""
+      then
+	 if isfound(close_p, envtotags[i].b) or envtotags[i].d == "yes"
+	 then
+	    str = gsub(str, lpeg.P("\\begin") * spcenc^-1 * lpeg.P("{")
+			  * lpeg.Cs(envtotags[i].a) * lpeg.P("}")
+			  * bsqbracketsii * bcbracesii * spcenc^-1,
+		       "\\p at 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 at 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 at r ")
+   str = string.gsub(str, "\\p at ra%s+", "<p>")
+   str = string.gsub(str, "\\p at rb%s+", "</p>")
+   str = string.gsub(str, "\\p at 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 at rb <div%s%s%s><head>%s</head>\\p at 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 at rb <div%s type=\"%s\"><head>%s</head>\\p at 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 at 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 at 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 at 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 at 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 at 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 at default@rule\\endcsname\\NLS{}")
+		  else
+--		     table.insert(output, "\\noindent ")
+		     table.insert(output, "\\csname ekd at 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 at app}"
+      else
+	 return "\\boolfalse{do at app}"
+      end
+   else
+      table.insert(curcol_curabspg, curcol.."-"..cur_abs_pg)
+      if next(apparatuses) ~= nil then
+	 reset_bagunits()
+      end
+      return "\\booltrue{do at 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 at app\\endcsname{"
+      .. remove_note(str) .. "}"
+   else
+   return "\\linelabel{" .. current_lnlab .. "-b}\\wordboundary{}"
+      ..
+      current_lemma
+      ..
+      "\\linelabel{" .. current_lnlab .. "-e}"
+      ..
+      "\\csname append at app\\endcsname" .. "[" .. teitype ..  "]{"
+      .. remove_note(str) .. "}"
+   end
+end
+


Property changes on: trunk/Master/texmf-dist/tex/lualatex/ekdosis/ekdosis.lua
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/tex/lualatex/ekdosis/ekdosis.sty
===================================================================
--- trunk/Master/texmf-dist/tex/lualatex/ekdosis/ekdosis.sty	                        (rev 0)
+++ trunk/Master/texmf-dist/tex/lualatex/ekdosis/ekdosis.sty	2020-07-08 21:18:08 UTC (rev 55786)
@@ -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 at 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 at 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 at pkg@float
+\newif\if at pkg@footins
+\newif\if at pkg@ekddivs
+\newif\if at parnotesroman
+\newif\if at pkg@parnotes
+\newif\iftei at export
+\ekvdefinekeys{ekdosis}{
+  choice layout = {float = {\@pkg at floattrue},
+    footins = {\@pkg at footinstrue}},
+  initial layout = float,
+  unknown-choice layout = \PackageError{ekdosis}{unknown
+    layout=#1}{`layout' must be either `float' or `footins'.},
+  choice divs = {ekdosis = {\@pkg at ekddivstrue},
+    latex = {\@pkg at 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 at parnotestrue},
+    roman = {\@pkg at 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 at exporttrue
+      \AtBeginDocument{\luadirect{ekdosis.openteistream()}}%
+      \AtEndDocument{\luadirect{ekdosis.closeteistream()}}},
+    tidy = {\tei at 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 at pkg@parnotes
+  \RequirePackage{parnotes}
+\fi
+\luadirect{dofile(kpse.find_file("ekdosis.lua"))}
+\AtEndDocument{
+  \luadirect{ekdosis.closestream()}
+}
+\renewcommand\linenumberfont{\normalfont\footnotesize}
+\ekvdefinekeys{ekd at hooks}{
+  store appfontsize = \ekd at appfontsize,
+  store refnumstyle = \ekd at refnumstyle,
+  store postrefnum = \ekd at postrefnum,
+  initial appfontsize = \footnotesize,
+  initial refnumstyle = \bfseries,
+  initial postrefnum = ~
+}
+\NewDocumentCommand{\SetEkdosisHooks}{m}{\ekvset{ekd at hooks}{#1}}
+\ekvdefinekeys{ekd at witness}{
+  store settlement = \settlement at value,
+  store institution = \institution at value,
+  store repository = \repository at value,
+  store collection = \collection at value,
+  store idno = \idno at value,
+  store msName = \msName at value,
+  store origDate = \origDate at value
+}
+\NewDocumentCommand{\DeclareWitness}{m m m O{}}{%
+  \bgroup
+  \ekvset{ekd at witness}{#4}
+    \luadirect{ekdosis.newwitness(
+      \luastringN{#1},
+      \luastringN{#2},
+      \luastringN{#3},
+      \luastringO{\settlement at value},
+      \luastringO{\institution at value},
+      \luastringO{\repository at value},
+      \luastringO{\collection at value},
+      \luastringO{\idno at value},
+      \luastringO{\msName at value},
+      \luastringO{\origDate at 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 at mapps
+\ekvdefinekeys{ekd at newapp}{
+  choice direction = {LR = \def\direction at val{LR},
+                      RL = \def\direction at val{RL}},
+  unknown-choice direction = \PackageError{ekdosis}{unknown
+    direction=#1}{`direction' must be either `LR' or `RL'.},
+  store rule = \rule at val,
+  store delim = \delim at val,
+  store sep = \sep at val,
+  store bhook = \bhook at val,
+  store ehook = \ehook at val,
+  initial direction = LR,
+  initial ehook = {\csname ekd at end@apparatus\endcsname}
+}
+\NewDocumentCommand{\DeclareApparatus}{m O{}}{
+  \newbool{subsq at unit@#1}
+  \booltrue{subsq at unit@#1}
+  \unless\ifekd at mapps\global\ekd at mappstrue\fi
+  \bgroup
+  \ekvset{ekd at newapp}{#2}
+  \luadirect{ekdosis.newapparatus(
+    \luastringN{#1},
+    \luastring{\direction at val},
+    \luastringO{\rule at val},
+    \luastringO{\delim at val},
+    \luastringO{\sep at val},
+    \luastringO{\bhook at val},
+    \luastringO{\ehook at val}
+    )}
+  \egroup
+}
+\@onlypreamble\DeclareApparatus
+\newbool{do at app}
+\newif\ifekd at state
+\newif\ifekd at isinapp
+\newif\ifekd at isinlem
+\providebool{al at rlmode}
+\@ifpackageloaded{arabluatex}{}{%
+  \def\setRL{\booltrue{al at rlmode}\pardir TRT\textdir TRT}
+  \def\setLR{\boolfalse{al at rlmode}\pardir TLT \textdir TLT}
+}
+\protected\def\LRnum#1{\bgroup\textdir TLT#1\egroup}
+\newcounter{ekd at lab}
+\globalcounter{ekd at lab}
+\NewDocumentCommand{\unconditional at 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 at font\footnotesize
+    \interlinepenalty\interfootnotelinepenalty
+    \splittopskip\footnotesep
+    \splitmaxdepth \dp\strutbox \floatingpenalty \@MM
+    \hsize\columnwidth \@parboxrestore
+    \protected at edef\@currentlabel{%
+       \csname p at footnote\endcsname\@thefnmark
+    }%
+    \color at begingroup
+      \@makeblfntext{%
+        \rule\z@\footnotesep\ignorespaces#1\@finalstrut\strutbox}%
+    \color at endgroup}}%
+\newcommand\@makeblfntext[1]{%
+    \parindent 1em%
+    \noindent
+    \hb at xt@0em{\hss\@makefnmark}#1}
+\newif\ifrtl at app
+\NewDocumentCommand{\SetRTLapp}{}{\rtl at apptrue}
+\NewDocumentCommand{\SetLTRapp}{}{\rtl at appfalse}
+\edef\ekdsep{] }
+\NewDocumentCommand{\SetSeparator}{m}{\edef\ekdsep{#1}}
+\edef\ekd at end@apparatus{}
+\NewDocumentCommand{\SetEndApparatus}{m}{\edef\ekd at end@apparatus{#1}}
+\def\ekd at unit@delim{}
+\NewDocumentCommand{\SetUnitDelimiter}{m}{\def\ekd at unit@delim{#1}}
+\def\ekd at default@rule{\rule{2truein}{0.5pt}}
+\newif\iffootnoterule
+\footnoteruletrue
+\let\dflt at footnoterule\footnoterule
+\let\dflt at pcol@footnoterule\pcol at footnoterule
+\renewcommand\footnoterule{%
+  \iffootnoterule
+  \dflt at footnoterule%
+  \fi
+}
+\renewcommand\pcol at footnoterule{%
+  \iffootnoterule
+  \dflt at pcol@footnoterule%
+  \fi
+}
+\NewDocumentCommand{\SetDefaultRule}{m}{%
+  \def\@tempa{#1}
+  \ifx\@tempa\empty\def\ekd at default@rule{\mbox{}}%
+  \else%
+  \def\ekd at default@rule{#1}%
+  \fi}
+\newcommand*{\NLS}{%
+  \par%
+  \nobreak%
+  \vspace{-\parskip}%
+  \noindent%
+  \ignorespaces}
+\newif\ifsubsq at unit
+\subsq at unittrue
+\def\add@@apparatus{%
+  \if at pkg@parnotes\parnotes\else\fi%
+  \if at pkg@footins%
+  \bgroup%
+  \ifrtl at app\setRL\else\setLR\fi%
+  \blfootnote{%
+    \if at pkg@parnotes%
+    \if at parnotesroman%
+    \renewcommand*{\theparnotemark}{\roman{parnotemark}}\else\fi%
+    \parnoteclear\else\fi%
+    \footnotesize\apparatus\unless\ifekd at mapps\ekd at end@apparatus\fi%
+    \if at pkg@parnotes\parnotes\parnotereset\else\fi%
+  }%
+  \egroup%
+  \fi%
+  \if at pkg@float%
+  \keyparbox[!b]{}{\ifrtl at app\setRL\else\setLR\fi%
+    \if at pkg@parnotes%
+    \if at parnotesroman%
+    \renewcommand*{\theparnotemark}{\roman{parnotemark}}\else\fi%
+    \parnoteclear\else\fi%
+    \ekd at appfontsize\apparatus\unless\ifekd at mapps\ekd at end@apparatus\fi%
+    \if at pkg@parnotes\parnotes\parnotereset\else\fi%
+  }%
+  \fi%
+}
+\def\add at apparatus{%
+  \test at apparatus%
+  \ifbool{do at app}{\subsq at unitfalse\add@@apparatus}{}%
+}
+\NewDocumentCommand{\append at app}{o +m}{%
+  \ifekd at isinapp%
+    \ifekd at state%
+    \IfNoValueTF{#1}%
+      {\luadirect{ekdosis.appin(\luastringO{#2})}}%
+      {\luadirect{ekdosis.appin(\luastringO{#2}, \luastringO{#1})}}%
+    \fi%
+  \fi}
+\NewDocumentCommand{\append at 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 at type,
+   initial type = default
+ }
+\NewDocumentCommand{\EkdosisDefaultApparatus}{m}{%
+  \ekvset{appnote}{type=#1}}
+\NewDocumentCommand{\app}{O{} > { \TrimSpaces } +m}{%
+  \begingroup
+  \ekvset{appnote}{#1}%
+  \ekd at isinapptrue%
+  \stepcounter{ekd at lab}%
+  \zlabel{ekd:\theekd at lab}%
+  \luadirect{ekdosis.storeabspg(
+    \luastring{\zref at extract{ekd:\theekd at lab}{abspage}})}%
+  \ifekd at state\add at apparatus\fi%
+  \luadirect{tex.sprint(ekdosis.removesp(\luastringN{#2}))}%
+  \ekd at isinappfalse%
+  \endgroup}
+\def\current at ref@arg#1#2{{%\textdir TLT%
+    \unexpanded\expandafter{\ekd at refnumstyle}%
+    \ifnum%
+    \getpagerefnumber{#1}
+    =
+    \getpagerefnumber{#2}
+    \ifnum%
+    \getrefnumber{#1}
+    =
+    \getrefnumber{#2}
+    %
+    \ifekd at mapps%
+    \ifbool{subsq at unit@\ekdan at 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 at 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 at postrefnum}%
+}
+\def\current at ref{{%\textdir TLT%
+    \unexpanded\expandafter{\ekd at 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 at mapps%
+    \ifbool{subsq at unit@\ekdan at 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 at 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 at postrefnum}%
+}
+\ekvdefinekeys{lem}{
+  code wit = \def\ekdlr at wit{#1},
+  code alt  = \def\ekdlr at alt{#1},
+  code pre = \def\ekdlr at pre{#1},
+  code post = \def\ekdlr at post{#1},
+  code prewit = \def\ekdlr at prewit{#1},
+  code postwit = \def\ekdlr at postwit{#1},
+  store type = \ekdlr at type,
+  store sep = \ekdl at sep,
+  bool nolem = \ifekdl at nolem,
+  bool nosep = \ifekdl at nosep,
+  initial sep = \ekdsep
+}
+\ekvdefinekeys{rdg}{
+  code wit = \def\ekdlr at wit{#1},
+  code alt  = \def\ekdlr at alt{#1},
+  code pre = \def\ekdlr at pre{#1},
+  code post = \def\ekdlr at post{#1},
+  code prewit = \def\ekdlr at prewit{#1},
+  code postwit = \def\ekdlr at postwit{#1},
+  store type = \ekdlr at type,
+  bool nordg = \ifekdr at nordg
+}
+\NewDocumentCommand{\lem}{O{} m}{%
+  \ekd at isinlemtrue%
+  \luadirect{ekdosis.dolnlab(\luastringN{#2})}%
+  \bgroup%
+  \ekvset{lem}{#1}%
+  \ifekd at mapps%
+    \ifnum%
+    \luadirect{tex.sprint(ekdosis.get_bagunits(\luastringO{\ekdan at type}))}
+    = 1
+    \boolfalse{subsq at unit@\ekdan at type}%
+    \fi%
+    \luadirect{ekdosis.increment_bagunits(\luastringO{\ekdan at type})}%
+    \def\ekd at munit@delim{%
+      \luadirect{tex.sprint(ekdosis.getappdelim(\luastringO{\ekdan at type}))}}%
+  \fi%
+  \ifekdl at nolem\edef\lem at app{%
+    % \hskip .75em
+    \ifekd at mapps
+    \ifbool{subsq at unit@\ekdan at type}%
+    {\ekd at munit@delim}{}%
+    \else%
+    \ifsubsq at unit\unexpanded\expandafter{\ekd at unit@delim}\fi%
+    \fi%
+    \current at ref}%\hskip .25em}%
+  \else%
+  \ifbool{al at rlmode}{%
+    \edef\lem at app{%
+      % \hskip .75em
+      \ifekd at mapps
+      \ifbool{subsq at unit@\ekdan at type}%
+      {\ekd at munit@delim}{}%
+      \else%
+      \ifsubsq at unit\unexpanded\expandafter{\ekd at unit@delim}\fi%
+      \fi%
+      \current at ref%\hskip .25em
+      \ifdefined\ekdlr at alt%
+        \ifdefined\ekdlr at post%
+          \space\unexpanded\expandafter{\ekdlr at post}\space\else\fi
+        {\textdir TRT\unexpanded\expandafter{\ekdlr at alt}}%
+        \ifdefined\ekdlr at pre%
+          \space\unexpanded\expandafter{\ekdlr at pre}\space\else\fi
+      \else
+        \ifdefined\ekdlr at post%
+          \space\unexpanded\expandafter{\ekdlr at post}\space\else\fi
+        {\textdir TRT\unexpanded{#2}}%
+        \ifdefined\ekdlr at pre%
+          \space\unexpanded\expandafter{\ekdlr at pre}\space\else\fi
+      \fi
+      \ifdefined\ekdlr at postwit%
+        \space\unexpanded\expandafter{\ekdlr at postwit}\else\fi
+      \ifdefined\ekdlr at wit\space\getsiglum{\ekdlr at wit}\else\fi
+      \ifdefined\ekdlr at prewit%
+        \space\unexpanded\expandafter{\ekdlr at prewit}\space\else\fi
+      \ifekdl at nosep\else\unexpanded\expandafter{\ekdl at sep}\fi
+    }%
+  }%
+  {%
+    \edef\lem at app{%
+      % \hskip .75em
+      \ifekd at mapps
+      \ifbool{subsq at unit@\ekdan at type}%
+      {\ekd at munit@delim}{}%
+      \else%
+      \ifsubsq at unit\unexpanded\expandafter{\ekd at unit@delim}\fi%
+      \fi%
+      \current at ref%\hskip .25em
+      \ifdefined\ekdlr at alt%
+        \ifdefined\ekdlr at pre%
+          \space\unexpanded\expandafter{\ekdlr at pre}\space\else\fi
+        \ltx at ifpackageloaded{babel}%
+          {\noexpand\selectlanguage{\languagename}%
+            \unexpanded\expandafter{\ekdlr at alt}}%
+          {\unexpanded\expandafter{\ekdlr at alt}}%
+        \ifdefined\ekdlr at post%
+          \space\unexpanded\expandafter{\ekdlr at post}\space\else\fi
+      \else
+        \ifdefined\ekdlr at pre%
+          \space\unexpanded\expandafter{\ekdlr at pre}\space\else\fi
+          \ltx at ifpackageloaded{babel}%
+          {\noexpand\selectlanguage{\languagename}\unexpanded{#2}}{%
+            \unexpanded{#2}}%
+        \ifdefined\ekdlr at post%
+          \space\unexpanded\expandafter{\ekdlr at post}\space\else\fi
+      \fi
+      \ifdefined\ekdlr at prewit%
+        \space\unexpanded\expandafter{\ekdlr at prewit}\space\else\fi
+      \ifdefined\ekdlr at wit\space\getsiglum{\ekdlr at wit}\else\fi
+      \ifdefined\ekdlr at postwit%
+        \space\unexpanded\expandafter{\ekdlr at postwit}\else\fi
+      \ifekdl at nosep\else\unexpanded\expandafter{\ekdl at sep}\fi
+    }%
+  }%
+  \fi%
+  \ifekd at mapps%
+  \append at ln@app[\ekdan at type]{\lem at app}%
+  \else%
+  \append at ln@app{\lem at app}%
+  \fi%
+  \egroup%
+  \ekd at isinlemfalse%
+  \subsq at unittrue%
+}
+\NewDocumentCommand{\rdg}{O{} m}{%
+  \bgroup%
+  \ekvset{rdg}{#1}%
+  % \ifekdr at nordg\append at app{}\else% do we need \append at app{} here? If
+  %                               % so, keep in mind \ifekd at mapps,
+  %                               like so:
+  \ifekdr at nordg%
+    \ifekd at mapps%
+      \append at app[\ekdan at type]{}%
+    \else%
+    \append at app{}%
+    \fi%
+  \else%
+  \ifbool{al at rlmode}{%
+    \edef\rdg at app{%
+      \ifdefined\ekdlr at alt%
+        \ifdefined\ekdlr at post%
+          \space\unexpanded\expandafter{\ekdlr at post}\space\else\fi
+        {\textdir TRT\unexpanded\expandafter{\ekdlr at alt}}%
+        \ifdefined\ekdlr at pre%
+          \space\unexpanded\expandafter{\ekdlr at pre}\space\else\fi
+      \else
+        \ifdefined\ekdlr at post%
+          \space\unexpanded\expandafter{\ekdlr at post}\space\else\fi
+        {\textdir TRT\unexpanded{#2}}%
+        \ifdefined\ekdlr at pre%
+          \space\unexpanded\expandafter{\ekdlr at pre}\space\else\fi
+      \fi
+      \ifdefined\ekdlr at postwit%
+        \space\unexpanded\expandafter{\ekdlr at postwit}\else\fi
+      \ifdefined\ekdlr at wit\space\getsiglum{\ekdlr at wit}\else\fi
+      \ifdefined\ekdlr at prewit%
+        \space\unexpanded\expandafter{\ekdlr at prewit}\space\else\fi
+    }%
+  }%
+  {%
+    \edef\rdg at app{%
+      \ifdefined\ekdlr at alt%
+        \ifdefined\ekdlr at pre%
+          \space\unexpanded\expandafter{\ekdlr at pre}\space\else\fi
+        \ltx at ifpackageloaded{babel}%
+          {\noexpand\selectlanguage{\languagename}%
+            \unexpanded\expandafter{\ekdlr at alt}}%
+          {\unexpanded\expandafter{\ekdlr at alt}}%
+        \ifdefined\ekdlr at post%
+          \space\unexpanded\expandafter{\ekdlr at post}\space\else\fi
+      \else
+        \ifdefined\ekdlr at pre%
+          \space\unexpanded\expandafter{\ekdlr at pre}\space\else\fi
+          \ltx at ifpackageloaded{babel}%
+          {\noexpand\selectlanguage{\languagename}\unexpanded{#2}}{%
+            \unexpanded{#2}}%
+        \ifdefined\ekdlr at post%
+          \space\unexpanded\expandafter{\ekdlr at post}\space\else\fi
+      \fi
+      \ifdefined\ekdlr at prewit%
+        \space\unexpanded\expandafter{\ekdlr at prewit}\space\else\fi
+      \ifdefined\ekdlr at wit\space\getsiglum{\ekdlr at wit}\else\fi
+      \ifdefined\ekdlr at postwit%
+        \space\unexpanded\expandafter{\ekdlr at postwit}\else\fi
+    }%
+  }%
+  \ifekd at mapps%
+      \append at app[\ekdan at type]{\rdg at app}%
+  \else%
+  \append at app{\rdg at app}%
+  \fi%
+  \fi%
+  \egroup%
+}
+\ekvdefinekeys{note}{
+  store type = \ekdan at type,
+  store lem = \ekdn at lem,
+  code labelb = \def\ekdn at labelb{#1},
+  code labele = \def\ekdn at labele{#1},
+  store sep = \ekdn at sep,
+  initial type = default,
+  initial sep = \ekdsep
+}
+\NewDocumentCommand{\note at noapp}{O{} +m}{%
+  \bgroup%
+  \ekvset{note}{#1}%
+  \stepcounter{ekd at lab}%
+  \zlabel{ekd:\theekd at lab}%
+  \luadirect{ekdosis.storeabspg(
+    \luastring{\zref at extract{ekd:\theekd at lab}{abspage}})}%
+  \ifekd at state\add at apparatus\fi%
+  \ifekd at mapps%
+    \ifnum%
+      \luadirect{tex.sprint(ekdosis.get_bagunits(\luastringO{\ekdan at type}))}
+      = 1
+      \boolfalse{subsq at unit@\ekdan at type}%
+    \fi%
+  \luadirect{ekdosis.increment_bagunits(\luastringO{\ekdan at type})}%
+    \def\ekd at munit@delim{%
+      \luadirect{tex.sprint(ekdosis.getappdelim(\luastringO{\ekdan at type}))}}%
+  \fi%
+  \ifdefined\ekdn at labelb%
+    \luadirect{tex.sprint(ekdosis.setnotelab(\luastringO{\ekdn at labelb}))}%
+    \ifdefined\ekdn at labele\else\def\ekdn at labele{\ekdn at labelb}\fi%
+  \else\PackageError{ekdosis}{missing labelb}{`labelb' must be
+    set.}\fi%
+  \ifbool{al at rlmode}%
+  {\edef\note at contents{%
+      % \hskip .75em
+      \ifekd at mapps
+        \ifbool{subsq at unit@\ekdan at type}%
+        {\ekd at munit@delim}{}%
+      \else%
+        \ifsubsq at unit\unexpanded\expandafter{\ekd at unit@delim}\fi%
+      \fi%
+      \current at ref@arg{\ekdn at labelb}{\ekdn at labele}%\hskip .25em
+      \ifdefined\ekdn at lem%
+          {\textdir TRT\unexpanded\expandafter{\ekdn at lem}}%
+          \unexpanded\expandafter{\ekdn at sep}\else\fi%
+            {\textdir TRT\unexpanded{#2}}}}%
+  {\edef\note at contents{%
+      % \hskip .75em
+      \ifekd at mapps
+        \ifbool{subsq at unit@\ekdan at type}%
+        {\ekd at munit@delim}{}%
+      \else%
+        \ifsubsq at unit\unexpanded\expandafter{\ekd at unit@delim}\fi%
+      \fi%
+      \current at ref@arg{\ekdn at labelb}{\ekdn at labele}%\hskip .25em
+      \ifdefined\ekdn at lem
+        \ltx at ifpackageloaded{babel}%
+          {\noexpand\selectlanguage{\languagename}%
+            \unexpanded\expandafter{\ekdn at lem}}%
+          {\unexpanded\expandafter{\ekdn at lem}}%
+          \unexpanded\expandafter{\ekdn at sep}\else\fi%
+          \ltx at ifpackageloaded{babel}%
+          {\noexpand\selectlanguage{\languagename}\unexpanded{#2}}{%
+            \unexpanded{#2}}}}%
+  \ifekd at mapps%
+  \unconditional at appin[\ekdan at type]{\note at contents}%
+  \else%
+  \unconditional at appin{\note at contents}%
+  \fi%
+    \luadirect{ekdosis.setprevnotelab(\luastringO{\ekdn at labelb})}%
+  \egroup%
+  \subsq at unittrue%
+}
+\ekvdefinekeys{ekd at note}{
+  store pre = \pre at value,
+  store post = \post at value
+}
+\NewDocumentCommand{\ekd at note}{O{} m}{%
+  \bgroup%
+  \ekvset{ekd at note}{#1}%
+  \edef\note at contents{%
+    \ekvifdefinedNoVal{note}{pre}{}{%
+      \unexpanded\expandafter{\pre at value}}%
+    \unexpanded{#2}%
+    \ekvifdefinedNoVal{note}{post}{}{%
+      \unexpanded\expandafter{\post at value}}%
+  }%
+  \append at app{\note at contents}%
+  \egroup%
+}
+\NewDocumentCommand{\ekd at note@star}{O{} m}{%
+  \if at pkg@parnotes
+    \bgroup%
+      \ekvset{ekd at note}{#1}%
+      \edef\note at contents{%
+        \ekvifdefinedNoVal{note}{pre}{}{%
+          \unexpanded\expandafter{\pre at value}}%
+        \unskip\noexpand\parnote{#2}%
+        \ekvifdefinedNoVal{note}{post}{}{%
+          \unexpanded\expandafter{\post at value}}%
+      }%
+      \append at app{\note at contents}%
+    \egroup%
+  \else
+    \append at app{\unskip\footnote{#2}}%
+  \fi%
+}
+\NewDocumentCommand{\note at app}{s O{} +m}{%
+  \ifbool{al at rlmode}{%
+    \IfBooleanTF{#1}{\ekd at note@star[#2]{%
+          {\textdir TRT#3}}}
+    {\ekd at note[#2]{{\textdir TRT#3}}}%
+  }{%
+    \IfBooleanTF{#1}{\ekd at note@star[#2]{#3}}
+    {\ekd at note[#2]{#3}}%
+  }%
+}
+\NewDocumentCommand{\note}{s O{} +m}{%
+  \ifekd at state%
+    \ifekd at isinapp%
+      \ifekd at isinlem%
+        \note at noapp[#2]{#3}%
+      \else%
+        \IfBooleanTF{#1}{\note at app*[#2]{#3}}{\note at app[#2]{#3}}%
+      \fi%
+    \else%
+      \note at noapp[#2]{#3}%
+      \fi%
+  \fi%
+}
+\NewDocumentCommand{\apparatus}{}{%
+  \luadirect{tex.sprint(ekdosis.appout())}}
+\NewDocumentCommand{\test at apparatus}{}{%
+  \luadirect{tex.sprint(ekdosis.testapparatus())}}
+\NewDocumentCommand{\ekd at storecol}{}{%
+  \luadirect{ekdosis.storecurcol(\luastring{\thecolumn})}%
+}
+\NewDocumentCommand{\EkdosisOn}{}{%
+  \ekd at statetrue}
+\NewDocumentCommand{\EkdosisOff}{}{%
+  \ekd at statefalse%
+}
+\def\ekd at setlineno{%
+  \let\setpagewiselinenumbers\relax%
+  \let\pagewiselinenumbers\relax%
+  \let\endpagewiselinenumbers\relax%
+  \let\runningpagewiselinenumbers\relax%
+  \let\realpagewiselinenumbers\relax%
+}
+\NewDocumentEnvironment{ekdosis}{+b}{%
+  \ekd at setlineno%
+  \runninglinenumbers
+    \EkdosisOn#1}{%
+    \EkdosisOff
+  \endrunninglinenumbers%
+  \iftei at export
+  \luadirect{ekdosis.exporttei(\luastringN{\par #1\par })}\fi}
+\newif\ifekd at pagelineation
+\ekvdefinekeys{ekd at align}{
+  store tcols = \tcols at num,
+  store lcols = \lcols at num,
+  store texts = \texts at value,
+  store apparatus = \apparatus at value,
+  bool paired = \ifekd at paired,
+  choice lineation = {page = \ekd at pagelineationtrue,
+                      document = \ekd at pagelineationfalse},
+  unknown-choice lineation = \PackageError{ekdosis}{unknown
+    lineation=#1}{`lineation' must be either `page' or `document'.},
+  choice segmentation = {auto = \def\segmentation at val{auto},
+                         noauto = \def\segmentation at val{noauto}},
+  unknown-choice segmentation = \PackageError{ekdosis}{unknown
+    segmentation=#1}{`segmentation' must be either `auto' or
+    `noauto'.},
+  bool flush = \ifekd at flushapp,
+  initial tcols = 2,
+  initial lcols = 1,
+  initial texts = edition;translation,
+  initial apparatus = edition,
+  default segmentation = auto
+}
+\NewDocumentCommand{\SetEkdosisAlignment}{m}{
+  \ekvset{ekd at align}{#1}
+}
+\patchcmd{\pcol at nextpage}{%
+  \endgroup}{%
+  \ifekd at pagelineation\resetlinenumber\fi
+  \endgroup}{}{}
+\NewDocumentCommand{\EkdosisColStart}{}{%
+  \ekd at setlineno%
+  \runninglinenumbers
+  \ekd at storecol%
+  \stepcounter{ekd at lab}%
+  \zlabel{ekd:\theekd at lab}%
+  \luadirect{%
+    ekdosis.storeabspg(\luastring{\zref at extract{ekd:\theekd at lab}{abspage}},
+    "pg_i")}%
+  \ifekd at pagelineation
+    \luadirect{tex.sprint(ekdosis.checkresetlineno())}
+  \fi
+}
+\NewDocumentCommand{\EkdosisColStop}{}{%
+  \stepcounter{ekd at lab}%
+  \zlabel{ekd:\theekd at lab}%
+  \luadirect{%
+    ekdosis.storeabspg(\luastring{\zref at extract{ekd:\theekd at lab}{abspage}},
+    "pg_ii")}%
+  \endrunninglinenumbers%
+}
+\NewDocumentEnvironment{alignment}{O{}}
+{%
+  \ekvset{ekd at align}{#1}%
+  \luadirect{ekdosis.mkenvdata(
+    \luastring{\texts at value},
+    "texts"
+    )}
+  \ifekd at flushapp
+    \luadirect{ekdosis.newalignment("set")}
+  \fi
+  \luadirect{ekdosis.mkenvdata(
+    \luastring{\apparatus at value}, "apparatus"
+    )}
+  \setrunninglinenumbers
+  \luadirect{tex.sprint(ekdosis.mkenv())}
+  \ifekd at paired
+  \begin{paracol}[\lcols at num]{\tcols at num}
+  \else
+  \begin{paracol}[\lcols at num]*{\tcols at num}
+  \fi
+  }
+  {\end{paracol}
+  \iftei at export\luadirect{ekdosis.export_coldata_totei()}\fi
+  \ifekd at 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 at div}{
+  code type = \def\type at value{#1},
+  code n = \def\n at value{#1},
+  code head = \def\head at value{#1},
+  code barehead = \def\barehead at value{#1},
+  store depth = \depth at value,
+  choice toc = {book = \def\toc at value{book},
+                part = \def\toc at value{part},
+                chapter = \def\toc at value{chapter},
+                section = \def\toc at value{section},
+                subsection = \def\toc at value{subsection},
+                subsubsection = \def\toc at value{subsubsection},
+                paragraph = \def\toc at value{paragraph},
+                subparagraph = \def\toc at 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 at getfmtdiv}{m m}{%
+  \luadirect{tex.sprint(ekdosis.getfmtdiv(\luastringO{#1},
+    \luastringN{#2}))}%
+}
+\NewDocumentCommand{\ekddiv}{m}{
+  \begingroup
+  \ekvset{ekd at div}{#1}%
+  \ifdefined\head at value
+    \bgroup
+      \ekd at getfmtdiv{\depth at value}{b}%
+      \head at value
+      \ekd at getfmtdiv{\depth at value}{e}%
+    \egroup
+      \ifdefined\toc at value
+        \ltx at ifpackageloaded{hyperref}{\phantomsection}{}%
+          \ifdefined\barehead at value
+            \addcontentsline{toc}{\toc at value}{\barehead at value}%
+          \else
+            \addcontentsline{toc}{\toc at value}{\head at 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'.


Property changes on: trunk/Master/texmf-dist/tex/lualatex/ekdosis/ekdosis.sty
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Modified: trunk/Master/tlpkg/bin/tlpkg-ctan-check
===================================================================
--- trunk/Master/tlpkg/bin/tlpkg-ctan-check	2020-07-08 21:17:27 UTC (rev 55785)
+++ trunk/Master/tlpkg/bin/tlpkg-ctan-check	2020-07-08 21:18:08 UTC (rev 55786)
@@ -260,7 +260,7 @@
     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

Modified: trunk/Master/tlpkg/tlpsrc/collection-luatex.tlpsrc
===================================================================
--- trunk/Master/tlpkg/tlpsrc/collection-luatex.tlpsrc	2020-07-08 21:17:27 UTC (rev 55785)
+++ trunk/Master/tlpkg/tlpsrc/collection-luatex.tlpsrc	2020-07-08 21:18:08 UTC (rev 55786)
@@ -15,6 +15,7 @@
 depend combofont
 depend cstypo
 depend ctablestack
+depend ekdosis
 depend emoji
 depend emojicite
 depend enigma

Added: trunk/Master/tlpkg/tlpsrc/ekdosis.tlpsrc
===================================================================


More information about the tex-live-commits mailing list.