巨集內清單

巨集內清單

我試圖找到一種方法來使用宏,在其中演示命令的輸出,然後透過lstinline命令顯示命令。我讀到我需要轉義特殊字元(如{}),現在想知道是否有辦法自動執行此操作。不確定這是否可能。

理想情況下,該\commandExample{\qty{1.2}{\meter}}命令會產生Output:1.2 m - Code:\qty{1.2}{\meter}

微量元素:

\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啟用的數學轉義機制\lstset,以及允許\lstinline透過在 之間嵌套事物而在參數內轉義到數學模式的數學模式,在直接應用於 v 類型參數$...$時會被破壞。\lstinline

啟用 mathescape 後,該指令\lstinline{$x^2+y^2=2^2$}會為您提供大量模式錯誤訊息,! Undefined control sequence. \lst@arg ->$x以防$x^2+y^2=2^2$被標記為 v 類型參數。

因此,如果在現實場景中您不需要 mathescape 功能,我建議使用egreg 的程式碼。

如果在現實生活場景中您確實需要 mathescape 功能,請修改egreg的答案,以便\commandExample在適當的類別代碼制度下讀取並標記其參數,或嘗試將\scantokens\tl_rescan:nn應用於傳遞給的標記的方法\lstinline


一個小問題是:對於較新的 LaTeX 發行版,您的程式碼不提供\unit和 的任何定義\meter。因此,在下面的範例中,使用了命令\si和。\metre

一個問題是: 的一個特性是,如果它本身也包含 ,則\lstinline的參數\lstinline通常不能嵌套在{和之間。在這種情況下,參數需要嵌套在參數中未出現的字元之間。所以不會成功,但你需要做類似的事情。 (egreg 的答案中完成的另一個技巧是在 verbatim-catcode-régime 下標記化參數,以便在任何情況下它不包含類別 1 或類別 2。但是-type-category-code-régime 會中斷的一些特徵——至少是mathescape-feature。}{\lstinline{\unit{\meter}}\lstinline|\unit{\meter}|\lstinline{}v\lstinline

另一個問題是 TeX 期望值 的參數\lstinline在不同的類別代碼系統下被標記化。因此,\lstinline暫時更改類別代碼制度,以從令牌流中獲取屬於其參數的令牌。\lstinline依賴 TeX 需要從 .tex-input-file 中讀取,並在更改的類別代碼系統下對屬於參數的標記進行標記,以便可以從標記流中獲取它們。因此\lstinline僅適用於用戶級別/頂級。\lstinline當參數在未更改的類別代碼制度下標記化後傳入參數時不起作用,例如,當將調用\lstinline放入其他宏的定義文本中時,這些宏在未更改的類別代碼制度下獲取參數並將它們傳遞給\lstinline.

這個問題可以在某種程度上避免,方法是讓巨集\commandExample本身在獲取參數之前更改類別代碼制度,然後將它們傳遞給\lstinline嵌套在 中的\scantokens{...%}

但由此又出現了另一個問題:LaTeX 2ε、expl3 和 xparse 都沒有提供逐字參數類型,可以讓您保留並傳遞逐字分隔符號。

因此,在下面的範例中,\UDcollectverbarg提供了切換到逐字catcode 模式的命令,並獲取不帶逐字分隔符號和嵌套在逐字分隔符號之間的參數,以便可以正確地傳遞這些內容以進行進一步處理。

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

在此輸入影像描述

相關內容