檢查命令可擴展性的宏

檢查命令可擴展性的宏

我想創建檢查表達式是否完全可擴展的命令,如果不是則崩潰(最好列印錯誤訊息)。我想這樣做沒有考慮特定的 TeX 引擎。我認為這與這個問題有關檢查巨集是否完全可擴展,但提供的答案需要 LuaTeX。


測試程式碼

測試程式碼如下所示:

\documentclass[preview = true, varwidth = true]{standalone}
\usepackage{xparse}
\usepackage{xstring}

\NewDocumentCommand{\checkexpandability}{m}{
    % CODE HERE
}

\newcommand{\expandable}[1]{#1}
\newcommand{\notexpandable}[1]{%
    \edef\myvariable{\expandable{#1}}%
    \myvariable%
}

\begin{document}
\checkexpandability{\expandable{test}} % Should be OK
\checkexpandability{\notexpandable{test}} % Should CRASH
\checkexpandability{\IfBeginWith{string}{str}{true}{false}} % Should CRASH
\end{document}

萬一太複雜

如果這是不可行的,那麼我可以修改命令簽名以包含命令應擴展為的參數:

\begin{document}
\checkexpandability{\expandable{test}}{test} % Should be OK
\checkexpandability{\notexpandable{test}}{test} % Should CRASH
\checkexpandability{\IfBeginWith{string}{str}{true}{false}}{true} % Should CRASH
\end{document}

對可擴展性的評論

由於完全可擴展的定義並不像人們想像的那麼清晰(請參閱下面的評論),因此這個問題的上下文是我只是想創建一些可以幫助我調試某些程式碼的東西。我可以將問題限制在這個特定行為:巨集是否可以在上下文巨集中工作,例如命令\color

\documentclass[preview = true, varwidth = true]{standalone}
\usepackage{xcolor}

\newcommand{\expandable}[1]{#1}
\newcommand{\notexpandable}[1]{%
    \edef\myvariable{\expandable{#1}}%
    \myvariable%
}
    
\begin{document}
\color{\expandable{blue}} % OK
\color{\notexpandable{red}} % CRASHES
X
\end{document}

基本上,該\color命令完成了我正在尋找的工作,只是我想將其稱為\checkexpandability,更通用一點,並列印一條不錯的錯誤訊息。

答案1

我認為基本的誤解是

基本上,該\color命令完成了我正在尋找的工作,

\color命令不檢查請求的類型,它只是期望擴展後參數是定義的顏色名稱。如果擴充失敗,您會收到低階錯誤,或者如果它擴展為未定義的顏色,您會收到特定的錯誤訊息,但處理的任何部分都不是通用的,也不適用於除期望顏色的命令之外的命令。

可以實現的一個版本是具有預期擴展的版本,因為它只是詢問兩個參數在擴展後是否相等。 L3 編程層有幾個變體,或者您可以使用該ifthen套件和

\ifthenelse{\equal{\expandable{test}}{test}}{yes}{no}

如果參數擴展為相同的東西,它將返回 yes,如果不是,則返回 no,或者如果參數在擴展上下文中不安全(這就是通常所說的“不可擴展”的意思),則給出低級錯誤

答案2

要調試您的程式碼,我只需使用\typeout.

\documentclass[preview = true, varwidth = true]{standalone}
\usepackage{xcolor}

\newcommand{\expandable}[1]{#1}
\newcommand{\notexpandable}[1]{%
    \edef\myvariable{\expandable{#1}}%
    \myvariable%
}
    
\begin{document}
\typeout{\expandable{blue}} % OK, print "blue"
\typeout{\notexpandable{red}} % CRASHES
X
\end{document}

重點是,它將\typeout完全擴展它的參數,然後在終端上列印完全擴展的結果——這樣你就可以看一下終端。

對於第一種情況,它打印blue,所以一切都很好。對於第二種情況,它會崩潰。


當然,上述方法有兩個問題。

  • 即使\expandable{blue} 完全可擴展(無論它意味著什麼),\color在將結果解釋為顏色之前,可能無法保證完全擴展其參數。 (我猜透過海侖定律然而,這實際上是為了避免破壞“現有的包”。

    因此,如果您想更加確定,最好使用例如提前擴展它\ExpandArgs

  • 有關類別代碼的資訊以及隱藏在代碼中的任何特殊字元(例如空格與製表符)都會遺失。

    實際上這並不重要,但有時卻很重要。 (例如,當您嘗試調試某些試圖逐字捕獲環境主體的套件時)

    如果是這樣的話,可以考慮嘗試一下我的包裹。 (現在的程式碼一團糟,但它工作得很好,並且有一些套件的源代碼更糟)

相關內容