texjporg / platex

pLaTeX community edition
BSD 3-Clause "New" or "Revised" License
49 stars 8 forks source link

目次の中の \ref で後ろの空白が喰われる + スペースファクター #31

Closed aminophen closed 7 years ago

aminophen commented 7 years ago

Twitter で拾いました。→ https://twitter.com/aminophen/status/823578764994936834

\documentclass{article}
\begin{document}
\tableofcontents
\section{Something}\label{a}
\section{Sec. \ref{a} is empty}
\end{document}

これは latex では問題なく処理できますが、platex では目次の \ref (今回は 1)の後に toc で \relax が吐かれてしまうために、空白が喰われてしまいます。plcore の \@setref が xkanjiskip 対策で \null を \relax に変えていることが原因なので、これは pLaTeX の issue のようです。

wtsnjp commented 7 years ago

非常に素朴ですが,ひとまず \@setref を次のように定義し直すと(\relax の後ろに {} を入れただけです)上のケースでは期待通りの出力をするようになりました:

\def\@setref#1#2#3{%
  \ifx#1\relax
    \protect\G@refundefinedtrue
    \nfss@text{\reset@font\bfseries ??}%
    \@latex@warning{Reference `#3' on page \thepage \space
              undefined}%
  \else
    \expandafter#2#1\relax{}% change \null to \relax{}
  \fi}

ただし副作用がないかは大変怖いところです.

aminophen commented 7 years ago

ありがとうございます。私は texjporg/jsclasses#8 からの類推ですが、同じことを思っていました。

とりあえずテスト版ということで exppl2e.sty に入れるというのはどうでしょう?

aminophen commented 7 years ago

aebcbb2 で exppl2e.sty に @wtsnjp さんのコードを入れ、tests/setref.tex を追加しました。

GitHub では日本語が文字化けしていて見づらいですが、追加した説明文は

% \changes{v????}{????/??/??}{目次で\cs{ref}を使った場合に後ろの空白が消える
%    現象に対処するため、\cs{relax}のあとに\{\}を追加}
% しかし、単に|\null|を|\relax|に置き換えるだけでは、|\section|のような
% 「動く引数」で|\ref|などを使った場合に、目次で後ろの空白が消えてしまいます。
% そこで、|\relax|のあとに|{}|を追加しました。

と書いています。

本家 LaTeX の場合は \null\hbox {} に展開されて aux や toc に書かれるわけですから、今回の変更により \relax {} が書き出されるのは特に問題ないのではないかと思います。

kuroky49 commented 7 years ago
\documentclass{jsarticle}
\makeatletter
\renewcommand{\thesection}{\kansuji\c@section}
\makeatother

\begin{document}
\tableofcontents

\section{ほげ}\label{sec:hoge}
\section{第\ref{sec:hoge}節へのアンチテーゼふが}
\end{document}

のようなときにうまくいくでしょうか?(横書きだと稀かもしれませんが,縦書きもありますので.)

aminophen commented 7 years ago

aux/toc 内で 第一\relax {}節 となるので、挙動としては問題ないはずです。確かにテストファイルにも追加した方が安心しますね。(jsarticle は \kanjiskip を \section のようなフォントサイズ変更に連動させて切り替えてしまうので、\kanjiskip20pt のような可視化がキャンセルされて見づらく、jarticle でテストケースにしておきます。)

aminophen commented 7 years ago

いわゆる「緑」の本 (p.169) の「\@setref と目次・スペースファクター」というコラムに

オリジナルの定義では,"see Appendix A." のような記述が文末にあり,かつ,"Appendix A" の "A" を相互参照で取得した場合などにスペースファクターを補正する目的で \null (= \hbox{}) を用いています. (…中略…) そこで,\@setref の(オリジナルの定義の) "\expandafter#2#1\null" の部分の null を "\spacefactor\@m{}" に変更するのもよいでしょう.こうすると,"スペースファクター","和欧文間スペース","toc ファイルなどでの参照結果の直後の空白文字" の全てが正しく処理されます.

とあります。2003 年の本書で既に,pLaTeX による \@setref の目次での不具合だけでなく,スペースファクターの未考慮についても指摘があります。前回入れた \relax\relax{} についても,やはりスペースファクター未考慮です(以下のソースで確認できます)。

\makeatletter
%% LaTeX
\def\@setref#1#2#3{%
  \ifx#1\relax
  \protect\G@refundefinedtrue
  \nfss@text{\reset@font\bfseries ??}%
  \@latex@warning{Reference `#3' on page \thepage \space
  undefined}%
  \else
  \expandafter#2#1\null
  \fi}
%% pLaTeX (old)
\def\@setref#1#2#3{%
  \ifx#1\relax
  \protect\G@refundefinedtrue
  \nfss@text{\reset@font\bfseries ??}%
  \@latex@warning{Reference `#3' on page \thepage \space
  undefined}%
  \else
  \expandafter#2#1\relax% change \null to \relax
  \fi}
%% pLaTeX (2017/04/08)
\def\@setref#1#2#3{%
  \ifx#1\relax
  \protect\G@refundefinedtrue
  \nfss@text{\reset@font\bfseries ??}%
  \@latex@warning{Reference `#3' on page \thepage \space
  undefined}%
  \else
  \expandafter#2#1\relax{}% change \null to \relax{}
  \fi}
%% "Green book"
%\def\@setref#1#2#3{%
%  \ifx#1\relax
%  \protect\G@refundefinedtrue
%  \nfss@text{\reset@font\bfseries ??}%
%  \@latex@warning{Reference `#3' on page \thepage \space
%  undefined}%
%  \else
%  \expandafter#2#1\spacefactor\@m{}% change \null to \spacefactor\@m{}
%  \fi}
\makeatother

\documentclass{article}
\parindent0pt
\ifx\xkanjiskip\undefined\else\xkanjiskip20pt\fi
\begin{document}

\tableofcontents

% cf. 1) wrong spacing (inter-word)
\section{See Appendix A. Here,}\label{test1}
% cf. 2) correct spacing (sentence-ending)
\section{See Appendix A\@. Here,}
% test for \spacefactor (should be sentence-ending)
\section{See Appendix \ref{testA}. Here,}

% cf. 1) wrong spacing (inter-word)
See Appendix A. Here,\par
% cf. 2) correct spacing (sentence-ending)
See Appendix A\@. Here,\par
% test for \spacefactor (should be sentence-ending)
See Appendix \ref{testA}. Here,\par

\appendix
% test for \xkanjiskip
\section{ここは第\ref{testA}章です。}\label{testA}
% test for trailing space in \tableofcontents
\section{Here is the section \ref{test1} for testing.}

\end{document}

次の版では,この「緑」の指摘をそのまま取り込むことを検討中です。

aminophen commented 7 years ago

a06e767 でカーネルへ。