From e0c6872cf40896c7be36b11dcc744620f10adf1d Mon Sep 17 00:00:00 2001 From: Norbert Preining Date: Mon, 2 Sep 2019 13:46:59 +0900 Subject: Initial commit --- macros/latex/contrib/scontents/README.md | 31 + macros/latex/contrib/scontents/scontents.dtx | 1844 ++++++++++++++++++++++++++ macros/latex/contrib/scontents/scontents.pdf | Bin 0 -> 198211 bytes 3 files changed, 1875 insertions(+) create mode 100644 macros/latex/contrib/scontents/README.md create mode 100644 macros/latex/contrib/scontents/scontents.dtx create mode 100644 macros/latex/contrib/scontents/scontents.pdf (limited to 'macros/latex/contrib/scontents') diff --git a/macros/latex/contrib/scontents/README.md b/macros/latex/contrib/scontents/README.md new file mode 100644 index 0000000000..c446c1bf8d --- /dev/null +++ b/macros/latex/contrib/scontents/README.md @@ -0,0 +1,31 @@ +## scontents — Stores LaTeX contents in memory or files +- Version: 1.2 +- Date: 2019/08/28 +- Author: Pablo González + +## Description +The `scontents` package stores valid `LaTeX` code in memory (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) + +## Installation + +The package `scontents` is present in `TeXLive` and `MiKTeX`, use the +package manager to install. For a manual installation, put `scontents.dtx` +in your working directory and run `tex scontents.dtx`. + +## 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.pdf (documentation) +- scontents.dtx (master file that produced all files) diff --git a/macros/latex/contrib/scontents/scontents.dtx b/macros/latex/contrib/scontents/scontents.dtx new file mode 100644 index 0000000000..9084a7ea35 --- /dev/null +++ b/macros/latex/contrib/scontents/scontents.dtx @@ -0,0 +1,1844 @@ +% \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} + +%^^A------------------- ONLY FOR DOCUMENTATION ------------------------%% +%^^A Colors for options +\definecolor{optcolor}{rgb}{0.281,0.275,0.485} +\definecolor{mypkgcolor}{RGB}{0,128,128}% +%^^A Custom \meta[...]{...}, \marg[...]{...} and \oarg[...]{...} with color +\ExplSyntaxOn +%^^A 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 } + } +%^^A 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, + } +%^^A 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} + } + +%^^A \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} + } + +%^^A \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}}% + } + +%^^A \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}}% + } + +%^^A \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}}% + } + } + +%^^A \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}} + } + } + +%^^A \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 + +%^^A 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 +%^^A 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 + +%^^A Don't copy numbers in code example +\newcommand*{\noaccsupp}[1]{\BeginAccSupp{ActualText={}}#1\EndAccSupp{}} + +%^^A 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 + +%^^A \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 + +%^^A \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} + } + +%^^A Set default style +\lstset{style=inline} + +%^^A Get file info +\GetFileInfo{\jobname.sty} + +%^^A 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 = {filecontents, filecontentsdef, xparse, expl3, l3seq, Store contents}, + pdfstartview = {FitH},% + bookmarksopenlevel = 1,% + } + +%^^A 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}% + +%^^A 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}) 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{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 +% 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{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 \texttt{scontents} package} +% \label{sec:pkgscontents} +% +% \subsection{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. +% +% \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 +% +% \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{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}. +% +% \vspace*{-10pt} +% +% \begin{function}{\setupsc} +% \begin{syntax} +% \cmdexamp{setupsc}{key=val} +% \end{syntax} +% +% The command \ics*{setupsc} configures the options in a global way, +% for \ics*{Scontents}, \ics*{Scontents*} and environment \myenv*{scontents}. +% it can be used both in the preamble and in the body of the document +% as many times as desired. +% \end{function} +% +% \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{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 encapsulates the \myenv{filecontentsdef*} and +% \myenv{filecontentsdefmacro} environments provided by the \mypkg{filecontentsdef} +% package. This allows you to record content including verbatim for later reuse. +% \end{function} +% +% 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. +% +% \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 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} +% +% The command to store content directly in memory, the star version allows to save +% \meta{verbatim} contents. +% +% \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 \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. +% +% 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} +% +% \subsection*{Options for command} +% \label{sec:optcmdsc} +% +% 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} +% +% \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 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]{seq name} +% \cmdexamp*{typestored}[index]{seq name} +% \end{syntax} +% \end{function} +% +% 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. +% +% 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}. +% +% \subsection{The environment \env{verbatimsc}} +% \label{sec:verbatimsc} +% +% \vspace*{-10pt} +% +% \begin{function}{verbatimsc} +% Internal environment used by \cs{typestored} and \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 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 +% +% \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]{seq name} +% \end{syntax} +% 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}. +% \end{function} +% +% \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} +% +% \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} +% +% \section{Change history} +% \label{sec:changes} +% +% \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 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. +% \begin{macrocode} +\RequirePackage{filecontentsdef}[2019/04/20] +\RequirePackage{l3keys2e} +\RequirePackage{xparse}[2019/05/28] +\ProvidesExplPackage{scontents}{2019/08/28}{1.2} + {Stores LaTeX contents in memory or files} +% \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! + } + \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. +% \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} +% +%%^^A Internal quarks +% \begin{macro}{\@@_rescan_tokens:w} +% \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: +% \begin{macrocode} +\cs_new_eq:NN \@@_rescan_tokens:w \tex_scantokens:D +% \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_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} +\NewDocumentEnvironment { 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_new_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 \@@_rescan_tokens:w { \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} +\NewDocumentCommand { \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 \@@_rescan_tokens:w { \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} +\NewDocumentCommand { \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} +\NewDocumentCommand { \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 \@@_rescan_tokens:w + { + \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} } +\NewDocumentEnvironment { 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 \@@_rescan_tokens:w #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} +\NewDocumentCommand { \setupsc } { m } + { \keys_set:nn { scontents } {#1} } +% \end{macrocode} +% \end{macro} +% +% \subsection{The command meaningsc} +% +% \begin{macro}[do-not-index=\v]{\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} +\NewDocumentCommand { \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} +\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 +% \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 +% +% \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 +% +% \fi +% +% \Finale diff --git a/macros/latex/contrib/scontents/scontents.pdf b/macros/latex/contrib/scontents/scontents.pdf new file mode 100644 index 0000000000..6e78f883be Binary files /dev/null and b/macros/latex/contrib/scontents/scontents.pdf differ -- cgit v1.2.3