Auflistungen innerhalb von Makro

Auflistungen innerhalb von Makro

Ich versuche, eine Möglichkeit zu finden, ein Makro zu erstellen, mit dem ich die Ausgabe eines Befehls demonstriere und dann den Befehl über einen lstinlineBefehl zeige. Ich habe gelesen, dass ich die Sonderzeichen (wie {und }) maskieren muss, und frage mich nun, ob es eine Möglichkeit gibt, dies automatisch zu tun. Ich bin mir nicht sicher, ob das überhaupt möglich ist.

\commandExample{\qty{1.2}{\meter}}Im Idealfall würde der BefehlOutput:1.2 m - Code:\qty{1.2}{\meter}

MWE:

\documentclass{report}
\usepackage{graphicx}
\usepackage{xcolor}
\usepackage{siunitx}
\usepackage{listings}

\definecolor{lightgrey}{rgb}{0.9,0.9,0.9}
\definecolor{darkgreen}{rgb}{0,0.6,0}

\lstset{language=[LaTeX]TeX,
  caption           = {Missing Caption}
  ,label            = {lst:missingLabel}
  ,basicstyle       = \footnotesize\ttfamily %\footnotesize % \small\ttfamily
  ,frame            = shadowbox%
  ,numbers          = left%
  ,breaklines       = true%
  ,keywordstyle     = \color{darkgreen}%
  ,commentstyle     = \color{red}%
  ,tabsize          = 2%
  ,backgroundcolor  = \color{lightgrey}%
  %,texcsstyle       = {*\bf\color{blue}}%
  %,otherkeywords    = $, \{, \}, \[, \]%
  ,morekeywords     = {includegraphics }%
  ,moretexcs    =  {graphicspath}%
  }

