diff options
author | Karl Berry <karl@freefriends.org> | 2019-07-30 21:11:25 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2019-07-30 21:11:25 +0000 |
commit | 161fbf358154d8331102533f2502b0142508311c (patch) | |
tree | 645d5fff0ae53ec060a514a29f73470e110d1182 | |
parent | 8d8689cf2a834a431395e4beb28926f111f8cbb5 (diff) |
scontents (30jul19)
git-svn-id: svn://tug.org/texlive/trunk@51779 c570f23f-e606-0410-a88d-b1316a301751
-rw-r--r-- | Master/texmf-dist/doc/latex/scontents/README.md | 26 | ||||
-rw-r--r-- | Master/texmf-dist/doc/latex/scontents/scontents.pdf | bin | 0 -> 182019 bytes | |||
-rw-r--r-- | Master/texmf-dist/source/latex/scontents/scontents.dtx | 1798 | ||||
-rw-r--r-- | Master/texmf-dist/source/latex/scontents/scontents.ins | 9 | ||||
-rw-r--r-- | Master/texmf-dist/tex/latex/scontents/scontents.sty | 287 | ||||
-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/scontents.tlpsrc | 0 |
9 files changed, 2123 insertions, 1 deletions
diff --git a/Master/texmf-dist/doc/latex/scontents/README.md b/Master/texmf-dist/doc/latex/scontents/README.md new file mode 100644 index 00000000000..71639b8d695 --- /dev/null +++ b/Master/texmf-dist/doc/latex/scontents/README.md @@ -0,0 +1,26 @@ +# scontents — Store LaTeX content in Sequences (l3seq) +- Version: 1.0 +- Date: 2019/07/30 +- Authors: Pablo González and Phelype Oleinik + +## Description +The `scontents` package stores valid `LaTeX` code in sequences using the +`l3seq` module of `expl3`. The stored content (including verbatim) can be +used as many times as desired in the document, additionally can be written +to external files if desired. + +## Requirements +The package requires the following packages: +- [filecontentsdef](https://ctan.org/pkg/filecontentsdef) +- [l3keys2e](https://ctan.org/pkg/l3keys2e) +- [xparse](https://ctan.org/pkg/xparse) + +## License +The scontents package may be modified and distributed under the terms and +conditions of the [LaTeX Project Public License](https://www.latex-project.org/lppl/), version 1.3c or greater. + +## Contents +- README.md (this file) +- scontents.sty (the sty) +- scontents.pdf (documentation) +- scontents.dtx (master file that produced all files) diff --git a/Master/texmf-dist/doc/latex/scontents/scontents.pdf b/Master/texmf-dist/doc/latex/scontents/scontents.pdf Binary files differnew file mode 100644 index 00000000000..240570a5e1d --- /dev/null +++ b/Master/texmf-dist/doc/latex/scontents/scontents.pdf diff --git a/Master/texmf-dist/source/latex/scontents/scontents.dtx b/Master/texmf-dist/source/latex/scontents/scontents.dtx new file mode 100644 index 00000000000..c376fd9dc2c --- /dev/null +++ b/Master/texmf-dist/source/latex/scontents/scontents.dtx @@ -0,0 +1,1798 @@ +% \iffalse meta-comment +%<*internal> +\iffalse +%</internal> +%<*readme> +# scontents — Store LaTeX content in Sequences (l3seq) +- Version: 1.0 +- Date: 2019/07/30 +- Authors: Pablo González and Phelype Oleinik + +## Description +The `scontents` package stores valid `LaTeX` code in sequences using the +`l3seq` module of `expl3`. The stored content (including verbatim) can be +used as many times as desired in the document, additionally can be written +to external files if desired. + +## Requirements +The package requires the following packages: +- [filecontentsdef](https://ctan.org/pkg/filecontentsdef) +- [l3keys2e](https://ctan.org/pkg/l3keys2e) +- [xparse](https://ctan.org/pkg/xparse) + +## License +The scontents package may be modified and distributed under the terms and +conditions of the [LaTeX Project Public License](https://www.latex-project.org/lppl/), version 1.3c or greater. + +## Contents +- README.md (this file) +- scontents.sty (the sty) +- scontents.pdf (documentation) +- scontents.dtx (master file that produced all files) +%</readme> +%<*internal> +\fi +\def\nameofplainTeX{plain} +\ifx\fmtname\nameofplainTeX\else + \expandafter\begingroup +\fi +%</internal> +%<*install> +\input l3docstrip.tex +\keepsilent +\askforoverwritefalse +\nopreamble\nopostamble +\usedir{tex/latex/scontents} +\generate{ + \file{\jobname.sty}{\from{\jobname.dtx}{package}} +} +%</install> +%<install>\endbatchfile +%<*internal> +\usedir{source/latex/scontents} +\generate{ + \file{\jobname.ins}{\from{\jobname.dtx}{install}} +} +\nopreamble\nopostamble +\usedir{doc/latex/scontents} +\generate{ + \file{README.md}{\from{\jobname.dtx}{readme}} +} +\ifx\fmtname\nameofplainTeX + \expandafter\endbatchfile +\else + \expandafter\endgroup +\fi +%</internal> +%<*driver> +\documentclass[full]{l3doc} +\usepackage[top=0.5in,bottom=0.5in,left=2.0in,right=1in,footskip=0.2in,headsep=10pt]{geometry} +\usepackage{unicode-math} +\setmathfont[Scale = 0.95]{Latin Modern Math} +\setmainfont[ + Numbers = OldStyle, + Ligatures = TeX, + Scale = 0.95, + UprightFont = *-Regular, + ItalicFont = *-Italic, + BoldFont = *-Bold, + BoldItalicFont = *-BoldItalic, + SmallCapsFeatures = {Letters=SmallCaps}, + Extension =.otf]{LibertinusSerif} +\setsansfont[ + Numbers = OldStyle, + Ligatures = TeX, + Scale = 0.95, + UprightFont = *-Regular, + ItalicFont = *-Italic, + BoldFont = *-Bold, + SmallCapsFeatures = {Letters=SmallCaps}, + Extension = .otf]{LibertinusSans} +\setmonofont[ + Scale = 0.80, + Extension = .otf, + UprightFont = *-Regular , + ItalicFont = *-RegularIt, + BoldFont = *-Medium , + BoldItalicFont = *-MediumIt + ]{SourceCodePro} +\newfontfamily\lmmitalic{lmmono10-italic.otf}[ + Scale = 0.95,% + Extension = .otf,% + ItalicFont = lmmono10-italic,% + SmallCapsFont = lmmonocaps10-oblique,% + SlantedFont = lmmonoslant10-regular, + ] +\newfontfamily\fetamontotf{ffmw10.otf}[ + Scale = 0.95,% + RawFeature = {+latn,+rand,+kern,+size},% + ] +\usepackage[svgnames]{xcolor} +\usepackage{fontawesome5} +\usepackage[sf,bf,compact,medium,pagestyles]{titlesec} +\usepackage{hyperxmp,lastpage,imakeidx,microtype,attachfile2} +\usepackage{adjustbox,multicol,listings,accsupp,titletoc} +\usepackage{scontents} % main + +\usepackage[contents]{colordoc} + +% Patching colordoc.sty to work with l3doc.cls +\ExplSyntaxOn +\cs_new_eq:cN { liii@xmacro@code } \__codedoc_xmacro_code:n +\ExplSyntaxOff +\begingroup +\makeatletter +\catcode`\[\@ne\catcode`\]\tw@ +\@makebracesactive +\gdef{[\@openingbrace[\char'173]] +\gdef}[\@closingbrace[\char'175]] +\catcode`\|\z@\catcode`\%12 +\catcode`\ \active\catcode`\\\active +|gdef|xmacro@code#1% \end{macrocode}[|liii@xmacro@code[#1]|end[macrocode]] +|catcode`| 12|gdef|sxmacro@code#1% \end{macrocode*}[|liii@xmacro@code[#1]|end[macrocode*]] +|endgroup + +\EnableCrossrefs +\PageIndex +\CodelineIndex +\DoNotIndex{\ , \1,\^} +\expandafter\DoNotIndex\expandafter{\string\{} +\expandafter\DoNotIndex\expandafter{\string\}} +\expandafter\DoNotIndex\expandafter{\string\begin} +\newcommand{\HP}[1]{\emph{\hyperpage{#1}}\normalsize} +\def\MYSortIndex#1#2{\index[mydoc]{#1\actualchar#2|HP}} + +\indexsetup{level=\section,firstpagestyle=myheader} +\makeindex[name=mydoc,options=-s gind.ist,columnsep=15pt,title={Index of Documentation}] +\makeindex[options=-s gind.ist,columnsep=15pt,title={Index of Implementation}] +\setlength{\parindent}{0pt} + +%%-------------------- ONLY FOR DOCUMENTATION ------------------------%% +% Colors for options +\definecolor{optcolor}{rgb}{0.281,0.275,0.485} +\definecolor{mypkgcolor}{RGB}{0,128,128}% +% Custom \mymeta[...]{...}, \mymarg[...]{...} and \myoarg[...]{...} for color +\ExplSyntaxOn +%^^A user level commands +\NewDocumentCommand{\mymeta}{O{}m} + { + \mydoc_mymeta_generic:Nnn \mydoc_mymeta:n { #1 } { #2 } + } +\NewDocumentCommand{\mymarg}{O{}m} + { + \mydoc_mymeta_generic:Nnn \mydoc_mymarg:n { #1 } { #2 } + } +\NewDocumentCommand{\myoarg}{O{}m} + { + \mydoc_mymeta_generic:Nnn \mydoc_myoarg:n { #1 } { #2 } + } +%^^A variables and keys +\tl_new:N \l_mydoc_mymeta_font_tl + +\keys_define:nn { mydoc / mymeta } + { + type .choice:, + type / tt .code:n = \tl_set:Nn \l_mydoc_mymeta_font_tl { \ttfamily }, + type / rm .code:n = \tl_set:Nn \l_mydoc_mymeta_font_tl { \rmfamily }, + type .initial:n = tt, + cf .tl_set:N = \l_mydoc_mymeta_color_tl, + cf .initial:n = black, + ac .tl_set:N = \l_mydoc_mymeta_anglecolor_tl, + ac .initial:n = black, + sbc .tl_set:N = \l_mydoc_mymeta_brackcolor_tl, + sbc .initial:n = black, + cbc .tl_set:N = \l_mydoc_mymeta_bracecolor_tl, + cbc .initial:n = black, + } +%^^A internal commands +\cs_new_protected:Npn \mydoc_mymeta_generic:Nnn #1 #2 #3 + { + \group_begin: + \keys_set:nn { mydoc / mymeta } { #2 } + \color{ \l_mydoc_mymeta_color_tl } + \l_mydoc_mymeta_font_tl + #1 { #3 } % #1 is \mydoc_mymeta:n, \mydoc_mymarg:n or \mydoc_myoarg:n + \group_end: + } +\cs_new_protected:Npn \mydoc_mymeta:n #1 + { + \mydoc_mymeta_angle:n { \textlangle } + \mydoc_mymeta_mymeta:n { #1 } + \mydoc_mymeta_angle:n { \textrangle } + } +\cs_new_protected:Npn \mydoc_mymarg:n #1 + { + \mydoc_mymeta_brace:n { \textbraceleft } + \mydoc_mymeta:n { #1 } + \mydoc_mymeta_brace:n { \textbraceright } + } +\cs_new_protected:Npn \mydoc_myoarg:n #1 + { + \mydoc_mymeta_brack:n { [ } + \mydoc_mymeta:n { #1 } + \mydoc_mymeta_brack:n { ] } + } +\cs_new_protected:Npn \mydoc_mymeta_mymeta:n #1 + { + \textnormal{\textit{#1}} + } +\cs_new_protected:Npn \mydoc_mymeta_angle:n #1 + { + \group_begin: + \fontfamily{lmr}\selectfont + \textcolor{\l_mydoc_mymeta_anglecolor_tl}{#1} + \group_end: + } +\cs_new_protected:Npn \mydoc_mymeta_brace:n #1 + { + \group_begin: + \color{\l_mydoc_mymeta_bracecolor_tl} + #1 + \group_end: + } +\cs_new_protected:Npn \mydoc_mymeta_brack:n #1 + { + \textcolor{\l_mydoc_mymeta_brackcolor_tl}{#1} + } + +% \envexamp{m} +\newsavebox{\marginexa} +\NewDocumentCommand{\envexamp}{m} + { + \begin{lrbox}{\marginexa}% + \begin{minipage}[t]{\marginparwidth}% + \raggedleft\ttfamily\small + \textcolor{gray}{\textbackslash begin\{\textcolor{mypkgcolor}{\bfseries{#1}}\}\myoarg + [type=tt,sbc=gray,ac=NavyBlue,cf=optcolor]{key=val}}\par% + \mymeta[ac=gray,cf=gray]{env ~ contents}\par% + \textcolor{gray}{\textbackslash end\{{\textcolor{mypkgcolor}{\bfseries{#1}}}\}}\par + \end{minipage}% + \end{lrbox}% + \leavevmode% + \marginpar{\usebox{\marginexa}}% + \ignorespaces% + } + +% \cmdexamp{s m o m o} +\DeclareDocumentCommand{\cmdexamp}{s m o m o} + { + \group_begin: + \small\ttfamily + \adjustbox{outer=-0.5\marginparsep}{\textcolor{mypkgcolor}{\textbackslash#2}} + \IfBooleanTF{#1}{ \textcolor{red}{*} }{ \hphantom{*} } + \IfValueT{#3}{ \myoarg[type=tt,sbc=gray,ac=NavyBlue,cf=optcolor]{#3} } + \IfValueTF{#5} + { + \mymeta[ac=OrangeRed,type=tt,cf=MediumOrchid]{#5}% + \mymeta[type=tt,cbc=OrangeRed,ac=NavyBlue,cf=MediumOrchid]{#4} + \mymeta[ac=OrangeRed,type=tt,cf=MediumOrchid]{#5}% + } + { \mymarg[type=tt,cbc=OrangeRed,ac=NavyBlue,cf=MediumOrchid]{#4} } + \par + \group_end: + \MYSortIndex{Commands}{Commands ~ provide ~ by ~ \textcolor{gray}{scontents}>\texttt{\textbackslash#2}}% + } + +% \keyexamp{mmm} +\DeclareDocumentCommand{\keyexamp}{ m m m } + { + \par + \adjustbox{outer=-\marginparsep}{\textcolor{mypkgcolor}{\small\ttfamily{#1}}} + \textcolor{gray}{\,\bfseries\texttt{=}}\,{} + \mymarg[type=tt,cbc=OrangeRed,ac=NavyBlue,cf=MediumOrchid]{\small{#2}} + \hfill\textcolor{gray}{\small\textsf{(default: ~ \texttt{#3})}} + \par + \MYSortIndex{Keys}{Keys>\texttt{#1}}% + } + +% \mypkg{sm} +\NewDocumentCommand{\mypkg}{sm} + { + \IfBooleanTF{#1} + { + \normalsize{\sffamily\textcolor{mypkgcolor}{s}\textcolor{OrangeRed}{content}\textcolor{mypkgcolor}{s}} + \MYSortIndex{packages}{Packages>\texttt{#2}} + } + { + \textcolor{gray}{\textsf{#2}} + \MYSortIndex{packages}{Packages>\texttt{#2}}% + } + } + +% \myenv{sm} +\DeclareDocumentCommand{\myenv}{sm} + { + \IfBooleanTF{#1} + { + \textcolor{mypkgcolor}{\ttfamily{#2}}% + \MYSortIndex{environment}{Environment ~ provide ~ by ~ \textcolor{gray}{scontents}:>\texttt{#2}} + } + { + \textcolor{gray}{\ttfamily{#2}}% + \MYSortIndex{environment}{Environments>\texttt{#2}} + } + } + +% \ics{sm} +\DeclareDocumentCommand{\ics}{sm} + { + \IfBooleanTF{#1} + { + \textcolor{mypkgcolor}{\ttfamily\textbackslash{#2}} + \MYSortIndex{Commands}{Commands ~ provide ~ by ~ \textcolor{gray}{scontents}>\texttt{\textbackslash#2}} + } + { + \textcolor{gray}{\ttfamily\textbackslash{#2}} + \MYSortIndex{#2}{\texttt{\textbackslash#2}} + } + } +\ExplSyntaxOff + +% email https://tex.stackexchange.com/a/663 +\catcode`\_=11\relax% +\newcommand\email[1]{\_email #1\q_nil}% +\def\_email#1@#2\q_nil{% + \href{mailto:#1@#2}{{\emailfont #1\emailampersat #2}}% +}% +\newcommand\emailfont{\sffamily}% +\newcommand\emailampersat{{\color{optcolor}\footnotesize @}}% +\catcode`\_=8\relax% + +\makeatletter +% Logo whit textffmw font for title +\newsavebox{\logobox} +\savebox{\logobox}{% + \normalsize\fetamontotf{\textcolor{mypkgcolor}{s}\textcolor{OrangeRed}{content}\textcolor{mypkgcolor}{s}}} +\newcommand{\mylogo}{% + \settoheight{\@tempdima}{L}% + \resizebox{!}{\@tempdima}{\usebox{\logobox}}% + } +\makeatother + +% don't copy numbers in code example +\newcommand*{\noaccsupp}[1]{\BeginAccSupp{ActualText={}}#1\EndAccSupp{}} + +% Create a language for documentation +\lstdefinelanguage{scontents-doc}{ + texcsstyle=*,% + escapechar=`,% + showstringspaces=false,% + extendedchars=true, % + stringstyle = {\color{red}},% + basicstyle=\ttfamily\small,% +% comments + morecomment=[l]{\%},% + commentstyle=\lmmitalic\small\itshape\color{lightgray},% +% Important words 1 + keywordstyle=[1]{\bfseries\color{NavyBlue}},% + keywords=[1]{begin,end,documentclass},% +% Other words 2 + keywordstyle=[2]{\color{blue!75}},% + keywords=[2]{usepackage,section},% +% Other words 3 + keywordstyle=[3]{\color{optcolor!85}},% + keywords=[3]{document,article},% +% Reserved words 4(inputfile options) + keywordstyle=[4]{\bfseries\color{mypkgcolor}},% + keywords=[4]{scontents,Scontents,getstored,typestored,verbatimsc,endverbatimsc,countsc},% +% Reserved in orange + keywordstyle=[5]{\color{OrangeRed}},% + keywords=[5]{makeatletter,makeatother,foreach,DefineVerbatimEnvironment,lstnewenvironment,newminted},% +% Reserved in orange + keywordstyle=[6]{\color{red}},% + keywords=[6]{verb,myverb,store-cmd,store-env},% +% literateee + literate=*{\{}{{\bfseries\textcolor{gray}{\{}}}{1} + {\}}{{\bfseries\textcolor{gray}{\}}}}{1} + {[}{{\bfseries\textcolor{optcolor}{[}}}{1} + {]}{{\bfseries\textcolor{optcolor}{]}}}{1} + {,}{{\textcolor{gray}{,}}}{1} + {\$}{{\textcolor{blue}{\$}}}{1} + {*}{{\bfseries\textcolor{red}{*}}}{1} + {@}{{\textcolor{red}{@}}}{1} + {=}{{\textcolor{red}{=}}}{1},% +}[keywords,tex,comments,strings]% end languaje + +% \begin{examplecode}[optlst]...\end{examplecode} +\lstnewenvironment{examplecode}[1][]{% +\lstset{ + language=scontents-doc,% + stringstyle = {\color{red}},% + basicstyle=\ttfamily\small,% + numbersep=1em,% + numberstyle=\tiny\color{lightgray}\noaccsupp,% + rulecolor=\color{gray!50},% + framesep=\fboxsep,% + framerule=\fboxrule,% + xleftmargin=\dimexpr\fboxsep+\fboxrule\relax,% + xrightmargin=\dimexpr\fboxsep+\fboxrule\relax,% + #1,% + }% close lstset +}{}% close examplecode + +% \lstinline[style=inline]|...| +\lstdefinestyle{inline} + { + language=scontents-doc,% + numbersep=1em,% + numberstyle=\tiny\color{lightgray}\noaccsupp,% + basicstyle=\ttfamily\small\color{gray},% + escapechar=`,% + upquote=true,% + literate=*{\%}{{\bfseries\textcolor{gray}{\%}}}{1} + } + +% set default style +\lstset{style=inline} + +% Get file info +\GetFileInfo{\jobname.sty} + +% Config hyperref +\hypersetup{ + linkcolor = blue!50, + citecolor = red!50,% + urlcolor = magenta,% + colorlinks = true,% + linktoc = all,% + pdftitle = {.:: The scontents package --- \fileinfo{} ::.},% + pdfauthor = {Pablo González L and Phelype Oleinik}, + pdfsubject = {Documentation for \fileversion{} [\filedate] },% + pdfcopyright = {\textcopyright 2019 by Pablo González and Phelype Oleinik}, + pdfcontacturl = {https://github.com/pablgonz/scontents}, + pdfkeywords = {filecontents, filecontentsdef, xparse, expl3, l3seq, Store contents}, + pdfstartview = {FitH},% + bookmarksopenlevel = 2,% + } + +% Configuration titleps +\settitlemarks{section} +\renewpagestyle{plain}[\color{gray}\small\sffamily]{ +\setfoot{}{}{\thepage/\pageref{LastPage}}} + +\newpagestyle{myheader}[\color{gray}\small\sffamily]{ +\renewcommand\makeheadrule{\color{gray}\rule[0.45\baselineskip]{\linewidth}{0.4pt}} +\setfoot{\scalebox{0.8}{\mylogo}\space\textcopyright\space 2019 by Pablo González and Phelype Oleinik} + {} + {\thepage/\pageref{LastPage}} +\sethead{\raisebox{0.75\baselineskip}{Documentation for \fileversion\space[\filedate]}} + {} + {\raisebox{0.75\baselineskip}{\scshape\small\S.\thesection\space\sectiontitle}} +} + +% add headheight +\setlength{\headheight}{21pt}% + +% Table of contents +\titlecontents{section}[0mm]{}% + {\bfseries\contentspush{\makebox[4mm][l]{\thecontentslabel\hfill}}}% + {\hspace*{-4mm}}% numberless + {\hspace{0.25em}\titlerule*[6pt]{.}\contentspage}% +\titlecontents{subsection}[4mm]{}% + {\contentspush{\makebox[6mm][l]{\thecontentslabel\hfill}}} + {\hspace*{-10mm}}% numberless + {\hspace{0.25em}\titlerule*[6pt]{.}\contentspage}% +\titlecontents{subsubsection}[10mm]{}% + {\contentspush{\makebox[8mm][l]{\thecontentslabel\hfill}}} + {\hspace*{-18mm}}% numberless + {\hspace{0.25em}\titlerule*[6pt]{.}\contentspage}% + +% Table of contents +\makeatletter +\renewcommand\tableofcontents{% +\begingroup% +\section*{\contentsname\quad{\color{gray}\leaders\hrule height 5pt depth -4.4pt\hfill}% + \@mkboth{% + \MakeUppercase\contentsname}{\MakeUppercase\contentsname}}% +\vspace*{-14pt} +\setlength{\columnsep}{10pt}% + \begin{multicols}{2}% + \@starttoc{toc}% +\end{multicols}% +\vspace*{-3pt}{\color{gray}\hrule height 0.6pt}% +\vspace*{5pt} +\endgroup +} +\makeatother + +\begingroup\expandafter\expandafter\expandafter\endgroup +\expandafter\ifx\csname pdfxform\endcsname\relax + \usepackage{luatex85} % For LuaTeX +\fi + +\begin{document} + \DocInput{\jobname.dtx} +\end{document} +%</driver> +% \fi +% +% \title{ +% \scalebox{1.1}{\mylogo}\\[2pt] +% \large +% \textsf{Store \hologo{LaTeX} contents in seq}\\[3pt] +% \Large +% \fileversion{} --- \filedate\thanks{ +% This file describes a documentation for \fileversion, last revised +% \filedate.}\\[25pt] +% \author{ +% \large +% \raisebox{-1pt}{\textcopyright}{}2019 by Pablo González and Phelype Oleinik +% \thanks{E-mail: \textsf{\guillemotleft}\email{pablgonz@educarchile.cl}\textsf{\guillemotright}}% +% } +% \small +% \textsc{ctan}: \url{http://www.ctan.org/pkg/scontents}\\ +% \textsc{git}: \url{https://github.com/pablgonz/scontents} +% \vspace*{-2cm} +% } +% \date{} +% \maketitle +% +% \begin{abstract} +% The \mypkg*{scontents} package stores valid \hologo{LaTeX} code in sequences using +% the \mypkg{l3seq} module of \mypkg{expl3}. The stored content (including +% \emph{verbatim}) can be used as many times as desired in the document, +% additionally can be written to external files if desired. +% \end{abstract} +% +% \tableofcontents +% +% \setlength{\parskip}{3pt} +% +% \section[Description]{Description} +% +% The \mypkg*{scontents} package encapsulates the \mypkg{filecontentsdef} +% package of \textsc{Jean Fran\c{c}ois Burnol} which allows you to save the +% content in a |\macro| and save it in external files, adding a user interface +% style \myoarg{key = val} along with the ability to save content in sequences +% for later use in different parts of the document. +% +% \section{Motivation and Acknowledgments} +% +% In \hologo{LaTeX} there is no direct way to record content for later use, although +% you can do this using \verb|\macros|, recording \meta{verbatim content} is a +% problem, usually you can avoid this by creating external files or boxes. The +% general idea of this package is to try to imitate this implementation +% \emph{buffers} that has \hologo{ConTeXt} which allows you to save content in +% memory, including \emph{verbatim}, to be used later. The package +% \mypkg{filecontentsdef} solves this problem and since \mypkg{expl3} has an +% excellent way to manage data, I decided to combine the best of both. +% +% This package would not be possible without the great work of \textsc{Jean +% Fran\c{c}ois Burnol} who was kind enough to take my requirements into account +% and add the \myenv{filecontentsdefmacro} environment. Also a special thanks to +% all the \hologo{LaTeX3} team for their great work and to the different members +% of the \href{https://tex.stackexchange.com}{TeX-SX} community who have provided +% great answers and ideas. Here a note of the main ones: +% +% \begin{enumerate}[nosep] +% \item \href{https://tex.stackexchange.com/q/45946/7832}{Stack datastructure using LaTeX} +% +% \item \href{https://tex.stackexchange.com/q/5338/7832}{LaTeX equivalent of ConTeXt buffers} +% +% \item \href{https://tex.stackexchange.com/q/215563/7832}{Storing an array of strings in a command} +% +% \item \href{https://tex.stackexchange.com/q/184503/7832}{Collecting contents of environment and store them for later retrieval} +% +% \item \href{https://tex.stackexchange.com/q/373647/7832}{Collect contents of an environment (that contains verbatim content)} +% \end{enumerate} +% +% \section[License and Requirements]{License and Requirements} +% \label{sec:Licenseandreq} +% +% Permission is granted to copy, distribute and/or modify this software under +% the terms of the LaTeX Project Public License (lppl), version 1.3 or later +% (\url{http://www.latex-project.org/lppl.txt}). The software has the status +% \enquote{maintained}. +% +% The \mypkg*{scontents} package loads \mypkg{xparse}, +% \mypkg{filecontentsdef} and \mypkg{l3keys2e}. This package can be used +% with |xelatex|, |lualatex|, |pdflatex| and the classical workflow +% |latex|-|dvips|-|ps2pdf|. +% +% \thispagestyle{plain} +% +% \newpage +% +% \pagestyle{myheader} +% +% \section{The scontents package} +% +% The \mypkg*{scontents} package provides the \myenv*{scontents} environment, +% \ics*{Scontents} and \ics*{Scontents*} command to stored contents and \ics*{getstored} +% command to get the \meta{stored content} along with other utilities described in this +% documentation. +% +% \subsection{Loading package} +% \label{sec:loadoptpkg} +% +% The package is loaded in the usual way: +% \iffalse +%<*example> +% \fi +\begin{examplecode}[frame=single] +\usepackage{scontents} +\end{examplecode} +% \iffalse +%</example> +% \fi +% Or +% \iffalse +%<*example> +% \fi +\begin{examplecode}[frame=single] +\usepackage`\myoarg[type=tt,cbc=OrangeRed,ac=NavyBlue,cf=optcolor]{key=val}`{scontents} +\end{examplecode} +% \iffalse +%</example> +% \fi +% \subsection{Configuration of the options} +% \label{sec:confopt} +% +% Most of the options can be passed directly to the package or can be +% configured by means of the command \ics*{setupsc}. +% +% \cmdexamp{setupsc}{key=val} +% The command \ics*{setupsc} configures the options in a global way, +% it can be used both in the preamble and in the body of the document +% as many times as desired. +% +% The summary with all possible options can be found in \ref{sec:optover}. +% +% \section{User interface} +% \label{sec:userinterface} +% +% The user interface provided by the package provides an environment and several +% commands with some limitations that must be taken into account. +% +% \subsection{The environment scontents} +% \label{sec:envscontents} +% +% \envexamp{scontents} +% The \myenv*{scontents} environment encapsulates the \ics{filecontentsdef*} and % +% \ics{filecontentsdefmacro} environments provided by the \mypkg{filecontentsdef} +% package. This allows you to record content including verbatim for later +% reuse. Some considerations to keep in mind: +% +% \begin{enumerate}[nosep] +% \item The environment cannot be nested. +% \item Both \lstinline[style=inline]|\begin| and \lstinline[style=inline]|\end| +% must be on different lines. +% \item The \myoarg{key=val} options must be passed on one line right after +% starting the environment. +% \item The content of the environment is treated in the same way as +% \myenv{filecontents*} environment. +% \item If you don't want the extra space added by \hologo{TeX}, you should use +% \ics{relax} or \lstinline[style=inline]|%| at the end of environment. +% \end{enumerate} +% +% For more technical information about the environment it is better to read +% the documentation of the \mypkg{filecontentsdef} package. +% +% \subsubsection*{Options for environment} +% +% The environment options can be configured globally using option +% in package or the \ics*{setupsc} command and locally +% using \myoarg{key=val} in the environment. +% +% \medskip +% +% \keyexamp{store-env}{seq name}{contents} +% The name of the sequence in which the content recorded by the environment +% was stored. +% +% \medskip +% +% \keyexamp{print-env}{true\textbar false}{false} +% It will show the current content of the environment. +% +% \medskip +% +% \keyexamp{write-env}{file.ext}{not used} +% In addition to storing the content of the environment will write this in +% an external file. +% +% \medskip +% +% \keyexamp{write-out}{file.ext}{not used} +% It will write the contents of the environment in an external file, but, +% it will not store the contents of this one. It is analogous to the +% \myenv{filecontents*} environment. +% +% \subsection{The command \cs{Scontents}} +% \label{sec:Scontents} +% +% \cmdexamp{Scontents}[key=val]{argument} +% The \ics*{Scontents} command reads the \meta{argument} in standard mode. +% It is not possible to pass environments such as \meta{verbatim}, but it is +% possible to use the implementation of \ics{Verb} provided by the +% \mypkg{fvextra} package for contents on one line and \ics{lstinline} from +% \mypkg{listings} package, but it is preferable to use the starred version. +% +% It can be used anywhere in the document and cannot be used as an \meta{argument} +% for another command. +% +% \cmdexamp*{Scontents}[key=val]{argument} +% \cmdexamp*{Scontents}[key=val]{argument}[del] +% The \ics*{Scontents*} command reads the \meta{argument} under verbatim +% category code regimen. If its first delimiter is a brace, it will be assumed that +% the \meta{argument} is nested into braces. Otherwise it will be assumed that +% the ending of that argument is delimited by that first delimiter-like the +% argument of \ics{verb}. Some considerations to keep in mind: +% +% \begin{enumerate}[nosep] +% \item Blank lines are preserved. +% \item The command cannot be used as an argument for another command. +% \item If you don't want the extra space added by \hologo{TeX}, you should use +% \ics{relax} or \lstinline[style=inline]|%| at the end. +% \end{enumerate} +% +% \subsubsection*{Options for command} +% +% The command options (including star version) can be configured globally +% using option in package or the \ics*{setupsc} command and locally +% using \myoarg{key=val}. +% \medskip +% +% \keyexamp{store-cmd}{seq name}{contents} +% The name of the sequence in which the content recorded by \ics*{Scontents} +% was stored. +% +% \medskip +% +% \keyexamp{print-cmd}{true\textbar false}{false} +% It will show the current content of \ics*{Scontents}. +% +% \subsection{The command \cs{getstored}} +% \label{sec:getstored} +% +% \cmdexamp{getstored}[index]{seq name} +% The command \ics*{getstored} gets the content stored in \meta{seq name} +% according to the index in which it was stored. The command is robust and expandable +% and can be used as an \meta{argument} for another command. If the optional argument +% is not passed it defaults to the last element saved in the \meta{seq name}. +% +% \subsection{The command \cs{typestored}} +% \label{sec:typestored} +% +% \cmdexamp{typestored}[index]{seq name} +% The command \ics*{typestored} shows the content stored in \meta{seq name} in +% \emph{verbatim} mode. Internally places the content into the \myenv*{verbatimsc} environment. +% +% \cmdexamp*{typestored}[index]{seq name} +% The command \ics*{typestored*} must be used for content stored by \ics*{Scontents*} command. +% Internally places the content into the \myenv*{verbatimsc} environment. +% +% If the optional argument is not passed it defaults to the +% last element saved in the \meta{seq name}. +% +% One consideration to keep in mind is that this is a \emph{representation} of the content +% in a \meta{verbatim} environment and not a real \meta{verbatim} environment, the line ends +% are not respected. The \myenv*{verbatimsc} environment can be in the following ways: +% +% Using the package \mypkg{fancyvrb}: +% \iffalse +%<*example> +% \fi +\begin{examplecode}[frame=single] +\makeatletter +\let\verbatimsc\@undefined +\let\endverbatimsc\@undefined +\makeatother +\DefineVerbatimEnvironment{verbatimsc}{Verbatim}{numbers=left} +\end{examplecode} +% \iffalse +%</example> +% \fi +% Using the package \mypkg{minted}: +% \iffalse +%<*example> +% \fi +\begin{examplecode}[frame=single] +\makeatletter +\let\verbatimsc\@undefined +\let\endverbatimsc\@undefined +\makeatother +\usepackage{minted} +\newminted{tex}{linenos} +\newenvironment{verbatimsc}{\VerbatimEnvironment\begin{texcode}}{\end{texcode}} +\end{examplecode} +% \iffalse +%</example> +% \fi +% Using the package \mypkg{listings}: +% \iffalse +%<*example> +% \fi +\begin{examplecode}[frame=single] +\makeatletter +\let\verbatimsc\@undefined +\let\endverbatimsc\@undefined +\makeatother +\usepackage{listings} +\lstnewenvironment{verbatimsc} + { + \lstset{ + basicstyle=\small\ttfamily, + columns=fullflexible, + language=[LaTeX]TeX, + numbers=left, + numberstyle=\tiny\color{gray}, + keywordstyle=\color{red} + } + }{} +\end{examplecode} +% \iffalse +%</example> +% \fi +% +% \subsection{Other commands provided} +% +% \subsubsection*{The command \cs{meaningsc}} +% \label{sec:meaningsc} +% +% \cmdexamp{meaningsc}[index]{seq name} +% The command \ics*{meaningsc} executes \ics{meaning} on the content stored +% in \meta{seq name}. If the optional argument is not passed it defaults to the +% last element saved in the \meta{seq name}. +% +% \subsubsection*{The command \cs{countsc}} +% \label{sec:countsc} +% +% \cmdexamp{countsc}{seq name} +% The command \ics*{countsc} count a number of contents stored in \meta{seq name}. +% +% \subsubsection*{The command \cs{cleansc}} +% \label{sec:cleansc} +% +% \cmdexamp{cleansc}{seq name} +% The command \ics*{cleansc} remove all contents stored in \meta{seq name}. +% +% \subsection{Options Overview} +% \label{sec:optover} +% +% \newcommand*{\xmark}{\textcolor{red}{✘}}% +% \newcommand*{\cmark}{\textcolor{green}{✔}}% +% +% Summary table of available options +% +% +% \begin{tabular}{cccccc} +% \toprule +% \texttt{key} & package & \ics{setupsc} & \myenv*{scontents} & \ics*{Scontents} & \ics*{Scontents*}\\ +% \midrule +% \texttt{store-env} & \cmark & \cmark & \cmark & \xmark & \xmark \\ +% \texttt{store-cmd} & \cmark & \cmark & \xmark & \cmark & \cmark \\ +% \texttt{print-env} & \cmark & \cmark & \cmark & \xmark & \xmark \\ +% \texttt{print-cmd} & \cmark & \cmark & \xmark & \cmark & \cmark \\ +% \texttt{print-all} & \cmark & \cmark & \cmark & \xmark & \xmark \\ +% \texttt{write-env} & \xmark & \xmark & \cmark & \xmark & \xmark \\ +% \texttt{write-out} & \xmark & \xmark & \cmark & \xmark & \xmark \\ +% \bottomrule +% \end{tabular} +% +% \section{Examples} +% These are some (adapted) examples that have served as inspiration for +% the creation of this package. +% +% \subsection{From answers package} +% +% \subsubsection*{Example 1} +% +% \begin{VerbatimOut}{scexamp1.ltx} +% \documentclass[12pt,a4paper]{article} +% \usepackage[store-cmd=solutions]{scontents} +% \usepackage{pgffor} +% \newtheorem{ex}{Exercise} +% \begin{document} +% \section{Problems} +% \begin{ex} +% First exercise +% \Scontents{ +% First solution. +% } +% \end{ex} +% \begin{ex} +% Second exercise +% \Scontents{ +% Second solution. +% } +% \end{ex} +% \section{Solutions} +% \foreach \i in {1,...,\countsc{solutions}} { +% \noindent\textbf{\i} \getstored[\i]{solutions}\par +% } +% \end{document} +% \end{VerbatimOut} +% +% Adaptation of example 1 (ansexam1) of the package \mypkg{answers} +% \textattachfile[color=0 0 1]{scexamp1.ltx}{\faFile*[regular]}. +% \lstinputlisting[language=scontents-doc,numbers=left]{scexamp1.ltx} +% +% \subsection{From filecontentsdef package} +% +% \subsubsection*{Example 2} +% +% \begin{VerbatimOut}{scexamp2.ltx} +% \documentclass{article} +% \usepackage[store-env=defexercise,store-cmd=defexercise]{scontents} +% \usepackage{pgffor} +% \pagestyle{empty} +% \begin{document} +% \Scontents{ +% Prove that \[x^n+y^n=z^n\] is not solvable in positive integers if $n$ is at +% most $-3$.\par +% } +% \Scontents*{Refute the existence of black holes in less than $140$ characters.\relax} +% \begin{scontents}[write-env=\jobname-3.txt] +% \def\NSA{NSA}% +% Prove that factorization is easily done via probabilistic algorithms and +% advance evidence from knowledge of the names of its employees in the +% seventies that the \NSA\ has known that for 40 years.\par +% \end{scontents} +% +% \foreach \i in {1,...,3} { +% \begin{itemize} +% \item \getstored[\i]{defexercise} +% \end{itemize}} +% +% \section{\getstored[2]{defexercise}} % \getstored are robust :) +% \end{document} +% \end{VerbatimOut} +% +% Adaptation of example from package \mypkg{filecontentsdef} +% \textattachfile[color=0 0 1]{scexamp2.ltx}{\faFile*[regular]}. +% \lstinputlisting[language=scontents-doc,numbers=left]{scexamp2.ltx} +% +% \subsection{From TeX-SX} +% +% \subsubsection*{Example 3} +% +% \begin{VerbatimOut}{scexamp3.ltx} +% \documentclass{article} +% \usepackage[store-cmd=tikz]{scontents} +% \usepackage{tikz} +% \pagestyle{empty} +% \Scontents*{\matrix{ \node (a) {$a$} ; & \node (b) {$b$} ; \\ } ;} +% \Scontents*{\matrix[ampersand replacement=\&] +% { \node (a) {$a$} ; \& \node (b) {$b$} ; \\ } ;} +% \Scontents*{\matrix{\node (a) {$a$} ; & \node (b) {$b$} ; \\ } ; } +% \begin{document} +% \section{tikzpicture} +% \begin{tikzpicture} +% \getstored[1]{tikz} +% \end{tikzpicture} +% \begin{tikzpicture} +% \getstored[2]{tikz} +% \end{tikzpicture} +% \begin{tikzpicture} +% \getstored[3]{tikz} +% \end{tikzpicture} +% \section{source} +% \foreach \i in {1,...,\countsc{tikz}}{ +% \typestored*[\i]{tikz}} +% \end{document} +% \end{VerbatimOut} +% Adapted from \href{https://tex.stackexchange.com/q/5338/7832}{LaTeX equivalent of ConTeXt buffers} +% \textattachfile[color=0 0 1]{scexamp3.ltx}{\faFile*[regular]}. +% \lstinputlisting[language=scontents-doc,numbers=left]{scexamp3.ltx} +% +% \subsubsection*{Example 4} +% +% \begin{VerbatimOut}{scexamp4.ltx} +% \documentclass{article} +% \usepackage{scontents} +% \usepackage{pgffor} +% \pagestyle{empty} +% \begin{document} +% \begin{scontents}[store-env=a] +% Something for a +% \end{scontents} +% +% \begin{scontents}[store-env=a] +% Something for b +% \end{scontents} +% +% \begin{scontents}[store-env=a] +% Something with no label +% \end{scontents} +% +% \textbf{Let's print them} +% +% This is a: \getstored[1]{a} +% +% This is b: \getstored[2]{a} +% +% \textbf{Print all of them} +% +% \foreach \i in {1,...,\countsc{a}} {\getstored[\i]{a}\par} +% \end{document} +% \end{VerbatimOut} +% +% Adapted from \href{https://tex.stackexchange.com/q/184503/7832}{Collecting contents of environment and store them for later retrieval} +% \textattachfile[color=0 0 1]{scexamp4.ltx}{\faFile*[regular]}. +% \lstinputlisting[language=scontents-doc,numbers=left]{scexamp4.ltx} +% +% \subsubsection*{Example 5} +% +% \begin{VerbatimOut}{scexamp5.ltx} +% \documentclass{article} +% \usepackage{scontents} +% \pagestyle{empty} +% \setlength{\parindent}{0pt} +% \begin{document} +% \section{Problem stated the first time} +% \begin{scontents}[print-env=true,store-env=problem] +% This is normal text. \verb+This is from the verb command+. This is normal text. +% \verb*|This is from the verb* command|. This is normal text. +% \begin{verbatim} +% This is from the verbatim environment: +% &%{} +% \end{verbatim} +% \end{scontents} +% \section{Problem restated} +% \getstored[1]{problem} +% \section{Problem restated once more} +% \getstored[1]{problem} +% \end{document} +% \end{VerbatimOut} +% +% Adapted from \href{https://tex.stackexchange.com/q/373647/7832}{Collect contents of an environment (that contains verbatim content)} +% \textattachfile[color=0 0 1]{scexamp5.ltx}{\faFile*[regular]}. +% \lstinputlisting[language=scontents-doc,numbers=left]{scexamp5.ltx} +% +% \subsection{Customization of verbatimsc} +% +% \subsubsection*{Example 6} +% +% \begin{VerbatimOut}{scexamp6.ltx} +% \documentclass{article} +% \usepackage{scontents} +% \makeatletter +% \let\verbatimsc\@undefined +% \let\endverbatimsc\@undefined +% \makeatother +% \usepackage{fvextra} +% \usepackage{xcolor} +% \definecolor{mygray}{gray}{0.9} +% \usepackage{tcolorbox} +% \newenvironment{verbatimsc}% +% {\VerbatimEnvironment +% \begin{tcolorbox}[colback=mygray, boxsep=0pt, arc=0pt, boxrule=0pt] +% \begin{Verbatim}[fontsize=\scriptsize, breaklines, breakafter=*, breaksymbolsep=0.5em, +% breakaftersymbolpre={\,\tiny\ensuremath{\rfloor}}]}% +% {\end{Verbatim}% +% \end{tcolorbox}} +% \setlength{\parindent}{0pt} +% \pagestyle{empty} +% \begin{document} +% +% \section{Test \texttt{\textbackslash begin\{scontents\}} whit \texttt{fancyvrb}} +% Test \verb+\begin{scontents}+ \par +% +% \begin{scontents} +% Using \verb+scontents+ env no \verb+[key=val]+, save in seq \verb+contents+ +% with index 1. +% +% Prove new \Verb*{ fancyvrb whit braces } and environment \verb+Verbatim*+ +% \begin{verbatim} +% verbatim environment +% \end{verbatim} +% \end{scontents} +% +% \section{Test \texttt{\textbackslash Scontents} whit \texttt{fancyvrb}} +% +% \Scontents{ We have coded this in \LaTeX: $E=mc^2$.} +% +% \section{Test \texttt{\textbackslash getstored}} +% +% \getstored[1]{contents}\par +% \getstored[2]{contents} +% +% \section{Test \texttt{\textbackslash meaningsc}} +% +% \meaningsc[1]{contents}\par +% +% \meaningsc[2]{contents} +% +% \section{Test \texttt{\textbackslash typestored}} +% +% \typestored[1]{contents} +% +% \typestored*[2]{contents} +% \end{document} +% \end{VerbatimOut} +% Customization of \myenv*{verbatimsc} using the \mypkg{fancyvrb} and \mypkg{tcolorbox} package +% \textattachfile[color=0 0 1]{scexamp6.ltx}{\faFile*[regular]}. +% \lstinputlisting[language=scontents-doc,numbers=left]{scexamp6.ltx} +% +% \subsubsection*{Example 7} +% +% \begin{VerbatimOut}{scexamp7.ltx} +% \documentclass{article} +% \usepackage{scontents} +% \makeatletter +% \let\verbatimsc\@undefined +% \let\endverbatimsc\@undefined +% \makeatother +% \usepackage{xcolor} +% \usepackage{listings} +% \lstnewenvironment{verbatimsc} +% { +% \lstset{ +% basicstyle=\small\ttfamily, +% breaklines=true, +% columns=fullflexible, +% language=[LaTeX]TeX, +% numbers=left, +% numbersep=1em, +% numberstyle=\tiny\color{gray}, +% keywordstyle=\color{red} +% } +% }{} +% \setlength{\parindent}{0pt} +% \pagestyle{empty} +% \begin{document} +% +% \section{Test \texttt{\textbackslash begin\{scontents\}} whit \texttt{listings}} +% Test \verb+\begin{scontents}+ \par +% +% \begin{scontents} +% Using \verb+scontents+ env no \verb+[key=val]+, save in seq \verb+contents+ with index 1.\par +% +% Prove \lstinline[basicstyle=\ttfamily]| lstinline | and environment \verb+Verbatim*+ +% \begin{verbatim} +% verbatim environment +% \end{verbatim} +% \end{scontents} +% +% \section{Test \texttt{\textbackslash Scontents*} whit \texttt{listings}} +% +% \Scontents*+ We have coded this in \lstinline[basicstyle=\ttfamily]|\LaTeX: $E=mc^2$| +% and more.+ +% +% \section{Test \texttt{\textbackslash getstored}} +% +% \getstored[2]{contents}\par +% +% \getstored[1]{contents} +% +% \section{Test \texttt{\textbackslash typestored}} +% +% \typestored[1]{contents} +% \typestored*[2]{contents} +% \end{document} +% \end{VerbatimOut} +% Customization of \myenv*{verbatimsc} using the \mypkg{listings} package +% \textattachfile[color=0 0 1]{scexamp7.ltx}{\faFile*[regular]}. +% \lstinputlisting[language=scontents-doc,numbers=left]{scexamp7.ltx} +% +% \subsubsection*{Example 8} +% +% \begin{VerbatimOut}{scexamp8.ltx} +% \documentclass{article} % need shell-escape +% \usepackage{scontents} +% \makeatletter +% \let\verbatimsc\@undefined +% \let\endverbatimsc\@undefined +% \makeatother +% \usepackage{minted} +% \newminted{tex}{linenos} +% \newenvironment{verbatimsc}{\VerbatimEnvironment\begin{texcode}}{\end{texcode}} +% \pagestyle{empty} +% \begin{document} +% \section{Test \texttt{\textbackslash begin\{scontents\}} whit \texttt{minted}} +% Test \verb+\begin{scontents}+ \par +% +% \begin{scontents} +% Using \verb+scontents+ env no \verb+[key=val]+, save in seq \verb+contents+ with index 1.\par +% +% Prove new \Verb*{ new fvextra whit braces } and environment \verb+Verbatim*+ +% \begin{verbatim} +% verbatim environment +% \end{verbatim} +% \end{scontents} +% +% \section{Test \texttt{\textbackslash Scontents} whit \texttt{minted}} +% +% \Scontents{ We have coded \par this in \LaTeX: $E=mc^2$.} +% +% \section{Test \texttt{\textbackslash getstored}} +% \getstored[2]{contents}\par +% +% \getstored[1]{contents} +% +% \section{Test \texttt{\textbackslash typestored}} +% +% \typestored[1]{contents} +% \end{document} +% \end{VerbatimOut} +% Customization of \myenv*{verbatimsc} using the \mypkg{minted} package +% \textattachfile[color=0 0 1]{scexamp8.ltx}{\faFile*[regular]}. +% \lstinputlisting[language=scontents-doc,numbers=left]{scexamp8.ltx} +% +% \newpage +% +% \printindex[mydoc] +% \newpage +% \StopEventually{^^A +% \newgeometry{top=0.5in,bottom=0.5in,left=1.0in,right=1in,footskip=0.2in,headsep=10pt} +% \addtocontents{toc}{\protect\setcounter{tocdepth}{2}} +% \cleardoublepage +% \phantomsection +% \printindex +% } +% +% \section{Implementation} +% \label{sec:Implementation} +% \addtocontents{toc}{\protect\setcounter{tocdepth}{0}} +% \iffalse +%<*package> +% \fi +% +% \subsection{Declaration of the package} +% +% First we set up the module name for \pkg{l3doc}: +% \begin{macrocode} +%<@@=scontents> +% \end{macrocode} +% +% Then, we can give the traditional declaration of a package written with +% \pkg{expl3} and the necessary packages for its operation. +% \begin{macrocode} +\RequirePackage{filecontentsdef}[2019/04/20] +\RequirePackage{l3keys2e} +\RequirePackage{xparse}[2019/05/03] +\ProvidesExplPackage{scontents}{2019/07/30}{1.0} + {Store LaTeX content in Sequences (l3seq)} +% \end{macrocode} +% A check to make sure that \pkg{xparse} is not too old +% \begin{macrocode} +\@ifpackagelater { xparse } { 2019/05/03 } + { } + { + \PackageError { scontents } { Support~package~xparse~too~old } + { + You~need~to~update~your~installation~of~the~bundles~ + 'l3kernel'~and~'l3packages'.\MessageBreak + Loading~scontents~will~abort! + } + \tex_endinput:D + } +% \end{macrocode} +% +% \subsection{Definition of common keys} +% +% We create some common keys that will be used by the options passed to +% the package as well as by the environments and commands defined. +% \begin{macrocode} +\keys_define:nn { scontents } + { + store-env .tl_set:N = \l_@@_name_seq_env_tl, + store-env .initial:n = contents, + print-env .bool_set:N = \l_@@_print_env_bool, + print-env .initial:n = false, + store-cmd .tl_set:N = \l_@@_name_seq_cmd_tl, + store-cmd .initial:n = contents, + print-cmd .bool_set:N = \l_@@_print_cmd_bool, + print-cmd .initial:n = false, + print-all .meta:n = { print-env = true , print-cmd = true }, + store-env .value_required:n = true, + store-cmd .value_required:n = true, + print-env .value_required:n = true, + print-cmd .value_required:n = true, + print-all .value_required:n = true + } +% \end{macrocode} +% +% We process the keys as options passed on to the package. +%%^^A Process options for pkg +% \begin{macrocode} +\ProcessKeysOptions { scontents } +% \end{macrocode} +% +% \subsection{Internal variables} +% +% Now we declare the internal variables we will use. +% +%%^^A Internal tl vars +% \begin{macro}{\l_@@_macro_tmp_tl,\l_@@_fname_out_tl,\l_@@_temp_tl} +% \cs{l_@@_macro_tmp_tl} is a temporary token list to hold the contents +% of the macro/environment, \cs{l_@@_fname_out_tl} is used as the name +% of the output file, when there's one, and \cs{l_@@_temp_tl} is a +% generic temporary token list. +% \begin{macrocode} +\tl_new:N \l_@@_macro_tmp_tl +\tl_new:N \l_@@_fname_out_tl +\tl_new:N \l_@@_temp_tl +% \end{macrocode} +% \end{macro} +% +%%^^A Internal bool vars +% \begin{macro}{\l_@@_typeverb_env_bool,\l_@@_writing_bool, +% \l_@@_storing_bool} +% The boolean \cs{l_@@_typeverb_env_bool} keeps track whether the +% starred variant of the \cs{typestored} macro was used, +% \cs{l_@@_writing_bool} if we should write to a file, and +% \cs{l_@@_storing_bool} determines whether it is in write-only mode +% when the |write-out| option is used. +% \begin{macrocode} +\bool_new:N \l_@@_typeverb_env_bool +\bool_set_true:N \l_@@_typevrb_env_bool +\bool_new:N \l_@@_writing_bool +\bool_set_false:N \l_@@_writing_bool +\bool_new:N \l_@@_storing_bool +\bool_set_true:N \l_@@_storing_bool +% \end{macrocode} +% \end{macro} +% +%%^^A Internal quarks +% \begin{macro}{\q_@@_stop,\q_@@_mark} +% Some quarks used along the code as macro delimiters. +% \begin{macrocode} +\quark_new:N \q_@@_stop +\quark_new:N \q_@@_mark +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\g_@@_end_verbatimsc_tl} +% A token list to match when ending verbatim environments. +% \begin{macrocode} +\tl_new:N \g_@@_end_verbatimsc_tl +\tl_gset_rescan:Nnn + \g_@@_end_verbatimsc_tl + { + \char_set_catcode_escape:N \| + \char_set_catcode_other:N \\ + \char_set_catcode_other:N \{ + \char_set_catcode_other:N \} + } + { \end{verbatimsc} } +% \end{macrocode} +% \end{macro} +% +% \subsection{Add keys for environment} +% +% We define a set of keys for environment \env{scontents}. +%%^^A Add keys to scontents environnment +% \begin{macrocode} +\keys_define:nn { scontents } + { + write-env .code:n = { + \bool_set_true:N \l_@@_writing_bool + \tl_set:Nn \l_@@_fname_out_tl {#1} + }, + write-out .code:n = { + \bool_set_false:N \l_@@_storing_bool + \bool_set_true:N \l_@@_writing_bool + \tl_set:Nn \l_@@_fname_out_tl {#1} + }, + write-env .value_required:n = true, + write-out .value_required:n = true + } +% \end{macrocode} +% +% \subsection{Define keys for command} +% +% A sub/keys for command |\Scontents| and |\Scontents*| +% +%%^^A A sub/keys for command |\Scontents| +% \begin{macrocode} +\keys_define:nn { scontents / Scontents } + { + print-cmd .meta:nn = { scontents } { print-cmd = #1 }, + store-cmd .meta:nn = { scontents } { store-cmd = #1 } + } +% \end{macrocode} +% +% \subsection{Programming of the sequences} +% +%%^^A Append content to seq +% \begin{macro}{\@@_append_contents:nn,\@@_getfrom_seq:nn} +% The storage of the package is done using |seq| variables. Here we +% set up the macros that will manage the variables. +% +% \cs{@@_append_contents:nn} creates a seq variable if one didn't +% exist and appends the contents in the argument to the right of the +% sequence. \cs{@@_getfrom_seq:nn} retrieves the saved item from the +% sequence. +% \begin{macrocode} +\cs_new_protected:Npn \@@_append_contents:nn #1#2 + { + \tl_if_blank:nT {#1} + { \msg_error:nn { scontents } { empty-store-cmd } } + \seq_if_exist:cF { g_@@_seq_name_#1_seq } + { \seq_new:c { g_@@_seq_name_#1_seq } } + \seq_gput_right:cn { g_@@_seq_name_#1_seq } {#2} + } +\cs_generate_variant:Nn \@@_append_contents:nn { Vx } +\cs_new:Npn \@@_getfrom_seq:nn #1#2 + { \seq_item:cn { g_@@_seq_name_#2_seq } {#1} } +% \end{macrocode} +% \end{macro} +% +% \subsection{Construction of environment scontents} +% +% We define the environment \env{scontents}, next to the system |key=val|. +% The environment is divided into three parts. This implementation is taken +% from answer by Enrico Gregorio in \url{https://tex.stackexchange.com/a/487746/7832}. +% +%%^^A Define |scontents| whit [key=val] (delaying) +% \begin{macro}{scontents} +% This is the main environment used in the document. +% \begin{macrocode} +\ProvideDocumentEnvironment { scontents } { } + { + \char_set_catcode_active:N \^^M + \@@_start_environment:w + } + { + \@@_stop_environment: + \@@_atend_environment: + } +% \end{macrocode} +% \end{macro} +% +% \subsubsection{The environment itself} +% +% The environment itself +% +%%^^A First \cs{@@_start_environment:w} +% \begin{macro}{\@@_start_environment:w,\@@_stop_environment:} +% Here we make |^^M| an active character so that the end of line can +% be ``seen'' to be used as a delimiter. First we check if the line +% directly after |\begin{scontents}| contains an optional argument +% enclosed in |[...]|, or other tokens. The trailing tokens are +% treated as junk and an error is raised. The +% \cs{@@_environment_inline:w} macro checks for those cases. +% \begin{macrocode} +\group_begin: + \char_set_catcode_active:N \^^M + \cs_new_protected:Npn \@@_start_environment:w #1 ^^M + { + \@@_environment_inline:w #1 \q_@@_mark + \group_begin: + \bool_if:NTF \l_@@_writing_bool + { + \use:c { filecontentsdef* } { \l_@@_fname_out_tl } + { \l_@@_macro_tmp_tl } ^^M + } + { \filecontentsdefmacro { \l_@@_macro_tmp_tl } ^^M } + } + \cs_new_protected:Npn \@@_stop_environment: + { + \bool_if:NTF \l_@@_writing_bool + { \endfilecontentsdef } + { \endfilecontentsdefmacro } + \group_end: + } +\group_end: +% \end{macrocode} +% \end{macro} +% +% \subsubsection{key val for environment} +% +% Define a |key=val| for environment \env{scontents} +% +%%^^A key val for environment scontents +% \begin{macro}{\@@_environment_inline:w,\@@_environment_keys:w, +% \@@_environment_junk:nw,\@@_environment_junk:xw} +% The macro \cs{@@_environment_inline:w} is called from the +% \env{scontents} environment with the tokens following the +% |\begin{scontents}|. If the immediate next token (ignoring spaces) +% is a |[|, then we look for an optional argument delimited by a |]|. +% All the remaining tokens are treated as junk and an error is raised +% if they are non-blank. +% \begin{macrocode} +\cs_new_protected:Npn \@@_environment_inline:w + { + \peek_charcode_ignore_spaces:NTF [ % ] + { \@@_environment_keys:w } + { + \@@_environment_junk:xw + { after~\c_backslash_str begin{scontents} } + } + } +\cs_new_protected:Npn \@@_environment_keys:w [ #1 ] + { + \keys_set_known:nn { scontents } {#1} + \@@_environment_junk:xw + { after~optional~argument~to~\c_backslash_str begin{scontents} } + } +\cs_new_protected:Npn \@@_environment_junk:nw #1 #2 \q_@@_mark + { + \tl_if_blank:nF {#2} + { \msg_error:nnnn { scontents } { junk-after-begin } {#1} {#2} } + } +\cs_generate_variant:Nn \@@_environment_junk:nw { x } +% \end{macrocode} +% \end{macro} +% +% \subsubsection{Recording of the content in the sequence} +% +% \begin{macro}{\@@_atend_environment:,\@@_stored_to_seq:} +% Finishes the environment by optionally calling \cs{@@_stored_to_seq:} +% and then clearing the temporary token list. +% +% The \cs{@@_stored_to_seq:} function replaces a carriage return +% (\textsc{ascii} 13) by a new line character (\textsc{ascii} 10) for +% optionally logging the contents of the current \env{scontents} +% environment. +% +%^^A TODO: Perhaps replace the regex by a delimited macro to improve +%^^A performance... Or temporarily redefine ^^M to mean ^^J... +%^^A Reply: Or maybe it is better to preserve the end of line with +%^^A \tex_newlinechar:D = 13 \scan_stop: +% \begin{macrocode} +\cs_new_protected:Npn \@@_atend_environment: + { + \bool_if:NT \l_@@_storing_bool + { + \@@_stored_to_seq: + \bool_if:NT \l_@@_print_env_bool + { \@@_getfrom_seq:nn { -1 } { \l_@@_name_seq_env_tl } } + } + \tl_clear:N \l_@@_macro_tmp_tl + } +\cs_gset_protected:Npn \@@_stored_to_seq: + { + \regex_replace_all:nnN { \^^M } { \^^J } \l_@@_macro_tmp_tl + \tl_log:N \l_@@_macro_tmp_tl + \@@_append_contents:Vx \l_@@_name_seq_env_tl + { \exp_not:N \tex_scantokens:D { \tl_use:N \l_@@_macro_tmp_tl } } + } +% \end{macrocode} +% \end{macro} +% +% \subsection{The \cs{Scontents} command} +% +% User command to stored content, adapted from +% \url{https://tex.stackexchange.com/a/500281/7832}. +% +%%^^A User command to stored content +% +% \begin{macro}{\Scontents,\@@_norm:n,\@@_verb:w} +% The \cs{Scontents} macro starts by parsing an optional argument and +% then delegates to \cs{@@_verb:w} or \cs{@@_norm:n} depending whether +% a star argument is present. +% +% \cs{@@_norm:n} grabs a normal argument, adds it to the |seq| varaible, +% and optionally prints it. +% +% \cs{@@_verb:w} grabs a verbatim argument using \pkg{xparse}'s |v| +% argument parser. +% +%^^A NOTE: Any particular reason why \keys_set_known:nn instead of just +%^^A \keys_set:nn? The latter reports if an unknown key is used... +%^^A Reply: The redirection of error messages has never worked well for me +%^^A perhaps it would be better to implement it. +% \begin{macrocode} +\ProvideDocumentCommand { \Scontents }{ !s !O{} } + { + \group_begin: + \IfNoValueF {#2} + { \keys_set_known:nn { scontents / Scontents } {#2} } + \IfBooleanTF{#1} + { \@@_verb:w } + { \@@_norm:n } + } +\cs_new_protected:Npn \@@_norm:n #1 + { + \exp_args:NV \@@_append_contents:nn \l_@@_name_seq_cmd_tl {#1} + \bool_if:NT \l_@@_print_cmd_bool + { \@@_getfrom_seq:nn { -1 } { \l_@@_name_seq_cmd_tl } } + \group_end: + } +\NewDocumentCommand { \@@_verb:w } { +v } + { + \tl_set:Nn \l_@@_temp_tl {#1} + \regex_replace_all:nnN { \^^M } { \^^J } \l_@@_temp_tl + \tl_log:N \l_@@_temp_tl + \exp_args:NVx \@@_append_contents:nn \l_@@_name_seq_cmd_tl + { \exp_not:N \tex_scantokens:D { \tl_use:N \l_@@_temp_tl } } + \bool_if:NT \l_@@_print_cmd_bool + { \@@_getfrom_seq:nn { -1 } { \l_@@_name_seq_cmd_tl } } + \group_end: + } +% \end{macrocode} +% \end{macro} +% +% \subsection{The command \cs{getstored}} +% +% +% \begin{macro}{\getstored} +% User command \cs{getstored} to extract stored content in |seq| +% (robust). +% \begin{macrocode} +\ProvideDocumentCommand { \getstored } { O{1} m } + { \@@_getfrom_seq:nn {#1} {#2} } +% \end{macrocode} +% \end{macro} +% +% \subsection{The \cs{typestored} command} +% +% This implementation is an adaptation taken from answer by Phelype Oleinik +% in (\url{https://tex.stackexchange.com/a/497651/7832}). +% +% \begin{macro}{\typestored,\@@_fcdef_print:N,\@@_xverb:w,verbatimsc} +% The \cs{typestored} commands fetches a buffer from memory, prints it +% to the log file, +%^^A NOTE: Perhaps this logging should be optional, with a key to switch +%^^A it on and off. +%^^A Reply:I used * because it's easier to associate it with \Scontents* +% and then calls \pkg{filecontentsdef}'s \tn{filecontentsdef@get} macro +% to read the contents of the token list and pass them to +% \cs{@@_fcdef_print:N}. +% \begin{macrocode} +\ProvideDocumentCommand { \typestored } { s O{1} m } + { + \group_begin: + \tl_set:Nx \l_@@_temp_tl { \@@_getfrom_seq:nn {#2} {#3} } + \tl_log:N \l_@@_temp_tl + \IfBooleanTF {#1} + { \bool_set_false:N \l_@@_typeverb_env_bool } + { \bool_set_true:N \l_@@_typeverb_env_bool } + \use:c { filecontentsdef@get } \@@_fcdef_print:N \l_@@_temp_tl + \group_end: + } +% \end{macrocode} +% The \cs{@@_fcdef_print:N} macro is defined with active carriage return +% (\textsc{ascii} 13) characters to mimick an actual verbatim environment +% ``on the loose''. The contents of the environment are placed in a +% \env{verbatimsc} environment and rescanned using \tn{scantokens}. +% \begin{macrocode} +\group_begin: + \char_set_catcode_active:N \^^M + \cs_new_protected:Npn \@@_fcdef_print:N #1 + { + \tl_if_blank:VT #1 + { \msg_error:nnn { scontents } { empty-variable } {#1} } + \cs_set_eq:NN \@@_fcdef_saved_EOL: ^^M + \cs_set_eq:NN ^^M \scan_stop: + \use:x + { + \exp_not:N \tex_scantokens:D + { + \exp_not:N \begin{verbatimsc} ^^M + \@@_strip_scantokens:N #1 + \bool_if:NF \l_@@_typeverb_env_bool { ^^M } + \g_@@_end_verbatimsc_tl + } + } + \cs_set_eq:NN ^^M \@@_fcdef_saved_EOL: + } +\group_end: +% \end{macrocode} +% Finally, the \env{verbatimsc} environment is defined. +%^^A An idea taken from spverbatim +% \begin{macrocode} +\use:x + { \cs_gset_protected:Npn \exp_not:N \@@_xverb:w ##1 \g_@@_end_verbatimsc_tl } + { #1 \end{verbatimsc} } +\ProvideDocumentEnvironment { verbatimsc } { } + { + \cs_set_eq:cN { @xverbatim } \@@_xverb:w + \verbatim + } + { } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{ +% \@@_strip_scantokens:N, +% \@@_strip_scantokens:n, +% \@@_if_scantokens:Nw, +% } +% The \cs{@@_strip_scantokens:n} (\cs{@@_strip_scantokens:N}) macro +% takes a token list (variable) as argument and examines it. If the +% argument token list is \emph{exactly} |\scantokens{|\meta{stuff}|}|, +% then the function returns \meta{stuff}, otherwise it returns the +% input token list without change. The token list is wrapped in +% \cs{exp_not:n} to avoid further expansion. +% \begin{macrocode} +\cs_new:Npn \@@_strip_scantokens:N #1 + { \exp_args:NV \@@_strip_scantokens:n #1 } +\cs_new:Npn \@@_strip_scantokens:n #1 + { + \tl_if_head_is_N_type:nTF {#1} + { + \@@_if_scantokens:NwTF #1 \q_@@_mark + { + \exp_args:No \tl_if_single_token:nTF { \use_none:nn #1 ? } + { \exp_not:o { \use_ii:nn #1 } } + { \exp_not:n {#1} } + } + { \exp_not:n {#1} } + } + { \exp_not:n {#1} } + } +\prg_new_conditional:Npnn \@@_if_scantokens:Nw #1#2 \q_@@_mark { TF } + { + \token_if_eq_meaning:NNTF \tex_scantokens:D #1 + { \prg_return_true: } + { \prg_return_false: } + } +% \end{macrocode} +% \end{macro} +% +% \subsection{The command \cs{setupsc}} +% +% User command \cs{setupsc} to setup module. +%%^^A User command to setup module +% \begin{macro}{\setupsc} +% A user-level wrapper for \cs{keys_set:nn}|{ scontents }| +% \begin{macrocode} +\ProvideDocumentCommand { \setupsc } { m } + { \keys_set:nn { scontents } {#1} } +% \end{macrocode} +% \end{macro} +% +% \subsection{The command meaningsc} +% +% \begin{macro}{\meaningsc} +% User command \cs{meaningsc} to see content stored in seq. +%^^A NOTE: Perhaps replace \cs{regex_replace_all:nnN} by something more +%^^A efficient... +%^^A Reply: I've only used it to avoid ΩΩ ... +% \begin{macrocode} +\ProvideDocumentCommand { \meaningsc } { O{1} m } + { + \group_begin: + \tl_set:Nx \l_@@_temp_tl { \@@_getfrom_seq:nn {#1} {#2} } + \tl_log:N \l_@@_temp_tl + \tl_set:Nx \l_@@_temp_tl { \@@_strip_scantokens:N \l_@@_temp_tl } + \regex_replace_all:nnN { \v{1,} } { } \l_@@_temp_tl + \ttfamily + \cs_replacement_spec:N \l_@@_temp_tl + \group_end: + } +% \end{macrocode} +% \end{macro} +% +% \subsection{The command \cs{countsc}} +% +% \begin{macro}{\countsc} +% User command \cs{countsc} to count number of contents stored in seq. +% \begin{macrocode} +\ProvideExpandableDocumentCommand { \countsc } { m } + { \seq_count:c { g_@@_seq_name_#1_seq } } +% \end{macrocode} +% \end{macro} +% +% \subsection{The command \cs{cleanseqsc}} +% +% \begin{macro}{\cleanseqsc} +% A user command \cs{cleanseqsc} to clear (remove) a defined seq +% \begin{macrocode} +\ProvideExpandableDocumentCommand { \cleanseqsc } { m } + { \seq_clear_new:c { g_@@_seq_name_#1_seq } } +% \end{macrocode} +% \end{macro} +% +% \subsection{Messages} +% Messages used throughout the package. +%%^^A Messages +% +% \begin{macrocode} +\msg_new:nnn { scontents } { junk-after-begin } + { + Junk~characters~#1~\msg_line_context: : + \\ \\ + #2 + } +\msg_new:nnn { scontents } { empty-stored-content } + { Empty~value~for~key~`getstored'~\msg_line_context:. } +\msg_new:nnn { scontents } { empty-variable } + { Variable~`#1'~empty~\msg_line_context:. } +% \end{macrocode} +% +% \subsection{Finish package} +% Finish package +%%^^A Finish package +% +% \begin{macrocode} +\file_input_stop: +% \end{macrocode} +% \iffalse +%</package> +% \fi +% \Finale diff --git a/Master/texmf-dist/source/latex/scontents/scontents.ins b/Master/texmf-dist/source/latex/scontents/scontents.ins new file mode 100644 index 00000000000..2b0d3865154 --- /dev/null +++ b/Master/texmf-dist/source/latex/scontents/scontents.ins @@ -0,0 +1,9 @@ +\input l3docstrip.tex +\keepsilent +\askforoverwritefalse +\nopreamble\nopostamble +\usedir{tex/latex/scontents} +\generate{ + \file{\jobname.sty}{\from{\jobname.dtx}{package}} +} +\endbatchfile diff --git a/Master/texmf-dist/tex/latex/scontents/scontents.sty b/Master/texmf-dist/tex/latex/scontents/scontents.sty new file mode 100644 index 00000000000..2f3dca7e604 --- /dev/null +++ b/Master/texmf-dist/tex/latex/scontents/scontents.sty @@ -0,0 +1,287 @@ +\RequirePackage{filecontentsdef}[2019/04/20] +\RequirePackage{l3keys2e} +\RequirePackage{xparse}[2019/05/03] +\ProvidesExplPackage{scontents}{2019/07/30}{1.0} + {Store LaTeX content in Sequences (l3seq)} +\@ifpackagelater { xparse } { 2019/05/03 } + { } + { + \PackageError { scontents } { Support~package~xparse~too~old } + { + You~need~to~update~your~installation~of~the~bundles~ + 'l3kernel'~and~'l3packages'.\MessageBreak + Loading~scontents~will~abort! + } + \tex_endinput:D + } +\keys_define:nn { scontents } + { + store-env .tl_set:N = \l__scontents_name_seq_env_tl, + store-env .initial:n = contents, + print-env .bool_set:N = \l__scontents_print_env_bool, + print-env .initial:n = false, + store-cmd .tl_set:N = \l__scontents_name_seq_cmd_tl, + store-cmd .initial:n = contents, + print-cmd .bool_set:N = \l__scontents_print_cmd_bool, + print-cmd .initial:n = false, + print-all .meta:n = { print-env = true , print-cmd = true }, + store-env .value_required:n = true, + store-cmd .value_required:n = true, + print-env .value_required:n = true, + print-cmd .value_required:n = true, + print-all .value_required:n = true + } +%%^^A Process options for pkg +\ProcessKeysOptions { scontents } +%%^^A Internal tl vars +\tl_new:N \l__scontents_macro_tmp_tl +\tl_new:N \l__scontents_fname_out_tl +\tl_new:N \l__scontents_temp_tl +%%^^A Internal bool vars +\bool_new:N \l__scontents_typeverb_env_bool +\bool_set_true:N \l__scontents_typevrb_env_bool +\bool_new:N \l__scontents_writing_bool +\bool_set_false:N \l__scontents_writing_bool +\bool_new:N \l__scontents_storing_bool +\bool_set_true:N \l__scontents_storing_bool +%%^^A Internal quarks +\quark_new:N \q__scontents_stop +\quark_new:N \q__scontents_mark +\tl_new:N \g__scontents_end_verbatimsc_tl +\tl_gset_rescan:Nnn + \g__scontents_end_verbatimsc_tl + { + \char_set_catcode_escape:N \| + \char_set_catcode_other:N \\ + \char_set_catcode_other:N \{ + \char_set_catcode_other:N \} + } + { \end{verbatimsc} } +%%^^A Add keys to scontents environnment +\keys_define:nn { scontents } + { + write-env .code:n = { + \bool_set_true:N \l__scontents_writing_bool + \tl_set:Nn \l__scontents_fname_out_tl {#1} + }, + write-out .code:n = { + \bool_set_false:N \l__scontents_storing_bool + \bool_set_true:N \l__scontents_writing_bool + \tl_set:Nn \l__scontents_fname_out_tl {#1} + }, + write-env .value_required:n = true, + write-out .value_required:n = true + } +%%^^A A sub/keys for command |\Scontents| +\keys_define:nn { scontents / Scontents } + { + print-cmd .meta:nn = { scontents } { print-cmd = #1 }, + store-cmd .meta:nn = { scontents } { store-cmd = #1 } + } +%%^^A Append content to seq +\cs_new_protected:Npn \__scontents_append_contents:nn #1#2 + { + \tl_if_blank:nT {#1} + { \msg_error:nn { scontents } { empty-store-cmd } } + \seq_if_exist:cF { g__scontents_seq_name_#1_seq } + { \seq_new:c { g__scontents_seq_name_#1_seq } } + \seq_gput_right:cn { g__scontents_seq_name_#1_seq } {#2} + } +\cs_generate_variant:Nn \__scontents_append_contents:nn { Vx } +\cs_new:Npn \__scontents_getfrom_seq:nn #1#2 + { \seq_item:cn { g__scontents_seq_name_#2_seq } {#1} } +%%^^A Define |scontents| whit [key=val] (delaying) +\ProvideDocumentEnvironment { scontents } { } + { + \char_set_catcode_active:N \^^M + \__scontents_start_environment:w + } + { + \__scontents_stop_environment: + \__scontents_atend_environment: + } +%%^^A First \cs{@@_start_environment:w} +\group_begin: + \char_set_catcode_active:N \^^M + \cs_new_protected:Npn \__scontents_start_environment:w #1 ^^M + { + \__scontents_environment_inline:w #1 \q__scontents_mark + \group_begin: + \bool_if:NTF \l__scontents_writing_bool + { + \use:c { filecontentsdef* } { \l__scontents_fname_out_tl } + { \l__scontents_macro_tmp_tl } ^^M + } + { \filecontentsdefmacro { \l__scontents_macro_tmp_tl } ^^M } + } + \cs_new_protected:Npn \__scontents_stop_environment: + { + \bool_if:NTF \l__scontents_writing_bool + { \endfilecontentsdef } + { \endfilecontentsdefmacro } + \group_end: + } +\group_end: +%%^^A key val for environment scontents +\cs_new_protected:Npn \__scontents_environment_inline:w + { + \peek_charcode_ignore_spaces:NTF [ % ] + { \__scontents_environment_keys:w } + { + \__scontents_environment_junk:xw + { after~\c_backslash_str begin{scontents} } + } + } +\cs_new_protected:Npn \__scontents_environment_keys:w [ #1 ] + { + \keys_set_known:nn { scontents } {#1} + \__scontents_environment_junk:xw + { after~optional~argument~to~\c_backslash_str begin{scontents} } + } +\cs_new_protected:Npn \__scontents_environment_junk:nw #1 #2 \q__scontents_mark + { + \tl_if_blank:nF {#2} + { \msg_error:nnnn { scontents } { junk-after-begin } {#1} {#2} } + } +\cs_generate_variant:Nn \__scontents_environment_junk:nw { x } +\cs_new_protected:Npn \__scontents_atend_environment: + { + \bool_if:NT \l__scontents_storing_bool + { + \__scontents_stored_to_seq: + \bool_if:NT \l__scontents_print_env_bool + { \__scontents_getfrom_seq:nn { -1 } { \l__scontents_name_seq_env_tl } } + } + \tl_clear:N \l__scontents_macro_tmp_tl + } +\cs_gset_protected:Npn \__scontents_stored_to_seq: + { + \regex_replace_all:nnN { \^^M } { \^^J } \l__scontents_macro_tmp_tl + \tl_log:N \l__scontents_macro_tmp_tl + \__scontents_append_contents:Vx \l__scontents_name_seq_env_tl + { \exp_not:N \tex_scantokens:D { \tl_use:N \l__scontents_macro_tmp_tl } } + } +%%^^A User command to stored content +\ProvideDocumentCommand { \Scontents }{ !s !O{} } + { + \group_begin: + \IfNoValueF {#2} + { \keys_set_known:nn { scontents / Scontents } {#2} } + \IfBooleanTF{#1} + { \__scontents_verb:w } + { \__scontents_norm:n } + } +\cs_new_protected:Npn \__scontents_norm:n #1 + { + \exp_args:NV \__scontents_append_contents:nn \l__scontents_name_seq_cmd_tl {#1} + \bool_if:NT \l__scontents_print_cmd_bool + { \__scontents_getfrom_seq:nn { -1 } { \l__scontents_name_seq_cmd_tl } } + \group_end: + } +\NewDocumentCommand { \__scontents_verb:w } { +v } + { + \tl_set:Nn \l__scontents_temp_tl {#1} + \regex_replace_all:nnN { \^^M } { \^^J } \l__scontents_temp_tl + \tl_log:N \l__scontents_temp_tl + \exp_args:NVx \__scontents_append_contents:nn \l__scontents_name_seq_cmd_tl + { \exp_not:N \tex_scantokens:D { \tl_use:N \l__scontents_temp_tl } } + \bool_if:NT \l__scontents_print_cmd_bool + { \__scontents_getfrom_seq:nn { -1 } { \l__scontents_name_seq_cmd_tl } } + \group_end: + } +\ProvideDocumentCommand { \getstored } { O{1} m } + { \__scontents_getfrom_seq:nn {#1} {#2} } +\ProvideDocumentCommand { \typestored } { s O{1} m } + { + \group_begin: + \tl_set:Nx \l__scontents_temp_tl { \__scontents_getfrom_seq:nn {#2} {#3} } + \tl_log:N \l__scontents_temp_tl + \IfBooleanTF {#1} + { \bool_set_false:N \l__scontents_typeverb_env_bool } + { \bool_set_true:N \l__scontents_typeverb_env_bool } + \use:c { filecontentsdef@get } \__scontents_fcdef_print:N \l__scontents_temp_tl + \group_end: + } +\group_begin: + \char_set_catcode_active:N \^^M + \cs_new_protected:Npn \__scontents_fcdef_print:N #1 + { + \tl_if_blank:VT #1 + { \msg_error:nnn { scontents } { empty-variable } {#1} } + \cs_set_eq:NN \__scontents_fcdef_saved_EOL: ^^M + \cs_set_eq:NN ^^M \scan_stop: + \use:x + { + \exp_not:N \tex_scantokens:D + { + \exp_not:N \begin{verbatimsc} ^^M + \__scontents_strip_scantokens:N #1 + \bool_if:NF \l__scontents_typeverb_env_bool { ^^M } + \g__scontents_end_verbatimsc_tl + } + } + \cs_set_eq:NN ^^M \__scontents_fcdef_saved_EOL: + } +\group_end: +\use:x + { \cs_gset_protected:Npn \exp_not:N \__scontents_xverb:w ##1 \g__scontents_end_verbatimsc_tl } + { #1 \end{verbatimsc} } +\ProvideDocumentEnvironment { verbatimsc } { } + { + \cs_set_eq:cN { @xverbatim } \__scontents_xverb:w + \verbatim + } + { } +\cs_new:Npn \__scontents_strip_scantokens:N #1 + { \exp_args:NV \__scontents_strip_scantokens:n #1 } +\cs_new:Npn \__scontents_strip_scantokens:n #1 + { + \tl_if_head_is_N_type:nTF {#1} + { + \__scontents_if_scantokens:NwTF #1 \q__scontents_mark + { + \exp_args:No \tl_if_single_token:nTF { \use_none:nn #1 ? } + { \exp_not:o { \use_ii:nn #1 } } + { \exp_not:n {#1} } + } + { \exp_not:n {#1} } + } + { \exp_not:n {#1} } + } +\prg_new_conditional:Npnn \__scontents_if_scantokens:Nw #1#2 \q__scontents_mark { TF } + { + \token_if_eq_meaning:NNTF \tex_scantokens:D #1 + { \prg_return_true: } + { \prg_return_false: } + } +%%^^A User command to setup module +\ProvideDocumentCommand { \setupsc } { m } + { \keys_set:nn { scontents } {#1} } +\ProvideDocumentCommand { \meaningsc } { O{1} m } + { + \group_begin: + \tl_set:Nx \l__scontents_temp_tl { \__scontents_getfrom_seq:nn {#1} {#2} } + \tl_log:N \l__scontents_temp_tl + \tl_set:Nx \l__scontents_temp_tl { \__scontents_strip_scantokens:N \l__scontents_temp_tl } + \regex_replace_all:nnN { \v{1,} } { } \l__scontents_temp_tl + \ttfamily + \cs_replacement_spec:N \l__scontents_temp_tl + \group_end: + } +\ProvideExpandableDocumentCommand { \countsc } { m } + { \seq_count:c { g__scontents_seq_name_#1_seq } } +\ProvideExpandableDocumentCommand { \cleanseqsc } { m } + { \seq_clear_new:c { g__scontents_seq_name_#1_seq } } +%%^^A Messages +\msg_new:nnn { scontents } { junk-after-begin } + { + Junk~characters~#1~\msg_line_context: : + \\ \\ + #2 + } +\msg_new:nnn { scontents } { empty-stored-content } + { Empty~value~for~key~`getstored'~\msg_line_context:. } +\msg_new:nnn { scontents } { empty-variable } + { Variable~`#1'~empty~\msg_line_context:. } +%%^^A Finish package +\file_input_stop: diff --git a/Master/tlpkg/bin/tlpkg-ctan-check b/Master/tlpkg/bin/tlpkg-ctan-check index 786d331a6e0..4011c35646f 100755 --- a/Master/tlpkg/bin/tlpkg-ctan-check +++ b/Master/tlpkg/bin/tlpkg-ctan-check @@ -605,7 +605,7 @@ my @TLP_working = qw( scale scalebar scalerel scanpages schedule schemabloc schemata sclang-prettifier schule schulschriften schwalbe-chess - sciposter scientific-thesis-cover + sciposter scientific-thesis-cover scontents scratch scratch3 scratchx screenplay screenplay-pkg scrjrnl scrlttr2copy scsnowman sdrt sduthesis diff --git a/Master/tlpkg/libexec/ctan2tds b/Master/tlpkg/libexec/ctan2tds index 6188fc81738..87916587cd1 100755 --- a/Master/tlpkg/libexec/ctan2tds +++ b/Master/tlpkg/libexec/ctan2tds @@ -2720,6 +2720,7 @@ my $core_latex = "$Master/texmf-dist/tex/latex"; 'psfragx' => 'latex', # requires interaction 'pxrubrica' => 'platex', 'schedule' => 'latex', # requires interaction + 'scontents' => 'etex', 'silence' => 'latex -translate-file=empty.tcx', # no 8-bit 'skdoc' => 'tex', 'svg' => 'etex -interaction=nonstopmode', diff --git a/Master/tlpkg/tlpsrc/collection-latexextra.tlpsrc b/Master/tlpkg/tlpsrc/collection-latexextra.tlpsrc index 3abebe7bf93..3a7014b4d85 100644 --- a/Master/tlpkg/tlpsrc/collection-latexextra.tlpsrc +++ b/Master/tlpkg/tlpsrc/collection-latexextra.tlpsrc @@ -982,6 +982,7 @@ depend scalebar depend scalerel depend scanpages depend schedule +depend scontents depend scrlttr2copy depend sdrt depend secdot diff --git a/Master/tlpkg/tlpsrc/scontents.tlpsrc b/Master/tlpkg/tlpsrc/scontents.tlpsrc new file mode 100644 index 00000000000..e69de29bb2d --- /dev/null +++ b/Master/tlpkg/tlpsrc/scontents.tlpsrc |