% \iffalse meta-comment
% vim: textwidth=75
%<*internal>
\iffalse
%</internal>
%<*readme>
|
-------:| -----------------------------------------------------------------
ekdosis:| Typesetting TEI xml compliant critical editions
 Author:| Robert Alessi
 E-mail:| alessi@robertalessi.net
License:| Released under the GNU General Public License v3 or later
    See:| http://www.gnu.org/licenses/


Short description:
Some text about the package: probably the same as the abstract.
%</readme>
%<*luapre>
--[[
This file is part of the `ekdosis' package

ekdosis -- Typesetting TEI xml compliant critical editions
Copyright (C) 2020  Robert Alessi

Please send error reports and suggestions for improvements to Robert
Alessi <alessi@robertalessi.net>

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see
<http://www.gnu.org/licenses/>.
--]]

%</luapre>
%<*internal>
\fi
\def\nameofplainTeX{plain}
\ifx\fmtname\nameofplainTeX\else
  \expandafter\begingroup
\fi
%</internal>
%<*install>
\input docstrip.tex
\keepsilent
\askforoverwritefalse
\preamble
-------:| -----------------------------------------------------------------
ekdosis:| Typesetting TEI xml compliant critical editions
 Author:| Robert Alessi
 E-mail:| alessi@robertalessi.net
License:| Released under the GNU General Public License v3 or later
    See:| http://www.gnu.org/licenses/

This file is part of the `ekdosis' package

ekdosis -- Typesetting TEI xml compliant critical editions
Copyright (C) 2020  Robert Alessi

Please send error reports and suggestions for improvements to Robert
Alessi <alessi@robertalessi.net>

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see
<http://www.gnu.org/licenses/>.

This work consists of the file ekdosis.dtx 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.
Running "make install" installs the files in the local 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
%</install>
%<install>\endbatchfile
%<*internal>
\usedir{source/lualatex/ekdosis}
\generate{
  \file{\jobname.ins}{\from{\jobname.dtx}{install}}
}
\nopreamble\nopostamble
\usedir{doc/lualatex/ekdosis}
\generate{
  \file{README.txt}{\from{\jobname.dtx}{readme}}
}
\ifx\fmtname\nameofplainTeX
  \expandafter\endbatchfile
\else
  \expandafter\endgroup
\fi
%</internal>
% \fi
%
% \iffalse
%<*driver>
\ProvidesFile{ekdosis.dtx}
%</driver>
%<package>\NeedsTeXFormat{LaTeX2e}[1999/12/01]
%<package>\ProvidesPackage{ekdosis}
%<*package>
    [2020/06/03 v0.99 Typesetting TEI xml compliant critical editions]
%</package>
%<*driver>
\documentclass{ltxdoc}
\usepackage[letterpaper,margin=25mm,left=50mm,nohead]{geometry}
\usepackage{dox}
\doxitem{Option}{option}{options}
\usepackage{microtype}
\usepackage{fontspec}
\usepackage[english]{babel}
\babelfont{rm}{Old Standard}
\babelfont{sf}{NewComputerModern Sans}
\babelfont{tt}{NewComputerModern Mono}
\usepackage{metalogox}
\usepackage{hologo}
\usepackage{latexcolors}
\usepackage{hyperxmp}
\usepackage{uri}
\usepackage[numbered]{hypdoc}
\hypersetup{unicode=true, colorlinks, allcolors=cinnamon, keeppdfinfo,
  linktocpage=true, pdfauthor={Robert Alessi}, pdftitle={The ekdosis
    package}, pdfcontactemail={alessi@robertalessi.net},
  pdfcontacturl={http://www.robertalessi.net/ekdosis},
  pdfcopyright={Copyright (C) 2018 Robert Alessi
    <alessi@robertalessi.net>. This document is licensed under the
    Creative Commons Attribution-ShareAlike 4.0 International
    License. To view a copy of this license, visit
    http://creativecommons.org/licenses/by-sa/4.0/ or send a letter to
    Creative Commons, PO Box 1866, Mountain View, CA 94042, USA.},
  pdflicenseurl={https://creativecommons.org/licenses/by-sa/4.0/legalcode},
  pdfmetalang={en-US}, pdftype={Text}, pdfkeywords={Arabic language,
    arabtex, luatex}}
\usepackage[lot]{multitoc}
\usepackage{ekdosis}
\usepackage{arabluatex}
\usepackage{relsize}
\usepackage{units}
\usepackage[newfloat=true]{minted}
\newminted[ekdlua]{lua}{linenos, fontsize=\relsize{-0.5},
  xleftmargin=12pt, breaklines,
  numberblanklines=false, numbersep=3pt, firstnumber=last}
\renewcommand{\theFancyVerbLine}{\rmfamily\smaller\arabic{FancyVerbLine}}
\usepackage[contents]{colordoc}
\newcommand{\package}[1]{\textsf{#1}\index{#1=#1 (package)}}
\usepackage{tikz}
\usepackage[breakable, skins, xparse, minted]{tcolorbox}
\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{0}
%
% \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}
%
% \title{\tcbox[colframe=black, enhanced, tikznode, drop lifted
% shadow, colback=white, boxrule=.25mm]%
% {ἔκδοσις\\
% Typesetting \texttt{TEI xml} compliant critical editions\\
% \fileversion\ --- \filedate}}
%  
% \author{Robert Alessi \\
% \href{mailto:alessi@robertalessi.net?Subject=ekdosis package}%
% {\texttt{alessi@robertalessi.net}}}
% 
% \date{}
%
% \maketitle
% \footnotesize
% \ekdtableofcontents
% \normalsize
%
%\changes{v1.00}{2020/07/01}{First public release}
%
% \begin{abstract}
% ==== Put abstract text here. ====
% \end{abstract}
%
% \section{Usage}
%
% ==== Put descriptive text here. ====
% 
% \DescribeMacro{\dummyMacro}
% This macro does nothing.\index{doing nothing|usage} It is merely an
% example.  If this were a real macro, you would put a paragraph here
% describing what the macro is supposed to do, what its mandatory and
% optional arguments are, and so forth.
% 
% \DescribeEnv{dummyEnv}
% This environment does nothing.  It is merely an example.
% If this were a real environment, you would put a paragraph here
% describing what the environment is supposed to do, what its
% mandatory and optional arguments are, and so forth.
%
% \section{Grid}
% \begin{keyfigure}[H]{c={Grid
%   typesetting},l={fig:grid-typesetting},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}.}}
%   \begin{tikzpicture}
%     \draw[lightgray,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. I saw my friend
%     Peter at the station yesterday. I saw my friend Peter at the
%     station yesterday. I saw my friend Peter at the station
%     yesterday.\par
%     \rule{3cm}{0.01cm}\par\footnotesize%
%     \textbf{1}~Peter A: John B \textbf{2}~Peter A: John B
%     \textbf{3}~Peter A: John B \textbf{4}~Peter A: John B}; \node at
%     (0,3) {\scriptsize $\approx$ \unit[25]{pt}}; \draw [->] (0,2.9)
%     -- (0,2);
%   \end{tikzpicture}
% \end{keyfigure}
% 
% \StopEventually{}
% \section{Implementation}
%
% \iffalse
%<*package>
% \fi
% 
% \package{ekdosis} relies on Lua functions and tables. Read the
% |.lua| files that accompany \package{ekdosis} for more
% information.
%    \begin{macrocode}
\RequirePackage{iftex}
%    \end{macrocode}
% \package{ekdosis} requires {\LuaLaTeX} of course. Issue an error
% if the document is processed with another engine.
%    \begin{macrocode}
\RequireLuaTeX
%    \end{macrocode}
% Packages that are required by \package{ekdosis}:
%    \begin{macrocode}
\RequirePackage{xkeyval}
\newif\if@pkg@float
\newif\if@pkg@footins
\define@choicekey{ekdosis.sty}{layout}{float, footins}[float]{%
  \edef\layout@float{float}
  \edef\layout@footins{footins}
  \edef\@tempa{#1}
  \ifx\@tempa\layout@float\@pkg@floattrue\fi
  \ifx\@tempa\layout@footins\@pkg@floatfalse\@pkg@footinstrue\fi
}
\newif\if@pkg@ekddivs
\define@choicekey+{ekdosis.sty}{divs}{ekdosis, latex}[ekdosis]{
  \edef\divs@ekdosis{ekdosis}
  \edef\divs@latex{latex}
  \edef\@tempa{#1}
  \ifx\@tempa\divs@ekdosis\@pkg@ekddivstrue\fi
  \ifx\@tempa\divs@latex
    \@pkg@ekddivsfalse
    \AtBeginDocument{\luadirect{ekdosis.setekddivsfalse()}}
  \fi
}{\PackageError{ekdosis}{divs option must be either 'ekdosis' or 'latex'}}
\newif\if@parnotesroman
\newif\if@pkg@parnotes
\define@choicekey+{ekdosis.sty}{parnotes}{true, false, roman}[true]{%
  \edef\@pntrue{true}\edef\@pnfalse{false}\edef\@pnrm{roman}
  \edef\@tempa{#1}
  \ifx\@tempa\@pnfalse
  \else
  \ifx\@tempa\@pntrue\@pkg@parnotestrue
  \else
  \ifx\@tempa\@pnrm
    \@pkg@parnotestrue\@parnotesromantrue
  \fi\fi\fi
}{\PackageWarning{ekdosis}{parnotes: erroneous input (ignored)}}
\newif\iftei@export
\define@choicekey{ekdosis.sty}{teiexport}{true, false, tidy}[true]{%
  \edef\@exptrue{true}\edef\@expfalse{false}\edef\@exptidy{tidy}
  \edef\@tempa{#1}
  \ifx\@tempa\@expfalse
  \else
  \ifx\@tempa\@exptrue
  \tei@exporttrue
  \AtBeginDocument{\luadirect{ekdosis.openteistream()}}%
  \AtEndDocument{\luadirect{ekdosis.closeteistream()}}
  \else
  \ifx\@tempa\@exptidy
  \tei@exporttrue
  \AtBeginDocument{\luadirect{ekdosis.openteistream()}}%
  \AtEndDocument{\luadirect{ekdosis.closeteistream("tidy")}}
  \else\fi\fi\fi}
\ExecuteOptionsX{layout,divs}
\ProcessOptionsX\relax
\RequirePackage{luacode}
\RequirePackage{paracol}
\RequirePackage{expkv-def}
\RequirePackage{xparse}
\RequirePackage{etoolbox}
\RequirePackage{lineno}
\RequirePackage{keyfloat}
\RequirePackage{refcount}
\RequirePackage[user,abspage]{zref}
\RequirePackage{ltxcmds}
\if@pkg@parnotes
  \RequirePackage{parnotes}
\fi
%    \end{macrocode}
% 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}
% Hooks
%    \begin{macrocode}
\ekvdefinekeys{ekd@hooks}{
  store appfontsize = \ekd@appfontsize,
  store refnumstyle = \ekd@refnumstyle,
  store postrefnum = \ekd@postrefnum,
  initial appfontsize = \footnotesize,
  initial refnumstyle = \bfseries,
  initial postrefnum = ~
}
\NewDocumentCommand{\SetEkdosisHooks}{m}{\ekvset{ekd@hooks}{#1}}
%    \end{macrocode}
% Build and process the list of witnesses and hands.
%    \begin{macrocode}
\ekvdefinekeys{ekd@witness}{
  store settlement = \settlement@value,
  store repository = \repository@value,
  store idno = \idno@value,
  store msName = \msName@value,
  store origDate = \origDate@value
}
\NewDocumentCommand{\DeclareWitness}{m m m O{}}{%
  \bgroup
  \ekvset{ekd@witness}{#4}
    \luadirect{ekdosis.newwitness(
      \luastringN{#1},
      \luastringN{#2},
      \luastringN{#3},
      \luastringO{\settlement@value},
      \luastringO{\repository@value},
      \luastringO{\idno@value},
      \luastringO{\msName@value},
      \luastringO{\origDate@value})}
    \egroup
  }
\@onlypreamble\DeclareWitness
\NewDocumentCommand{\DeclareHand}{m m m +O{}}{
  \luadirect{ekdosis.newhand(\luastringN{#1},
    \luastringN{#2},
    \luastringN{#3},
    \luastringN{#4})}
}
\@onlypreamble\DeclareHand
\NewDocumentCommand{\DeclareScholar}{m m}{
  \luadirect{ekdosis.newscholar(\luastringN{#1},
    \luastringN{#2})}
}
\@onlypreamble\DeclareScholar
\NewDocumentCommand{\DeclareShorthand}{m m m}{
  \luadirect{ekdosis.newshorthand(\luastringN{#1},
    \luastringN{#2},
    \luastringN{#3})}
}
\@onlypreamble\DeclareShorthand
\NewDocumentCommand{\getsiglum}{m}{%
  \luadirect{tex.sprint(ekdosis.getsiglum(\luastringN{#1}))}%
}
\NewDocumentCommand{\SigLine}{m}{%
  \luadirect{tex.sprint(ekdosis.basic_cs(\luastringN{#1}))}
}
%    \end{macrocode}
% Add a \hologo{(La)TeX} command to be processed as a |TEI xml| tag:
%    \begin{macrocode}
\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})}
}
%    \end{macrocode}
% Set |TEI| file name
%    \begin{macrocode}
\NewDocumentCommand{\SetTEIFileName}{m}{
  \luadirect{ekdosis.setteifilename(\luastringN{#1})}
}
\@onlypreamble\SetTEIFileName
\NewDocumentCommand{\SetxmlBibResource}{m}{
  \luadirect{ekdosis.setxmlbibresource(\luastringN{#1})}
}
\@onlypreamble\SetxmlBibResource
%    \end{macrocode}
% Multi-layer apparatuses
%    \begin{macrocode}
\newif\ifekd@mapps
\ekvdefinekeys{ekd@newapp}{
  choice direction = {LR = \def\direction@val{LR},
                      RL = \def\direction@val{RL}},
  store rule = \rule@val,
  store delim = \delim@val,
  store sep = \sep@val,
  store bhook = \bhook@val,
  store ehook = \ehook@val,
  initial direction = LR,
  initial ehook = {\csname ekd@end@apparatus\endcsname}
}
\NewDocumentCommand{\DeclareApparatus}{m O{}}{
  \newbool{subsq@unit@#1}
  \booltrue{subsq@unit@#1}
  \unless\ifekd@mapps\global\ekd@mappstrue\fi
  \bgroup
  \ekvset{ekd@newapp}{#2}
  \luadirect{ekdosis.newapparatus(
    \luastringN{#1},
    \luastring{\direction@val},
    \luastringO{\rule@val},
    \luastringO{\delim@val},
    \luastringO{\sep@val},
    \luastringO{\bhook@val},
    \luastringO{\ehook@val}
    )}
  \egroup
}
\@onlypreamble\DeclareApparatus
%    \end{macrocode}
%    \begin{macrocode}
\newbool{do@app}
\newif\ifekd@state
\newif\ifekd@isinapp
\newif\ifekd@isinlem
\providebool{al@rlmode}
\@ifpackageloaded{arabluatex}{}{%
  \def\setRL{\booltrue{al@rlmode}\pardir TRT\textdir TRT}
  \def\setLR{\boolfalse{al@rlmode}\pardir TLT \textdir TLT}
}
\protected\def\LRnum#1{\bgroup\textdir TLT#1\egroup}
\newcounter{ekd@lab}
\globalcounter{ekd@lab}
 % \def\unconditional@appin#1{%
 %   \luadirect{ekdosis.appin(\luastringN{#1})}%
 % }
\NewDocumentCommand{\unconditional@appin}{o m}{%
  \IfNoValueTF{#1}
  {\luadirect{ekdosis.appin(\luastringO{#2})}}
  {\luadirect{ekdosis.appin(\luastringO{#2}, \luastringO{#1})}}%
}
% \def\blfootnote{\gdef\@thefnmark{\relax}\@footnotetext}
\def\blfootnote{\gdef\@thefnmark{}\@blfootnotetext}
\long\def\@blfootnotetext#1{\insert\footins{%
    \reset@font\footnotesize
    \interlinepenalty\interfootnotelinepenalty
    \splittopskip\footnotesep
    \splitmaxdepth \dp\strutbox \floatingpenalty \@MM
    \hsize\columnwidth \@parboxrestore
    \protected@edef\@currentlabel{%
       \csname p@footnote\endcsname\@thefnmark
    }%
    \color@begingroup
      \@makeblfntext{%
        \rule\z@\footnotesep\ignorespaces#1\@finalstrut\strutbox}%
    \color@endgroup}}%
\newcommand\@makeblfntext[1]{%
    \parindent 1em%
    \noindent
    \hb@xt@0em{\hss\@makefnmark}#1}
\newif\ifrtl@app
\NewDocumentCommand{\SetRTLapp}{}{\rtl@apptrue}
\NewDocumentCommand{\SetLTRapp}{}{\rtl@appfalse}
\edef\ekdsep{] }
\NewDocumentCommand{\SetSeparator}{m}{\edef\ekdsep{#1}}
\edef\ekd@end@apparatus{}
\NewDocumentCommand{\SetEndApparatus}{m}{\edef\ekd@end@apparatus{#1}}
\def\ekd@unit@delim{}
\NewDocumentCommand{\SetUnitDelimiter}{m}{\def\ekd@unit@delim{#1}}
\def\ekd@default@rule{\rule{2truein}{0.5pt}}
 % \def\ekd@default@rule{\vskip-\baselineskip\mbox{}\newline%
 %    \rule{2truein}{0.5pt}}
 % \def\footnoterule{\vskip-\baselineskip}
 % \def\pcol@footnoterule{}
\newif\iffootnoterule
\let\dflt@footnoterule\footnoterule
\let\dflt@pcol@footnoterule\pcol@footnoterule
\renewcommand\footnoterule{%
  \iffootnoterule
  \dflt@footnoterule%
  \else
  % \noindent\ekd@default@rule%
  % \advance\skip\footins 4\p@\@plus2\p@\relax%
  \fi
}
\renewcommand\pcol@footnoterule{%
  \iffootnoterule
  \dflt@pcol@footnoterule%
  \else
  % \noindent\ekd@default@rule%
  % \advance\skip\footins 4\p@\@plus2\p@\relax%
  \fi
}
\newcommand*{\NLS}{%
  \par%
  \nobreak%
  \vspace{-\parskip}%
  \noindent%
  \ignorespaces}
\NewDocumentCommand{\SetDefaultRule}{m}{%
  \def\@tempa{#1}
  \ifx\@tempa\empty\def\ekd@default@rule{\mbox{}}%
  \else%
  \def\ekd@default@rule{#1}%
  \fi}
\newif\ifsubsq@unit
\subsq@unittrue
\def\add@@apparatus{%
  \if@pkg@parnotes\parnotes\else\fi%
  \if@pkg@footins%
  \bgroup%
  \ifrtl@app\setRL\else\setLR\fi%
  \blfootnote{%
    \if@pkg@parnotes%
    \if@parnotesroman%
    \renewcommand*{\theparnotemark}{\roman{parnotemark}}\else\fi%
    \parnoteclear\else\fi%
    \footnotesize\apparatus\unless\ifekd@mapps\ekd@end@apparatus\fi%
    \if@pkg@parnotes\parnotes\parnotereset\else\fi%
  }%
  \egroup%
  \fi%
  \if@pkg@float%
  \keyparbox[!b]{}{\ifrtl@app\setRL\else\setLR\fi%
    \if@pkg@parnotes%
    \if@parnotesroman%
    \renewcommand*{\theparnotemark}{\roman{parnotemark}}\else\fi%
    \parnoteclear\else\fi%
    \ekd@appfontsize\apparatus\unless\ifekd@mapps\ekd@end@apparatus\fi%
    \if@pkg@parnotes\parnotes\parnotereset\else\fi%
  }%
  \fi%
  % \unless\ifekd@mapps\unconditional@appin{%
  %   \expandafter{\ekd@default@rule}\newline}\fi
}
\def\add@apparatus{%
  \test@apparatus%
  \ifbool{do@app}{\subsq@unitfalse\add@@apparatus}{}%
}
\NewDocumentCommand{\append@app}{o +m}{%
  \ifekd@isinapp%
    \ifekd@state%
    \IfNoValueTF{#1}%
      {\luadirect{ekdosis.appin(\luastringO{#2})}}%
      {\luadirect{ekdosis.appin(\luastringO{#2}, \luastringO{#1})}}%
    \fi%
  \fi}
\NewDocumentCommand{\append@ln@app}{o +m}{%
  \IfNoValueTF{#1}
  {\luadirect{tex.sprint(ekdosis.mdvappend(\luastringO{#2}))}}
  {\luadirect{tex.sprint(ekdosis.mdvappend(\luastringO{#2},
      \luastringO{#1}))}}}
\define@cmdkey[ekd]{appnote}[ekdan@]{type}{}
\NewDocumentCommand{\app}{O{} > { \TrimSpaces } +m}{%
  \presetkeys[ekd]{appnote}{type=default}{}%
  \setkeys[ekd]{appnote}{#1}%
  \ekd@isinapptrue%
  \stepcounter{ekd@lab}%
  \zlabel{ekd:\theekd@lab}%
  \luadirect{ekdosis.storeabspg(
    \luastring{\zref@extract{ekd:\theekd@lab}{abspage}})}%
  \ifekd@state\add@apparatus\fi%
  \luadirect{tex.sprint(ekdosis.removesp(\luastringN{#2}))}%
  \ekd@isinappfalse}
\def\current@ref@arg#1#2{{%\textdir TLT%
    \unexpanded\expandafter{\ekd@refnumstyle}%
    \ifnum%
    \getpagerefnumber{#1}
    =
    \getpagerefnumber{#2}
      \ifnum%
      \getrefnumber{#1}
      =
      \getrefnumber{#2}
      %
      \ifekd@mapps%
      \ifbool{subsq@unit@\ekdan@type}{%
        \ifnum%
        \getrefnumber{#1}
        =
        \getrefnumber{\luadirect{tex.sprint(ekdosis.getprevnotelab())}}
        \else
        \LRnum{\getrefnumber{#1}}% issue the no
        \fi%
      }%
      {\LRnum{\getrefnumber{#1}}}% issue the no
      \else
      \ifsubsq@unit%
      %
      \ifnum%
      \getrefnumber{#1}
      =
      \getrefnumber{\luadirect{tex.sprint(ekdosis.getprevnotelab())}}
      \else
      \LRnum{\getrefnumber{#1}}% issue the no
      \fi
      %
      \else
      \LRnum{\getrefnumber{#1}}% issue the no
      \fi
      \fi
      %
      \else
      \LRnum{\getrefnumber{#1}}--%
      \LRnum{\getrefnumber{#2}}% issue the nos
      \fi%
      \else
      \LRnum{\getrefnumber{#1}}--%
      \LRnum{\getpagerefnumber{#2}}.%
      \LRnum{\getrefnumber{#2}}% issue pg and ln nos
      \fi%
    }\unexpanded\expandafter{\ekd@postrefnum}%
  }%
  \def\current@ref{{%\textdir TLT%
      \unexpanded\expandafter{\ekd@refnumstyle}%
    \ifnum%
    \getpagerefnumber{\luadirect{tex.sprint(ekdosis.getlnlab())}-b}
    =
    \getpagerefnumber{\luadirect{tex.sprint(ekdosis.getlnlab())}-e}
      \ifnum%
      \getrefnumber{\luadirect{tex.sprint(ekdosis.getlnlab())}-b}
      =
      \getrefnumber{\luadirect{tex.sprint(ekdosis.getlnlab())}-e}
      %
      \ifekd@mapps%
      \ifbool{subsq@unit@\ekdan@type}{%
        \ifnum%
        \getrefnumber{\luadirect{tex.sprint(ekdosis.getlnlab())}-b}
        =
        \getrefnumber{\luadirect{tex.sprint(ekdosis.getprevlnlab())}-b}
        \else
        \LRnum{\getrefnumber{\luadirect{tex.sprint(ekdosis.getlnlab())}-b}}% issue the no
        \fi%
      }{\LRnum{\getrefnumber{\luadirect{tex.sprint(ekdosis.getlnlab())}-b}}}% issue the no
      \else
      \ifsubsq@unit%
      %
      \ifnum%
      \getrefnumber{\luadirect{tex.sprint(ekdosis.getlnlab())}-b}
      =
      \getrefnumber{\luadirect{tex.sprint(ekdosis.getprevlnlab())}-b}
      \else
      \LRnum{\getrefnumber{\luadirect{tex.sprint(ekdosis.getlnlab())}-b}}% issue the no
      \fi
      %
      \else
      \LRnum{\getrefnumber{\luadirect{tex.sprint(ekdosis.getlnlab())}-b}}% issue the no
      \fi
      \fi
      %
      \else
      \LRnum{\getrefnumber{\luadirect{tex.sprint(ekdosis.getlnlab())}-b}}--%
      \LRnum{\getrefnumber{\luadirect{tex.sprint(ekdosis.getlnlab())}-e}}% issue the nos
      \fi%
      \else
      \LRnum{\getrefnumber{\luadirect{tex.sprint(ekdosis.getlnlab())}-b}}--%
      \LRnum{\getpagerefnumber{\luadirect{tex.sprint(ekdosis.getlnlab())}-e}}.%
      \LRnum{\getrefnumber{\luadirect{tex.sprint(ekdosis.getlnlab())}-e}}% issue pg and ln nos
      \fi%
    }\unexpanded\expandafter{\ekd@postrefnum}%
  }%
\define@cmdkeys[ekd]{lemrdg}[ekdlr@]{wit, alt, pre, post, prewit,
  postwit, type}
\define@cmdkey[ekd]{lem}[ekdl@]{sep}{}
\presetkeys[ekd]{lem}{sep=\ekdsep}{}
\define@boolkeys[ekd]{lem}[ekdl@]{nolem, nosep}[true]
\define@boolkeys[ekd]{rdg}[ekdr@]{nordg}[true]
\NewDocumentCommand{\lem}{O{} m}{%
  \ekd@isinlemtrue%
  \luadirect{ekdosis.dolnlab(\luastringN{#2})}%
  \bgroup%
  \setkeys[ekd]{lemrdg,lem}{#1}%
  \ifekd@mapps%
    \ifnum%
    \luadirect{tex.sprint(ekdosis.get_bagunits(\luastringO{\ekdan@type}))}
    = 1
    \boolfalse{subsq@unit@\ekdan@type}%
    \fi%
    \luadirect{ekdosis.increment_bagunits(\luastringO{\ekdan@type})}%
    \def\ekd@munit@delim{%
      \luadirect{tex.sprint(ekdosis.getappdelim(\luastringO{\ekdan@type}))}}%
  \fi%
  \ifekdl@nolem\edef\lem@app{%
    % \hskip .75em
    \ifekd@mapps
    \ifbool{subsq@unit@\ekdan@type}%
    {\ekd@munit@delim}{}%
    \else%
    \ifsubsq@unit\unexpanded\expandafter{\ekd@unit@delim}\fi%
    \fi%
    \current@ref}%\hskip .25em}%
  \else%
  \ifbool{al@rlmode}{%
    \edef\lem@app{%
      % \hskip .75em
      \ifekd@mapps
      \ifbool{subsq@unit@\ekdan@type}%
      {\ekd@munit@delim}{}%
      \else%
      \ifsubsq@unit\unexpanded\expandafter{\ekd@unit@delim}\fi%
      \fi%
      \current@ref%\hskip .25em
      \ifdefined\ekdlr@alt%
        \ifdefined\ekdlr@post%
          \space\unexpanded\expandafter{\ekdlr@post}\space\else\fi
        {\textdir TRT\unexpanded\expandafter{\ekdlr@alt}}%
        \ifdefined\ekdlr@pre%
          \space\unexpanded\expandafter{\ekdlr@pre}\space\else\fi
      \else
        \ifdefined\ekdlr@post%
          \space\unexpanded\expandafter{\ekdlr@post}\space\else\fi
        {\textdir TRT\unexpanded{#2}}%
        \ifdefined\ekdlr@pre%
          \space\unexpanded\expandafter{\ekdlr@pre}\space\else\fi
      \fi
      \ifdefined\ekdlr@postwit%
        \space\unexpanded\expandafter{\ekdlr@postwit}\else\fi
      \ifdefined\ekdlr@wit\space\getsiglum{\ekdlr@wit}\else\fi
      \ifdefined\ekdlr@prewit%
        \space\unexpanded\expandafter{\ekdlr@prewit}\space\else\fi
      \ifekdl@nosep\else\unexpanded\expandafter{\ekdl@sep}\fi
    }%
  }%
  {%
    \edef\lem@app{%
      % \hskip .75em
      \ifekd@mapps
      \ifbool{subsq@unit@\ekdan@type}%
      {\ekd@munit@delim}{}%
      \else%
      \ifsubsq@unit\unexpanded\expandafter{\ekd@unit@delim}\fi%
      \fi%
      \current@ref%\hskip .25em
      \ifdefined\ekdlr@alt%
        \ifdefined\ekdlr@pre%
          \space\unexpanded\expandafter{\ekdlr@pre}\space\else\fi
        \ltx@ifpackageloaded{babel}%
          {\noexpand\selectlanguage{\languagename}%
            \unexpanded\expandafter{\ekdlr@alt}}%
          {\unexpanded\expandafter{\ekdlr@alt}}%
        \ifdefined\ekdlr@post%
          \space\unexpanded\expandafter{\ekdlr@post}\space\else\fi
      \else
        \ifdefined\ekdlr@pre%
          \space\unexpanded\expandafter{\ekdlr@pre}\space\else\fi
          \ltx@ifpackageloaded{babel}%
          {\noexpand\selectlanguage{\languagename}\unexpanded{#2}}{%
            \unexpanded{#2}}%
        \ifdefined\ekdlr@post%
          \space\unexpanded\expandafter{\ekdlr@post}\space\else\fi
      \fi
      \ifdefined\ekdlr@prewit%
        \space\unexpanded\expandafter{\ekdlr@prewit}\space\else\fi
      \ifdefined\ekdlr@wit\space\getsiglum{\ekdlr@wit}\else\fi
      \ifdefined\ekdlr@postwit%
        \space\unexpanded\expandafter{\ekdlr@postwit}\else\fi
      \ifekdl@nosep\else\unexpanded\expandafter{\ekdl@sep}\fi
    }%
  }%
  \fi%
  \ifekd@mapps%
  \append@ln@app[\ekdan@type]{\lem@app}%
  \else%
  \append@ln@app{\lem@app}%
  \fi%
  \egroup%
  \ekd@isinlemfalse%
  \subsq@unittrue%
}
\NewDocumentCommand{\rdg}{O{} m}{%
  \bgroup%
  \setkeys[ekd]{lemrdg,rdg}{#1}%
  % \ifekdr@nordg\append@app{}\else% do we need \append@app{} here? If
  %                               % so, keep in mind \ifekd@mapps,
  %                               like so:
  \ifekdr@nordg%
    \ifekd@mapps%
      \append@app[\ekdan@type]{}%
    \else%
    \append@app{}%
    \fi%
  \else%
  \ifbool{al@rlmode}{%
    \edef\rdg@app{%
      \ifdefined\ekdlr@alt%
        \ifdefined\ekdlr@post%
          \space\unexpanded\expandafter{\ekdlr@post}\space\else\fi
        {\textdir TRT\unexpanded\expandafter{\ekdlr@alt}}%
        \ifdefined\ekdlr@pre%
          \space\unexpanded\expandafter{\ekdlr@pre}\space\else\fi
      \else
        \ifdefined\ekdlr@post%
          \space\unexpanded\expandafter{\ekdlr@post}\space\else\fi
        {\textdir TRT\unexpanded{#2}}%
        \ifdefined\ekdlr@pre%
          \space\unexpanded\expandafter{\ekdlr@pre}\space\else\fi
      \fi
      \ifdefined\ekdlr@postwit%
        \space\unexpanded\expandafter{\ekdlr@postwit}\else\fi
      \ifdefined\ekdlr@wit\space\getsiglum{\ekdlr@wit}\else\fi
      \ifdefined\ekdlr@prewit%
        \space\unexpanded\expandafter{\ekdlr@prewit}\space\else\fi
    }%
  }%
  {%
    \edef\rdg@app{%
      \ifdefined\ekdlr@alt%
        \ifdefined\ekdlr@pre%
          \space\unexpanded\expandafter{\ekdlr@pre}\space\else\fi
        \ltx@ifpackageloaded{babel}%
          {\noexpand\selectlanguage{\languagename}%
            \unexpanded\expandafter{\ekdlr@alt}}%
          {\unexpanded\expandafter{\ekdlr@alt}}%
        \ifdefined\ekdlr@post%
          \space\unexpanded\expandafter{\ekdlr@post}\space\else\fi
      \else
        \ifdefined\ekdlr@pre%
          \space\unexpanded\expandafter{\ekdlr@pre}\space\else\fi
          \ltx@ifpackageloaded{babel}%
          {\noexpand\selectlanguage{\languagename}\unexpanded{#2}}{%
            \unexpanded{#2}}%
        \ifdefined\ekdlr@post%
          \space\unexpanded\expandafter{\ekdlr@post}\space\else\fi
      \fi
      \ifdefined\ekdlr@prewit%
        \space\unexpanded\expandafter{\ekdlr@prewit}\space\else\fi
      \ifdefined\ekdlr@wit\space\getsiglum{\ekdlr@wit}\else\fi
      \ifdefined\ekdlr@postwit%
        \space\unexpanded\expandafter{\ekdlr@postwit}\else\fi
    }%
  }%
  \ifekd@mapps%
      \append@app[\ekdan@type]{\rdg@app}%
  \else%
  \append@app{\rdg@app}%
  \fi%
  \fi%
  \egroup%
}
\define@cmdkeys[ekd]{note}[ekdn@]{lem, labelb, labele}
\define@cmdkey[ekd]{note}[ekdn@]{sep}{}
\presetkeys[ekd]{note}{sep=\ekdsep}{}
\NewDocumentCommand{\note@noapp}{O{} +m}{%
  \presetkeys[ekd]{appnote}{type=default}{}%
  \bgroup%
  \setkeys[ekd]{appnote,note}{#1}%
  \stepcounter{ekd@lab}%
  \zlabel{ekd:\theekd@lab}%
  \luadirect{ekdosis.storeabspg(
    \luastring{\zref@extract{ekd:\theekd@lab}{abspage}})}%
  \ifekd@state\add@apparatus\fi%
  \ifekd@mapps%
    \ifnum%
      \luadirect{tex.sprint(ekdosis.get_bagunits(\luastringO{\ekdan@type}))}
      = 1
      \boolfalse{subsq@unit@\ekdan@type}%
    \fi%
  \luadirect{ekdosis.increment_bagunits(\luastringO{\ekdan@type})}%
    \def\ekd@munit@delim{%
      \luadirect{tex.sprint(ekdosis.getappdelim(\luastringO{\ekdan@type}))}}%
  \fi%  
  \ifdefined\ekdn@labelb%
    \luadirect{tex.sprint(ekdosis.setnotelab(\luastringO{\ekdn@labelb}))}%
    \ifdefined\ekdn@labele\else\def\ekdn@labele{\ekdn@labelb}\fi%
  \else\PackageError{ekdosis}{missing labelb}{`labelb' must be
    set.}\fi%
  \ifbool{al@rlmode}%
  {\edef\note@contents{%
      % \hskip .75em
      \ifekd@mapps
        \ifbool{subsq@unit@\ekdan@type}%
        {\ekd@munit@delim}{}%
      \else%
        \ifsubsq@unit\unexpanded\expandafter{\ekd@unit@delim}\fi%
      \fi%
      \current@ref@arg{\ekdn@labelb}{\ekdn@labele}%\hskip .25em
      \ifdefined\ekdn@lem%
          {\textdir TRT\unexpanded\expandafter{\ekdn@lem}}%
          \unexpanded\expandafter{\ekdn@sep}\else\fi%
            {\textdir TRT\unexpanded{#2}}}}%
  {\edef\note@contents{%
      % \hskip .75em
      \ifekd@mapps
        \ifbool{subsq@unit@\ekdan@type}%
        {\ekd@munit@delim}{}%
      \else%
        \ifsubsq@unit\unexpanded\expandafter{\ekd@unit@delim}\fi%
      \fi%
      \current@ref@arg{\ekdn@labelb}{\ekdn@labele}%\hskip .25em
      \ifdefined\ekdn@lem
        \ltx@ifpackageloaded{babel}%
          {\noexpand\selectlanguage{\languagename}%
            \unexpanded\expandafter{\ekdn@lem}}%
          {\unexpanded\expandafter{\ekdn@lem}}%
          \unexpanded\expandafter{\ekdn@sep}\else\fi%
          \ltx@ifpackageloaded{babel}%
          {\noexpand\selectlanguage{\languagename}\unexpanded{#2}}{%
            \unexpanded{#2}}}}%
  \ifekd@mapps%
  \unconditional@appin[\ekdan@type]{\note@contents}%
  \else%
  \unconditional@appin{\note@contents}%
  \fi%
    \luadirect{ekdosis.setprevnotelab(\luastringO{\ekdn@labelb})}%
  \egroup%
  \subsq@unittrue%
}
\ekvdefinekeys{ekd@note}{
  store pre = \pre@value,
  store post = \post@value
}
\NewDocumentCommand{\ekd@note}{O{} m}{%
  \bgroup%
  \ekvset{ekd@note}{#1}%
  \edef\note@contents{%
    \ekvifdefinedNoVal{note}{pre}{}{%
      \unexpanded\expandafter{\pre@value}}%
    \unexpanded{#2}%
    \ekvifdefinedNoVal{note}{post}{}{%
      \unexpanded\expandafter{\post@value}}%
  }%
  \append@app{\note@contents}%
  \egroup%
}
\NewDocumentCommand{\ekd@note@star}{O{} m}{%
  \if@pkg@parnotes
    \bgroup%
      \ekvset{ekd@note}{#1}%
      \edef\note@contents{%
        \ekvifdefinedNoVal{note}{pre}{}{%
          \unexpanded\expandafter{\pre@value}}%
        \unskip\noexpand\parnote{#2}%
        \ekvifdefinedNoVal{note}{post}{}{%
          \unexpanded\expandafter{\post@value}}%
      }%
      \append@app{\note@contents}%
    \egroup%
  \else
    \append@app{\unskip\footnote{#2}}%
  \fi%
}
\NewDocumentCommand{\note@app}{s O{} +m}{%
  \ifbool{al@rlmode}{%
    \IfBooleanTF{#1}{\ekd@note@star[#2]{\unexpanded{%
          {\textdir TRT#3}}}}
    {\ekd@note[#2]{\unexpanded{{\textdir TRT#3}}}}%
  }{%
    \IfBooleanTF{#1}{\ekd@note@star[#2]{\unexpanded{#3}}}
    {\ekd@note[#2]{\unexpanded{#3}}}%
  }%
}
\NewDocumentCommand{\note}{s O{} +m}{%
  \ifekd@state%
    \ifekd@isinapp%
      \ifekd@isinlem%
        \note@noapp[#2]{#3}%
      \else%
        \IfBooleanTF{#1}{\note@app*[#2]{#3}}{\note@app[#2]{#3}}%
      \fi%
    \else%
      \note@noapp[#2]{#3}%
      \fi%
  \fi%
}
\NewDocumentCommand{\apparatus}{}{%
  \luadirect{tex.sprint(ekdosis.appout())}}
\NewDocumentCommand{\test@apparatus}{}{%
  \luadirect{tex.sprint(ekdosis.testapparatus())}}
\NewDocumentCommand{\ekd@storecol}{}{%
  \luadirect{ekdosis.storecurcol(\luastring{\thecolumn})}%
}
\NewDocumentCommand{\EkdosisOn}{}{%
  \ekd@statetrue}
\NewDocumentCommand{\EkdosisOff}{}{%
  \ekd@statefalse%
}
\def\ekd@setlineno{%
  \let\setpagewiselinenumbers\relax%
  \let\pagewiselinenumbers\relax%
  \let\endpagewiselinenumbers\relax%
  \let\runningpagewiselinenumbers\relax%
  \let\realpagewiselinenumbers\relax%
}
\NewDocumentEnvironment{ekdosis}{+b}{%
  \ekd@setlineno%
  \runninglinenumbers
    % \EkdosisColStart
    \EkdosisOn#1}{%
    \EkdosisOff
    % \EkdosisColStop
  \endrunninglinenumbers%
  \iftei@export\luadirect{ekdosis.exporttei(\luastringN{\par #1\par })}\else\fi}
%    \end{macrocode}
% Alignment:---
%    \begin{macrocode}
\ekvdefinekeys{ekd@align}{
  store tcols = \tcols@num,
  store lcols = \lcols@num,
  store texts = \texts@value,
  store apparatus = \apparatus@value,
  bool paired = \ifekd@paired,
  bool pagelineation = \ifekd@pagelineation,
  choice segmentation = {auto = \def\segmentation@val{auto},
                         noauto = \def\segmentation@val{noauto}},
  initial tcols = 2,
  initial lcols = 1,
  initial texts = edition;translation,
  initial apparatus = edition,
  default segmentation = auto
}
\NewDocumentCommand{\SetEkdosisAlignment}{m}{
  \ekvset{ekd@align}{#1}
}
\patchcmd{\pcol@nextpage}{%
  \endgroup}{%
  \ifekd@pagelineation\resetlinenumber\fi
  \endgroup}{}{}
\NewDocumentCommand{\EkdosisColStart}{}{%
  \ekd@setlineno%
  \runninglinenumbers
  \ekd@storecol%
  \stepcounter{ekd@lab}%
  \zlabel{ekd:\theekd@lab}%
  \luadirect{%
    ekdosis.storeabspg(\luastring{\zref@extract{ekd:\theekd@lab}{abspage}},
    "pg_i")}%
  \ifekd@pagelineation
    \luadirect{tex.sprint(ekdosis.checkresetlineno())}
  \fi
}
\NewDocumentCommand{\EkdosisColStop}{}{%
  \stepcounter{ekd@lab}%
  \zlabel{ekd:\theekd@lab}%
  \luadirect{%
    ekdosis.storeabspg(\luastring{\zref@extract{ekd:\theekd@lab}{abspage}},
    "pg_ii")}%
  \endrunninglinenumbers%
}
\NewDocumentEnvironment{alignment}{O{}}
{%
  \ekvset{ekd@align}{#1}%
  \luadirect{ekdosis.mkenvdata(
    \luastring{\texts@value},
    "texts"
    )}
  \luadirect{ekdosis.mkenvdata(
    \luastring{\apparatus@value}, "apparatus"
    )}
  \setrunninglinenumbers
  \luadirect{tex.sprint(ekdosis.mkenv())}
  \ifekd@paired
  \begin{paracol}[\lcols@num]{\tcols@num}
  \else
  \begin{paracol}[\lcols@num]*{\tcols@num}
  \fi
  }
  {\end{paracol}
  \iftei@export\luadirect{ekdosis.export_coldata_totei()}\fi
  \luadirect{ekdosis.flushenvdata()}
  \luadirect{ekdosis.flushcolnums()}
  }
%    \end{macrocode}
% Divisions of the Body
%    \begin{macrocode}
\NewDocumentCommand{\MkBodyDivs}{mmmmmm}{
  \luadirect{ekdosis.mkdivdepths(
    \luastringN{#1},
    \luastringN{#2},
    \luastringN{#3},
    \luastringN{#4},
    \luastringN{#5},
    \luastringN{#6}
    )
  }
}
%    \end{macrocode}
% Divisions specific to ekdosis:---
%    \begin{macrocode}
\ekvdefinekeys{ekd@div}{
  code type = \def\type@value{#1},
  code n = \def\n@value{#1},
  code head = \def\head@value{#1},
  code barehead = \def\barehead@value{#1},
  store depth = \depth@value,
  choice toc = {book = \def\toc@value{book},
                part = \def\toc@value{part},
                chapter = \def\toc@value{chapter},
                section = \def\toc@value{section},
                subsection = \def\toc@value{subsection},
                subsubsection = \def\toc@value{subsubsection},
                paragraph = \def\toc@value{paragraph},
                subparagraph = \def\toc@value{subparagraph}},
  initial depth = 1
}

\NewDocumentCommand{\ekdfmtdiv}{m m m}{
  \luadirect{ekdosis.fmtdiv(\luastring{#1}, \luastringN{#2}, \luastringN{#3})}
}
\NewDocumentCommand{\ekd@getfmtdiv}{m m}{%
  \luadirect{tex.sprint(ekdosis.getfmtdiv(\luastringO{#1}, \luastringN{#2}))}%
}
\NewDocumentCommand{\ekddiv}{m}{
  \begingroup
  \ekvset{ekd@div}{#1}%
  \ifdefined\head@value
    \bgroup
      \ekd@getfmtdiv{\depth@value}{b}%
      \head@value
      \ekd@getfmtdiv{\depth@value}{e}%
    \egroup
      \ifdefined\toc@value
        \ltx@ifpackageloaded{hyperref}{\phantomsection}{}%
          \ifdefined\barehead@value
            \addcontentsline{toc}{\toc@value}{\barehead@value}%
          \else
            \addcontentsline{toc}{\toc@value}{\head@value}%
          \fi
      \fi
  \fi
  \endgroup
}
%    \end{macrocode}
% Very basic implementation of poetry lines:---
%    \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{ekdlua}
-- `'
-- This table will hold the functions:
ekdosis = {}

-- lpeg equivalent for string.gsub()
local function gsub(s, patt, repl)
  patt = lpeg.P(patt)
  patt = lpeg.Cs((patt / repl + 1)^0)
  return lpeg.match(patt, s)
end

-- some basic patterns:
local letters = lpeg.R("az", "AZ")
local ascii = lpeg.R("az", "AZ", "@@")
local dblbkslash = lpeg.Cs("\\")
local bsqbrackets = lpeg.Cs{ "[" * ((1 - lpeg.S"[]") + lpeg.V(1))^0 * "]" }
local bcbraces = lpeg.Cs{ "{" * ((1 - lpeg.S"{}") + lpeg.V(1))^0 * "}" }
local spce = lpeg.Cs(" ")
local spcenc = lpeg.P(" ")
local cmdstar = lpeg.Cs(spce * lpeg.P("*"))
local bsqbracketsii = lpeg.Cs(bsqbrackets^-2)
local bcbracesii = lpeg.Cs(bcbraces^-2)
local cmd = lpeg.Cs(dblbkslash * ascii^1 * cmdstar^-1)
local rawcmd = lpeg.Cs(dblbkslash * ascii^1)
local aftercmd = lpeg.Cs(lpeg.S("*[{,.?;:'`\"") + dblbkslash)
local cmdargs = lpeg.Cs(spce^-1 * bsqbracketsii * bcbracesii * bsqbrackets^-1)
local app = lpeg.Cs("app")
local lemrdg = lpeg.Cs(lpeg.Cs("lem") + lpeg.Cs("rdg"))
local note = lpeg.Cs("note")
local lnbrk = lpeg.Cs("\\\\")
local poemline = lpeg.Cs(lnbrk * bsqbrackets^-1)
local endpoem = lpeg.Cs(lnbrk * lpeg.S("*!") * bsqbrackets^-1)
local sections = lpeg.Cs(lpeg.P("book") + lpeg.P("part") + lpeg.P("chapter")
			    + lpeg.P("section") + lpeg.P("subsection")
			    + lpeg.P("subsubsection"))
local par =  lpeg.P(lpeg.P("\\par") * spce^1)
local parb = lpeg.P(lpeg.Cs("\\p@rb") * spce^1)
local para = lpeg.P(lpeg.Cs("\\p@ra") * spce^1)

-- Bind to local variables
local next = next

-- General
xmlids = {}

local function xmlidfound(element)
   for i = 1,#xmlids do
      if xmlids[i].xmlid == element then
	 return true
      end
   end
   return false
end

-- Witnesses
listWit = {}
idsRend = {}
shorthands = {}

local function isfound(table, value)
   for i = 1,#table do
      if table[i] == value then
	 return true
      end
   end
   return false
end

local function isintable(table, value)
   for i = 1,#table do
      if table[i].a == value then
	 return true
      end
   end
   return false
end

local function get_a_index(id, table)
   local idfound = nil
   for i = 1,#table
   do
      if table[i].a == id then
	 idfound = i
	 break
      end
   end
   return idfound
end

local function getindex(id, table)
   local idfound = nil
   for i = 1,#table
   do
      if table[i].xmlid == id then
	 idfound = i
	 break
      end
   end
   return idfound
end

function ekdosis.newwitness(id,
			    siglum,
			    description,
			    Settlement,
			    Repository,
			    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,
				repository = Repository,
				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="footnote", b="note", c=" place=\"bottom\""},
   {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="s",
    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\"/>"}
}

local envtotags = {
   {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=\"centered\""},
   {a="verse", b="lg", c=""},
   {a="arab", b="p",
    c=" xml:lang=\"ar-Latn\" type=\"transliterated\" subtype=\"arabtex\""}
}

local close_p = {
   "p",
   "lg"
}

local forbid_xmlid = true

function ekdosis.newcmdtotag(cmd, tag, attr)
   if forbid_xmlid
   then
      attr = string.gsub(attr, "xml:id", "n") -- xml:id is not allowed here
   else
   end
   if isintable(cmdtotags, cmd)
   then
      local index = get_a_index(cmd, cmdtotags)
      table.remove(cmdtotags, index)
      table.insert(cmdtotags, {a = cmd, b = tag, c = " "..attr})
      table.sort(cmdtotags, function(a ,b) return(#a.a > #b.a) end)
   else
      table.insert(cmdtotags, {a = cmd, b = tag, c = " "..attr})
      table.sort(cmdtotags, function(a ,b) return(#a.a > #b.a) end)
   end
   return true
end

function ekdosis.newpatttotag(pat, repl)
   pat = string.gsub(pat, "([%[%]])", "%%%1")
   pat = string.gsub(pat, "%#[1-9]", "(.-)")
   repl = string.gsub(repl, "%#([1-9])", "%%%1")
   table.insert(texpatttotags, { a = pat, b = repl })
   table.sort(texpatttotags, function(a ,b) return(#a.a > #b.a) end)
   return true
end

function ekdosis.newenvtotag(env, tag, attr, closep)
   if forbid_xmlid
   then
      attr = string.gsub(attr, "xml:id", "n") -- xml:id is not allowed here
   else
   end
   if isintable(envtotags, env)
   then
      local index = get_a_index(env, envtotags)
      table.remove(envtotags, index)
      table.insert(envtotags, {a = env, b = tag, c = " "..attr, d = closep})
      table.sort(envtotags, function(a ,b) return(#a.a > #b.a) end)
   else
      table.insert(envtotags, {a = env, b = tag, c = " "..attr, d = closep})
      table.sort(envtotags, function(a ,b) return(#a.a > #b.a) end)
   end
   return true
end

-- Get values of attributes
local function get_attr_value(str, attr)
   str = str..","
   local attrval = string.match(str, "%f[%w]"..attr.."%s?%=%s?%b{}")
      or string.match(str, "%f[%w]"..attr.."%s?%=%s?.-%,")
      or ""
   attrval = string.gsub(attrval, attr.."%s?%=%s?(%b{})", function(bbraces)
			    bbraces = string.sub(bbraces, 2, -2)
			    return string.format("%s", bbraces)
   end)
   attrval = string.gsub(attrval, attr.."%s?%=%s?(.-)%s?%,", "%1")
   return attrval
end

local function xml_entities(str)
   str = string.gsub(str, "%<", "&lt;")
   str = string.gsub(str, "%>", "&gt;")
   return str
end

local function note_totei(str)
   str = gsub(str,
	      dblbkslash *
		 note *
		 spcenc^-1 *
		 bsqbrackets *
		 bcbraces *
		 spcenc^-1,
	      function(bkslash, cmd, opt, arg)
		 opt = string.sub(opt, 2, -2)
		 arg = string.sub(arg, 2, -2)
		 teitype = get_attr_value(opt, "type")
		 if teitype ~= "" then teitype = " type=\""..teitype.."\"" else end
		 right = get_attr_value(opt, "labelb")
		 left = get_attr_value(opt, "labele")
		 if left ~= ""
		 then
		    return string.format(
		       "<%s%s target=\"#range(right(%s),left(%s))\">%s</%s><anchor xml:id=\"%s\"/>",
		       cmd, teitype, right, left, arg, cmd, right)
		 elseif left == ""
		 then
		    return string.format(
		       "<%s%s target=\"#right(%s)\">%s</%s><anchor xml:id=\"%s\"/>",
		       cmd, teitype, right, arg, cmd, right)
		 end
   end)
   return str
end

local function app_totei(str)
   str = gsub(str,
	      dblbkslash *
		 app *
		 spcenc^-1 *
		 bsqbrackets *
		 bcbraces *
		 spcenc^-1,
	      function(bkslash, cmd, opt, arg)
		 opt = string.sub(opt, 2, -2)
		 arg = string.sub(arg, 2, -2)
		 opt = get_attr_value(opt, "type")
		 if opt ~= "" then opt = " type=\""..opt.."\"" else end
		 return app_totei(string.format("<%s%s>%s</%s>",
						cmd, opt, arg, cmd))
   end)
   return str
end

local function lem_rdg_totei(str)
   str = gsub(str,
	      spcenc^-1 *
		 dblbkslash *
		 lemrdg *
		 spcenc^-1 *
		 bsqbrackets *
		 bcbraces *
		 spcenc^-1,
	      function(bkslash, cmd, opt, arg)
		 opt = string.sub(opt, 2, -2)
		 arg = string.sub(arg, 2, -2)
		 -- opt = get_attr_value(opt, "wit")
		 --
		 teiwit = get_attr_value(opt, "wit")
		 if teiwit ~= "" then teiwit = " wit=\""..ekdosis.getsiglum(teiwit, "tei").."\"" else end
		 teitype = get_attr_value(opt, "type")
		 if teitype ~= "" then teitype = " type=\""..teitype.."\"" else end
		 --
		 if opt == ""
		 then
		    return lem_rdg_totei(string.format("<%s>%s</%s>",
						       cmd, arg, cmd))
		 else
		    -- opt = ekdosis.getsiglum(opt, "tei")
		    return lem_rdg_totei(string.format("<%s%s%s>%s</%s>",
						       cmd, teiwit, teitype, arg, cmd))
		 end
   end)
   str = gsub(str, spcenc^-0 * dblbkslash * lemrdg * spcenc^-1 * bcbraces * spcenc^-1,
	      function(bkslash, cmd, arg)
		 arg = string.sub(arg, 2, -2)
		 return lem_rdg_totei(string.format("<%s>%s</%s>", cmd, arg, cmd))
   end)
   return str
end

local function relocate_notes(str)
   str = string.gsub(str, "(%<lem.-%>.-)(%<note.->.-%<%/note%>)(.-%<%/lem%>)", "%1%3%2")
   return str
end

local function linestotei(str)
--   str = "\n<l>"..str
   str = string.gsub(str, "^%s?(.-)%s?$", "\n<l>%1</l>\n")
--   str = gsub(str, endpoem, "</l>\n")
   str = gsub(str, poemline * spcenc^-1 * lpeg.P("&gt;"), "\n<lb/>")
   str = gsub(str, poemline * spcenc^-1, "</l>\n<l>")
--   str = str.."</l>\n"
   return str
end

-- better use lpeg: look into this later
local function versetotei(str)
   str = string.gsub(str, "(\\begin%s?%{ekdverse%})(%b[])(.-)(\\end%s?%{ekdverse%})", function(benv, opt, arg, eenv)
			arg = linestotei(arg)
			return string.format("%s%s%s%s", benv, opt, arg, eenv)
   end)
   str = string.gsub(str, "(\\begin%s?%{ekdverse%})(.-)(\\end%s?%{ekdverse%})", function(benv, arg, eenv)
			arg = linestotei(arg)
			return string.format("%s%s%s", benv, arg, eenv)
   end)
   str = string.gsub(str, "(\\begin%s?%{verse%})(%b[])(.-)(\\end%s?%{verse%})", function(benv, opt, arg, eenv)
			arg = linestotei(arg)
			return string.format("%s%s%s%s", benv, opt, arg, eenv)
   end)
   str = string.gsub(str, "(\\begin%s?%{verse%})(.-)(\\end%s?%{verse%})", function(benv, arg, eenv)
			arg = linestotei(arg)
			return string.format("%s%s%s", benv, arg, eenv)
   end)
   return str
end

local function envtotei(str)
   for i = 1,#envtotags
   do
      if envtotags[i].b ~= ""
      then
	 if isfound(close_p, envtotags[i].b) or envtotags[i].d == "yes"
	 then
	    str = gsub(str, lpeg.P("\\begin") * spcenc^-1 * lpeg.P("{")
			  * lpeg.Cs(envtotags[i].a) * lpeg.P("}")
			  * bsqbracketsii * bcbracesii * spcenc^-1,
		       "\\p@rb <"..envtotags[i].b..envtotags[i].c..">")
	    str = gsub(str, spcenc^-1 * lpeg.P("\\end") * spcenc^-1 * lpeg.P("{")
			  * lpeg.Cs(envtotags[i].a) * lpeg.P("}"),
		       "</"..envtotags[i].b..">\\p@ra ")
	 else
	    str = gsub(str, lpeg.P("\\begin") * spcenc^-1 * lpeg.P("{")
			  * lpeg.Cs(envtotags[i].a) * lpeg.P("}")
			  * bsqbracketsii * bcbracesii * spcenc^-1,
		       "<"..envtotags[i].b..envtotags[i].c..">")
	    str = gsub(str, spcenc^-1 * lpeg.P("\\end") * spcenc^-1 * lpeg.P("{")
			  * lpeg.Cs(envtotags[i].a) * lpeg.P("}"),
		       "</"..envtotags[i].b..">")
	 end
      else
	 str = gsub(str, lpeg.P("\\begin") * spcenc^-1 * lpeg.P("{")
		       * lpeg.Cs(envtotags[i].a) * lpeg.P("}")
		       * bsqbracketsii * bcbracesii * spcenc^-1,
		    "")
	 str = gsub(str, spcenc^-1 * lpeg.P("\\end") * spcenc^-1 * lpeg.P("{")
		       * lpeg.Cs(envtotags[i].a) * lpeg.P("}"),
		    "")
      end
   end
   str = gsub(str, lpeg.P("\\begin") * spcenc^-1 * lpeg.P("{")
		 * lpeg.Cs(ascii^1) * lpeg.P("}") * bsqbracketsii
		 * bcbracesii * spcenc^-1,
	      "<%1>")
   str = gsub(str, spcenc^-1 * lpeg.P("\\end") * spcenc^-1 * lpeg.P("{")
		 * lpeg.Cs(ascii^1) * lpeg.P("}") * bsqbracketsii
		 * bcbracesii,
	      "</%1>")
   return str
end

local function texpatttotei(str)
   for i = 1,#texpatttotags do
      str = string.gsub(str, texpatttotags[i].a, texpatttotags[i].b)
   end
   return str
end

local function cmdtotei(str)
   for i = 1,#cmdtotags
   do
      str = gsub(str, lpeg.P("\\") * lpeg.Cs(cmdtotags[i].a) * spcenc^-1 * bsqbrackets * -bcbraces, "\\%1%2{}")
      str = gsub(str, lpeg.P("\\") * lpeg.Cs(cmdtotags[i].a) * spcenc^-1 * -(bsqbrackets + bcbraces), "\\%1[]{}")
      str = string.gsub(str, "(\\"..cmdtotags[i].a..")%s?%*?(%b{})", "%1[]%2")
      str = string.gsub(str, "(\\"..cmdtotags[i].a..")%s?%*?(%b[])(%b{})",
			function(cmd, arg, body)
			   body = string.sub(body, 2, -2)
			   arg = string.sub(arg, 2, -2)
			   arg = string.gsub(arg, "(%b{})", function(braces)
						braces = string.sub(braces, 2, -2)
						return string.format("\"%s\"", braces)
			   end)
			   body = cmdtotei(body)
			   -- return string.format("<"..cmdtotags[i].b..cmdtotags[i].c.." %s>%s</"..cmdtotags[i].b..">", arg, body)
			   if cmdtotags[i].b ~= ""
			   then
			      return string.format("<"..cmdtotags[i].b..cmdtotags[i].c..">%s</" ..
						   cmdtotags[i].b..">", body)
			   else
			      return ""
			   end
      end)
   end
   -- temporarily:
   str = string.gsub(str, "\\(linelabel)%s?(%b{})",
		     function(cmd, body)
			body = string.sub(body, 2, -2)
			body = cmdtotei(body)
			return string.format("<anchor xml:id=\"%s\"/>", body)
   end)
   str = string.gsub(str, "\\(%a+)%s?%*?(%b[])(%b{})",
		     function(cmd, opt, body)
			body = string.sub(body, 2, -2)
			body = cmdtotei(body)
			return string.format("<%s>%s</%s>", cmd, body, cmd)
   end)
   str = string.gsub(str, "\\(%a+)%s?%*?(%b{})",
		     function(cmd, body)
			body = string.sub(body, 2, -2)
			body = cmdtotei(body)
			return string.format("<%s>%s</%s>", cmd, body, cmd)
   end)
   str = string.gsub(str, "(%s)(%>)", "%2")
   return str
end

local function partotei(str)
   str = gsub(str, lpeg.P(lpeg.P("\\par") * spcenc^1)^1, "\\par ")
   str = gsub(str, ((para + parb) * par^-1)^2, "\\p@r ")
   str = string.gsub(str, "\\p@ra%s+", "<p>")
   str = string.gsub(str, "\\p@rb%s+", "</p>")
   str = string.gsub(str, "\\p@r%s+", "")   
   str = string.gsub(str, "%s?\\par%s?", "<p>", 1)
   str = string.gsub(str, "(%<p%>)(%s-)(%<%/?div%d?)", "%3")
   str = string.gsub(str, "%s?\\par%s?", "</p><p>")
   str = string.gsub(str, "<p>%s?</p>", "")
   str = string.gsub(str, "(%<p%>)%s?(%</div%>)$", "%2")
   str = string.gsub(str, "(%<p%>)%s?$", "")
   str = string.gsub(str, "(<p>)%s?(<div.->)", "%2%1")
   return str
end

local function self_close_tags(str)
   str = gsub(str, lpeg.P("<" * -lpeg.S("/"))
		 * lpeg.Cs(letters^1)
		 * lpeg.Cs((1 - lpeg.S"<>")^0)
		 * lpeg.P(">")
		 * lpeg.P("</")
		 * lpeg.Cs(letters^1)
		 * lpeg.P(">"), function(ftag, arg, ltag)
		    if ftag == ltag
		    then
		       return string.format("<%s%s/>", ftag, arg)
		    else
		    end
   end)
   return str
end

local divdepth = {
   book = 1,
   part = 2,
   chapter = 3,
   section = 4,
   subsection = 5,
   subsubsection = 6
}

function ekdosis.mkdivdepths(...)
   divdepth = {}
   local num = 1
   for _, y in ipairs{...}
   do
      if y == "book" or "part" or "chapter"
	 or "section" or "subsection" or "subsubsection"
      then
	 divdepth[y] = num
	 num = num + 1
      else
      end
   end
   return true
end

-- LaTeX side: format the divisions
local fmtdiv = {}

function ekdosis.fmtdiv(n, fmtb, fmte)
   if isintable(fmtdiv, n)
   then
      local index = get_a_index(n, fmtdiv)
      table.remove(fmtdiv, index)
   else
   end
   table.insert(fmtdiv, { a = n, formatb = fmtb, formate = fmte} )
   return true
end

function ekdosis.getfmtdiv(n, pos)
   local index = get_a_index(n, fmtdiv)
   if index ~= nil
   then
      if pos == "b"
      then
	 return fmtdiv[index].formatb
      elseif pos == "e"
      then
	 return fmtdiv[index].formate
      end
   else
      return ""
   end
end

local ekddivs = true

function ekdosis.setekddivsfalse()
   ekddivs = false
end

local function ekddivs_totei(str)
   str = gsub(str, dblbkslash * lpeg.Cs("ekddiv") * spce^-1 * bcbraces,
	      function(bkslash, cmd, space, arg)
		 if ekddivs
		 then
		    arg = string.sub(arg, 2, -2)
		    teitype = get_attr_value(arg, "type")
		    tein = get_attr_value(arg, "n")
		    teihead = get_attr_value(arg, "head")
		    teidepth = get_attr_value(arg, "depth")
		    if teitype ~= "" then teitype = " type=\""..teitype.."\"" else end
		    if tein ~= "" then tein = " n=\""..tein.."\"" else end
		    if teidepth ~= ""
		    then
		       teidepth = " depth=\""..teidepth.."\""
		    else
		       teidepth = " depth=\"1\""
		    end
		    return string.format("\\p@rb <div%s%s%s><head>%s</head>\\p@ra ",
					 teitype, tein, teidepth, teihead)
		 else
		    return ""
		 end
   end)
   return str
end

local function section_totei(str)
   str = gsub(str, dblbkslash * sections * spce^-1 * bcbraces, "%1%2%3[]%4")
   str = gsub(str, dblbkslash * sections * spce^-1 * bsqbrackets * bcbraces,
	      function(bkslash, secname, space, opt, arg)
		 if ekddivs
		 then
		    return ""
		 else
		    ctr = divdepth[secname]
		    arg = string.sub(arg, 2, -2)
		    return string.format("\\p@rb <div%s type=\"%s\"><head>%s</head>\\p@ra ",
					 ctr, secname, arg)
		 end
   end)
   return str
end

local used_ndivs = {}

local function close_ekddivs_at_end(str)
   local isdiv = false
   if string.find(str, "</div>$")
   then
      isdiv = true
      str = string.gsub(str, "(.*)(</div>)$", "%1")
   else
   end
   -- collect used depth numbers
   for i in string.gmatch(str, "<div .-depth%=\"%d\".->")
   do
      i = string.match(i, "depth=\"%d\"")
      i = string.match(i, "%d")
      if isintable(used_ndivs, i)
      then
      else
	 table.insert(used_ndivs, {a = i} )
      end
   end
   if next(used_ndivs) ~= nil
   then
      table.sort(used_ndivs, function(a ,b) return(#a.a > #b.a) end)
   else
   end
   local firstdiv = string.match(str, "<div .-depth%=\"%d\".->") or ""
   firstdiv = string.match(firstdiv, "depth%=\"%d\"") or ""
   firstdiv = string.match(firstdiv, "%d") or ""
   local lastdiv = string.match(string.reverse(str), ">.-\"%d\"%=htped.- vid<") or ""
   lastdiv = string.match(lastdiv, "\"%d\"%=htped") or ""
   lastdiv = string.match(lastdiv, "%d") or ""
   local firstdivindex = get_a_index(firstdiv, used_ndivs)
   local lastdivindex = get_a_index(lastdiv, used_ndivs)
   firstdivindex = tonumber(firstdivindex)
   lastdivindex = tonumber(lastdivindex)
   local closedivs = ""
   if isintable(used_ndivs, firstdiv)
   then
      while lastdivindex >= firstdivindex
      do
	 closedivs = closedivs.."</div>"
	 lastdivindex = lastdivindex - 1
      end
   end
   if isdiv
   then
      return str..closedivs.."</div>"
   else
      return str..closedivs
   end
end

local function close_ndivs_at_end(str)
   local isdiv = false
   if string.find(str, "</div>$")
   then
      isdiv = true
      str = string.gsub(str, "(.*)(</div>)$", "%1")
   else
   end
   -- collect used div numbers
   for i in string.gmatch(str, "<div[1-6]")
   do
      i = string.match(i, "[1-6]")
      if isintable(used_ndivs, i)
      then
      else
   	 table.insert(used_ndivs, {a = i} )
      end
   end
   if next(used_ndivs) ~= nil
   then
      table.sort(used_ndivs, function(a ,b) return(#a.a > #b.a) end)
   else
   end
   local firstdiv = string.match(str, "<div[1-6]") or ""
   firstdiv = string.match(firstdiv, "[1-6]") or ""
   local lastdiv = string.match(string.reverse(str), "[1-6]vid<") or ""
   lastdiv = string.match(lastdiv, "[1-6]") or ""
   local firstdivindex = get_a_index(firstdiv, used_ndivs)
   local lastdivindex = get_a_index(lastdiv, used_ndivs)
   firstdivindex = tonumber(firstdivindex)
   lastdivindex = tonumber(lastdivindex)
   local closedivs = ""
   if isintable(used_ndivs, firstdiv)
   then
      while lastdivindex >= firstdivindex
      do
	 closedivs = closedivs.."</div"..used_ndivs[lastdivindex].a..">"
	 lastdivindex = lastdivindex - 1
      end
   end
   if isdiv
   then
      return str..closedivs.."</div>"
   else
      return str..closedivs
   end
end

local function close_ekddivs_in_between(str)
   local maxdepth = 1
   for i in string.gmatch(str, "<div.-depth=\"(%d)\".->", "%1")
   do
      if tonumber(i) > tonumber(maxdepth)
      then
	 maxdepth = i
      else
      end
   end
   for ndivi = 1, maxdepth
   do
      str = string.gsub(str, "(<div .-depth%=\")("..ndivi..")(\".->)(.-)(<div .-depth%=\")(%d)(\".->)",
			function(bdivi, ndivi, edivi, between, bdivii, ndivii, edivii)
			   local firstdiv = ndivi
			   local lastdiv = ndivii
			   local firstdivindex = get_a_index(firstdiv, used_ndivs)
			   local lastdivindex = get_a_index(lastdiv, used_ndivs)
			   firstdivindex = tonumber(firstdivindex)
			   lastdivindex = tonumber(lastdivindex)
			   local closedivs = ""
			   if firstdivindex >= lastdivindex
			   then
			      while firstdivindex >= lastdivindex
			      do
				 closedivs = closedivs.."</div>"
				 firstdivindex = firstdivindex - 1
			      end
			   end
			   return string.format("%s%s%s%s%s%s%s%s",
						bdivi, ndivi, edivi, between, closedivs, bdivii, ndivii, edivii)
      end)
   end
   str = string.gsub(str, "(<div.-)(%sdepth%=\"%d\")(.->)", "%1%3")
   used_ndivs = {}
   return str
end

local function close_ndivs_in_between(str)
   for ndivi = 1, 6
   do
      str = string.gsub(str, "(<div)("..ndivi..")(.->)(.-)(<div)([1-6])(.->)",
			function(bdivi, ndivi, edivi, between, bdivii, ndivii, edivii)
			   local firstdiv = ndivi
			   local lastdiv = ndivii
			   local firstdivindex = get_a_index(firstdiv, used_ndivs)
			   local lastdivindex = get_a_index(lastdiv, used_ndivs)
			   firstdivindex = tonumber(firstdivindex)
			   lastdivindex = tonumber(lastdivindex)
			   local closedivs = ""
			   if firstdivindex >= lastdivindex
			   then
			      while firstdivindex >= lastdivindex
			      do
			   	 closedivs = closedivs.."</div"..used_ndivs[firstdivindex].a..">"
			   	 firstdivindex = firstdivindex - 1
			      end
			   end
			   return string.format("%s%s%s%s%s%s%s%s",
						bdivi, ndivi, edivi, between, closedivs, bdivii, ndivii, edivii)
			
   end)
   end
   used_ndivs = {}
   return str
end

local function textotei(str)
   str = xml_entities(str)
   str = texpatttotei(str)
   str = note_totei(str)
   str = app_totei(str)
   str = lem_rdg_totei(str)
   str = relocate_notes(str)
   str = versetotei(str)
   str = envtotei(str)
   str = ekddivs_totei(str)
   str = section_totei(str)
   str = cmdtotei(str)
   str = self_close_tags(str)
   str = partotei(str)
   if ekddivs
   then
      str = close_ekddivs_at_end(str)
      str = close_ekddivs_in_between(str)
   else
      str = close_ndivs_at_end(str)
      str = close_ndivs_in_between(str)
   end
   return str
end

local teifilename = tex.jobname.."-tei"

function ekdosis.setteifilename(str)
   teifilename = str
   return true
end

function ekdosis.openteistream()
   local f = io.open(teifilename.."_tmp.xml", "a+")
   f:write('<?xml version="1.0" encoding="utf-8"?>', "\n")
   f:write("<TEI xmlns=\"http://www.tei-c.org/ns/1.0\">", "\n")
   f:write("<teiHeader>", "\n")
   f:write("<fileDesc>", "\n")
   f:write("<titleStmt>", "\n")
   f:write("<title><!-- Title --></title>", "\n")
   f:write("<respStmt>", "\n")
   f:write("<resp><!-- Edited by --></resp>", "\n")
   f:write("<name><!-- Name --></name>", "\n")
   f:write("</respStmt>", "\n")
   f:write("</titleStmt>", "\n")
   f:write("<publicationStmt>", "\n")
   f:write("<distributor><!-- Distributor name  --></distributor>", "\n")
   f:write("</publicationStmt>", "\n")
   f:write("<sourceDesc>", "\n")
   f:write("<listWit>", "\n")
   for i = 1,#listWit do
      f:write('<witness xml:id=\"', listWit[i].xmlid, "\">", "\n")
      f:write('<abbr type="siglum">', textotei(listWit[i].abbr), "</abbr>", "\n")
      f:write(textotei(listWit[i].detailsDesc), "\n")
      f:write("<msDesc>", "\n")
      if listWit[i].msIdentifier.settlement == ""
	 and listWit[i].msIdentifier.repository == ""
	 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.repository ~= "" then
	    f:write("<repository>", textotei(listWit[i].msIdentifier.repository), "</repository>", "\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)
   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 aligned_texts = {}
local texts_w_apparatus = {}
local coldata_totei = {}

local function sanitize_envdata(str)  -- look for a better way to achieve this
   str = string.gsub(str, "(%a+)%s+(%b[])", "%1%2")
   str = string.gsub(str, "(%a+)(%b[])%s+", "%1%2")
   str = string.gsub(str, "%s+(%a+)(%b[])", "%1%2")
   str = gsub(str, lpeg.Cs(letters^1)
		 * spcenc^-1
		 * -bsqbrackets
		 * lpeg.Cs(";"), "%1[]%2")
   str = string.gsub(str, "%s+(%a+)(%b[])", "%1%2")
   return str
end

function ekdosis.mkenvdata(str, opt)
   if not string.find(str, "%;", -1) then str = str .. ";" else end
   --   str = str ..";"
   --   str = string.gsub(str, "%s+", "")
   local fieldstart = 1
   local col = 0
   if opt == "texts" then
      str = sanitize_envdata(str)
      repeat
	 local _s, nexti = string.find(str, "%b[]%s-%;", fieldstart)
	 local namediv = string.gsub(string.sub(str, fieldstart, nexti-1), "(%a+)%s-(%b[])", "%1")
	 local attr = string.gsub(string.sub(str, fieldstart, nexti-1), "(%a+)%s-(%b[])", "%2")
	 attr = string.sub(attr, 2, -2)
	 if forbid_xmlid
	 then
	    attr = string.gsub(attr, "xml:id", "n") -- xml:id is not allowed here
	 else
	 end
	 table.insert(aligned_texts, { text = namediv,
				       attribute = attr,
				       column = col })
	 table.insert(coldata_totei, { environment = namediv,
				       data = {} })
	 col = col + 1
	 fieldstart = nexti + 1
      until fieldstart > string.len(str)
      return aligned_texts
   elseif opt == "apparatus" then
      repeat
	 local nexti = string.find(str, "%;", fieldstart)
	 table.insert(texts_w_apparatus, string.sub(str, fieldstart, nexti-1))
	 fieldstart = nexti +1
      until fieldstart > string.len(str)
      return texts_w_apparatus
   end
end

-- Reminder: the following two variables are already set above
-- local prevcol = nil
-- local curcol = "x"

function ekdosis.storecurcol(n)
      curcol = n
   return true
end

function ekdosis.flushcolnums()
   prevcol = nil
   curcol = "x"
   return true
end

function ekdosis.flushenvdata()
   aligned_texts = {}
   texts_w_apparatus = {}
   coldata_totei = {}
   return true
end

function ekdosis.storecoldata(nthcol, chunk)
   local tindex = tonumber(nthcol) + 1
   table.insert(coldata_totei[tindex].data, chunk)
   return true
end

local environment_div = {}

function ekdosis.newscholar(id, siglum)
   if xmlidfound(id)
   then
      tex.print("\\unexpanded{\\PackageWarning{ekdosis}{\""
	    ..id..
	    "\" already exists as a xml:id. " 
	    ..
	    "Please pick another id.}}")
   else
      table.insert(xmlids, {xmlid = id})
      table.sort(xmlids, function(a ,b) return(#a.xmlid > #b.xmlid) end)
      table.insert(idsRend, {xmlid = id, abbr = siglum})
      table.sort(idsRend, function(a ,b) return(#a.xmlid > #b.xmlid) end)
   end
   return true
end


local function build_envdiv(str)
   if not environment_div[str]
   then
      environment_div[str] = 1
   else
      environment_div[str] = environment_div[str] + 1
   end
   local div = "div-"..str.."_"..environment_div[str]
   if xmlidfound(div)
   then
      tex.print("\\unexpanded{\\PackageWarning{ekdosis}{\""
		   ..div..
		   "\" already exists as a xml:id. " 
		   ..
		   "ekdosis has generated some random id.}}")
      return "div-"..math.random(1000,9999)
   else
      table.insert(xmlids, {xmlid = div})
      table.sort(xmlids, function(a ,b) return(#a.xmlid > #b.xmlid) end)
      return div
   end
end

function ekdosis.mkenv()
   local environments = {}
   for i = 1,#aligned_texts
   do
      if isfound(texts_w_apparatus, aligned_texts[i].text)
      then
	 table.insert(environments, "\\NewDocumentEnvironment{".. aligned_texts[i].text.."}{+b}"
			 .."{\\begin{nthcolumn}{".. aligned_texts[i].column.."}"
			 .."\\par"
			 .."\\EkdosisColStart"
			 .."\\EkdosisOn#1"
		         .."}{\\EkdosisOff"
			 .."\\EkdosisColStop"
		         .."\\end{nthcolumn}"
			 .."\\csname iftei@export\\endcsname\\luadirect{ekdosis.storecoldata("
			 .. aligned_texts[i].column
			 ..", \\luastringN{\\par#1\\par})}\\fi"
			 .."}")
	 table.insert(environments, "\\NewDocumentEnvironment{".. aligned_texts[i].text.."*}{+b}"
			 .."{\\begin{nthcolumn*}{".. aligned_texts[i].column.."}[]"
			 .."\\par"
			 .."\\EkdosisColStart"
			 .."\\EkdosisOn#1"
		         .."}{\\EkdosisOff"
			 .."\\EkdosisColStop"
		         .."\\end{nthcolumn*}"
			 .."\\csname iftei@export\\endcsname\\luadirect{ekdosis.storecoldata("
			 .. aligned_texts[i].column
			 ..", \\luastringN{\\par#1\\par})}\\fi"
			 .."}")
      else
	 table.insert(environments, "\\NewDocumentEnvironment{".. aligned_texts[i].text.."}{+b}"
			 .."{\\begin{nthcolumn}{".. aligned_texts[i].column.."}"
			 .."\\par"
			 .."#1"
		         .."}{\\end{nthcolumn}"
			 .."\\csname iftei@export\\endcsname\\luadirect{ekdosis.storecoldata("
			 .. aligned_texts[i].column
			 ..", \\luastringN{\\par#1\\par})}\\fi"
			 .."}")
	 table.insert(environments, "\\NewDocumentEnvironment{".. aligned_texts[i].text.."*}{+b}"
			 .."{\\begin{nthcolumn*}{"..aligned_texts[i].column.."}[]"
			 .."\\par"
			 .."#1"
			 .."}{"
		         .."\\end{nthcolumn*}"
			 .."\\csname iftei@export\\endcsname\\luadirect{ekdosis.storecoldata("
			 .. aligned_texts[i].column
			 ..", \\luastringN{\\par#1\\par})}\\fi"
			 .."}")
      end
      forbid_xmlid = false
      if aligned_texts[i].attribute ~= ""
      then
	 ekdosis.newenvtotag(aligned_texts[i].text, "div",
			     "xml:id=\""
				..build_envdiv(aligned_texts[i].text)
				.."\" "
				..aligned_texts[i].attribute)
      else
	 ekdosis.newenvtotag(aligned_texts[i].text, "div",
			     "xml:id=\""
				..build_envdiv(aligned_texts[i].text)
				.."\"")
      end
      forbid_xmlid = true
   end
   str = table.concat(environments)
   return str
end

function ekdosis.export_coldata_totei()
   for i = 1,#coldata_totei
   do
      ekdosis.exporttei("\\begin{".. coldata_totei[i].environment .."}"
			   .. table.concat(coldata_totei[i].data)
			.. "\\end{".. coldata_totei[i].environment .."}")
   end
end

-- handle multiple layers in apparatuses
--
local apparatuses = {}
local bagunits = {}

function ekdosis.newapparatus(teitype,
			      appdir,
			      apprule,
			      appdelim,
			      appsep,
			      appbhook,
			      appehook)
   if isintable(apparatuses, teitype)
   then
      tex.print("\\unexpanded{\\PackageWarning{ekdosis}{\""
		   ..teitype..
		   "\" already exists.}}")
   else
      table.insert(apparatuses, {a = teitype,
				 direction = appdir,
				 rule = apprule,
				 delim = appdelim,
				 sep = appsep,
				 bhook = appbhook,
				 ehook = appehook})
   end
   bagunits[teitype] = 1
   return true
end

function ekdosis.getappdelim(str)
   for i = 1,#apparatuses
   do
      if apparatuses[i].a == str then
	 delimfound = apparatuses[i].delim
	 break
      end
   end
   return delimfound
end

function ekdosis.get_bagunits(teitype)
   return bagunits[teitype]
end

function ekdosis.increment_bagunits(teitype)
   bagunits[teitype] = (bagunits[teitype] or 0) + 1
end

local function reset_bagunits()
   for i = 1,#apparatuses
   do
      bagunits[apparatuses[i].a] = 1
   end
end

function ekdosis.appin(str, teitype)
   local f = io.open(tex.jobname.."_tmp.ekd", "a+")
   if next(apparatuses) == nil
   then
      f:write("<", cur_abs_pg, "-", curcol, "-0>", str, "</", cur_abs_pg, "-", 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, "-", curcol, "-", appno, ">", str, "</", cur_abs_pg, "-", curcol, "-", appno, ">\n")
   end
   f:close()
   return true
end

function ekdosis.appout()
   local file = io.open(tex.jobname..".ekd", "r")
   if file ~= nil then io.close(file)
      f = assert(io.open(tex.jobname..".ekd", "r"))
      t = f:read("*a")
      local output = {}
      if next(apparatuses) == nil then
	 -- table.insert(output, "BEGIN")
	 table.insert(output, "\\noindent\\csname ekd@default@rule\\endcsname\\NLS{}")
--	 table.insert(output, "\\noindent ")
	 for i in string.gmatch(t,
				"<"..cur_abs_pg.."%-"..curcol.."%-0>.-</"..cur_abs_pg.."%-"..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.."%-"..curcol.."%-"..n..">.-</"..cur_abs_pg.."%-"..curcol.."%-"..n..">")	  
	    then
	       -- table.insert(output, "BEGIN")
	       table.insert(output, "\\bgroup{}")
	       if apparatuses[n].direction == "LR"
	       then
		  table.insert(output, "\\pardir TLT\\textdir TLT{}")
	       elseif apparatuses[n].direction == "RL"
	       then
		  table.insert(output, "\\pardir TRT\\textdir TRT{}")
	       end
	       if apparatuses[n].rule == "none"
	       then
		  if n > 1
		  then
		     table.insert(output, "\\NLS{}")
		  else
		     table.insert(output, "\\noindent ")
		  end
	       elseif apparatuses[n].rule ~= ""
	       then
		  if n > 1
		  then
		     table.insert(output, "\\NLS{}" .. apparatuses[n].rule .. "\\NLS{}")
		  else
--		     table.insert(output, "\\noindent ")
		     table.insert(output, apparatuses[n].rule .. "\\NLS{}")
		  end
	       else
		  if n > 1
		  then
		     table.insert(output, "\\NLS\\csname ekd@default@rule\\endcsname\\NLS{}")
		  else
--		     table.insert(output, "\\noindent ")
		     table.insert(output, "\\csname ekd@default@rule\\endcsname\\NLS{}")
		  end
	       end
	       if apparatuses[n].sep ~= ""
	       then
		  table.insert(output, "\\edef\\ekdsep{" .. apparatuses[n].sep .. "}")
	       else
	       end
	       if apparatuses[n].bhook ~= ""
	       then
		  table.insert(output, apparatuses[n].bhook)
	       else
		  table.insert(output, "\\relax")
	       end
	       for i in string.gmatch(t,
				      "<"..cur_abs_pg.."%-"..curcol.."%-"..n..">.-</"..cur_abs_pg.."%-"..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.."%-"..curcol.."%-[0-9]>", "")
      str = string.gsub(str, "<"..cur_abs_pg.."%-"..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
      return "\\boolfalse{do@app}"
   else
      table.insert(curcol_curabspg, curcol.."-"..cur_abs_pg)
      if next(apparatuses) ~= nil then
	 reset_bagunits()
      end
      return "\\booltrue{do@app}"
   end
end

local lnlabs = {}
local lnlab_salt = 0
local current_lnlab = nil
local prev_lnlab = nil
local current_notelab = nil
local prev_notelab = nil
local current_lemma = nil
local salt = 0

local function mdvisintable(table, value)
   for _, v in pairs(table) do
      if v == value then return true end
   end
   return false
end

function ekdosis.dolnlab(str)
   prev_lnlab = current_lnlab
   current_lemma = str
   i = md5.sumhexa(str)
   if not mdvisintable(lnlabs, i) then
      table.insert(lnlabs, i)
   else
      i = i..salt
      table.insert(lnlabs, i)
      salt = salt + 1
   end
   current_lnlab = i
   return true
end

function ekdosis.getlnlab()
   return current_lnlab
end

function ekdosis.getprevlnlab()
   return prev_lnlab
end

function ekdosis.setnotelab(str)
   current_notelab = str
   return "\\linelabel{" .. current_notelab .. "}"
end

function ekdosis.getnotelab()
   return current_notelab
end

function ekdosis.setprevnotelab(str)
   prev_notelab = str
   return true
end

function ekdosis.getprevnotelab()
   return prev_notelab
end

local function remove_note(str)
   str = gsub(str, dblbkslash * lpeg.P("note") * cmdargs, "")
   return str
end

function ekdosis.mdvappend(str, teitype)
   if teitype == nil
   then
   return "\\linelabel{" .. current_lnlab .. "-b}\\wordboundary{}"
      ..
      current_lemma
      ..
      "\\linelabel{" .. current_lnlab .. "-e}"
      ..
      "\\csname append@app\\endcsname{"
      .. remove_note(str) .. "}"
   else
   return "\\linelabel{" .. current_lnlab .. "-b}\\wordboundary{}"
      ..
      current_lemma
      ..
      "\\linelabel{" .. current_lnlab .. "-e}"
      ..
      "\\csname append@app\\endcsname" .. "[" .. teitype ..  "]{"
      .. remove_note(str) .. "}"
   end
end

% \end{ekdlua}
% \iffalse
%</lua>
% \fi
\endinput
