Desvantagens do método csname para evitar espaços após o comando

Desvantagens do método csname para evitar espaços após o comando

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 \relaxtoken. Se você colocar #1entre \endcsnamee \relaxna \satipmacro, ele só funcionará se #1estiver 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 ipnã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 xe \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 \protectedantes 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}

informação relacionada