Eu tive um problema semelhante a este:Espaço após comandos LaTeX
Minha primeira tentativa foi algo assim:
\newcommand{\satip}{SAT\textgreater IP}
Isso leva ao problema conhecido, que os espaços após o comando são consumidos:
\satip is a cool Protocol. %Produces: SAT>IPis a cool Protocol.
space missing ^^^
Pesquisei e encontrei a pergunta mencionada. As soluções fornecidas ajudaram muito, mas não fiquei totalmente satisfeito com nenhuma delas. \satip/
só parece um pouco estranho em um documento de látex, gosto \satip{}
muito mais. Só que, se eu esquecer de colocar {}
atrás do comando, falta espaço na saída. Portanto, gostaria de receber um erro se usá-lo errado.
Solução possível:
\def\satip#{SAT\textgreater IP}
%\satip is a cool Protocol. %doesn't compile, error
Dessa forma, a chave aberta é aplicada, mas as chaves podem conter algo:
\satip{is} a cool Protocol.
Isso compila bem, mas como não faz sentido, gostaria que produzisse um erro. Minha maneira atual de lidar com o problema é esta:
\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
Agora minha pergunta:
Esta Macro precisa de uma segunda etapa de expansão. Isso poderia causar algum problema? Existem outros problemas? (Como não encontrei isso em nenhum lugar antes.)
PS: Desculpe pelo título ruim, não encontrei algo melhor. Sinta-se à vontade para editar.
Responder1
Você sempre pode usar
\newcommand*\satip{SAT\textgreater IP}
\satip{} is a cool protocol
Eu não vejo o problema.
A propósito, sua última definição define a macro com nome satip{}
(chavesincluídono nome da macro) a ser seguido por um \relax
token. Se você colocar #1
entre \endcsname
e \relax
na \satip
macro, ele só funcionará se #1
estiver vazio (ou seja, somente se forem fornecidos colchetes vazios \satip{} is...
).
Pode ser que isso alcance o que você deseja?
\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}
Responder2
Eu não usaria {}
no nome da macro auxiliar, mas o método é válido:
\newcommand{\satip}[1]{\csname satip\string+\endcsname #1\relax}
\expandafter\def\csname satip\string+\endcsname\relax{%
SAT\textgreater IP%
}
irá desencadear um erro caso \satip{x}
seja usado
! Use of \satip+ doesn't match its definition.
<argument> x
Mas \satip ip
não faria isso. Você deveria fazerdoispassos:
\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%
}
Agora, ambos \satip x
e \satip{x}
desencadeariam erros:
! 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}
?
Observe \protected
antes da definição de \satip
, para que não seja expandido em contextos de “argumentos móveis”.
Uma versão abstrata:
\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}
Se isso é útil, deixo a decisão para você.
Uma implementação diferente: verifique o e {
, em seguida, verifique se }
há consumo de ambos os tokens em caso de sucesso.
\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}