diff options
author | Karl Berry <karl@freefriends.org> | 2024-08-29 20:39:45 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2024-08-29 20:39:45 +0000 |
commit | 5356980faaec739ffb82f2f950a10257aef9a77d (patch) | |
tree | 3fbf6e9e8097f492ab51a5945c3cb0eef0dc87e6 | |
parent | 6e0931c360d843dca63b865645eee56357719006 (diff) |
enverb (29aug24)
git-svn-id: svn://tug.org/texlive/trunk@72137 c570f23f-e606-0410-a88d-b1316a301751
-rw-r--r-- | Master/texmf-dist/doc/latex/enverb/README.md | 34 | ||||
-rw-r--r-- | Master/texmf-dist/doc/latex/enverb/doc-enverb.tex | 47 | ||||
-rw-r--r-- | Master/texmf-dist/doc/latex/enverb/doc-examples.tex | 178 | ||||
-rw-r--r-- | Master/texmf-dist/doc/latex/enverb/doc-keys.tex | 111 | ||||
-rw-r--r-- | Master/texmf-dist/doc/latex/enverb/doc-using-contents.tex | 40 | ||||
-rw-r--r-- | Master/texmf-dist/doc/latex/enverb/enverb-doc.pdf | bin | 0 -> 346942 bytes | |||
-rw-r--r-- | Master/texmf-dist/doc/latex/enverb/enverb-doc.tex | 87 | ||||
-rw-r--r-- | Master/texmf-dist/doc/latex/enverb/preamble-examples.tex | 199 | ||||
-rw-r--r-- | Master/texmf-dist/doc/latex/enverb/preamble-logo.tex | 25 | ||||
-rw-r--r-- | Master/texmf-dist/source/latex/enverb/enverb.dtx | 720 | ||||
-rw-r--r-- | Master/texmf-dist/tex/latex/enverb/enverb.sty | 380 | ||||
-rwxr-xr-x | Master/tlpkg/bin/tlpkg-ctan-check | 2 | ||||
-rwxr-xr-x | Master/tlpkg/libexec/ctan2tds | 1 | ||||
-rw-r--r-- | Master/tlpkg/tlpsrc/collection-latexextra.tlpsrc | 1 | ||||
-rw-r--r-- | Master/tlpkg/tlpsrc/enverb.tlpsrc | 0 |
15 files changed, 1824 insertions, 1 deletions
diff --git a/Master/texmf-dist/doc/latex/enverb/README.md b/Master/texmf-dist/doc/latex/enverb/README.md new file mode 100644 index 00000000000..2c035b8eb66 --- /dev/null +++ b/Master/texmf-dist/doc/latex/enverb/README.md @@ -0,0 +1,34 @@ +------------------------------------------------------------------------------- +# `enverb` -- read an environment verbatim + +Version 2024-08-28 v1.0 + +Released under the LaTeX Project Public License v1.3c or later +See http://www.latex-project.org/lppl.txt + +Hosted on the Island of TeX at https://gitlab.com/islandoftex/texmf/enverb + +------------------------------------------------------------------------------- + +Copyright (C) 2023-2024 Jonathan P. Spratte + +This work may be distributed and/or modified under the conditions of the LaTeX +Project Public License (LPPL), either version 1.3c of this license or (at your +option) any later version. The latest version of this license is in the file: + + http://www.latex-project.org/lppl.txt + +This work is "maintained" (as per LPPL maintenance status) by + Jonathan P. Spratte + +------------------------------------------------------------------------------- + +## Summary of Contents + +`enverb` provides means to read the contents of a user-defined environment +verbatim. It also provides facilities to then typeset them inside a +listing-environment provided by LaTeX or another package or to evaluate them as +normal LaTeX code. This gives one the full flexibility of LaTeX to customise the +looks of documentation and examples without the need of any temporary files. +Additionally you can define your own processing of the contents, either line +oriented or processing the entire contents at once, however you see fit. diff --git a/Master/texmf-dist/doc/latex/enverb/doc-enverb.tex b/Master/texmf-dist/doc/latex/enverb/doc-enverb.tex new file mode 100644 index 00000000000..c0c578f0ef5 --- /dev/null +++ b/Master/texmf-dist/doc/latex/enverb/doc-enverb.tex @@ -0,0 +1,47 @@ +\subsection{Grabbing an Environment Verbatim} +\begin{function}{\enverb} + \begin{syntax} + \cs{enverb}\marg{key=value}\oarg{key=value} + \cs{enverb}\meta{*}\marg{key=value} + \end{syntax} + This function will store the contents of the enclosing environment verbatim + inside of \cs{enverbBody}. It should be the last thing you invoke inside the + |\begin| code of your environment and mustn't be enclosed in any nested + environment. Both the mandatory and the optional \meta{key=value} argument are + parsed by \cs{enverb} -- see \autoref{sec:keys} about the specifics of this. + The mandatory argument is meant for a package/code developer to assign the + sensible default values for the envisioned functionality and always parsed + inside the keyset of \cs{enverb}, while the optional one is meant to be used + by the user and as such should be the first thing inside the enclosing + environment (if the user wants to use an optional argument).\par + \cs{enverb} sets the special characters + \begingroup + \def\do#1% + {% + \ifx\ #1\else + , \texttt{\csname @gobble\expandafter\endcsname\string#1}% + \fi + }% + \csname @secondoftwo\expandafter\endcsname\romannumeral`\^^@\dospecials + \endgroup + \ to the category code 12 (other), and makes both spaces and tabulators active + tokens. By default each line break will be a category code 12 carriage return + (character code 13), but see the |eol| option in \autoref{sec:keys}.\par + A line that contains only whitespace on input will be output as an empty + line.\par + The \cs{enverb} syntax of the optional argument has a few peculiarities. It is + scanned for the opening bracket either on the same line as the |\begin| + statement of the enclosing environment, or on any subsequent line until a + non-whitespace character is found. The optional argument is read using the + \enquote{normal} (so surrounding) category code regime, but it is scanned for + it in a way that the first token is still read verbatim if no optional + argument was given.\par + The first non-whitespace token that's not an opening bracket must not be found + on the same line as the |\begin| statement, and if there was an optional + argument there shouldn't be any non-whitespace token trailing it in that line. + Additionally there should be no non-whitespace material following the |\end| + statement (anything preceding it in the same line is for the most part + ignored; |\begin| and |\end| are not balanced, the first |\end| with the + correct environment as argument terminates scanning).\par + The starred version of \cs{enverb} doesn't search for an optional argument. +\end{function} diff --git a/Master/texmf-dist/doc/latex/enverb/doc-examples.tex b/Master/texmf-dist/doc/latex/enverb/doc-examples.tex new file mode 100644 index 00000000000..043890dc10c --- /dev/null +++ b/Master/texmf-dist/doc/latex/enverb/doc-examples.tex @@ -0,0 +1,178 @@ +\subsection{Examples} + +The following preamble should work for all of the examples in this section +(except for the last one, which can be placed as is in the preamble since it +loads all the packages it needs). +\begin{ex}[no-tcb] + \documentclass{article} + + \usepackage{enverb} + \usepackage{color} + \usepackage{multicol} + \usepackage{listings} +\end{ex} + +\subsubsection{A Boxed Verbatim Display} +Defining a boxed verbatim macro is pretty simple, we just need to set up the +|bol| and |eol| hooks such that line breaks are respected, the rest of the setup +already works with \LaTeX's default definition for active spaces (and tabs). +\begin{ex}[store,no-tcb] + \newenvironment{myenv} + {\enverb{bol=\strut, eol=\strut\par}} + {% + \par + \medskip + \noindent + \fbox + {% + \parbox + {\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax} + {% + \raggedright\frenchspacing\ttfamily + \enverbBody + }% + }% + \par + \medskip + } +\end{ex} +The probably most complicated part there is the calculation of the |\parbox|'s +width, which is just a line width compensated by the space taken up by |\fbox|. + +If we now use this environment we get a nice display of our verbatim contents +(you might want to play with this and see what happens if your input lines are +longer than a |\linewidth|; also note that the spaces after |\begin| and |\end| +are optional just like within the normal category code regime, \envlogo\ will +still find the end of its scope). +\begin{ex}[restore] + \begin {myenv} + \This is a% + \begin{environment} + that looks \good + \end {myenv} +\end{ex} + +\subsubsection{A Page-Breakable Boxed Verbatim Display} +The previous example was boxed, lets put that to the next level. We can also +achieve page- (and column-)breakable boxed verbatim environments. The simple +minded trick here is to draw only line segments at the start and end of each +line using the |\vrule| primitive. As a result this will look horribly wrong for +lines longer than a single output line, but that would require too much hassle +(we just pay attention on our input formatting). + +As an added bonus this should have line counters at the start of each line. For +that we first define a little helper. +\begin{ex}[store,no-tcb] + \newcount\myline + \newcommand\linecounting + {% + \advance\myline1 + \textcolor[gray]{.7}{\footnotesize\the\myline}% + \quad + } +\end{ex} +Next we can define our environment. The |bol| and |eol| hooks look similar to +the previous example, but this time they got some added contents for the +additional formatting. Also, we borrow some code from \LaTeX's starred +\env{verbatim} to make spaces visible (since they are active in |\enverb| this +is also pretty straight forward). +\begin{ex}[store,no-tcb] + \newenvironment{myenv} + {% + \enverb + { + bol=\noindent\strut\vrule\hskip\fboxsep\linecounting + ,eol=\hfill\hskip\fboxsep\vrule\strut\par + }% + } + {% + \medskip + \hrule + \ttfamily\frenchspacing + \UseName{@setupverbvisiblespace}\UseName{@vobeyspaces}% + \enverbBody + \hrule + \medskip + } +\end{ex} +The entire result can then be used with ease. +\begin{ex}[restore,same-line=.38] + \begin{multicols}{2} + Text above + \begin{myenv} + This \is + {an} $example$ + ^of verbatim_ + input\, being + displayed boxed. + \end{myenv} + Text below + \end{multicols} +\end{ex} + +\subsubsection{The Real Deal -- Using the Body Twice} +All of the above is just pretty playthings that are easily possible with +\envlogo\ (and with relative few lines of code) though most likely better done +by more full fledged packages like \pkg{listings} or similar. The original +reason for all this was to gain control over both the listing and typeset result +for code documentation. A simple example could be the following: +\begin{ex}[store,no-tcb] + \newenvironment{myenv} + {\enverb{}} + {% + \par\noindent + \begin{minipage}{0.48\linewidth} + \enverbListing{lstlisting}{} + \end{minipage}% + \hfill + \colorbox{yellow} + {% + \begin{minipage}{\dimexpr0.48\linewidth-2\fboxsep\relax} + \enverbExecute + \end{minipage}% + }% + \par + } +\end{ex} +Which if used looks like the following (admittedly not that pretty): +\begin{ex}[restore] + \begin{myenv} + This% + is% + great.% + \end{myenv} +\end{ex} + +\subsubsection{\envlogo's Style} +And if you wondered, you guessed it, all examples in this documentation are +typeset using an \envlogo\ derived environment with a few bells and whistles +more (for instance collecting material, typesetting the verbatim listing, but +executing it together with a later code block). + +The following is a complete listing of everything that sets up the looks of this +documentation's example blocks. Note that the macros starting with |\enverb@ex@| +are not internals of \envlogo\ but exclusive to the code formatting the +examples. +\begin{exwrap}{breakable} + \footnotesize + \lstinputlisting{preamble-examples.tex} +\end{exwrap} + +And if we use that we can do all sorts of interesting things: +\begingroup + \NewEnvironmentCopy{ex2}{ex} + \begin{ex2}[same-line=.4] + We define a helper: + \begin{ex}[store,no-tcb] + \newcommand\foo{bar} + \end{ex} + And then can use it: + \begin{ex}[restore] + This is \foo + \end{ex} + A wider example: + \begin{ex}[below] + This is a wider example. + \end{ex} + \end{ex2} +\endgroup diff --git a/Master/texmf-dist/doc/latex/enverb/doc-keys.tex b/Master/texmf-dist/doc/latex/enverb/doc-keys.tex new file mode 100644 index 00000000000..6d36075d26f --- /dev/null +++ b/Master/texmf-dist/doc/latex/enverb/doc-keys.tex @@ -0,0 +1,111 @@ +\subsection{Available Keys\label{sec:keys}} +\begin{function}{\enverbsetup} + \begin{syntax} + \cs{enverbsetup} \marg{key=value} + \end{syntax} + This macro can be used to (locally) change the settings of \envlogo\ outside + of the |\enverb| macro. +\end{function} + +The available keys are: +\begin{function}{ignore} + \begin{syntax} + ignore = \meta{int}\keydefault{\emph{unused}} + \end{syntax} + Set up the number of tokens to ignore at the start of each line. This is only + applied after the matching |\end| was found, hence doesn't affect the + |\end|-line. A line containing any non-whitespace tokens but in total + fewer tokens (counting whitespace) than \meta{int} will lead to undefined + behaviour.\par + |ignore| and |auto-ignore| are mutually exclusive. +\end{function} + +\begin{function}{auto-ignore} + \begin{syntax} + auto-ignore\keydefault{true} + auto-ignore = \meta{bool} + \end{syntax} + If this is true (or no value is given) the number of leading tokens is + determined by the number of leading tokens found in the line with the matching + |\end|. This allows for nice nesting of indentation levels in your \LaTeX\ + sources without affecting functionality. A line containing any non-whitespace + tokens but in total fewer tokens (counting whitespace) than the leading tokens + in the |\end|-line will lead to undefined behaviour.\par + |ignore| and |auto-ignore| are mutually exclusive. +\end{function} + +\begin{function}{more-ignore} + \begin{syntax} + more-ignore = \meta{int}\keydefault{2} + \end{syntax} + If |auto-ignore| is true this specifies how many tokens in addition to the + number of leading tokens shall be ignored at the start of each line. This + allows for even the contents of the |\enverb|-environment to be further + indented than the |\begin| and |\end| statement. +\end{function} + +\begin{function}{bol} + \begin{syntax} + bol = \meta{tokens}\keydefault{\emph{empty}} + bol+ = \meta{tokens} + +bol = \meta{tokens} + \end{syntax} + Defines which \meta{tokens} are placed at the \textbf{b}egin \textbf{o}f + \textbf{l}ines. Your \meta{tokens} can be arbitrary contents and are placed as + is (so can contain macros which work as you intend when using + \cs{enverbBody}). Keep in mind that if you want to use this with + \cs{enverbExecute} or \cs{enverbListing} your tokens should be rescanned to + the same code after they got |\detokenize|d.\par + The |bol+| variant adds your \meta{tokens} after the current contents of + |bol|, while |+bol| adds them in front of the contents. +\end{function} + +\begin{function}{eol} + \begin{syntax} + eol = \meta{tokens}\keydefault{\emph{\string^\string^M\textsubscript{12}}} + eol+ = \meta{tokens} + +eol = \meta{tokens} + \end{syntax} + Defines which \meta{tokens} are placed at the \textbf{e}nd \textbf{o}f + \textbf{l}ines. Your \meta{tokens} can be arbitrary contents and are placed as + is (so can contain macros which work as you intend when using + \cs{enverbBody}). Keep in mind that if you want to use this with + \cs{enverbExecute} or \cs{enverbListing} your tokens should be rescanned to + the same code after they got |\detokenize|d.\par + The |eol+| variant adds your \meta{tokens} after the current contents of + |eol|, while |+eol| adds them in front of the contents. +\end{function} + +\begin{function}{key-handler} + \begin{syntax} + key-handler = \meta{code}\keydefault{\emph{throw an error}} + \end{syntax} + If used any undefined keys encountered while parsing the mandatory and + optional arguments of \cs{enverb} is parsed via \meta{code}. Inside your + \meta{code} use |#1| to specify where to input the list of unknown keys. This + can be used to specify additional keys to provide an interface to control your + wrapping code. This includes the handling of any unknown keys encountered + while parsing the mandatory \meta{key=value} argument of \cs{enverb}. +\end{function} + +\begin{function}{key-set} + \begin{syntax} + key-set = \meta{set} + \end{syntax} + \envlogo\ uses \pkg{expkv} for its key-parsing. This key is a special form of + |key-handler| defining a handler that parses the unknown keys as part of + \meta{set} in \pkg{expkv} (so basically a shorthand for + |key-handler = \ekvset{|\meta{set}|}{#1}|). +\end{function} + +\begin{function}{oarg-not-enverb} + \begin{syntax} + oarg-not-enverb\keydefault{false} + oarg-not-enverb = \meta{bool} + \end{syntax} + If this is true (or no value is given) the \meta{key=value} list in the + optional argument to \cs{enverb} is not parsed as keys of \envlogo\ but only + inside your defined |key-handler|. Obviously this key doesn't have any effect + if only used as part of the optional argument of \cs{enverb}. +\end{function} + diff --git a/Master/texmf-dist/doc/latex/enverb/doc-using-contents.tex b/Master/texmf-dist/doc/latex/enverb/doc-using-contents.tex new file mode 100644 index 00000000000..c3a147ab97f --- /dev/null +++ b/Master/texmf-dist/doc/latex/enverb/doc-using-contents.tex @@ -0,0 +1,40 @@ +\subsection{Using Verbatim Environment Contents} +\begin{function}{\enverbBody} + \begin{syntax} + \cs{enverbBody} + \end{syntax} + This macro holds the contents of the last scanned \cs{enverb}-body, + assignments to it by the package are all local. +\end{function} + +\begin{function}{\enverbExecute} + \begin{syntax} + \cs{enverbExecute} + \end{syntax} + This function executes the current contents of \cs{enverbBody} as though they + would be part of your input at this place (using |\scantokens|, it is tried as + good as possible to tackle |\scantokens|'s shortcomings; also it is assumed + that you didn't change the |eol| key, or else the newlines aren't carried over + but whatever your |eol| value set is used). The entire contents are + |\detokenize|d once before |\scantokens| does its magic (shouldn't affect the + verbatimly read material, but is deemed a sensible safety measure if something + unexpected happens; this also assumes that anything you placed inside |bol| or + |eol| is rescanned into the same stuff once |\detokenize|d).\par + The function isn't fully expandable, the contents are executed at the current + group level. +\end{function} + +\begin{function}{\enverbListing} + \begin{syntax} + \cs{enverbListing} \marg{env} \marg{args} + \end{syntax} + This function is meant to reuse the current contents of \cs{enverbBody} inside + another verbatim environment. The used mechanism is tested to work with + \env{verbatim}, and environments defined by \pkg{fancyvrb}, \pkg{listings} and + \pkg{minted} (provided you use the default |eol| setting). \meta{env} is the + environment name in which the contents should be nested, and \meta{args} is + material to be placed after the |\begin| statement (just as you input them, + with the outer braces from this argument removed).\par + Just like |\enverbExecute| this |\detokenize|s the current content of + \cs{enverbBody} as well as your \meta{args} and uses |\scantokens|. +\end{function} diff --git a/Master/texmf-dist/doc/latex/enverb/enverb-doc.pdf b/Master/texmf-dist/doc/latex/enverb/enverb-doc.pdf Binary files differnew file mode 100644 index 00000000000..fc5c35311e1 --- /dev/null +++ b/Master/texmf-dist/doc/latex/enverb/enverb-doc.pdf diff --git a/Master/texmf-dist/doc/latex/enverb/enverb-doc.tex b/Master/texmf-dist/doc/latex/enverb/enverb-doc.tex new file mode 100644 index 00000000000..985e9e03b8d --- /dev/null +++ b/Master/texmf-dist/doc/latex/enverb/enverb-doc.tex @@ -0,0 +1,87 @@ +\IfFileExists{enverb.sty}{\RequirePackage{enverb}}{} + +\PassOptionsToPackage{full}{textcomp} +\documentclass{l3doc} + +\usepackage[oldstylenums,nott]{kpfonts} +\usepackage{randtext,xcolor,array} +\usepackage{xistercian} +\usepackage{accsupp} +\usepackage{csquotes} +\usepackage{multicol} +%\usepackage{microtype} + +\input{preamble-logo} +\input{preamble-examples} + +\newcommand\keydefault[1]{\hfill\textcolor{enverbgrey}{default: #1}} + +\let\metaORIG\meta +\protected\def\meta #1{\texttt{\metaORIG{#1}}} +\renewcommand*\thefootnote{\cistercian{footnote}} +\hypersetup{linkcolor=red!80!black,urlcolor=purple!80!black} +\makeatletter +\@ifdefinable\gobbledocstriptag{\def\gobbledocstriptag#1>{}} +\protected\def\savefootnotestuff + {% + \let\mysavethefootnote\thefootnote + \let\mysave@makefnmark\@makefnmark + \let\mysave@makefntext\@makefntext + } +\def\restorefootnotestuff{\texorpdfstring\restorefootnotestuff@{}} +\def\restorefootnotestuff@ + {% + \global\let\thefootnote\mysavethefootnote + \global\let\@makefnmark\mysave@makefnmark + \global\let\@makefntext\mysave@makefntext + } +\makeatother + +\begin{document} +\savefootnotestuff +\title + {% + \restorefootnotestuff + The \envlogo\ package\\[\medskipamount] + \Large read an environment verbatim% + } +\GetFileInfo{enverb.sty} +\date{\filedate\space\fileversion} +\author{Jonathan P. Spratte\thanks{\protect\randomize{jspratte@yahoo.de}}} + +\maketitle + +\begin{abstract} + \noindent\parfillskip=0pt + The \envlogo\ package provides a simple yet effective way to collect the + verbatim contents of an environment into a macro, which the user can then pick + up to implement additional functionality, for instance a simple output routine + or rescanning the contents into code listings or for typesetting alike. + Arbitrary contents can be placed on either end of each line allowing flexible + line-oriented processing. +\end{abstract} + +\tableofcontents + +\begin{documentation} +\section{Documentation} +Originally I was unsatisfied by the degree of freedom and customisation present +in the available verbatim-environment providing packages like \pkg{listings}, +\pkg{minted}, \emph{etc.}, when one wants to document \TeX\ code and show the +results next to it (or I didn't bother to dig through their manuals). Also I +didn't like them producing temporary files so long as that's not necessary. As a +result I implemented what was basically the first version of \envlogo\ for one +of my other packages. + +\input{doc-enverb} +\input{doc-using-contents} +\input{doc-keys} +\input{doc-examples} +\end{documentation} + +\clearpage +\begin{implementation} + \section{Implementation} + \DocInput{enverb.dtx} +\end{implementation} +\end{document} diff --git a/Master/texmf-dist/doc/latex/enverb/preamble-examples.tex b/Master/texmf-dist/doc/latex/enverb/preamble-examples.tex new file mode 100644 index 00000000000..da18ed38a62 --- /dev/null +++ b/Master/texmf-dist/doc/latex/enverb/preamble-examples.tex @@ -0,0 +1,199 @@ +\makeatletter +\RequirePackage{enverb} +\global\let\enverb@ex@stored\@empty +\ekvdefinekeys{enverb/ex} + { + boolTF store = \enverb@ex@ifstore + ,invboolTF no-store = \enverb@ex@ifstore + ,boolTF restore = \enverb@ex@ifrestore + ,boolTF no-lst = \enverb@ex@ifnolst + ,also nmeta no-lst = below + ,nmeta undo-no-lst = {no-lst=false, undo-below} + ,boolTF no-tcb = \enverb@ex@ifnotcb + ,also nmeta no-tcb = below + ,nmeta undo-no-tcb = {no-tcb=false, undo-below} + ,boolTF same-line = \enverb@ex@ifsameline + ,unknown-choice same-line = + \let\enverb@ex@ifsameline\@firstoftwo\def\enverb@ex@codeshare{#1} + ,initial same-line = 0.6 + ,invboolTF other-line = \enverb@ex@ifsameline + ,nmeta below = {other-line} + ,nmeta undo-below = {same-line} + ,store inter = \enverb@ex@inter + ,code aboveskip = \def\enverb@ex@above{\vskip#1\relax} + ,code belowskip = \def\enverb@ex@below{\vskip#1\relax} + ,default aboveskip = \medskipamount + ,default belowskip = \medskipamount + ,initial aboveskip + ,initial belowskip + ,noval no-aboveskip = \let\enverb@ex@above\@empty + ,noval no-belowskip = \let\enverb@ex@below\@empty + % listings + ,store lst = \enverb@ex@options@lst + ,initial lst = {aboveskip=0pt, belowskip=0pt} + ,store same-line-lst = \enverb@ex@options@lst@same + ,meta slst = same-line-lst={#1} + ,store other-line-lst = \enverb@ex@options@lst@other + ,meta olst = other-line-lst={#1} + % tcolorbox + ,store tcb = \enverb@ex@options@tcb + ,initial tcb = {nobeforeafter} + ,store same-line-tcb = \enverb@ex@options@tcb@same + ,initial same-line-tcb = {box align=center} + ,meta stcb = same-line-tcb={#1} + ,store other-line-tcb = \enverb@ex@options@tcb@other + ,meta otcb = other-line-tcb={#1} + } +\newenvironment{ex} + {\enverb{key-set=enverb/ex}} + {% + \par + \enverb@ex@above + \noindent + \expanded{\noexpand\begin{exwrap}{\enverb@ex@ifsameline{}{breakable}}} + \enverb@ex@ifnolst + {}% + {% + \enverb@ex@ifsameline + {\noindent\begin{minipage}[c]{\enverb@ex@codeshare\linewidth}}% + {}% + \ExpandArgs{ne}\enverbListing{lstlisting}% + {% + [{% + \unexpanded\expandafter{\enverb@ex@options@lst},% + \enverb@ex@ifsameline + {\unexpanded\expandafter{\enverb@ex@options@lst@same}}% + {\unexpanded\expandafter{\enverb@ex@options@lst@other}}% + }]% + }% + \enverb@ex@ifsameline + {\end{minipage}}% + {}% + }% + \enverb@ex@ifstore + {% + \xdef\enverb@ex@stored + {% + \unexpanded\expandafter{\enverb@ex@stored}% + \unexpanded\expandafter{\enverbBody}% + }% + }% + {}% + \enverb@ex@ifrestore + {% + \edef\enverbBody + {% + \unexpanded\expandafter{\enverb@ex@stored}% + \unexpanded\expandafter{\enverbBody}% + }% + \global\let\enverb@ex@stored\@empty + }% + {}% + \enverb@ex@ifnotcb + {}% + {% + \enverb@ex@ifsameline{}{\medskip}% + \expanded{\noexpand\begin{exbox}% + {% + \unexpanded\expandafter{\enverb@ex@options@tcb},% + \enverb@ex@ifsameline + {\unexpanded\expandafter{\enverb@ex@options@tcb@same}}% + {\unexpanded\expandafter{\enverb@ex@options@tcb@other}}% + }}% + {\linewidth\enverb@ex@ifsameline{-\enverb@ex@codeshare\linewidth}{}}% + \enverbExecute + \end{exbox}% + }% + \end{exwrap}% + \par + \enverb@ex@below + \@endpetrue + } + +\RequirePackage{listings}% >>= +\newcommand\extexcsstyle{\exbasestyle\color{green!50!black}\bfseries} +\newcommand\exbasestyle{\ttfamily} +\lstset + { + language=[LaTeX]TeX + ,flexiblecolumns=true + ,basicstyle=\exbasestyle + ,texcsstyle=*\extexcsstyle + ,moretexcs=% + {% + UseName,ExpandArgs,textcolor,color,colorbox,expanded,unexpanded,@empty,% + @firstoftwo,@endpetrue,RequirePackage,lstset,usetikzlibrary,% + pgfmathsetseed,newtcolorbox,tcbsubskin,tikzset,dimexpr% + } + ,moretexcs=[2]{enverb,enverbBody,enverbExecute,enverbListing} + ,texcsstyle=*[2]\exbasestyle\color{enverbred}\bfseries + ,literate={\{}{{\extexcsstyle\string{\iffalse}\fi}}{1} + {\}}{{\extexcsstyle\iffalse{\fi\string}}}{1} + }% =<< +\RequirePackage[most]{tcolorbox}%>>= +\RequirePackage{tikz} +\usetikzlibrary{decorations.pathmorphing,calc} +\pgfmathsetseed{1} % To have predictable results +% Define paper style +\tikzset{ + % based on https://tex.stackexchange.com/questions/580671 + ragged border/.style={% + decoration={random steps, segment length=2mm, amplitude=0.5mm}, + decorate, + } +} +\tcbsubskin{exwrap}{standard} + {% + width=\linewidth + ,colframe=enverbgrey + ,colback=enverbred!15!white + ,title=Example + ,nobeforeafter + ,arc=5mm + ,sharp corners=northwest + ,toprule at break=-1sp + ,bottomrule at break=-1sp + } +\tcbsubskin{exwrap-first}{exwrap}{sharp corners=south} +\tcbsubskin{exwrap-mid}{exwrap}{sharp corners=all} +\tcbsubskin{exwrap-last}{exwrap}{sharp corners=north} +\newtcolorbox{exbox}[2] + {% + colback=white% + ,colframe=white% + ,geometry nodes=true + ,interior code= + {% + \fill[white] + decorate[ragged border]{ + ($(frame.south east) - (0, 1mm)$) -- + ($(frame.south west) - (0, 1mm)$) + } + -- (frame.south west) -- ++(0, 1pt) -| (frame.south east) -- cycle; + \fill[white] + decorate[ragged border]{ + ($(frame.north east) + (0, 1mm)$) -- + ($(frame.north west) + (0, 1mm)$) + } + -- (frame.north west) -- ++(0, -1pt) -| (frame.north east) -- cycle; + } + ,fontupper=\small + ,width={\dimexpr#2\relax}% + ,sharp corners=all + ,boxsep=0pt + ,top=\fboxsep + ,bottom=\fboxsep + ,left=\fboxsep + ,right=\fboxsep + ,#1% + } +\newtcolorbox{exwrap}[1] + {% + skin=exwrap + ,skin first=exwrap-first + ,skin middle=exwrap-mid + ,skin last=exwrap-last + ,#1% + } +%=<< +\makeatother diff --git a/Master/texmf-dist/doc/latex/enverb/preamble-logo.tex b/Master/texmf-dist/doc/latex/enverb/preamble-logo.tex new file mode 100644 index 00000000000..177f8f3e26a --- /dev/null +++ b/Master/texmf-dist/doc/latex/enverb/preamble-logo.tex @@ -0,0 +1,25 @@ +\definecolor{enverbred}{HTML}{9F393D} +\colorlet{enverbgrey}{black!75} +\newcommand\envlogo% >>= + {% + \texorpdfstring + {\envLogo}% + {enverb}% + }% =<< +\protected\def\envLogo% >>= + {% + \mbox + {% + \BeginAccSupp{ActualText=enverb}% + \href{https://gitlab.com/islandoftex/texmf/enverb}{\envLogoFormat}% + \EndAccSupp{}% + }% + }% =<< +\protected\def\envLogoFormat% >>= + {% + \begingroup + \normalfont\rmfamily\bfseries + \textcolor{enverbgrey}{en\kern-0.045em v}\kern-.485em + \textcolor{enverbred}{v\kern-0.045em erb}% + \endgroup + }% =<< diff --git a/Master/texmf-dist/source/latex/enverb/enverb.dtx b/Master/texmf-dist/source/latex/enverb/enverb.dtx new file mode 100644 index 00000000000..a33dc713d70 --- /dev/null +++ b/Master/texmf-dist/source/latex/enverb/enverb.dtx @@ -0,0 +1,720 @@ +% \iffalse meta-comment +% +% File: enverb.dtx Copyright (C) 2023-2024 Jonathan P. Spratte +% +% This work may be distributed and/or modified under the conditions of the +% LaTeX Project Public License (LPPL), either version 1.3c of this license or +% (at your option) any later version. The latest version of this license is in +% the file: +% +% http://www.latex-project.org/lppl.txt +% +% ------------------------------------------------------------------------------ +% +%<*driver>^^A>>= +\def\nameofplainTeX{plain} +\ifx\fmtname\nameofplainTeX\else + \expandafter\begingroup +\fi +\input l3docstrip.tex +\askforoverwritefalse +\preamble + +-------------------------------------------------------------- +enverb -- read an environment verbatim +E-mail: jspratte@yahoo.de +Released under the LaTeX Project Public License v1.3c or later +See http://www.latex-project.org/lppl.txt +-------------------------------------------------------------- + +Copyright (C) 2023-2024 Jonathan P. Spratte + +This work may be distributed and/or modified under the conditions of the +LaTeX Project Public License (LPPL), either version 1.3c of this license or +(at your option) any later version. The latest version of this license is in +the file: + + http://www.latex-project.org/lppl.txt + +This work is "maintained" (as per LPPL maintenance status) by + Jonathan P. Spratte. + +This work consists of the files enverb.dtx + enverb-doc.tex +and the derived files enverb-doc.pdf + enverb.sty + +\endpreamble +\postamble +\endpostamble +\generate{\file{enverb.sty}{\from{enverb.dtx}{pkg}}} +\ifx\fmtname\nameofplainTeX + \expandafter\endbatchfile +\else + \expandafter\endgroup +\fi +%</driver>^^A=<< +% \fi +% +% \gobbledocstriptag +%<*pkg> +% +% \subsection{Who we are} +% +% \begin{macro}[internal]{\enverb@date,\enverb@version} +% We store the package version and date inside macros. +% \begin{macrocode} +\newcommand*\enverb@date{2024-08-28} +\newcommand*\enverb@version{1.0} +% \end{macrocode} +% \end{macro} +% +% And the package identification: +% \begin{macrocode} +\ProvidesPackage{enverb} + [\enverb@date\space v\enverb@version\space read an environment verbatim] +% \end{macrocode} +% +% \subsection{Some required \LaTeXe\ style argument grabbers} +% \begin{macro}[internal]{\@thirdofthree,\@firstofnine} +% This here are just two argument grabbers that aren't defined in all versions +% of \LaTeXe. +% \begin{macrocode} +\providecommand\@thirdofthree[3]{#3} +\providecommand\@firstofnine[9]{#1} +% \end{macrocode} +% \end{macro} +% +% \subsection{Borrow some code} +% \begin{macro}[internal] +% {\enverb@count,\enverb@ifxTF,\enverb@chargen,\enverb@othercr} +% We'll make use of the following two \pkg{expl3} functions, but since the +% remainder of this package is coded in \LaTeXe\ style we stick to that. +% \begin{macrocode} +\ExplSyntaxOn +\cs_new_eq:NN \enverb@count \tl_count:n +\cs_new_eq:NN \enverb@ifxTF \token_if_eq_meaning:NNTF +\cs_new_eq:NN \enverb@chargen \char_generate:nn +\cs_set:Npx \enverb@othercr { \char_generate:nn {13} {12} } +\ExplSyntaxOff +% \end{macrocode} +% \end{macro} +% +% \subsection{Key-value Setup} +% First we need to load a package to allow us defining our keys, then we define +% a bunch of keys: +% \begin{macrocode} +\RequirePackage{expkv-def} +% \end{macrocode} +% +% \begin{macrocode} +\ekvdefinekeys{enverb} + { + protect code ignore = \let\enverb@ifautoignore\@secondoftwo + ,also eint ignore = \enverb@ignore + ,boolTF auto-ignore = \enverb@ifautoignore + ,initial auto-ignore + ,eint more-ignore = \enverb@moreignore + ,initial more-ignore = 2 + ,long store bol = \enverb@bol@content + ,long code bol+ = \enverb@add\enverb@bol@content{#1} + ,long code +bol = \enverb@pre\enverb@bol@content{#1} + ,long store eol = \enverb@eol@content + ,einitial eol = \enverb@othercr + ,long code eol+ = \enverb@add\enverb@eol@content{#1} + ,long code +eol = \enverb@pre\enverb@eol@content{#1} + ,protect code key-handler = \protected\long\def\enverb@keyhandler##1{#1} + ,protect code key-set = \protected\long\ekvsetdef\enverb@keyhandler{#1} + ,unknown code = \enverb@add\enverb@unknown@kv{, {#3} = {#2} } + ,unknown noval = \enverb@add\enverb@unknown@kv{, {#2} } + ,boolTF oarg-not-enverb = \enverb@ifoargtokeyhandler + } +% \end{macrocode} +% \begin{macro}{\enverbsetup} +% We need a user facing macro to set our keys. +% \begin{macrocode} +\protected\long\ekvsetdef\enverbsetup{enverb} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\enverb@unknown@kv} +% This is a storage for all unknown keys encountered. +% \begin{macrocode} +\let\enverb@unknown@kv\@empty +% \end{macrocode} +% \end{macro} +% +% \subsection{Miscellaneous Auxiliary Functions} +% +% \begin{macro}[internal]{\enverb@stop} +% A very simple minded stop-macro, just gobble up to the eponymous mark. +% \begin{macrocode} +\long\def\enverb@stop#1\enverb@stop{} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\enverb@error} +% \begin{macrocode} +\protected\def\enverb@error{\PackageError{enverb}} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\enverb@misused} +% This is an error message that'd be used inside a |\lowercase| environment if +% put where it originally should've been. Hence we define it now to get +% correct formatting. +% \begin{macrocode} +\protected\def\enverb@misused + {% + \enverb@error + {Misused \string\enverb. Input already tokenised}% + {% + It seems you used the \string\enverb\space based environment + {\@currenvir} inside another\MessageBreak + macro's or a primitive's argument; that doesn't work.% + }% + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\enverb@keyhandler, \enverb@keyhandler@} +% This is the initial definition of the handler for unknown keys, namely throw +% an error containing the list of unknown keys. +% \begin{macrocode} +\protected\long\def\enverb@keyhandler#1% + {% + \if\relax\detokenize{#1}\relax + \expandafter\@gobbletwo + \fi + \@firstofone + {% + \enverb@error + {% + Unknown keys encountered: + \expanded + {% + \ekvparse + {\MessageBreak\@spaces\unexpanded}% + {\MessageBreak\@spaces\enverb@keyhandler@}% + {#1}% + }% + \@gobble + }% + {% + Perhaps you misspelled some key names? Or you forgot to set up + custom key\MessageBreak + parsing.% + }% + }% + } +\long\def\enverb@keyhandler@#1{\unexpanded{#1} = \unexpanded} +% \end{macrocode} +% \end{macro} +% +% \subsection{Collector} +% +% Much of the code in this package works under a weird category code regime, +% which the following sets up. After this |~| will be an active newline +% character, |:| will be an active space, and |;| will be an active tab. +% \begin{macrocode} +\begingroup +\lccode`\~=`\^^M +\catcode`\:=13 +\lccode`\:=`\ % <- space +\catcode`\;=13 +\lccode`\;=`\^^I % <- tab +\lowercase{\endgroup +% \end{macrocode} +% +% \begin{macro}[internal] +% {\enverb@body@space,\enverb@body@tab,\enverb@body@newline,\enverb@collect} +% To quickly check whether a line contains only spaces or tabs we define them +% as empty, that way we can remove them simply by one step of |\romannumeral| +% expansion. The newlines on the other hand grab the entire next line, check +% whether the matching |\end| is encountered, and if not leave the contents +% in |\unexpanded|. This grabbing is not done by the newline characters +% directly, but instead via |\enverb@collect| so that low level errors are +% easier to understand. +% \begin{macrocode} +\def\enverb@body@space{} +\def\enverb@body@tab{} +\def\enverb@body@newline{\enverb@collect} +\def\enverb@collect#1~% + {\enverb@ifnotend{#1}{\enverb@bol\unexpanded{#1}\enverb@eol\enverb@collect}} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\enverbBody} +% \begin{macro}[internal]{\enverb@body@setup} +% This function sets up the entire category code regime and initial +% assignments of special tokens. +% \begin{macrocode} +\protected\def\enverb@body@setup + {% + \let\enverbBody\@empty + \let\do\@makeother\dospecials + \endlinechar=`\^^M + \catcode`\^^M=13 \let~\enverb@body@newline + \catcode`\ =13 \let:\enverb@body@space + \catcode`\^^I=13 \let;\enverb@body@tab + \let\enverb@bol\relax + \let\enverb@eol\relax + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}[internal] +% { +% \enverb@ifxanyTF, \enverb@ifxanyTF@, \enverb@ifxanyTF@ifdone, +% \enverb@ifxanyTF@F, \enverb@ifxanyTF@T +% } +% This function provides a loop to check a list of symbols whether any of them +% matches the meaning of the first argument. +% \begin{macrocode} +\long\def\enverb@ifxanyTF#1#2% + {\enverb@ifxanyTF@#1#2\enverb@ifxanyTF@} +\long\def\enverb@ifxanyTF@#1#2% + {% + \enverb@ifxanyTF@ifdone#2\enverb@ifxanyTF@F\enverb@ifxanyTF@ + \enverb@ifxTF#1#2\enverb@ifxanyTF@T{\enverb@ifxanyTF@#1}% + } +\long\def\enverb@ifxanyTF@ifdone#1\enverb@ifxanyTF@{} +\long\def\enverb@ifxanyTF@F + \enverb@ifxanyTF@\enverb@ifxTF#1\enverb@ifxanyTF@T#2#3#4% + {#4} +\long\def\enverb@ifxanyTF@T#1\enverb@ifxanyTF@#2#3{#2} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\enverb@search@oarg@a, \enverb@search@oarg@ifx} +% This function shall search for the optional argument. The first case is +% rather easy, namely we check for a space (remember that |:| is an active +% space character in the current context). If this isn't the first line (so +% the line containing the |\begin| statement) that space is added to the body +% and searching continues.\par +% Next repeat the same logic but for an active tab (|;|). Afterwards we check +% for an active newline (|~|) which if found sets the conditional for the +% first line to false, still applying the same logic otherwise.\par +% Lastly we check for the open bracket. If it's found we collect our optional +% argument, otherwise the body starts, which is either an illegal character +% immediately following the |\begin| line, or we normally collect the body. +% +% \begin{macrocode} +\def\enverb@search@oarg@ifx#1#2% + {% + \enverb@ifxTF#1\@let@token + {% + \ifenverb@firsteol#2\else\enverb@body@add{#1}\fi + \enverb@search@oarg@b + }% + } +\protected\def\enverb@search@oarg@a + {% + \enverb@search@oarg@ifx:{}% + {% + \enverb@search@oarg@ifx;{}% + {% + \enverb@search@oarg@ifx~\enverb@firsteolfalse + {% + \enverb@ifxTF{[}\@let@token + {\enverb@oarg}% + {% + \enverb@ifxanyTF\@let@token + {% + \@sptoken\par\bgroup\egroup$&##^_% $ + } + {% + \enverb@misused + \endgroup + }% + {% + \ifenverb@firsteol + \expandafter\enverb@body@after@begin + \else + \expandafter\enverb@body + \fi + }% + }% + }% + }% + }% + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal] +% {\enverb@body, \enverb@body@after@oarg, \enverb@body@after@begin} +% The body collection works by collecting everything inside a macro in one +% sweep, and a second pass over the collected material to strip leading spaces +% if the |ignore| or |auto-ignore| feature is used. This macro starts the +% first sweep. Since during the collection of the optional argument we might +% already have collected a few tokens we place those at the start by expanding +% the current definition of |\enverbBody| once. +% \begin{macrocode} +\protected\def\enverb@body + {\edef\enverbBody{\iffalse}\fi\expandafter\enverb@collect\enverbBody} +% \end{macrocode} +% The other two macros also start collecting the body, but are only called +% after either an optional argument was found, or if the first non-ignored +% character of the optional argument search was encountered before the first +% newline. In both cases we check whether the remainder of that line can be +% considered blank, and if so collect the body. +% \begin{macrocode} +\def\enverb@body@after@oarg#1~% + {\enverb@ensure@blank{#1}{closing bracket}\enverb@body} +\def\enverb@body@after@begin#1~% + {\enverb@ensure@blank{#1}{\string\begin}\enverb@body} +% \end{macrocode} +% This is also the last place we need the strange category setup in, so we +% close the delimiting brace of the |\lowercase| above here. +% \begin{macrocode} +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\enverb@ensure@blank} +% We actually need to define the check for an empty line. This check here +% works for our specifically set up regime of spaces and tabs (which both +% expand to nothing, the same trick is basically used twice, though we once +% fully expand and once use romannumeral-expansion). +% \begin{macrocode} +\newcommand\enverb@ensure@blank[2] + {% + \expandafter\enverb@ifempty\expanded{{#1}}{}% + {% + \expanded + {% + \noexpand\enverb@error + {% + Line after #2 not empty.\noexpand\MessageBreak + Contains: \detokenize\expandafter{\romannumeral`\^^@#1}% + }% + {% + \noexpand\enverb will try to ignore this. You should clean up + your input.% + }% + }% + }% + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal] +% {\enverb@ifempty,\enverb@ifempty@,\enverb@ifempty@true} +% This is just a quick argument-grabbing based test for an empty argument. +% \begin{macrocode} +\newcommand\enverb@ifempty[1] + {% + \enverb@ifempty@\enverb@ifempty@A#1\enverb@ifempty@B.\enverb@ifempty@true + \enverb@ifempty@A\enverb@ifempty@B + } +\def\enverb@ifempty@#1\enverb@ifempty@A\enverb@ifempty@B#2#3{#3} +\def\enverb@ifempty@true\enverb@ifempty@A\enverb@ifempty@B#1#2{#1} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\enverb@add,\enverb@pre,\enverb@body@add} +% These are just two functions to add things to a token list storing macro, +% one is available for arbitrary contents, the other is used for the |body|. +% \begin{macrocode} +\protected\long\def\enverb@add#1#2{\edef#1{\unexpanded\expandafter{#1#2}}} +\protected\long\def\enverb@pre#1#2% + {\edef#1{\unexpanded{#2}\unexpanded\expandafter{#1}}} +\protected\def\enverb@body@add{\enverb@add\enverbBody} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\enverb} +% This macro is the front facing command that starts the entire grabbing +% logic. The first thing we need to do is define the auxiliary we use to check +% whether we're done collecting the body, which is dependent on the current +% environment's name. Next we store the mandatory argument in |marg| and +% initialise the |oarg|-storage, category regime, and |firsteol|-boolean. +% Finally we start searching for the optional argument. +% \begin{macrocode} +\NewDocumentCommand \enverb { s +m } + {% + \expandafter\enverb@ifnotend@setup@perhaps\expanded + {{\string{\@currenvir\string}}}% + \let\enverb@collected@oarg\@empty + \edef\enverb@collected@marg{\unexpanded{#2}}% + \begingroup + \enverb@body@setup + \IfBooleanTF{#1}% + {\enverb@body@after@begin}% + {% + \enverb@firsteoltrue + \enverb@search@oarg + }% + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal] +% {\ifenverb@firsteol,\enverb@firsteoltrue,\enverb@firsteolfalse} +% A simple \TeX-style boolean to keep track whether we're in front of the +% first newline. +% \begin{macrocode} +\newif\ifenverb@firsteol +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\enverb@search@oarg, \enverb@search@oarg@b} +% The core function to search for an optional argument was already defined +% above, these are the first and third step of that functionality (starting +% and resuming to search). +% \begin{macrocode} +\protected\def\enverb@search@oarg{\futurelet\@let@token\enverb@search@oarg@a} +\protected\def\enverb@search@oarg@b{\expandafter\enverb@search@oarg\@gobble} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\enverb@oarg, \enverb@oarg@} +% This is used once the opening brace of the optional argument is found. First +% we close the group in which the body's category code regime is active, then +% we actually collect the optional argument with the normal category codes, +% restore the body's regime and collect it. +% \begin{macrocode} +\protected\def\enverb@oarg{\endgroup\enverb@oarg@} +\NewDocumentCommand\enverb@oarg@{+O{}} + {% + \enverb@add\enverb@collected@oarg{#1}% + \begingroup + \enverb@body@setup + \enverb@body@after@oarg + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\enverb@ifnotend, \enverb@ifnotend} +% These functions check whether the input contains the string representation +% |\end|. If it does they invoke \cs[no-index]{enverb@ifnotend@maybe} with the +% tokens in front of |\end| and after it as two arguments. Otherwise the third +% argument after \cs{enverb@ifnotend@}'s expansion is directly used, which is +% the second (curried) argument to \cs{enverb@ifnotend}. +% \begin{macrocode} +\newcommand\enverb@ifnotend[1]% + {% + \def\enverb@ifnotend##1% + {% + \enverb@ifnotend@ + ##1\enverb@mark\enverb@ifnotend@maybe + #1\enverb@mark\@thirdofthree + \enverb@stop + }% + \def\enverb@ifnotend@##1#1##2\enverb@mark##3##4\enverb@stop{##3{##1}{##2}}% + } +\expandafter\enverb@ifnotend\expanded{{\expandafter\@gobble\string\\end}} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\enverb@ifnotend@maybe} +% This function will be used if an |\end| was encountered and should check +% whether that is indeed the end of our environment, it uses a second stage +% \cs[no-index]{enverb@ifnotend@perhaps} for that check. The |\romannumeral| +% expansion it employs will strip any leading spaces or tabs from |#2|. +% \begin{macrocode} +\newcommand\enverb@ifnotend@maybe[2] + {\expandafter\enverb@ifnotend@perhaps\expandafter{\romannumeral`\^^@#2}{#1}} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal] +% { +% \enverb@ifnotend@setup@perhaps, +% \enverb@ifnotend@perhaps, \enverb@ifnotend@perhaps@, +% \@thirdofthree +% } +% We need an expandable and fast check to see whether some input really +% contains the |\end| of our environment. Checking for |\end| itself is +% already done above, we need to check for the correct argument to it. The +% following does so by argument grabbing logic. +% \begin{macrocode} +\protected\def\enverb@ifnotend@setup@perhaps#1% + {% + \def\enverb@ifnotend@perhaps##1% + {% + \enverb@ifnotend@perhaps@\enverb@mark##1\enverb@mark\enverb@ifnotend@end + \enverb@mark#1\enverb@mark\@thirdofthree + \enverb@stop + }% + \def\enverb@ifnotend@perhaps@ + ##1\enverb@mark#1##2\enverb@mark##3##4\enverb@stop + {##3{##2}}% + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\enverb@ifnotend@end} +% If the correct |\end| statement was found this function will be called by +% \cs[no-index]{enverb@ifnotend@perhaps}. It's first argument will be anything +% in that line following the |\end| statement, the second argument will be the +% material in front of it. And |#3| will be whatever the argument to +% \cs[no-index]{enverb@ifnotend} was. +% +% The first thing we need to do is end the body collection by placing the +% matching closing brace. After that we throw an error on lost content after +% the |\end| if it's non-blank. And finally we need to smuggle the collected +% body outside the current group's scope. +% \begin{macrocode} +\def\enverb@ifnotend@end#1#2#3% + {% + \iffalse{\fi}% + \enverb@ensure@blank{#1}{\string\end}% + \expandafter\enverb@finalise\expandafter{\enverbBody}{#2}% + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\enverb@finalise} +% The finalising function closes the group containing the body's catcode +% regime. The already tokenised body is |#1|, and |#2| is the contents found +% in front of the |\end| statement, which we might use for the auto-ignore +% feature. +% +% It then does the key=val parsing, sets up the aftertreatment and assigns the +% final meaning to \cs{enverbBody}. Eventually it calls the end code of the +% enclosing environment. +% \begin{macrocode} +\protected\def\enverb@finalise#1#2% + {% + \endgroup + \expandafter\enverbsetup\expandafter{\enverb@collected@marg}% + \enverb@ifoargtokeyhandler + {% + \expandafter\enverb@keyhandler\expanded + {{% + \unexpanded\expandafter{\enverb@unknown@kv},% + \unexpanded\expandafter{\enverb@collected@oarg}% + }}% + }% + {% + \expandafter\enverbsetup\expandafter{\enverb@collected@oarg}% + \expandafter\enverb@keyhandler\expandafter{\enverb@unknown@kv}% + }% + \enverb@ifautoignore + {\enverb@setup@ignore{\enverb@count{#2}+\enverb@moreignore}}% + {\enverb@setup@ignore\enverb@ignore}% + \edef\enverb@line##1\enverb@eol + {% + \noexpand\unexpanded{##1}% + %\noexpand\detokenize{##1}% % TODO + \noexpand\unexpanded{\unexpanded\expandafter{\enverb@eol@content}}% + }% + \edef\enverbBody{#1}% + \expandafter\end\expandafter{\@currenvir}% + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\enverb@setup@ignore, \enverb@setup@ignore@} +% \begin{macrocode} +\protected\def\enverb@setup@ignore#1% + {\expandafter\enverb@setup@ignore@\the\numexpr#1\relax;\enverb@line} +\protected\def\enverb@setup@ignore@#1;#2% + {% + \ifnum#1>9 + \expandafter\@firstoftwo + \else + \expandafter\@secondoftwo + \fi + {\expandafter\enverb@setup@ignore@\the\numexpr#1-8;{\@firstofnine{#2}}}% +% \end{macrocode} +% Just to make sure that |\renewcommand| works correctly, we ensure the macro +% exists. +% \begin{macrocode} + {% + \let\enverb@bol@gobble\@empty + \expanded + {% + \unexpanded{\renewcommand\enverb@bol@gobble}\ifnum#1>\z@[#1]\fi + {\unexpanded{#2}}% + \unexpanded{\def\enverb@bol##1\enverb@eol}% + {% + \noexpand\unexpanded + {\unexpanded\expandafter{\enverb@bol@content}}% + \unexpanded{\expandafter\enverb@ifempty\expanded}{{##1}}% + {\noexpand\enverb@line}% + {\noexpand\enverb@bol@gobble}% + ##1\noexpand\enverb@eol + }% + }% + }% + } +% \end{macrocode} +% \end{macro} +% +% \subsection{Output Oriented Macros} +% +% \begin{macro}[internal]{\enverb@rmeol, \enverb@rmeol@} +% Many of our output routines require the |\scantokens| primitive. Since that +% one places an additional end of line at the end of its argument we need a +% way to remove it (this usually results in an additional space in the output +% otherwise). For that we place a comment character at the end of the input +% (if it's possible), if that's not available we hope that a stringified +% |\relax| will do. The code here will use \pkg{expl3} for ease of coding. +% \begin{macrocode} +\def\enverb@rmeol + {% + \ifnum\catcode`\%=14 + \enverb@chargen{`\%}{12}% + \expandafter\enverb@stop + \fi + \enverb@rmeol@0;% + \enverb@stop + } +\def\enverb@rmeol@#1;% + {% + \ifnum#1=128 + \string\relax + \expandafter\enverb@stop + \fi + \@firstofone + {% + \ifnum\catcode`\%=14 + \enverb@chargen{#1}{12}% + \expandafter\enverb@stop + \fi + \expandafter\enverb@rmeol@\the\numexpr#1+1;% + }% + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\enverbExecute} +% \begin{macrocode} +\NewDocumentCommand\enverbExecute{} + {% + \begingroup + \newlinechar=`\^^M + \expandafter + \endgroup + \scantokens\expanded + {{% + \detokenize\expandafter{\enverbBody}% + \enverb@rmeol + }}% + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\enverbListing} +% \begin{macro}[internal]{\enverbListing@} +% \begin{macrocode} +\NewDocumentCommand \enverbListing { m m } + {% + \scantokens\expanded + {{% + \string\begin{#1}\detokenize{#2}\enverb@othercr + \detokenize\expandafter{\enverbBody}% + \string\end{#1}\enverb@othercr + \enverb@rmeol + }}% + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \gobbledocstriptag +%</pkg> diff --git a/Master/texmf-dist/tex/latex/enverb/enverb.sty b/Master/texmf-dist/tex/latex/enverb/enverb.sty new file mode 100644 index 00000000000..bb15d3fec61 --- /dev/null +++ b/Master/texmf-dist/tex/latex/enverb/enverb.sty @@ -0,0 +1,380 @@ +%% +%% This is file `enverb.sty', +%% generated with the docstrip utility. +%% +%% The original source files were: +%% +%% enverb.dtx (with options: `pkg') +%% +%% -------------------------------------------------------------- +%% enverb -- read an environment verbatim +%% E-mail: jspratte@yahoo.de +%% Released under the LaTeX Project Public License v1.3c or later +%% See http://www.latex-project.org/lppl.txt +%% -------------------------------------------------------------- +%% +%% Copyright (C) 2023-2024 Jonathan P. Spratte +%% +%% This work may be distributed and/or modified under the conditions of the +%% LaTeX Project Public License (LPPL), either version 1.3c of this license or +%% (at your option) any later version. The latest version of this license is in +%% the file: +%% +%% http://www.latex-project.org/lppl.txt +%% +%% This work is "maintained" (as per LPPL maintenance status) by +%% Jonathan P. Spratte. +%% +%% This work consists of the files enverb.dtx +%% enverb-doc.tex +%% and the derived files enverb-doc.pdf +%% enverb.sty +%% +\newcommand*\enverb@date{2024-08-28} +\newcommand*\enverb@version{1.0} +\ProvidesPackage{enverb} + [\enverb@date\space v\enverb@version\space read an environment verbatim] +\providecommand\@thirdofthree[3]{#3} +\providecommand\@firstofnine[9]{#1} +\ExplSyntaxOn +\cs_new_eq:NN \enverb@count \tl_count:n +\cs_new_eq:NN \enverb@ifxTF \token_if_eq_meaning:NNTF +\cs_new_eq:NN \enverb@chargen \char_generate:nn +\cs_set:Npx \enverb@othercr { \char_generate:nn {13} {12} } +\ExplSyntaxOff +\RequirePackage{expkv-def} +\ekvdefinekeys{enverb} + { + protect code ignore = \let\enverb@ifautoignore\@secondoftwo + ,also eint ignore = \enverb@ignore + ,boolTF auto-ignore = \enverb@ifautoignore + ,initial auto-ignore + ,eint more-ignore = \enverb@moreignore + ,initial more-ignore = 2 + ,long store bol = \enverb@bol@content + ,long code bol+ = \enverb@add\enverb@bol@content{#1} + ,long code +bol = \enverb@pre\enverb@bol@content{#1} + ,long store eol = \enverb@eol@content + ,einitial eol = \enverb@othercr + ,long code eol+ = \enverb@add\enverb@eol@content{#1} + ,long code +eol = \enverb@pre\enverb@eol@content{#1} + ,protect code key-handler = \protected\long\def\enverb@keyhandler##1{#1} + ,protect code key-set = \protected\long\ekvsetdef\enverb@keyhandler{#1} + ,unknown code = \enverb@add\enverb@unknown@kv{, {#3} = {#2} } + ,unknown noval = \enverb@add\enverb@unknown@kv{, {#2} } + ,boolTF oarg-not-enverb = \enverb@ifoargtokeyhandler + } +\protected\long\ekvsetdef\enverbsetup{enverb} +\let\enverb@unknown@kv\@empty +\long\def\enverb@stop#1\enverb@stop{} +\protected\def\enverb@error{\PackageError{enverb}} +\protected\def\enverb@misused + {% + \enverb@error + {Misused \string\enverb. Input already tokenised}% + {% + It seems you used the \string\enverb\space based environment + {\@currenvir} inside another\MessageBreak + macro's or a primitive's argument; that doesn't work.% + }% + } +\protected\long\def\enverb@keyhandler#1% + {% + \if\relax\detokenize{#1}\relax + \expandafter\@gobbletwo + \fi + \@firstofone + {% + \enverb@error + {% + Unknown keys encountered: + \expanded + {% + \ekvparse + {\MessageBreak\@spaces\unexpanded}% + {\MessageBreak\@spaces\enverb@keyhandler@}% + {#1}% + }% + \@gobble + }% + {% + Perhaps you misspelled some key names? Or you forgot to set up + custom key\MessageBreak + parsing.% + }% + }% + } +\long\def\enverb@keyhandler@#1{\unexpanded{#1} = \unexpanded} +\begingroup +\lccode`\~=`\^^M +\catcode`\:=13 +\lccode`\:=`\ % <- space +\catcode`\;=13 +\lccode`\;=`\^^I % <- tab +\lowercase{\endgroup +\def\enverb@body@space{} +\def\enverb@body@tab{} +\def\enverb@body@newline{\enverb@collect} +\def\enverb@collect#1~% + {\enverb@ifnotend{#1}{\enverb@bol\unexpanded{#1}\enverb@eol\enverb@collect}} +\protected\def\enverb@body@setup + {% + \let\enverbBody\@empty + \let\do\@makeother\dospecials + \endlinechar=`\^^M + \catcode`\^^M=13 \let~\enverb@body@newline + \catcode`\ =13 \let:\enverb@body@space + \catcode`\^^I=13 \let;\enverb@body@tab + \let\enverb@bol\relax + \let\enverb@eol\relax + } +\long\def\enverb@ifxanyTF#1#2% + {\enverb@ifxanyTF@#1#2\enverb@ifxanyTF@} +\long\def\enverb@ifxanyTF@#1#2% + {% + \enverb@ifxanyTF@ifdone#2\enverb@ifxanyTF@F\enverb@ifxanyTF@ + \enverb@ifxTF#1#2\enverb@ifxanyTF@T{\enverb@ifxanyTF@#1}% + } +\long\def\enverb@ifxanyTF@ifdone#1\enverb@ifxanyTF@{} +\long\def\enverb@ifxanyTF@F + \enverb@ifxanyTF@\enverb@ifxTF#1\enverb@ifxanyTF@T#2#3#4% + {#4} +\long\def\enverb@ifxanyTF@T#1\enverb@ifxanyTF@#2#3{#2} +\def\enverb@search@oarg@ifx#1#2% + {% + \enverb@ifxTF#1\@let@token + {% + \ifenverb@firsteol#2\else\enverb@body@add{#1}\fi + \enverb@search@oarg@b + }% + } +\protected\def\enverb@search@oarg@a + {% + \enverb@search@oarg@ifx:{}% + {% + \enverb@search@oarg@ifx;{}% + {% + \enverb@search@oarg@ifx~\enverb@firsteolfalse + {% + \enverb@ifxTF{[}\@let@token + {\enverb@oarg}% + {% + \enverb@ifxanyTF\@let@token + {% + \@sptoken\par\bgroup\egroup$&##^_% $ + } + {% + \enverb@misused + \endgroup + }% + {% + \ifenverb@firsteol + \expandafter\enverb@body@after@begin + \else + \expandafter\enverb@body + \fi + }% + }% + }% + }% + }% + } +\protected\def\enverb@body + {\edef\enverbBody{\iffalse}\fi\expandafter\enverb@collect\enverbBody} +\def\enverb@body@after@oarg#1~% + {\enverb@ensure@blank{#1}{closing bracket}\enverb@body} +\def\enverb@body@after@begin#1~% + {\enverb@ensure@blank{#1}{\string\begin}\enverb@body} +} +\newcommand\enverb@ensure@blank[2] + {% + \expandafter\enverb@ifempty\expanded{{#1}}{}% + {% + \expanded + {% + \noexpand\enverb@error + {% + Line after #2 not empty.\noexpand\MessageBreak + Contains: \detokenize\expandafter{\romannumeral`\^^@#1}% + }% + {% + \noexpand\enverb will try to ignore this. You should clean up + your input.% + }% + }% + }% + } +\newcommand\enverb@ifempty[1] + {% + \enverb@ifempty@\enverb@ifempty@A#1\enverb@ifempty@B.\enverb@ifempty@true + \enverb@ifempty@A\enverb@ifempty@B + } +\def\enverb@ifempty@#1\enverb@ifempty@A\enverb@ifempty@B#2#3{#3} +\def\enverb@ifempty@true\enverb@ifempty@A\enverb@ifempty@B#1#2{#1} +\protected\long\def\enverb@add#1#2{\edef#1{\unexpanded\expandafter{#1#2}}} +\protected\long\def\enverb@pre#1#2% + {\edef#1{\unexpanded{#2}\unexpanded\expandafter{#1}}} +\protected\def\enverb@body@add{\enverb@add\enverbBody} +\NewDocumentCommand \enverb { s +m } + {% + \expandafter\enverb@ifnotend@setup@perhaps\expanded + {{\string{\@currenvir\string}}}% + \let\enverb@collected@oarg\@empty + \edef\enverb@collected@marg{\unexpanded{#2}}% + \begingroup + \enverb@body@setup + \IfBooleanTF{#1}% + {\enverb@body@after@begin}% + {% + \enverb@firsteoltrue + \enverb@search@oarg + }% + } +\newif\ifenverb@firsteol +\protected\def\enverb@search@oarg{\futurelet\@let@token\enverb@search@oarg@a} +\protected\def\enverb@search@oarg@b{\expandafter\enverb@search@oarg\@gobble} +\protected\def\enverb@oarg{\endgroup\enverb@oarg@} +\NewDocumentCommand\enverb@oarg@{+O{}} + {% + \enverb@add\enverb@collected@oarg{#1}% + \begingroup + \enverb@body@setup + \enverb@body@after@oarg + } +\newcommand\enverb@ifnotend[1]% + {% + \def\enverb@ifnotend##1% + {% + \enverb@ifnotend@ + ##1\enverb@mark\enverb@ifnotend@maybe + #1\enverb@mark\@thirdofthree + \enverb@stop + }% + \def\enverb@ifnotend@##1#1##2\enverb@mark##3##4\enverb@stop{##3{##1}{##2}}% + } +\expandafter\enverb@ifnotend\expanded{{\expandafter\@gobble\string\\end}} +\newcommand\enverb@ifnotend@maybe[2] + {\expandafter\enverb@ifnotend@perhaps\expandafter{\romannumeral`\^^@#2}{#1}} +\protected\def\enverb@ifnotend@setup@perhaps#1% + {% + \def\enverb@ifnotend@perhaps##1% + {% + \enverb@ifnotend@perhaps@\enverb@mark##1\enverb@mark\enverb@ifnotend@end + \enverb@mark#1\enverb@mark\@thirdofthree + \enverb@stop + }% + \def\enverb@ifnotend@perhaps@ + ##1\enverb@mark#1##2\enverb@mark##3##4\enverb@stop + {##3{##2}}% + } +\def\enverb@ifnotend@end#1#2#3% + {% + \iffalse{\fi}% + \enverb@ensure@blank{#1}{\string\end}% + \expandafter\enverb@finalise\expandafter{\enverbBody}{#2}% + } +\protected\def\enverb@finalise#1#2% + {% + \endgroup + \expandafter\enverbsetup\expandafter{\enverb@collected@marg}% + \enverb@ifoargtokeyhandler + {% + \expandafter\enverb@keyhandler\expanded + {{% + \unexpanded\expandafter{\enverb@unknown@kv},% + \unexpanded\expandafter{\enverb@collected@oarg}% + }}% + }% + {% + \expandafter\enverbsetup\expandafter{\enverb@collected@oarg}% + \expandafter\enverb@keyhandler\expandafter{\enverb@unknown@kv}% + }% + \enverb@ifautoignore + {\enverb@setup@ignore{\enverb@count{#2}+\enverb@moreignore}}% + {\enverb@setup@ignore\enverb@ignore}% + \edef\enverb@line##1\enverb@eol + {% + \noexpand\unexpanded{##1}% + %\noexpand\detokenize{##1}% % TODO + \noexpand\unexpanded{\unexpanded\expandafter{\enverb@eol@content}}% + }% + \edef\enverbBody{#1}% + \expandafter\end\expandafter{\@currenvir}% + } +\protected\def\enverb@setup@ignore#1% + {\expandafter\enverb@setup@ignore@\the\numexpr#1\relax;\enverb@line} +\protected\def\enverb@setup@ignore@#1;#2% + {% + \ifnum#1>9 + \expandafter\@firstoftwo + \else + \expandafter\@secondoftwo + \fi + {\expandafter\enverb@setup@ignore@\the\numexpr#1-8;{\@firstofnine{#2}}}% + {% + \let\enverb@bol@gobble\@empty + \expanded + {% + \unexpanded{\renewcommand\enverb@bol@gobble}\ifnum#1>\z@[#1]\fi + {\unexpanded{#2}}% + \unexpanded{\def\enverb@bol##1\enverb@eol}% + {% + \noexpand\unexpanded + {\unexpanded\expandafter{\enverb@bol@content}}% + \unexpanded{\expandafter\enverb@ifempty\expanded}{{##1}}% + {\noexpand\enverb@line}% + {\noexpand\enverb@bol@gobble}% + ##1\noexpand\enverb@eol + }% + }% + }% + } +\def\enverb@rmeol + {% + \ifnum\catcode`\%=14 + \enverb@chargen{`\%}{12}% + \expandafter\enverb@stop + \fi + \enverb@rmeol@0;% + \enverb@stop + } +\def\enverb@rmeol@#1;% + {% + \ifnum#1=128 + \string\relax + \expandafter\enverb@stop + \fi + \@firstofone + {% + \ifnum\catcode`\%=14 + \enverb@chargen{#1}{12}% + \expandafter\enverb@stop + \fi + \expandafter\enverb@rmeol@\the\numexpr#1+1;% + }% + } +\NewDocumentCommand\enverbExecute{} + {% + \begingroup + \newlinechar=`\^^M + \expandafter + \endgroup + \scantokens\expanded + {{% + \detokenize\expandafter{\enverbBody}% + \enverb@rmeol + }}% + } +\NewDocumentCommand \enverbListing { m m } + {% + \scantokens\expanded + {{% + \string\begin{#1}\detokenize{#2}\enverb@othercr + \detokenize\expandafter{\enverbBody}% + \string\end{#1}\enverb@othercr + \enverb@rmeol + }}% + } +%% +%% +%% End of file `enverb.sty'. diff --git a/Master/tlpkg/bin/tlpkg-ctan-check b/Master/tlpkg/bin/tlpkg-ctan-check index 0be2e7ee47c..733e091f331 100755 --- a/Master/tlpkg/bin/tlpkg-ctan-check +++ b/Master/tlpkg/bin/tlpkg-ctan-check @@ -303,7 +303,7 @@ my @TLP_working = qw( enctex encxvlna endfloat endheads endiagram endnotes endnotes-hy endnotesj endofproofwd engpron engrec engtlc enigma enotez ensps-colorscheme - enumitem enumitem-zref envbig environ envlab eolang + enumitem enumitem-zref envbig enverb environ envlab eolang epcqrcode epigrafica epigram epigraph epigraph-keys epiolmec eplain epsdice epsf epsf-dvipdfmx epsincl epslatex-fr epspdfconversion epstopdf epstopdf-pkg diff --git a/Master/tlpkg/libexec/ctan2tds b/Master/tlpkg/libexec/ctan2tds index 49220e7155f..933a935779c 100755 --- a/Master/tlpkg/libexec/ctan2tds +++ b/Master/tlpkg/libexec/ctan2tds @@ -3290,6 +3290,7 @@ my $core_latex = "$Master/texmf-dist/tex/latex"; 'emisa' => 'pdflatex-preserve-pdf', 'emo' => 'etex', 'engpron' => 'latex -translate-file=empty.tcx', # no 8-bit + 'enverb' => 'etex', 'ecclesiastic' => 'latex', # requires interaction 'emisa' => 'pdflatex-preserve-pdf', 'epstopdf-pkg' => 'tex', diff --git a/Master/tlpkg/tlpsrc/collection-latexextra.tlpsrc b/Master/tlpkg/tlpsrc/collection-latexextra.tlpsrc index 766485fd5ce..2eb921f42a4 100644 --- a/Master/tlpkg/tlpsrc/collection-latexextra.tlpsrc +++ b/Master/tlpkg/tlpsrc/collection-latexextra.tlpsrc @@ -452,6 +452,7 @@ depend ensps-colorscheme depend enumitem depend enumitem-zref depend envbig +depend enverb depend environ depend envlab depend epcqrcode diff --git a/Master/tlpkg/tlpsrc/enverb.tlpsrc b/Master/tlpkg/tlpsrc/enverb.tlpsrc new file mode 100644 index 00000000000..e69de29bb2d --- /dev/null +++ b/Master/tlpkg/tlpsrc/enverb.tlpsrc |