% \iffalse meta-comment %<*internal> \def\nameofplainTeX{plain} \ifx\fmtname\nameofplainTeX\else \expandafter\begingroup \fi % %<*install> \input l3docstrip.tex \keepsilent \askforoverwritefalse \nopreamble\nopostamble \usedir{tex/latex/scontents} \generate{% \file{\jobname.sty}{\from{\jobname.dtx}{package}}% }% % %\endbatchfile %<*internal> \usedir{source/latex/scontents} \generate{ \file{\jobname.ins}{\from{\jobname.dtx}{install}} } \ifx\fmtname\nameofplainTeX \expandafter\endbatchfile \else \expandafter\endgroup \fi % %<*driver> \documentclass[full]{l3doc} % imakeidx also opens a write stream for the .idx file, and that conflicts % with the one opened by l3doc. Here we close that write stream: \makeatletter \immediate\closeout\@indexfile \makeatother % and later we will copy the write stream opened by imakeidx into \@indexfile % so that entries written to both streams end up in the same file. \usepackage[top=0.5in,bottom=0.5in,left=2.0in,right=1in,footskip=0.2in,headsep=10pt]{geometry} \usepackage[osf,mono=false,scale=0.95,llscaled=0.95]{libertine} \usepackage{unicode-math} \setmathfont[Scale = 0.95]{latinmodern-math.otf} \usepackage[osf,scale=0.80,semibold]{sourcecodepro} \usepackage{fontawesome5} \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[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 undoes what \PageIndex does % \CodelineIndex tries to open another write stream for the index file. We don't % want that, so we temporarily make \makeindex a no-op: \let\ORGmakeindex\makeindex \def\makeindex{} \CodelineIndex \let\makeindex\ORGmakeindex \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[userdoc]{#1\actualchar#2|HP}} \indexsetup{level=\section,firstpagestyle=myheader} \makeindex[name=userdoc,options=-s gind.ist,columnsep=15pt,title={Index of Documentation}] \makeindex[options=-s gind.ist,columnsep=15pt,title={Index of Implementation}] % Now, after imakeidx opens the write stream for the index file, we copy % the reference to \@indexfile: \makeatletter \let\@indexfile\scontents@idxfile \makeatother \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 \meta[...]{...}, \marg[...]{...} and \oarg[...]{...} with color \ExplSyntaxOn % User level commands \NewDocumentCommand{\mymeta}{O{}m} { \userdoc_meta_generic:Nnn \userdoc_meta:n { #1 } { #2 } } \NewDocumentCommand{\mymarg}{O{}m} { \userdoc_meta_generic:Nnn \userdoc_marg:n { #1 } { #2 } } \NewDocumentCommand{\myoarg}{O{}m} { \userdoc_meta_generic:Nnn \userdoc_oarg:n { #1 } { #2 } } % Variables and keys \tl_new:N \l_userdoc_meta_font_tl \keys_define:nn { userdoc / mymeta } { type .choice:, type / tt .code:n = \tl_set:Nn \l_userdoc_meta_font_tl { \ttfamily }, type / rm .code:n = \tl_set:Nn \l_userdoc_meta_font_tl { \rmfamily }, type .initial:n = tt, cf .tl_set:N = \l_userdoc_meta_color_tl, cf .initial:n = black, ac .tl_set:N = \l_userdoc_meta_anglecolor_tl, ac .initial:n = black, sbc .tl_set:N = \l_userdoc_meta_brackcolor_tl, sbc .initial:n = black, cbc .tl_set:N = \l_userdoc_meta_bracecolor_tl, cbc .initial:n = black, } % Internal commands \cs_new_protected:Npn \userdoc_meta_generic:Nnn #1 #2 #3 { \group_begin: \keys_set:nn { userdoc / mymeta } { #2 } \color{ \l_userdoc_meta_color_tl } \l_userdoc_meta_font_tl #1 { #3 } % #1 is \userdoc_meta:n, \userdoc_marg:n or \userdoc_oarg:n \group_end: } \cs_new_protected:Npn \userdoc_meta:n #1 { \userdoc_meta_angle:n { \textlangle } \userdoc_meta_meta:n { #1 } \userdoc_meta_angle:n { \textrangle } } \cs_new_protected:Npn \userdoc_marg:n #1 { \userdoc_meta_brace:n { \textbraceleft } \userdoc_meta:n { #1 } \userdoc_meta_brace:n { \textbraceright } } \cs_new_protected:Npn \userdoc_oarg:n #1 { \userdoc_meta_brack:n { [ } \userdoc_meta:n { #1 } \userdoc_meta_brack:n { ] } } \cs_new_protected:Npn \userdoc_meta_meta:n #1 { \textnormal{\textit{#1}} } \cs_new_protected:Npn \userdoc_meta_angle:n #1 { \group_begin: \fontfamily{lmr}\selectfont \textcolor{\l_userdoc_meta_anglecolor_tl}{#1} \group_end: } \cs_new_protected:Npn \userdoc_meta_brace:n #1 { \group_begin: \color{\l_userdoc_meta_bracecolor_tl} #1 \group_end: } \cs_new_protected:Npn \userdoc_meta_brack:n #1 { \textcolor{\l_userdoc_meta_brackcolor_tl}{#1} } % \envexamp{m} \newsavebox{\boxexaenv} \NewDocumentCommand{\envexamp}{m} { \begin{lrbox}{\boxexaenv}% \begin{minipage}[t]{\marginparwidth}% \raggedright\ttfamily\small \textcolor{gray}{\textbackslash begin\{\textcolor{mypkgcolor}{\bfseries{#1}}\}\myoarg [type=tt,sbc=gray,ac=NavyBlue,cf=optcolor]{key=val}}\par% \hspace{0.5cm}\mymeta[ac=gray,cf=gray]{env ~ contents}\par% \textcolor{gray}{\textbackslash end\{{\textcolor{mypkgcolor}{\bfseries{#1}}}\}}\par \end{minipage}% \end{lrbox}% \usebox{\boxexaenv} } % \cmdexamp{s m o m o} \DeclareDocumentCommand{\cmdexamp}{s m o m o} { \group_begin: \small\ttfamily \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{black}{\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 fetamont 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}[key=val]...\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 \lstinline 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}, pdfsubject = {Documentation for \fileversion{} [\filedate] },% pdfcopyright = {\textcopyright 2019 by Pablo González}, pdfcontacturl = {https://github.com/pablgonz/scontents}, pdfkeywords = {contents, external files, expl3, xparse, l3seq, Store contents}, pdfstartview = {FitH},% bookmarksopenlevel = 1,% } % Configuration titleps and titlesec \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} {} {\thepage/\pageref{LastPage}} \sethead{\raisebox{0.75\baselineskip}{Documentation for \fileversion\space[\filedate]}} {} {\raisebox{0.75\baselineskip}{\scshape\small\S.\thesection\space\sectiontitle}} } \setlength{\headheight}{21pt}% \titlecontents{section}[0mm]{}% {\bfseries\contentspush{\makebox[5mm][l]{\thecontentslabel\hfill}}}% {\hspace*{-5mm}}% numberless {\hspace{0.25em}\titlerule*[6pt]{.}\contentspage}% \titlecontents{subsection}[5mm]{}% {\contentspush{\makebox[6mm][l]{\thecontentslabel\hfill}}} {\hspace*{-11mm}}% 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 \begin{document} \DocInput{\jobname.dtx} \end{document} % % \fi % % \title{ % \scalebox{1.025}{\mylogo}\\[2pt] % \Large % \textsf{Stores \hologo{LaTeX} contents}\\[3pt] % \fileversion{} --- \filedate\thanks{ % This file describes a documentation for \fileversion, last revised % \filedate.}\\[25pt] % \author{ % \large % \raisebox{-1pt}{\textcopyright}{}2019 by Pablo González % \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 memory % (sequences) using the \mypkg{l3seq} module of \mypkg{expl3}. The stored % content, including \emph{verbatim} material, can be used as many times % as desired in the document, additionally can be written to external files. % \end{abstract} % % \tableofcontents % % \setlength{\parskip}{3pt} % % \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, ideas were combined giving rise to this package. % % 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 % Phelype Oleinik who has collaborated and adapted a large part of the code and % all \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} % \label{sec:licence} % % 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{expl3}, \mypkg{xparse} 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 \texttt{scontents} package} % \label{sec:pkgscontents} % % \subsection{Description} % % The \mypkg*{scontents} package allows to store contents in memory (sequence) % or external files, provides a user interface style \myoarg{key = val} % along with the ability to store contents in sequences for later use in % different parts of the document. In some ways it works very much like % the \mypkg{filecontentsdef} package, with the difference that it preserves % the |TAB|s characters in the output files (see \ref{sec:tabcharacter}). % % The package is loaded in the usual way: % % \iffalse %<*example> % \fi \begin{examplecode}[frame=single] \usepackage{scontents} \end{examplecode} % \iffalse % % \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 % % \fi % % \subsection{The TAB character} % \label{sec:tabcharacter} % % In a standard \hologo{LaTeX} document, horizontal |TAB|s (\LKeyTab) typed % from the keyboard are treated as explicit spaces in most contexts. Some % users use this character to indented the source code of the document and % depending on the text editor used, some will use real |TAB|s (sometimes % called \enquote{hard tabs}), others with \enquote{soft tabs} % (\textvisiblespace\textvisiblespace or \textvisiblespace % \textvisiblespace\textvisiblespace\textvisiblespace) or both. % % At first glance it may seem the same, but the way in which |TAB|s (\enquote{hard tabs}) % are processed according to the context in which they are found within % a file, both in reading\footnote{Check the answer given by Ulrich Diez % in \href{https://tex.stackexchange.com/a/508103/7832}{Keyboard TAB % character in argument v (xparse)}.} and writing\footnote{Check the answer % given by Enrico Gregorio in \href{https://tex.stackexchange.com/a/58740/7832}{How to output a % tabulation into a file}.}, are different and may have adverse consequences. % % The behavior of this character for the \emph{stored} content can be % configured with the |widht-tab| key, but, these will be preserved by % writing an output file, unfortunately, dependent on the \hologo{TeX} % distribution you have and how the formats were initialized. % % With a \hologo{TeX}Live distribution, the formats for |latex|, |pdflatex| % and |lualatex| are prepared feeding the option |-translate-file=cp227.tcx|, % that makes the |TAB| character \enquote{printable}. To write a literal % |TAB| character using |xelatex| you must add the |-8bit| option on command % line, otherwise you will get \hologo{TeX}-|TAB|s (|^^I|) in the \mymeta{output file}. % % As a general recommendation \enquote{Do not use |TAB|s unless strictly % necessary}, for example within a verbatim environment that supports % this character such as |Verbatim| or |lstlisting| or when you want to % generate a |MakeFile| file. % % \subsection{Configuration of the options} % \label{sec:confopt} % % Most of the options can be passed directly to the package or using the % command the command \ics*{setupsc}. % % \vspace*{-10pt} % % \begin{function}{\setupsc} % \begin{syntax} % \cmdexamp{setupsc}{key=val} % \end{syntax} % % 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. % \end{function} % % \medskip % % \keyexamp{verb-font}{number}{ \textbackslash{}ttfamily } % Sets the font type used to display the stored content for the commands % \ics*{typestored} and \ics*{meaningsc}. This key is only available as % a package option or using \ics*{setupsc}. % % \subsection{Options Overview} % \label{sec:optover} % % \newcommand*{\xmark}{\textcolor{red}{✘}}% % \newcommand*{\cmark}{\textcolor{green}{✔}}% % % Summary table of available options. % % \setlength{\tabcolsep}{0.25em} % \begin{tabular}{cccccccc} % \toprule % \texttt{key} &package &\ics{setupsc} &\myenv*{scontents} &\ics*{Scontents} &\ics*{Scontents*} &\ics*{typestored} &\ics*{meaningsc}\\ % \midrule % \texttt{store-env} & \cmark & \cmark & \cmark & \xmark & \xmark & \xmark & \xmark \\ % \texttt{store-cmd} & \cmark & \cmark & \xmark & \cmark & \cmark & \xmark & \xmark \\ % \texttt{print-env} & \cmark & \cmark & \cmark & \xmark & \xmark & \xmark & \xmark \\ % \texttt{print-cmd} & \cmark & \cmark & \xmark & \cmark & \cmark & \xmark & \xmark \\ % \texttt{print-all} & \cmark & \cmark & \cmark & \xmark & \xmark & \xmark & \xmark \\ % \texttt{write-env} & \xmark & \xmark & \cmark & \xmark & \xmark & \xmark & \xmark \\ % \texttt{write-out} & \xmark & \xmark & \cmark & \xmark & \xmark & \xmark & \xmark \\ % \texttt{width-tab} & \cmark & \cmark & \xmark & \xmark & \xmark & \cmark & \cmark \\ % \texttt{force-eol} & \cmark & \cmark & \cmark & \xmark & \cmark & \xmark & \xmark \\ % \texttt{verb-font} & \cmark & \cmark & \xmark & \xmark & \xmark & \xmark & \xmark \\ % \bottomrule % \end{tabular} % % \section{User interface} % \label{sec:interface} % % The \emph{user interface} provided by this package consists in \myenv*{scontents} % environment, \ics*{Scontents} and \ics*{Scontents*} commands to stored % contents and \ics*{getstored} command to get the \meta{stored content} % along with other utilities described in this documentation. % % \subsection{The environment \env{scontents}} % \label{sec:scontents} % % \vspace*{-10pt} % % \begin{function}{scontents} % \begin{syntax} % \envexamp{scontents} % \end{syntax} % % The \myenv*{scontents} environment allows you to save the content to memory % or external files in a similar way to the package \mypkg{filecontentsdef}. % This allows you to record content, including \emph{verbatim}, for later reuse. % % Some considerations to keep in mind, |\begin{scontents}| and |\end{scontents}| % must be on different lines, the \myoarg{key=val} options must be passed on % \mymeta{one line} right after starting the environment and |TAB|s characters % are preserved when writing an \mymeta{external file}. % \end{function} % % The environment can be nested complying with the above considerations % and bearing in mind that within it should not be written literally, as a % comment or within verbatim environments |\begin{scontents}| and |\end{scontents}|. % For example: % % \iffalse %<*example> % \fi \begin{examplecode}[frame=single] \begin{scontents}[store-env=outer] This text is in the outermost environment. \begin{scontents}[store-env=inner] This text is found in the most inner environment. \end{scontents} This text is in the outermost environment. \end{scontents} \end{examplecode} % \iffalse % % \fi % % \subsection*{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 \mymeta{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{force-eol}{true\textbar false}{false} % This key is only necessary if the last line inside the environment is % |\end{Verbatim}| or the |\end{...}| of some environment created with % the package \mypkg{fancyvrb}. This adds an extra line to the \ics*{typestored} % output. % % \medskip % % \keyexamp{write-env}{file.ext}{not used} % In addition to storing the content of the environment will write this % in an external \mymeta{file.ext}, if \mymeta{file.ext} exists it will % be overwritten. The \mymeta{file.ext} will be created in the working % directory, relative or absolute paths are not supported, the way the % external \mymeta{file.ext} is recorded is similar to that produced by % \myenv{filecontents*} environment. If the content within the environment % has literal |TAB|s they will be recorded in \mymeta{file.ext}. % % To write a literal |TAB| character using |xelatex| you must add the |-8bit| % option on command line, otherwise you will get \hologo{TeX}-|TAB|s (|^^I|) in % the \mymeta{output file}. % % \medskip % % \keyexamp{write-out}{file.ext}{not used} % It will write the contents in an external \mymeta{file.ext}, but, it % will not store the contents of this one. The \mymeta{file.ext} will be % created in the working directory, relative or absolute paths are not % supported. The way the external \mymeta{file.ext} is recorded is similar % to that produced by \myenv{filecontents*} environment. If the content % within the environment has literal |TAB|s they will be recorded in % \mymeta{file.ext}. % % To write a literal |TAB| character using |xelatex| you must add the |-8bit| % option on command line, otherwise you will get \hologo{TeX}-|TAB|s (|^^I|) in % the \mymeta{output file}. % % \subsection{The command \cs{Scontents}} % \label{sec:Scontents} % % \vspace*{-10pt} % % \begin{function}{\Scontents} % \begin{syntax} % \cmdexamp{Scontents}[key=val]{argument} % \cmdexamp*{Scontents}[key=val]{argument} % \cmdexamp*{Scontents}[key=val]{argument}[del] % \end{syntax} % \end{function} % % The \ics*{Scontents} command reads the \mymeta{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. % % The \ics*{Scontents*} command reads the \mymeta{argument} under verbatim % category code regimen. If its first delimiter is a brace, it will be % assumed that the \mymeta{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}. Blank lines are preserved, % escaped |\{| and |\}| must also be balanced if the argument is used % with braces and |TAB|s characters typed from the keyboard are converted % into spaces. % % Both versions can be used anywhere in the document and cannot be used % as an \mymeta{argument} for other command. % % \subsection*{Options for command} % \label{sec:optcmdsc} % % The command options (including starred 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}. % % \medskip % % \keyexamp{force-eol}{true\textbar{}false}{false} % This key is only necessary if the last line inside the command is % |\end{Verbatim}| or the |\end{...}| of some environment created with % the package \mypkg{fancyvrb}. This adds an extra line to the \ics*{typestored} % output. % % \subsection{The command \cs{getstored}} % \label{sec:getstored} % % \vspace*{-10pt} % % \begin{function}{\getstored} % \begin{syntax} % \cmdexamp{getstored}[index]{seq name} % \end{syntax} % \end{function} % % The command \ics*{getstored} gets the content stored in \meta{seq name} % according to the \mymeta{index} in which it was stored. The command is % robust 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} % % \vspace*{-10pt} % % \begin{function}{\typestored} % \begin{syntax} % \cmdexamp{typestored}[index, width-tab=number]{seq name} % \end{syntax} % \end{function} % % The command \ics*{typestored} internally places the content stored in % the \meta{seq name} into the \myenv*{verbatimsc} environment. The \mymeta{index} % number corresponds to the position in which the content is stored in % the \meta{seq name}. % % If the optional argument is not passed it defaults to the last element % saved in the \meta{seq name}. % \medskip % % \keyexamp{width-tab}{number}{ 1 } % Establishes the equivalence in \mymeta{spaces} for the character |TAB| % typed from the keyboard. The value must be a \mymeta{positive integer}. % % \subsection{The environment \env{verbatimsc}} % \label{sec:verbatimsc} % % \vspace*{-10pt} % % \begin{function}{verbatimsc} % Internal environment used by \cs{typestored} to display \meta{verbatim style} % contents. % \end{function} % % 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 \myenv*{verbatimsc} environment can be customized 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 % % \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 % % \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 % % \fi % % \section{Other commands provided} % % \subsection{The command \cs{meaningsc}} % \label{sec:meaningsc} % % \vspace*{-10pt} % % \begin{function}{\meaningsc} % \begin{syntax} % \cmdexamp{meaningsc}[index, width-tab=number]{seq name} % \end{syntax} % The command \ics*{meaningsc} executes \ics{meaning} on the content stored % in \meta{seq name}. The \mymeta{index} number corresponds to the position % in which the content is stored in the \meta{seq name}. If the optional % argument is not passed it defaults to the last element saved in the \meta{seq name}. % \end{function} % % \medskip % % \keyexamp{width-tab}{number}{ 1 } % Establishes the equivalence in \mymeta{spaces} for the character |TAB| % typed from the keyboard. The value must be a \mymeta{positive integer}. % % \subsection{The command \cs{countsc}} % \label{sec:countsc} % % \vspace*{-10pt} % % \begin{function}{\countsc} % \begin{syntax} % \cmdexamp{countsc}{seq name} % \end{syntax} % The command \ics*{countsc} count a number of contents stored in \meta{seq name}. % \end{function} % % \subsection{The command \cs{cleansc}} % \label{sec:cleansc} % % \vspace*{-10pt} % % \begin{function}{\cleanseqsc} % \begin{syntax} % \cmdexamp{cleansc}{seq name} % \end{syntax} % The command \ics*{cleansc} remove all contents stored in \meta{seq name}. % \end{function} % % \newpage % % \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} % % \iffalse %<*example> % \fi \begin{scontents}[write-out=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{scontents} % \iffalse % % \fi % % 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} % % \iffalse %<*example> % \fi \begin{scontents}[write-out=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.} \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{scontents} % \iffalse % % \fi % % 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} % % \iffalse %<*example> % \fi \begin{scontents}[write-out=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} \typestored[1]{tikz} \typestored[2]{tikz} \typestored[3]{tikz} \end{document} \end{scontents} % \iffalse % % \fi % % 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} % % \iffalse %<*example> % \fi \begin{scontents}[write-out=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{scontents} % \iffalse % % \fi % % 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} % % \iffalse %<*example> % \fi \begin{scontents}[write-out=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.| \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{scontents} % \iffalse % % \fi % % 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} % % \iffalse %<*example> % \fi \begin{scontents}[write-out=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+{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{scontents} % \iffalse % % \fi % % 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} % % \iffalse %<*example> % \fi \begin{scontents}[write-out=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+{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{scontents} % \iffalse % % \fi % % 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} % % \iffalse %<*example> % \fi \begin{scontents}[write-out=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+{scontents}+ \par \begin{scontents}[write-env=usingtab.tex,force-eol=true] 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*+ % Real TABs here :) \begin{Verbatim}[obeytabs, showtabs, tab=\rightarrowfill, tabcolor=red,showspaces, spacecolor=blue] No tab One real tab Two real Tab plus one tab \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[1]{contents}\par \getstored[2]{contents} \section{Test \texttt{\textbackslash typestored}} \typestored[1]{contents} \typestored[2]{contents} \end{document} \end{scontents} % \iffalse % % \fi % % 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} % % \section{Change history} % \label{sec:changes} % % In this section you will find some (not all) of the changes in \mypkg*{scontents} % development, from the first public implementation using the \mypkg{filecontentsdef} % package to the current version with only \mypkg{expl3}. % % \setlist[itemize,1]{label=\textendash, wide=0.5em, nosep, noitemsep, leftmargin=10pt} % \newlength\descrwidth % \settowidth{\descrwidth}{\textsf{v1.0, (ctan), 2019/07/30} } % % \begin{description}[font=\small\sffamily, wide=0pt, style=multiline, leftmargin=\descrwidth, nosep, noitemsep] % \item [\fileversion{} (ctan), \filedate] % \begin{itemize} % \item The environment can now nest. % \item Added \verb+force-eol+, \verb+verb-font+ and \verb+width-tab+ keys. % \item The extra space has been removed when you run \verb+\getstored+. % \item Internal code has been rewritten more efficiently. % \item Remove \verb+\typestored*+. % \item Remove \verb+filecontentsdef+ dependency. % \item Changing \verb+\regex_replace_all:+ for \verb+\tl_replace_all:+. % \end{itemize} % \item [v1.2 (ctan), 2019/08/28] % \begin{itemize} % \item Restructuring of documentation. % \item Added copy of \verb+\tex_scantokens:D+. % \end{itemize} % \item [v1.1 (ctan), 2019/08/12] % \begin{itemize} % \item Extension of documentation. % \item Replace \verb+\tex_endinput:D+ by \verb+\file_input_stop:+. % \end{itemize} % \item [v1.0 (ctan), 2019/07/30] % \begin{itemize} % \item First public release, % \end{itemize} % \end{description} % % \newpage % % \printindex[userdoc] % % \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. % %%^^A Initial declaration of the package % \begin{macrocode} \RequirePackage{l3keys2e} \RequirePackage{xparse}[2019/05/28] \ProvidesExplPackage{scontents}{2019/09/24}{1.3} {Stores LaTeX contents in memory or files} % \end{macrocode} % % A check to make sure that \pkg{xparse} is not too old % %%^^A Checking the version of xparse % \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! } \file_input_stop: } % \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. % %%^^A Common keys available as package options % \begin{macrocode} \keys_define:nn { scontents } { store-env .tl_set:N = \l_@@_name_seq_env_tl, store-env .initial:n = contents, store-env .value_required:n = true, store-cmd .tl_set:N = \l_@@_name_seq_cmd_tl, store-cmd .initial:n = contents, store-cmd .value_required:n = true, verb-font .tl_set:N = \l_@@_verb_font_tl, verb-font .initial:n = \ttfamily, verb-font .value_required:n = true, print-env .bool_set:N = \l_@@_print_env_bool, print-env .initial:n = false, print-env .default:n = true, print-cmd .bool_set:N = \l_@@_print_cmd_bool, print-cmd .initial:n = false, print-cmd .default:n = true, force-eol .bool_set:N = \l_@@_forced_eol_bool, force-eol .initial:n = false, force-eol .default:n = true, width-tab .int_set:N = \l_@@_tab_width_int, width-tab .initial:n = 1, width-tab .value_required:n = true, print-all .meta:n = { print-env = #1 , print-cmd = #1 }, print-all .default:n = true, unknown .code:n = { \@@_parse_unknown_key:n {#1} } } % \end{macrocode} % % We process the keys as options passed on to the package. % %%^^A Process options for package % \begin{macrocode} \ProcessKeysOptions { scontents } % \end{macrocode} % % \subsection{Internal variables} % % Now we declare the internal variables we will use. % % \begin{macro}{\l_@@_macro_tmp_tl,\l_@@_fname_out_tl,\l_@@_temp_tl, % \l_@@_file_tl,\g_@@_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, \cs{l_@@_file_tl} holds the contents % of an environment as it's being read, and \cs{l_@@_temp_tl} and % \cs{g_@@_temp_tl} are generic temporary token lists. % %%^^A Internal token list vars % \begin{macrocode} \tl_new:N \l_@@_macro_tmp_tl \tl_new:N \l_@@_fname_out_tl \tl_new:N \l_@@_temp_tl \tl_new:N \l_@@_file_tl \tl_new:N \g_@@_temp_tl % \end{macrocode} % \end{macro} % % \begin{macro}{\l_@@_seq_item_int,\l_@@_env_nesting_int,\l_@@_tmpa_int} % \cs{l_@@_seq_item_int} stores the index in the sequence of the item % requested to \cs{typestored} or \cs{meaningsc}. \cs{l_@@_env_nesting_int} % stores the current nesting level of the \env{scontents} environment. % %%^^A Internal int vars % \begin{macrocode} \int_new:N \l_@@_seq_item_int \int_new:N \l_@@_env_nesting_int \int_new:N \l_@@_tmpa_int % \end{macrocode} % \end{macro} % % \begin{macro}{\l_@@_writing_bool,\l_@@_storing_bool} % The boolean \cs{l_@@_writing_bool} keeps track of whether 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. % %%^^A Internal bool vars % \begin{macrocode} \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} % % \begin{macro}{\g_@@_end_verbatimsc_tl,\c_@@_end_env_tl} % A token list to match when ending \env{verbatimsc} and \env{scontents} % environments. % %%^^A A token list to match \env{verbatimsc} and \env{scontents} % \begin{macrocode} \tl_new:N \g_@@_end_verbatimsc_tl \tl_gset_rescan:Nnn \g_@@_end_verbatimsc_tl { \char_set_catcode_other:N \\ \char_set_catcode_other:N \{ \char_set_catcode_other:N \} } { \end{verbatimsc} } \tl_const:Nx \c_@@_end_env_tl { \c_backslash_str end \c_left_brace_str scontents \c_right_brace_str } % \end{macrocode} % \end{macro} % % % \begin{macro}{\q_@@_stop,\q_@@_mark} % Some quarks used along the code as macro delimiters. % %%^^A Internal quarks % \begin{macrocode} \quark_new:N \q_@@_stop \quark_new:N \q_@@_mark % \end{macrocode} % \end{macro} % % \begin{macro}{\l_@@_file_iow} % An output stream for saving the contents of an environment to a file. % %%^^A Stream for saving the contents % \begin{macrocode} \iow_new:N \l_@@_file_iow % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_rescan_tokens:n} % \cs{tl_rescan:nn} doesn't fit the needs of this package because % it does not allow catcode changes inside the argument, so verbatim % commands used inside one of \mypkg*{scontents}'s commands/environments % will not work. Here we create a private copy of \cs{tex_scantokens:D} % which will serve our purposes. % %%^^A Copy of scantokens in expl3 % \begin{macrocode} \cs_new_protected:Npn \@@_rescan_tokens:n #1 { \tex_scantokens:D {#1} } \cs_generate_variant:Nn \@@_rescan_tokens:n { V, x } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_tab:,\@@_par:} % Control sequences to replace tab (|^^I|) and form feed (|^^L|) characters. % %%^^A Internal \tab and \par % \begin{macrocode} \cs_new:Npx \@@_tab: { \c_space_tl } \cs_new:Npn \@@_par: { ^^J ^^J } % \end{macrocode} % \end{macro} % % \begin{macro}{\tl_remove_once:NV,\tl_replace_all:Nxx, % \tl_replace_all:Nxn,\tl_replace_all:Nnx,\tl_if_empty:fTF} % Some nonstandard variants. % %%^^A Some nonstandard variants % \begin{macrocode} \cs_generate_variant:Nn \tl_remove_once:Nn { NV } \cs_generate_variant:Nn \tl_replace_all:Nnn { Nx, Nxx, Nnx } \prg_generate_conditional_variant:Nnn \tl_if_empty:n { f } { TF } % \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 }, force-eol .meta:nn = { scontents } { force-eol = #1 } } % \end{macrocode} % % \subsection{Handling undefined keys} % % \begin{macro}{\@@_parse_unknown_key:n,\@@_parse_unknown_key:nn} % The commands \cs{typestored} and \cs{meaningsc} accept an optional % argument for setting the \texttt{width-tab} to print the stored % contents. However their optional argument also contains the number % of the item to retrieve from the stored sequence. To avoid the % awkward \verb|\typestored[][]{...}| syntax, we'll make the % commands have a single optional argument which is processed by % \pkg{l3keys}, and the unknown keys are brought here to % \cs{@@_parse_unknown_key:n} to process. % % The key is stored in the token list variable \cs{l_keys_key_tl}, and % the value (if any) is passed as argument to this function. % % First we check if the key is an integer using \cs{int_to_roman:n}. % If it is, we check that the value passed to the key is blank % (otherwise something odd as |1=1| might have been used). If everything % is correct, then set the value of the integer which holds the index. % Otherwise raise an error about an unknown option. % %%^^A Parse unknown keys % \begin{macrocode} \cs_new_protected:Npn \@@_parse_unknown_key:n #1 { \exp_args:NV \@@_parse_unknown_key:nn \l_keys_key_tl {#1} } \cs_new_protected:Npn \@@_parse_unknown_key:nn #1 #2 { \tl_if_empty:fTF { \int_to_roman:n { -0 #1 } } { \tl_if_blank:nTF {#2} { \int_set:Nn \l_@@_seq_item_int {#1} } { \msg_error:nnnn { scontents } { key-value-unknown } {#1} {#2} } } { \tl_if_blank:nTF {#2} { \msg_error:nnn { scontents } { key-unknown } {#1} } { \msg_error:nnnn { scontents } { key-value-unknown } {#1} {#2} } } } % \end{macrocode} % \end{macro} % % \subsection{Programming of the sequences} % % \begin{macro}{\@@_append_contents:nn,\@@_getfrom_seq:nn,\@@_getfrom_seq:nnn} % 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. % %%^^A Programming of the sequences % \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_if_exist:cTF { g_@@_seq_name_#2_seq } { \exp_args:Nf \@@_getfrom_seq:nnn { \seq_count:c { g_@@_seq_name_#2_seq } } {#1} {#2} } { \msg_expandable_error:nnn { scontents } { undefined-storage } {#2} } } \cs_new:Npn \@@_getfrom_seq:nnn #1 #2 #3 { \bool_lazy_or:nnTF { \int_compare_p:nNn {#2} = { 0 } } { \int_compare_p:nNn { \int_abs:n {#2} } > {#1} } { \msg_expandable_error:nnnnn { scontents } { index-out-of-range } {#2} {#3} {#1} } { \seq_item:cn { g_@@_seq_name_#3_seq } {#2} } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_store_to_seq:NN} % The \cs{@@_store_to_seq:NN} writes the recorded contents % in |#1| to the log and stores it in |#2|. % %%^^A Storing content in sequences % \begin{macrocode} \cs_new_protected:Npn \@@_store_to_seq:NN #1 #2 { \tl_log:N #1 \@@_append_contents:Vx #2 { \exp_not:V #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}. % % % \begin{macro}{scontents} % This is the main environment used in the document. % %%^^A Definition of {scontents}[key=val] env % \begin{macrocode} \NewDocumentEnvironment { scontents } { } { \char_set_catcode_active:N \^^M \@@_start_environment:w } { \@@_stop_environment: \@@_atend_environment: } % \end{macrocode} % \end{macro} % % \subsubsection{key val for environment} % % Define a |key=val| for environment \env{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. % %%^^A Test [key=val] for environment scontents % \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{The environment itself} % % \begin{macro}{\@@_start_environment:w,\@@_stop_environment:} % Here we make |^^I|, |^^L|, and |^^M| active characters so that the end of % line can be ``seen'' to be used as a delimiter, and TeX doesn't try to % eliminate space-like characters. 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. % % \cs{@@_start_environment:w} calls the \cs{@@_file_tl_write_start:V} % function, which will then read the contents of the environment and % optionally store them in a token list or write to an external file. % % When that's done, \cs{@@_file_write_stop:N} does the cleanup and the % read token list is smuggled out of the verbatim group. This part of % the code is inspired and adapted from the code of the package \pkg{xsimverb} % by Clemens Niederberger. % %^^A Hm... Apparently this is not the verbatim group, but one level above. Is %^^A this group really necessary? %^^A Reply : Maybe the groups aren't in the right places, but when you remove %^^A them it just gives you errors...(test-pkg-current.tex) % %%^^A First start_environment/stop_environment % \begin{macrocode} \group_begin: \char_set_catcode_active:N \^^I \char_set_catcode_active:N \^^L \char_set_catcode_active:N \^^M \cs_new_protected:Npn \@@_start_environment:w #1 ^^M { \@@_environment_inline:w #1 \q_@@_mark \@@_make_control_chars_active: \group_begin: \@@_file_tl_write_start:V \l_@@_fname_out_tl } \cs_new_protected:Npn \@@_stop_environment: { \@@_file_write_stop:N \l_@@_macro_tmp_tl \exp_args:NNNV \group_end: \tl_set:Nn \l_@@_macro_tmp_tl \l_@@_macro_tmp_tl } % \end{macrocode} % \end{macro} % % \begin{macro}{ % \@@_file_tl_write_start:n, % \@@_file_tl_write_start:V, % \@@_verb_processor_iterate:w, % \@@_file_write_stop:N, % \@@_remove_leading_nl:n, % \@@_remove_leading_nl:w, % } % This is the main macro to collect the contents of a verbatim environment. % The macro starts a group, opens the output file, if necessary, sets verbatim % catcodes, and then issues |^^M| (set equal to \cs{@@_ret:w}) to read the % environment line by line until reaching its end. The output token list will % be appended with an active |^^J| character and the line just read, and this % line is written to the output file, if any. At the end of the environment % the output file is closed (if it was open), and the output token list is % smuggled out of the verbatim group. A leading |^^M| is removed from the % token list using \cs{@@_remove_leading_nl:n} (which expects an active |^^M| % token at the head of the token list; a low level TeX error is raised % otherwise). % %%^^A File write start/File write stop % \begin{macrocode} \cs_new_protected:Npn \@@_file_tl_write_start:n #1 { \group_begin: \bool_if:NT \l_@@_writing_bool { \file_if_exist:nTF {#1} { \msg_warning:nnx { scontents } { rewriting-file } {#1} } { \msg_warning:nnx { scontents } { writing-file } {#1} } \iow_open:Nn \l_@@_file_iow {#1} } \tl_clear:N \l_@@_file_tl \seq_map_function:NN \l_char_special_seq \char_set_catcode_other:N \int_step_function:nnN { 128 } { 255 } \char_set_catcode_letter:n \cs_set_protected:Npx \@@_ret:w ##1 ^^M { \exp_not:N \@@_verb_processor_iterate:w ##1 \c_@@_end_env_tl \c_@@_end_env_tl \exp_not:N \q_@@_stop } \@@_make_control_chars_active: \@@_ret:w } \use:x { \cs_new:Npn \exp_not:N \@@_verb_processor_iterate:w ##1 \c_@@_end_env_tl ##2 \c_@@_end_env_tl ##3 \exp_not:N \q_@@_stop } { \tl_if_blank:nTF {#3} { \@@_analyse_nesting:n {#1} \@@_verb_processor_output:n {#1} } { \@@_if_nested:TF { \@@_nesting_decr: \@@_verb_processor_output:x { \exp_not:n {#1} \c_@@_end_env_tl \exp_not:n {#2} } } { \tl_if_blank:nF {#1} { \@@_verb_processor_output:n {#1} } \cs_set_protected:Npx \@@_ret:w { \exp_not:N \end{scontents} \bool_lazy_or:nnF { \tl_if_blank_p:n {#2} } { \str_if_eq_p:ee {#2} { \c_percent_str } } { \msg_warning:nnn { scontents } { rescanning-text } {#2} \@@_rescan_tokens:n {#2} } } \char_set_active_eq:NN ^^M \@@_ret:w } } ^^M } \cs_new_protected:Npn \@@_file_write_stop:N #1 { \bool_if:NT \l_@@_writing_bool { \iow_close:N \l_@@_file_iow } \use:x { \group_end: \bool_if:NT \l_@@_storing_bool { \tl_set:Nn \exp_not:N #1 { \exp_args:NV \@@_remove_leading_nl:n \l_@@_file_tl \bool_if:NT \l_@@_forced_eol_bool { \exp_not:N ^^J } } } } } \cs_new:Npn \@@_remove_leading_nl:n #1 { \exp_not:o { \@@_remove_leading_nl:w #1 } } \cs_new:Npn \@@_remove_leading_nl:w ^^J { } % \end{macrocode} % \end{macro} % % \begin{macro}{ % \@@_verb_processor_output:n, % \@@_verb_processor_output:x, % \@@_analyse_nesting:n, % \@@_analyse_nesting:w, % \@@_nesting_decr:, % \@@_use_none_delimit_by_q_stop:w, % } % \begin{macro}[TF]{\@@_if_nested:} % \cs{@@_verb_processor_output:n} does the output of each line read, % to a token list and to a file, depending on the booleans % \cs{l_@@_writing_bool} and \cs{l_@@_storing_bool}. % % \cs{@@_analyse_nesting:n} looks for nested \cs{begin}|{scontents}| % and adds to a \cs{l_@@_env_nesting_int} counter. The \cs{@@_if_nested:} % conditional tests if we're in a nested environment, and % \cs{@@_nesting_decr:} reduces the nesting level, if an \cs{end}|{scontents}| % is found. % % Multiple \cs{end}|{scontents}| in the same line are not supported... % \begin{macrocode} \cs_new_protected:Npn \@@_verb_processor_output:n #1 { \bool_if:NT \l_@@_writing_bool { \iow_now:Nn \l_@@_file_iow {#1} } \bool_if:NT \l_@@_storing_bool { \tl_put_right:Nn \l_@@_file_tl { ^^J #1 } } } \cs_generate_variant:Nn \@@_verb_processor_output:n { x } \cs_new_protected:Npx \@@_analyse_nesting:n #1 { \int_zero:N \l_@@_tmpa_int \exp_not:N \@@_analyse_nesting:w #1 \c_backslash_str begin \c_left_brace_str \exp_not:N \q_@@_mark \c_right_brace_str \exp_not:N \q_@@_stop \int_compare:nNnT { \l_@@_tmpa_int } > { 1 } { \msg_warning:nn { scontents } { multiple-begin } } } \use:x { \cs_new_protected:Npn \exp_not:N \@@_analyse_nesting:w ##1 \c_backslash_str begin \c_left_brace_str ##2 \c_right_brace_str } { \if_meaning:w \q_@@_mark #2 \exp_after:wN \use_i:nn \else: \exp_after:wN \use_ii:nn \fi: { \@@_use_none_delimit_by_q_stop:w } { \str_if_eq:eeT {#2} {scontents} { \int_incr:N \l_@@_env_nesting_int \int_incr:N \l_@@_tmpa_int \@@_analyse_nesting:w } \@@_analyse_nesting:w } } \cs_new_protected:Npn \@@_nesting_decr: { \int_decr:N \l_@@_env_nesting_int } \prg_new_protected_conditional:Npnn \@@_if_nested: { TF } { \int_compare:nNnTF { \l_@@_env_nesting_int } > { \c_zero_int } { \prg_return_true: } { \prg_return_false: } } \cs_new:Npn \@@_use_none_delimit_by_q_stop:w #1 \q_@@_stop { } \group_end: \cs_generate_variant:Nn \@@_file_tl_write_start:n { V } % \end{macrocode} % \end{macro} % \end{macro} % % \subsubsection{Recording of the content in the sequence} % % \begin{macro}{\@@_atend_environment:} % Finishes the environment by optionally calling \cs{@@_store_to_seq:} % and then clearing the temporary token list. % %%^^A Second atend_environment/stored_to_seq % \begin{macrocode} \cs_new_protected:Npn \@@_atend_environment: { \bool_if:NT \l_@@_storing_bool { \@@_store_to_seq:NN \l_@@_macro_tmp_tl \l_@@_name_seq_env_tl } \bool_if:NT \l_@@_print_env_bool { \tl_gset_eq:NN \g_@@_temp_tl \l_@@_macro_tmp_tl \tl_gput_right:NV \g_@@_temp_tl \c_percent_str \group_insert_after:N \@@_rescan_tokens:V \group_insert_after:N \g_@@_temp_tl } \tl_clear: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}. % % \begin{macro}{\Scontents,\@@_norm_arg:n,\@@_verb_arg:w} % The \cs{Scontents} macro starts by parsing an optional argument and % then delegates to \cs{@@_verb_arg:w} or \cs{@@_norm_arg:n} depending whether % a star argument is present. % % \cs{@@_norm_arg:n} grabs a normal argument, adds it to the |seq| varaible, % and optionally prints it. % % \cs{@@_verb_arg: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. % %%^^A User command \Scontents to stored content % \begin{macrocode} \NewDocumentCommand { \Scontents }{ !s !O{} } { \group_begin: \IfNoValueF {#2} { \keys_set_known:nn { scontents / Scontents } {#2} } \char_set_catcode_active:n { 9 } \IfBooleanTF {#1} { \@@_verb_arg:w } { \@@_norm_arg:n } } \cs_new_protected:Npn \@@_norm_arg:n #1 { \exp_args:NV \@@_append_contents:nn \l_@@_name_seq_cmd_tl {#1} \bool_if:NT \l_@@_print_cmd_bool { \@@_rescan_tokens:n {#1} } \group_end: } \NewDocumentCommand { \@@_verb_arg:w } { +v } { \tl_set:Nx \l_@@_temp_tl { \exp_not:n {#1} \bool_if:NT \l_@@_forced_eol_bool { \exp_not:N ^^J } } \tl_replace_all:Nxx \l_@@_temp_tl { \iow_char:N \^^M } { \iow_char:N \^^J } \@@_store_to_seq:NN \l_@@_temp_tl \l_@@_name_seq_cmd_tl \bool_if:NT \l_@@_print_cmd_bool { \@@_rescan_tokens:V \l_@@_temp_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). % %%^^A User command \getstored to get content % \begin{macrocode} \NewDocumentCommand { \getstored } { O{1} m } { \group_begin: \@@_rescan_tokens:x { \@@_getfrom_seq:nn {#1} {#2} \c_percent_str } \group_end: } % \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,\@@_verb_print:N,\@@_xverb:w,verbatimsc} % The \cs{typestored} commands fetches a buffer from memory, prints it % to the log file, and then calls \cs{@@_verb_print:N}. % %%^^A User command \typestored to verbatimized content % \begin{macrocode} \NewDocumentCommand { \typestored } { o m } { \group_begin: \int_set:Nn \l_@@_seq_item_int { 1 } \IfValueT {#1} { \keys_set:nn { scontents } {#1} } \tl_set:Nx \l_@@_temp_tl { \exp_args:NV \@@_getfrom_seq:nn \l_@@_seq_item_int {#2} } \tl_log:N \l_@@_temp_tl \tl_if_empty:NF \l_@@_temp_tl { \@@_verb_print:N \l_@@_temp_tl } \group_end: } % \end{macrocode} % The \cs{@@_verb_print:N} macro is defined with active carriage return % (\textsc{ascii} 13) characters to mimick an actual verbatim environment % \enquote{on the loose}. The contents of the environment are placed in a % \env{verbatimsc} environment and rescanned using \cs{@@_rescan_tokens:x}. % %%^^A Internal verb_print:N, need to verbatimized content % \begin{macrocode} \group_begin: \char_set_catcode_active:N \^^M \cs_new_protected:Npn \@@_verb_print:N #1 { \tl_if_blank:VT #1 { \msg_error:nnn { scontents } { empty-variable } {#1} } \cs_set_eq:NN \@@_verb_print_EOL: ^^M \cs_set_eq:NN ^^M \scan_stop: \cs_set_eq:cN { do@noligs } \@@_do_noligs:N \@@_rescan_tokens:x { \exp_not:N \begin{verbatimsc} ^^M \exp_not:V #1 ^^M \g_@@_end_verbatimsc_tl } \cs_set_eq:NN ^^M \@@_verb_print_EOL: } \group_end: % \end{macrocode} % % Finally, the \env{verbatimsc} environment is defined. % %%^^A Definition of verbatimsc environment % \begin{macrocode} \cs_new_protected:Npn \@@_xverb: { \char_set_catcode_active:n { 9 } \char_set_active_eq:nN { 9 } \@@_tabs_to_spaces: \@@_xverb:w } \use:x { \cs_new_protected:Npn \exp_not:N \@@_xverb:w ##1 \g_@@_end_verbatimsc_tl } { #1 \end{verbatimsc} } \NewDocumentEnvironment { verbatimsc } { } { \cs_set_eq:cN { @xverbatim } \@@_xverb: \verbatim } { } % \end{macrocode} % \end{macro} % % \subsection{Some auxiliaries} % % \begin{macro}{\@@_tabs_to_spaces:} % In a verbatim context the |tab| character is made active and set % equal to \cs{@@_tabs_to_spaces:}, to produce as many spaces as % the |width-tab| key was set to. % %%^^A Tab to space % \begin{macrocode} \cs_new:Npn \@@_tabs_to_spaces: { \prg_replicate:nn { \l_@@_tab_width_int } { ~ } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_do_noligs:N} % \cs{@@_do_noligs:N} is an alternative definition for \LaTeXe's % \cs{do@noligs} which makes sure to not consume following space % tokens. The \LaTeXe{} version ends with \cs{char}|`#1|, which % leaves \TeX{} still looking for an \meta{optional~space}. % This version uses \cs{char_generate:nn} to ensure that doesn't % happen. % %%^^A Patch do_noligs for ligatures % \begin{macrocode} \cs_new:Npn \@@_do_noligs:N #1 { \char_set_catcode_active:N #1 \char_set_active_eq:Nc #1 { @@_active_char_ \token_to_str:N #1 : } \cs_set:cpx { @@_active_char_ \token_to_str:N #1 : } { \mode_leave_vertical: \tex_kern:D \c_zero_dim \char_generate:nn { `#1 } { 12 } } } % \end{macrocode} % \end{macro} % % \begin{macro}{ % \@@_set_active_eq:NN, % \@@_make_control_chars_active:, % } % Shortcut definitions for common catcode changes. % %%^^A Common catcode changes % \begin{macrocode} \cs_new_protected:Npn \@@_set_active_eq:NN #1 { \char_set_catcode_active:N #1 \char_set_active_eq:NN #1 } \cs_new_protected:Npn \@@_make_control_chars_active: { \@@_set_active_eq:NN \^^I \@@_tab: \@@_set_active_eq:NN \^^L \@@_par: \@@_set_active_eq:NN \^^M \@@_ret:w } % \end{macrocode} % \end{macro} % % \subsection{The command \cs{setupsc}} % % User command \cs{setupsc} to setup module. % % \begin{macro}{\setupsc} % A user-level wrapper for \cs{keys_set:nn}|{ scontents }|. % %%^^A User command \setupsc % \begin{macrocode} \NewDocumentCommand { \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 User command \meaningsc % \begin{macrocode} \NewDocumentCommand { \meaningsc } { o m } { \group_begin: \int_set:Nn \l_@@_seq_item_int { 1 } \IfValueT {#1} { \keys_set:nn { scontents } {#1} } \@@_meaningsc:n {#2} \group_end: } \group_begin: \char_set_catcode_active:N \^^I \cs_new_protected:Npn \@@_meaningsc:n #1 { \tl_set:Nx \l_@@_temp_tl { \exp_args:NV \@@_getfrom_seq:nn \l_@@_seq_item_int {#1} } \tl_replace_all:Nxn \l_@@_temp_tl { \iow_char:N \^^J } { ~ } \tl_log:N \l_@@_temp_tl \tl_use:N \l_@@_verb_font_tl \tl_replace_all:Nnx \l_@@_temp_tl { ^^I } { \@@_tabs_to_spaces: } \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|. % %%^^A User command \countsc % \begin{macrocode} \NewExpandableDocumentCommand { \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|. % %%^^A User command \cleanseqsc % \begin{macrocode} \NewDocumentCommand { \cleanseqsc } { m } { \seq_clear_new:c { g_@@_seq_name_#1_seq } } % \end{macrocode} % \end{macro} % % \subsection{Messages} % % Messages used throughout the package. % %%^^A Messages used throughout the package % \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:. } \msg_new:nnn { scontents } { rewriting-file } { Overwriting ~ file ~ `#1' } \msg_new:nnn { scontents } { writing-file } { Writing ~ file ~ `#1' } \msg_new:nnn { scontents } { rescanning-text } { Rescanning~text~`#1'~after~\c_backslash_str end{scontents}~\msg_line_context:.} \msg_new:nnn { scontents } { multiple-begin } { Multiple~\c_backslash_str begin{scontents}~\msg_line_context:.} \msg_new:nnn { scontents } { tab-to-space } { Tab~has~been~converted~to~Blank~Space } \msg_new:nnn { scontents } { feed-to-space } { Form~Feed~has~been~converted~to~Blank~Space } \msg_new:nnnn { scontents } { key-unknown } { The~key~'#1'~is~unknown~and~is~being~ignored. } { The~module~'scontents'~does~not~have~a~key~called~'#1'.\\ Check~that~you~have~spelled~the~key~name~correctly. } \msg_new:nnnn { scontents } { key-value-unknown } { The~key~'#1'~to~which~you~passed~'#2'~is~unknown~and~is~being~ignored. } { The~module~'scontents'~does~not~have~a~key~called~'#1'.\\ Check~that~you~have~spelled~the~key~name~correctly. } \msg_new:nnn { scontents } { undefined-storage } { Storage~named~'#1'~is~not~defined. } \msg_new:nnn { scontents } { index-out-of-range } { \int_compare:nNnTF {#1} = { 0 } { Index~of~sequence~cannot~be~zero. } { Index~'#1'~out~of~range~for~'#2'.~ \int_compare:nNnTF {#1} > { 0 } { Max = } { Min = -} #3. } } % \end{macrocode} % % \subsection{Finish package} % % Finish package % %%^^A Finish package :) % \begin{macrocode} \file_input_stop: % \end{macrocode} % \iffalse % % \fi % \Finale