ここでスキップ解除が機能しないのはなぜですか?

ここでスキップ解除が機能しないのはなぜですか?

次のように使用するマクロを定義しようとしています。

\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.
}

問題は、 が\unskip最後の改行を無視しないことです。 のようなコメントを追加するとas in XKCD 1285.%期待どおりに動作しますが、これは\unskip本来の動作ではないのでしょうか?

最初のスペースは正しく取り込まれます。 なしでは、\ignorespaces先頭に下線付きのスペースがありますが、\ignorespaces削除されます。 は、\unskip末尾の下線付きの文を削除するはずですが、削除されません。

私の理解では、それは\unskipのようなものだと思います\ignorepreviousspace。これは正しいですか?

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}

答え1

\uline引数を解析してテキストを単語に分割します。解析された単語はボックス内に配置され、その幅が測定され、マーク (線、二重線、波など) が重ねられます。したがって、\unskip新しい単語の先頭からボックスの先頭に移動します。削除するスペースはありません。したがって、効果はありません。

パッティング\unskip \uline{...}接着剤を除去するので優れています。しかし、\uline挿入スペースの代わりにそれらを追加します。最初のスペースは下線付きのスペース ( \leaders) で、2 番目は小さな負のスペース (-1/300 インチ) です。これはおそらく下線部分の重なりを良くするために追加されたものです。

\unskip後に1つだけ追加する\ulineその他、削除された回答(10K 以上のユーザーのみ表示されます)、コメントによって行末\thesisが削除された場合、偶然に動作します。段落の最後で、TeX は暗黙的に . によって最後のスペースを削除します\unskip

2つの解決策\unskip

\documentclass{article}
\usepackage[normalem]{ulem}
\newcommand*{\thesis}[1]{%
  \uline{\ignorespaces #1}%
  \unskip\unskip
}

\begin{document}
Before. \thesis{
  Foo.
  Bar.
  Baz.
} After.
\end{document}

結果

パッケージによるソリューションtrimspaces

次の例では、trimspacesテキストを に渡す前に、パッケージを使用してスペースを削除します\uline。これにより、ソリューションは の実装からより独立します\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}

答え2

Heikoは問題を解決する方法について詳しく説明しているので、私はサブ質問についてコメントすることにします。

私の理解では、それは\unskipのようなものだと思います\ignorepreviousspace。これは正しいですか?

基本的にはいいえ、その理解は正しくありません。完全に異なるレベルで機能します (\unskip 改行の前に、別のレベルで再び機能します)。\ignorespaces%

少し簡略化すると、TeXは次のようなシーケンスを読み取ります。文字ファイルから取り出してトークン(文字のグループをコマンド名として読み取るか、文字トークンにcatcode値を割り当てることによって)その後、これらのトークンのリストが処理され、最終的に水平または垂直のリスト植字箱と接着剤。

%レベルで動作する文字. が%見つかった場合、その行の残りの文字と行末の改行はスキップされ、トークンに変換されません。

\ignorespacesレベルで動作するトークン.\ignorespacesすべてのスペース トークン (通常は垂直モードでは無視され、水平モードでは単語間の結合を追加します) は、コマンドの影響が終了したときに最初の非スペース トークンが表示されるまで無視されます。

\unskipレベルで動作するリスト現在の水平リストに追加された前の項目 (スペースから追​​加されたか、明示的または暗黙的から追加されたかに関係なく\vskip)\hskipが現在のリストから削除され、破棄されます。(ページのメインの垂直リストを除きます。このリストでは、一度追加された項目を削除できず、\unskip何も実行されません)。

異なる構造で動作しているという事実は別として、\ignorespaces連続するスペースはいくつでも無視されますが、\unskipグルーノードは1つしか削除されません(この質問の段落の最後にある処理に関連します)。連続する2つのトークンを連続するスペースとして取得する必要があるため、通常は\ignorespaces無視するスペーストークンは1つだけです。文字単一のスペーストークンとしてトークン化されます。ただし、たとえばは\ignorespaces\space\space両方とも無視されます。

関連情報