매크로 내부 목록

매크로 내부 목록

명령의 출력을 보여준 다음 명령을 통해 명령을 표시하는 매크로를 갖는 방법을 찾으려고 노력 중입니다 lstinline. 특수 문자(예: {및 ) 를 탈출해야 한다는 내용을 읽었 }으며 이제 이를 자동으로 수행할 수 있는 방법이 있는지 궁금합니다. 이것이 가능한지 확실하지 않습니다.

이상적으로는 \commandExample{\qty{1.2}{\meter}}명령이 다음을 생성합니다.Output: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}

답변1

나는 그 주장을 그대로 흡수하고 \tl_rescan:nn그것을 조판하는 데 사용할 것입니다.

\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}

여기에 이미지 설명을 입력하세요

답변2

일반적으로egreg에서 제공하는 코드내 코드보다 선호됩니다.

\mathescape=true그러나 inside 를 통해 활성화되고 via 중첩 항목 \lstset인수 내에서 수학 모드로 탈출할 수 있는 mathescape 메커니즘은 v-type 인수에 직접 적용할 때 손상됩니다 .\lstinline$...$\lstinline

mathescape를 활성화하면 명령은 v-type-argument로 토큰화된 경우 \lstinline{$x^2+y^2=2^2$}패턴에 대한 많은 오류 메시지를 표시합니다 .! Undefined control sequence. \lst@arg ->$x$x^2+y^2=2^2$

따라서 실제 시나리오에서 mathescape 기능이 필요하지 않은 경우 egreg의 코드를 사용하는 것이 좋습니다.

실제 시나리오에서 mathescape 기능이 필요한 경우 egreg의 답변을 수정하여 \commandExample적절한 범주 코드 체제에서 해당 인수를 읽고 토큰화하거나 전달된 토큰에 적용되는 접근 방식을 \scantokens시도 \tl_rescan:nn하십시오 \lstinline.


사소한 문제는 최신 LaTeX 배포판에서는 코드가 \unit및 에 대한 정의를 제공하지 않는다는 것입니다 \meter. 따라서 아래 예에서는 명령 \si\metre대신 사용됩니다.

한 가지 문제는 다음과 같습니다. 의 특징 은 일반적으로 \lstinline의 인수가 및 if 자체에도 포함되어 있을 수 없다는 것입니다 . 이 경우 인수는 인수 내에서 발생하지 않는 문자 사이에 중첩되어야 합니다. 그래서 효과가 없을 것입니다. 그러나 다음과 같은 작업을 수행해야 합니다 . (egreg의 답변에서 수행되는 또 다른 트릭은 verbatim-catcode-régime에서 토큰화 인수를 사용하여 어떤 경우에도 카테고리 1 또는 카테고리 2를 포함하지 않도록 하는 것입니다. 그러나 -type-category-code-régime은 중단됩니다. 의 일부 기능 —적어도 mathescape 기능.)\lstinline{}{\lstinline{\unit{\meter}}\lstinline|\unit{\meter}|\lstinline{}v\lstinline

또 다른 문제는 TeX가 인수가 \lstinline다른 범주 코드 체제에서 토큰화되기를 기대한다는 것입니다. 따라서 \lstinline토큰 스트림에서 해당 인수에 속하는 토큰을 가져오기 위해 카테고리 코드 체계를 일시적으로 변경합니다. \lstinline.tex-input-file에서 읽어야 하고 변경된 범주 코드 체계 아래 인수에 속하는 토큰을 토큰화하여 토큰 스트림에서 가져올 수 있도록 TeX에 의존합니다. 따라서 \lstinline사용자 수준/최상위 수준에서만 작동합니다. \lstinline예를 들어 변경되지 않은 범주 코드 체제에서 인수를 가져와 에 전달하는 다른 매크로의 정의 텍스트에 호출을 배치하는 경우와 같이 변경되지 않은 범주 코드 체제에서 인수를 토큰화한 후 인수가 전달될 때 는 작동하지 \lstinline않습니다 \lstinline.

\commandExample이 문제는 인수를 잡고 에 중첩된 에 전달하기 전에 \lstinline매크로 자체에서 범주 코드 체계를 변경하도록 하여 어느 정도 우회할 수 있습니다 \scantokens{...%}.

그러나 이로 인해 또 다른 문제가 발생합니다. LaTeX 2ε, expl3, xparse 모두 ​​축어 구분 기호를 보존하고 전달할 수 있는 축어 인수 유형을 제공하지 않습니다.

따라서 아래 예에서는 \UDcollectverbarg축어적 catcode régime으로 전환하고 축어 구분 기호가 없거나 사이에 중첩된 인수를 잡아 이러한 항목이 추가 처리를 위해 적절하게 전달될 수 있도록 하는 명령이 제공됩니다.

\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}

여기에 이미지 설명을 입력하세요

관련 정보