csname 方法的缺點是避免指令後出現空格

csname 方法的缺點是避免指令後出現空格

我遇到了與此類似的問題:LaTeX 指令後的空格

我的第一次嘗試是這樣的:

\newcommand{\satip}{SAT\textgreater IP}

這導致了已知的問題,即命令後面的空格被耗盡:

\satip is a cool Protocol. %Produces: SAT>IPis a cool Protocol.
                             space missing ^^^

我四處搜尋,發現了提到的問題。提供的解決方案很有幫助,但我對其中任何一個都不完全滿意。\satip/只是在乳膠文檔中看起來有點奇怪,我\satip{}更喜歡。只是,如果我忘記放在{}指令後面,輸出就會缺少空格。因此,如果我使用錯誤,我希望得到一個錯誤。

可能的解決方案:

\def\satip#{SAT\textgreater IP}
%\satip is a cool Protocol. %doesn't compile, error

這樣就強制使用了左大括號,但大括號可以包含一些內容:

\satip{is} a cool Protocol.

這編譯得很好,但由於它沒有任何意義,我希望它產生一個錯誤。我目前處理問題的方法是這樣的:

\expandafter\def\csname satip{}\endcsname \relax{SAT\textgreater IP}
\def\satip#1{\csname satip{}\endcsname #1\relax}

%\satip{is} a cool Protocol. %Use of \satip{} doesn't match its definition.
%\satip is a cool Protocol. %Use of \satip{} doesn't match its definition.
\satip{} is a cool Protocol. %works

現在我的問題:

該巨集需要第二個擴充步驟。這會造成什麼麻煩嗎?還有其他問題嗎? (因為我以前沒有在任何地方找到過這個。)

PS:對不起,我的標題不好,我沒有想出更好的東西。請隨意編輯。

答案1

您可以隨時使用

\newcommand*\satip{SAT\textgreater IP}
\satip{} is a cool protocol

我沒有看到問題所在。


順便說一句,您的最後一個定義定義了帶有名稱的巨集satip{}(大括號包括在巨集名稱中)後面跟著一個\relax標記。如果將 and 放在#1巨集中\endcsname,則僅當 為空時才有效(即,僅當給出空大括號時)。\relax\satip#1\satip{} is...


也許這能達到你想要的目的?

\newcommand*\satip[1]
 {\if\relax\detokenize{#1}\relax
    SAT\textgreater IP%
  \else
    \GenericError{} % <- I don't know what this argument does
       {Wrong use of \string\satip{}.} % <- short version
       {Wrong use of \string\satip. You must use \string\satip\space followed by an empyt argument `{}'.}% <- long version
  \fi}

答案2

我不會{}在輔助巨集的名稱中使用,但該方法是合理的:

\newcommand{\satip}[1]{\csname satip\string+\endcsname #1\relax}
\expandafter\def\csname satip\string+\endcsname\relax{%
  SAT\textgreater IP%
}

\satip{x}如果使用的話會觸發錯誤

! Use of \satip+ doesn't match its definition.
<argument> x

然而\satip ip不會。你應該做腳步:

\newcommand{\satip}{}% initialize
\protected\def\satip#{\csname satip\string+\endcsname}
\expandafter\def\csname satip\string+\endcsname#1{%
  \csname satip\string+\string+\endcsname #1\relax
}
\expandafter\def\csname satip\string+\string+\endcsname\relax{%
  SAT\textgreater IP%
}

現在\satip x\satip{x}都會觸發錯誤:

! Use of \satip doesn't match its definition.
l.14 \satip x

? 
! Use of \satip++ doesn't match its definition.
<argument> x

l.16 \satip{x}

? 

請注意\protected的定義前面\satip,因此它不會在“移動參數”上下文中擴展。

抽象版本:

\documentclass{article}

\makeatletter
\newcommand\definestringcommand[2]{%
  \@ifdefinable#1{\@definestringcommand#1{#2}}%
}

\newcommand{\@definestringcommand}[2]{%
  \begingroup
  \escapechar=\m@ne % get rid of the backslash
  % require brace
  \protected\xdef#1##{\expandafter\noexpand\csname\string#1\string+\endcsname}%
  % examine the argument
  \expandafter\xdef\csname\string#1\string+\endcsname##1{%
    \expandafter\noexpand\csname\string#1\string+\string+\endcsname##1\relax
  }%
  \expandafter\gdef\csname\string#1\string+\string+\endcsname\relax{#2}%
  \endgroup
}
\makeatother

\definestringcommand{\satip}{SAT\textgreater IP}

\begin{document}

\satip is nice

\satip{x} is nice

\satip{} is nice

\end{document}

這是否有用,我將決定權留給你。

一種不同的實作:檢查{,然後檢查後續}是否成功吃掉這兩個令牌。

\documentclass{article}

\makeatletter
\newcommand\definestringcommand[2]{%
  \@ifdefinable#1{\@definestringcommand#1{#2}}%
}

\newcommand{\@definestringcommand}[2]{%
  \begingroup
  \escapechar=\m@ne % get rid of the backslash
  % require brace
  \protected\xdef#1##{%
    \expandafter\noexpand\csname\string#1\string+\endcsname
  }%
  \expandafter\gdef\csname\string#1\string+\endcsname{%
    #2%
    \afterassignment\@checkrightbrace\let\@forget= % the space counts
  }
  \endgroup
}
\newcommand{\@checkrightbrace}{%
  \@ifnextchar\egroup{\let\@forget= }{\@strcmderr\let\@forget= }%
}
\newcommand{\@strcmderr}{%
  \@latex@error{Non empty group}{The braces must contain nothing}%
}
\makeatother

\definestringcommand{\satip}{SAT\textgreater IP}

\begin{document}

\satip is nice

\satip{x} is nice

\satip{} is nice

\end{document}

相關內容