Estou tentando definir uma macro para ser usada da seguinte forma:
\usepackage[normalem]{ulem}
\newcommand{\thesis}[1]{\uline{\ignorespaces #1\unskip}}
% underlining required by school - I know, I know
% later...
\thesis{
This is the beginning of a multi-line thesis statement.
I use one sentence on each line throughout my document.
Thus, the thesis is broken as in XKCD 1285.
}
O problema é que \unskip
não engole a quebra de linha final. Se eu adicionar um comentário (como as in XKCD 1285.%
), ele funcionará conforme o esperado, mas não é isso que \unskip
deveria ser feito?
O espaço inicial é engolido corretamente. Sem \ignorespaces
há um espaço sublinhado no início, mas \ignorespaces
remove-o. O \unskip
deveria remover a instrução sublinhada no final, mas não o faz.
Meu entendimento é que \unskip
é mais ou menos assim \ignorepreviousspace
. Isso está correto?
MWE:
\documentclass{article}
\usepackage[normalem]{ulem}
\newcommand{\thesis}[1]{\uline{\ignorespaces #1\unskip}}
\begin{document}
\thesis{
Foo.
Bar.
Baz.
} % comment at end of previous line gives desired output
\end{document}
Responder1
\uline
analisa seu argumento para dividir o texto em palavras. Uma palavra analisada é colocada em uma caixa para medir sua largura e sobrepô-la com as marcações (linha, linha dupla, onda, ...). Portanto, \unskip
vai do início de uma nova palavra ao início de uma caixa. Não há espaço para remover. Portanto, não tem efeito.
Colocando\unskip
depois \uline{...}
é melhor porque remove a cola. Mas \uline
inserçõesdoisdeles no lugar de um espaço. O primeiro é o espaço sublinhado ( \leaders
), o segundo é um pequeno espaço negativo (-1/300 pol.), provavelmente adicionado para obter uma melhor sobreposição dos segmentos sublinhados.
Adicionando apenas um \unskip
depois \uline
nooutra resposta agora excluída(visível apenas para usuários com mais de 10 mil usuários), se o final da linha após \thesis
for removido por um comentário, funciona por acidente. No final de um parágrafo, o TeX remove o último espaço por um \unskip
.
Solução com dois\unskip
\documentclass{article}
\usepackage[normalem]{ulem}
\newcommand*{\thesis}[1]{%
\uline{\ignorespaces #1}%
\unskip\unskip
}
\begin{document}
Before. \thesis{
Foo.
Bar.
Baz.
} After.
\end{document}
Solução com pacotetrimspaces
O próximo exemplo usa package trimspaces
para remover os espaços antes de passar o texto para \uline
. Isso torna a solução mais independente da implementação do \uline
.
\documentclass{article}
\usepackage[normalem]{ulem}
\usepackage{trimspaces}
\makeatletter
\newcommand*{\thesis}[1]{%
\def\thesis@text{#1}%
\trim@spaces@in\thesis@text
\expandafter\uline\expandafter{\thesis@text}%
}
\makeatother
\begin{document}
Before. \thesis{
Foo.
Bar.
Baz.
} After.
\end{document}
Responder2
Heiko deu uma descrição completa de como resolver o problema, então vou me restringir a comentar a subquestão
Meu entendimento é que
\unskip
é mais ou menos assim\ignorepreviousspace
. Isso está correto?
Basicamente não, esse entendimento não está correto. \unskip
e \ignorespaces
trabalhar em níveis completamente diferentes (e %
antes que uma quebra de linha funcione novamente em outro nível).
Um pouco simplificado, o TeX lê uma sequência depersonagensdo arquivo, transformando-o então emfichas(seja lendo um grupo de caracteres como um nome de comando ou atribuindo valores de catcode a tokens de caracteres). Em seguida, essas listas de tokens são processadas e podem eventualmente produzirlistasde caixas compostas e cola.
%
funciona ao nívelpersonagens. Se a %
for visto, o restante dos caracteres nessa linha e a quebra de linha no final da linha serão ignorados e não serão transformados em tokens.
\ignorespaces
funciona ao nívelfichas. Depois que \ignorespaces
todos os tokens de espaço (que normalmente são ignorados no modo vertical ou adicionam cola entre palavras no modo horizontal) são ignorados até que o primeiro token que não seja de espaço seja visto quando os comandos afetam as extremidades.
\unskip
funciona ao nívellistas. Se o item anterior adicionado à lista horizontal atual (seja proveniente de um espaço ou de um explícito ou implícito \vskip
ou \hskip
for removido da lista atual e descartado. (Exceto na lista vertical principal da página onde você não pode remover itens depois de adicionados , e \unskip
é autônomo).
Além do fato de estarem operando em estruturas diferentes, observe (o que é relevante para o processamento no final de um parágrafo nesta questão) que \ignorespaces
ignora qualquer número de espaços consecutivos, mas \unskip
remove apenas um nó de cola. Normalmente, é claro, \ignorespaces
só há um token de espaço para ignorar, pois você precisa trabalhar para obter dois tokens consecutivos como espaço consecutivopersonagenssão tokenizados como um token de espaço único. Mas, por exemplo, \ignorespaces\space\space
ignoraria ambos.