\NewDocumentCommand{\commandExample}{m}{%
  Output:#1 - Code:\lstinline{#1}} 

\begin{document}

\commandExample{begin}.

\unit{\meter}

%\commandExample{\unit{\meter}} % This line causes it to crash

\end{document}

Antwort1

Ich würde das Argument wörtlich übernehmen und \tl_rescan:nnfür den Schriftsatz verwenden.

\documentclass{report}
\usepackage{graphicx}
\usepackage{xcolor}
\usepackage{siunitx}
\usepackage{listings}

\definecolor{lightgrey}{rgb}{0.9,0.9,0.9}
\definecolor{darkgreen}{rgb}{0,0.6,0}

\lstset{language=[LaTeX]TeX,
  caption           = {Missing Caption}
  ,label            = {lst:missingLabel}
  ,basicstyle       = \footnotesize\ttfamily
  ,frame            = shadowbox
  ,numbers          = left
  ,breaklines       = true
  ,keywordstyle     = \color{darkgreen}
  ,commentstyle     = \color{red}
  ,tabsize          = 2
  ,backgroundcolor  = \color{lightgrey}
  ,texcsstyle       = {*\bfseries\color{blue}}
  %,otherkeywords    = {$, \{, \}, \[, \]}
  ,morekeywords     = {includegraphics,unit}
  ,moretexcs    =  {graphicspath}%
  }

\ExplSyntaxOn
\NewDocumentCommand{\commandExample}{v}
 {
  Output:~\tl_rescan:nn {} {#1} ~ - ~ Code:~\lstinline{#1}
 }
\ExplSyntaxOff

\begin{document}

\commandExample{\unit{\meter}}

\commandExample{\textit{word}}

\end{document}

Bildbeschreibung hier eingeben

Antwort2

Allgemeinder von egreg bereitgestellte Codeist meinem Code vorzuziehen.

\mathescape=trueAber der Mathescape-Mechanismus, der innerhalb über aktiviert werden soll und der es ermöglicht, innerhalb des Arguments von durch Verschachtelung zwischen in \lstsetden Mathematikmodus zu wechseln , ist defekt, wenn er direkt auf das Argument vom Typ v angewendet wird.\lstinline$...$\lstinline

Wenn Mathescape aktiviert ist, \lstinline{$x^2+y^2=2^2$}erhalten Sie bei dem Befehl zahlreiche Musterfehlermeldungen, ! Undefined control sequence. \lst@arg ->$xfalls es $x^2+y^2=2^2$als Argument vom Typ v tokenisiert wurde.

Wenn Sie die Mathescape-Funktion im realen Szenario also nicht benötigen, empfehle ich die Verwendung des Codes von egreg.

Wenn Sie die Mathescape-Funktion im realen Szenario benötigen, ändern Sie entweder die Antwort von egreg so, dass \commandExampledas Argument gemäß dem entsprechenden Kategoriecode-Regime gelesen und tokenisiert wird, oder versuchen Sie einen Ansatz, bei dem „ \scantokensoder“ auch \tl_rescan:nnauf die übergebenen Token angewendet wird .\lstinline


Ein kleines Problem ist: Bei älteren LaTeX-Distributionen bietet Ihr Code keine Definition für \unitund \meter. Im folgenden Beispiel werden daher stattdessen die Befehle \siund \metreverwendet.

Ein Problem ist: Eine Besonderheit von \lstinlineist, dass das Argument von \lstinlinenormalerweise nicht zwischen {und verschachtelt werden kann, }wenn es selbst auch enthält {. In diesem Fall muss das Argument zwischen einem Zeichen verschachtelt werden, das nicht im Argument vorkommt. Das \lstinline{\unit{\meter}}würde also nicht funktionieren, aber Sie müssten etwas wie tun \lstinline|\unit{\meter}|. (Ein weiterer Trick, der in der Antwort von egreg verwendet wird, besteht darin, das Argument von \lstinlineunter dem verbatim-catcode-regime zu tokenisieren, sodass es in jedem Fall weder {Kategorie 1 noch }Kategorie 2 enthält. Aber v-type-category-code-régime verletzt einige Funktionen von \lstinline– zumindest die Mathescape-Funktion.)

Ein weiteres Problem besteht darin, dass TeX erwartet, dass das Argument von \lstinlineunter einem anderen Kategoriecode-Regime tokenisiert wird. \lstinlineÄndert daher vorübergehend das Kategoriecode-Regime, um die zu seinem Argument gehörenden Token aus dem Token-Stream zu erfassen. \lstinlineverlässt sich darauf, dass TeX aus der .tex-Eingabedatei lesen und die zum Argument gehörenden Token unter dem geänderten Kategoriecode-Regime tokenisieren muss, damit sie aus dem Token-Stream erfasst werden können. \lstinlineFunktioniert daher nur auf Benutzerebene/oberster Ebene. \lstinlineFunktioniert nicht, wenn Argumente übergeben werden, nachdem sie unter unverändertem Kategoriecode-Regime tokenisiert wurden, wie dies beispielsweise der Fall wäre, wenn Aufrufe von \lstinlinein die Definitionstexte anderer Makros eingefügt werden, die Argumente unter unverändertem Kategoriecode-Regime erfassen und sie an weitergeben \lstinline.

Dieses Problem lässt sich bis zu einem gewissen Grad umgehen, indem Ihr Makro \commandExampleselbst das Kategoriecode-Regime ändert, bevor es die Argumente erfasst und sie dann an weitergibt \lstinline, verschachtelt in \scantokens{...%}.

Hierdurch entsteht jedoch ein weiteres Problem: Weder LaTeX 2ε noch expl3 noch xparse bieten einen Verbatim-Argument-Typ, mit dem Sie das Verbatim-Trennzeichen beibehalten und weitergeben können.

Daher wird im folgenden Beispiel der Befehl \UDcollectverbargbereitgestellt, der zum wörtlichen Catcode-Regime wechselt und das Argument sowohl ohne als auch verschachtelt zwischen dem wörtlichen Trennzeichen erfasst, sodass diese Dinge ordnungsgemäß zur weiteren Verarbeitung weitergegeben werden können.

\makeatletter
%%======================Code for \UDcollectverbarg=============================
%% \UDcollectverbarg{<mandatory 1>}{<mandatory 2>}|<verbatim arg>|
%% 
%% reads <verbatim arg> under verbatim-catcode-regime and delivers:
%%
%%    <mandatory 1>{<mandatory 2>{<verbatim arg>}{|<verbatim arg>|}}
%%
%% Instead of verbatim-delimiter | the <verbatim arg> can be nested in braces.
%% You cannot use percent or spaces or horizontal tab as verbatim-delimiter.
%%
%% You can use <mandatory 1> for nesting calls to \UDcollectverbarg.
%% <mandatory 2> gets the <verbatim arg> twice: Once without verbatim-delimiters/braces,
%% once surrounded by verbatim-delimiters/braces.
%% Reason: When you feed it to \scantokens you don't need the verbatim-delimiters.
%%         When you use it for writing to temporary files and reading back,
%%         you need them.
%%=============================================================================
%% Check whether argument is empty:
%%=============================================================================
\@ifdefinable\UD@stopromannumeral{\chardef\UD@stopromannumeral=`\^^00}%
%%
%% \UD@CheckWhetherNull{<Argument which is to be checked>}%
%%                     {<Tokens to be delivered in case that argument
%%                       which is to be checked is empty>}%
%%                     {<Tokens to be delivered in case that argument
%%                       which is to be checked is not empty>}%
%%
%% The gist of this macro comes from Robert R. Schneck's \ifempty-macro:
%% <https://groups.google.com/forum/#!original/comp.text.tex/kuOEIQIrElc/lUg37FmhA74J>
\newcommand\UD@CheckWhetherNull[1]{%
  \romannumeral\expandafter\@secondoftwo\string{\expandafter
  \@secondoftwo\expandafter{\expandafter{\string#1}\expandafter
  \@secondoftwo\string}\expandafter\@firstoftwo\expandafter{\expandafter
  \@secondoftwo\string}\expandafter\UD@stopromannumeral\@secondoftwo}{%
  \expandafter\UD@stopromannumeral\@firstoftwo}%
}%
%%=============================================================================
\newcommand\UDcollectverbarg[2]{%
  \begingroup
  \let\do\@makeother % <- this and the next line switch to
  \dospecials        %    verbatim-category-code-régime.
  \catcode`\{=1      % <- give opening curly brace the usual catcode so a 
                     %    curly-brace-balanced argument can be gathered in
                     %    case of the first thing of the verbatimized-argument 
                     %    being a curly opening brace.
  \catcode`\ =10     % <- give space and horizontal tab the usual catcode so \UD@collectverbarg
  \catcode`\^^I=10   %    cannot catch a space or a horizontal tab as its 4th undelimited argument.
                     %    (Its 4th undelimited argument denotes the verbatim-
                     %     syntax-delimiter in case of not gathering a
                     %     curly-brace-nested argument.)
  \catcode`\%=14     % <- make percent comment.
  \kernel@ifnextchar\bgroup
  {% seems a curly-brace-nested argument is to be caught:
    \catcode`\}=2    % <- give closing curly brace the usual catcode also.
    \UD@collectverbarg{#1}{#2}{}%
  }{% seems an argument with verbatim-syntax-delimiter is to be caught:
    \do\{% <- give opening curly brace the verbatim-catcode again.
    \UD@collectverbarg{#1}{#2}%
  }%
}%
\newcommand\UD@collectverbarg[3]{%
  \do\ %   <- Now that \UD@collectverbarg has the delimiter or
  \do\^^I%    emptiness in its 4th arg, give space and horizontal tab
         %    the verbatim-catcode again.
  \do\^^M% <- Give the carriage-return-character the verbatim-catcode.
  \do\%%   <- Give the percent-character the verbatim-catcode.
  \long\def\@tempb##1#3{%
    \def\@tempb{##1}%
    \UD@CheckWhetherNull{#3}{%
      \def\@tempc{{##1}}%
    }{%
      \def\@tempc{#3##1#3}%
    }%
    \@onelevel@sanitize\@tempb % <- Turn characters into their "12/other"-pendants.
                               %    This may be important with things like the 
                               %    inputenc-package which may make characters 
                               %    active/which give them catcode 13(active).
    \@onelevel@sanitize\@tempc
    \expandafter\expandafter\expandafter\UD@@collectverbarg% <- this "spits out the result.
    \expandafter\expandafter\expandafter{%
    \expandafter\@tempb\expandafter}%
    \expandafter{\@tempc}{#1}{#2}%
  }%
  \@tempb
}%
\newcommand\UD@@collectverbarg[4]{%
  \endgroup
  #3{#4{#1}{#2}}%
}%
%%================= End of code for \UDcollectverbarg =========================
\makeatother
%%

\documentclass{report}
\usepackage{graphicx}
\usepackage{xcolor}
\usepackage{siunitx}
\usepackage{listings}

\definecolor{lightgrey}{rgb}{0.9,0.9,0.9}
\definecolor{darkgreen}{rgb}{0,0.6,0}

\lstset{language=[LaTeX]TeX,
  % !!! Let's enable the mathescape-feature to test if it works:
  mathescape=true,
  % 
  caption           = {Missing Caption}
  ,label            = {lst:missingLabel}
  ,basicstyle       = \footnotesize\ttfamily %\footnotesize % \small\ttfamily
  ,frame            = shadowbox%
  ,numbers          = left%
  ,breaklines       = true%
  ,keywordstyle     = \color{darkgreen}%
  ,commentstyle     = \color{red}%
  ,tabsize          = 2%
  ,backgroundcolor  = \color{lightgrey}%
  %,texcsstyle       = {*\bf\color{blue}}%
  %,otherkeywords    = $, \{, \}, \[, \]%
  ,morekeywords     = {includegraphics }%
  ,moretexcs    =  {graphicspath}%
  }


\makeatletter
\NewDocumentCommand{\commandExample}{}{%
  \UDcollectverbarg{\@firstofone}{\@commandExample}%
}%
\begingroup
\catcode`\X=14 %
\catcode`\%=12 X
\csname @firstofone\endcsname{X
  \endgroup
  \NewDocumentCommand{\@commandExample}{mm}{X
    \scantokens{Output: #1 - Code: \lstinline#2%}X
  }X
}%
\makeatother

\begin{document}

\verb:\commandExample{begin}: yields:

\commandExample{begin}

\medskip\hrule\medskip

\noindent Both with \verb|\lstinline| and thus with this variant of \verb|\commandExample| you can't have
\verb|{|  within arguments that are nested between \verb|{...}|. Use some verbatim-delimiter instead:
\medskip

\verb:\commandExample|\si{\metre}|: yields:

\commandExample|\si{\metre}|

\medskip\hrule\medskip

\noindent  \verb|mathescape|-thingies in the code seem to work, too:
\medskip

\verb:\commandExample|$x^2+y^2=z^2$|: yields:

\commandExample|$x^2+y^2=z^2$|

\medskip\hrule\medskip

\verb:\commandExample{$x^2+y^2=z^2$}: yields:

\commandExample{$x^2+y^2=z^2$}

\end{document}

Bildbeschreibung hier eingeben

verwandte Informationen