texjporg / platex

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

emath の \marusuuref でエラー #57

Closed doraTeX closed 6 years ago

doraTeX commented 6 years ago

31 および #55 に関連して。emath の \marusuuref でエラーが出るようになったという報告を受けました。

本質的には TeX Q&A 45421 にある次のソースで確認できます。

\documentclass{jsarticle}
\usepackage[noreplace]{otf}
\usepackage{amsmath} 

\makeatletter
\def\tagform@#1{\maketag@@@{$\cdots$\ignorespaces\ajMaru{\number#1}\unskip\@@italiccorr}}

\def\ref@chk#1{\ifx#1\relax\edef\@miteigi{1}\else\edef\@miteigi{0}\fi}%
\def\maruref#1{%
    \expandafter\ref@chk\csname r@#1\endcsname
    \if 1\@miteigi
      \protect\G@refundefinedtrue
      \nfss@text{\reset@font\bfseries ??}%
      \@latex@warning{Reference `#1' on page \thepage \space
             undefined}%
    \else
      {\count255=\ref{#1}\ajMaru{\number\count255}}%
    \fi
}
\makeatother

\begin{document}
\begin{align}
f(x) \label{数式}
\end{align}

\ref{数式} % → ただの "1" が出力される

\maruref{数式} % → 丸数字の 1 が出力される
\end{document}
You can't use `\spacefactor' in vertical mode.
\@setref@ ->\ifmmode \else \spacefactor 
                                        \@m \fi 
\maruref{数式}
                      % → 丸数字の 1 が出力される
\def\@setref@{\ifmmode\else\spacefactor\@m\fi}

\def\@setref@{\ifhmode\spacefactor\@m\fi}

とすれば一応対処できました。

aminophen commented 6 years ago

うーん,標準ではない使い方まで考えるのはちょっと辛いですが,変更を取り込むことにします。

ちなみに,この \maruref の定義は目次の中で使える実装にはなっていないようですね。(明確な意思を持ってかどうかはわかりませんが,\protect が使われていることから “robust にする気はある” コードのように見えて,実はそこより前で \edef しているので意味をなしていない。)

doraTeX commented 6 years ago

うーん,標準ではない使い方まで考えるのはちょっと辛いですが,変更を取り込むことにします。

まあ,emathは教育業界ではユーザがかなり多そうですからね……。よろしくお願いします。

ちなみに,この \maruref の定義は目次の中で使える実装にはなっていないようですね。

ほんとですね。とりあえず単に \def\maruref のところを \DeclareRobustCommand* に変更すれば大丈夫そうです。

aminophen commented 6 years ago

ユーザが多いのであれば,Travis CI などでも走らせられるテストケースに入れたいのですが,「再配布許諾が明文化されないものはテストケースに入れられない=サポート外」というスタンスを取らざるを得ないので,その辺はご了承ください。もちろん tDB さんに明文化を交渉していただけると助かるのですが。

これは別に emath などを嫌っているのではないですが,「今後の pLaTeX の変更で壊れる可能性は十分ある」ということは明言しておかないといけないな,と思います。

aminophen commented 6 years ago

もう一つ,\maruref には潜在的な欠陥があって,本来の 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}

だったならば失敗していたと思います。段落頭で \maruref{ラベル} すると,\count255 取得時に発生した \null が垂直モードで出力されることになるので,見た目としては余分な空行が発生しているような状態になります。たまたま pLaTeX が「\null を削除」していたから助かっている,という感じですね。

aminophen commented 6 years ago

以上の話を踏まえると,(pLaTeX 側も一応対処しますが)emath の実装は

\def\ref@chk#1{\ifx#1\relax\edef\@miteigi{1}\else\edef\@miteigi{0}\fi}%
\DeclareRobustCommand*{\maruref}[1]{%
    \expandafter\ref@chk\csname r@#1\endcsname
    \if 1\@miteigi
      \protect\G@refundefinedtrue
      \nfss@text{\reset@font\bfseries ??}%
      \@latex@warning{Reference `#1' on page \thepage \space
             undefined}%
    \else
      {\leavevmode\count255=\ref{#1}\ajMaru{\number\count255}}%
    \fi
}

とすべき,と思います。これで本 issue はそもそも発生しないと思います。

doraTeX commented 6 years ago

そうですね。ついでに(趣味の問題ですが)\ref@chk\@miteigi を定義せずとも単に \if 1\@miteigi のところを

\expandafter\ifx\csname r@#1\endcsname\relax

とすればよさそうに見えます。

aminophen commented 6 years ago

はい,私もそう思います。改善案を emath の方に送っていただけるといいと思います。

(というか,今定義されているマクロは emath そのものではないんですかね? その辺はよくわかりません)

doraTeX commented 6 years ago

今 emath.sty を見てみましたところ,

\def\marusuuref#1{%
    \expandafter\ref@chk\csname r@#1\endcsname
    \if 1\@miteigi
      \protect\G@refundefinedtrue
      \nfss@text{\reset@font\bfseries ??}%
      \@latex@warning{Reference `#1' on page \thepage \space
             undefined}%
    \else
      {\count255=\ref{#1}\maru{\number\count255}}%
    \fi
}

となっていました。マクロ名が \marusuuref である以外は同様のようです。(emath の \maruref は ajmacros ではなく \ooalign で○を合体させるタイプみたいです。)

改善案を emath の方に送っていただけるといいと思います。

送っておきます。

aminophen commented 6 years ago

結局 emath に提案するなら

\DeclareRobustCommand*{\marusuuref}[1]{%
    \expandafter\ifx\csname r@#1\endcsname\relax
      \protect\G@refundefinedtrue
      \nfss@text{\reset@font\bfseries ??}%
      \@latex@warning{Reference `#1' on page \thepage \space
             undefined}%
    \else
      {\leavevmode\count255=\ref{#1}\maru{\number\count255}}%
    \fi
}

が最善?

doraTeX commented 6 years ago

emath掲示板(パスワード認証つきページ内にあります)に,このページへのリンクを紹介しておきました。 (emath.sty をざっと検索してみると,\ref@chk は,他にも \eqref などの定義にも用いられているようですが,いずれも

\expandafter\ref@chk\csname r@#1\endcsname
\if 1\@miteigi

の形で用いられていますので,すべて同様の置き換えをすることで \ref@chk\@miteigi は不要にできそうです。)

aminophen commented 6 years ago

2017/11/05 付けで pLaTeX2e 2017/10/28+2 としてリリースしているので,完了とします.

aminophen commented 6 years ago

そもそも「LaTeX の \@setref に \null がある理由」が何なのか,といろいろ考えていて思いついた,まさに「重箱の隅」のようなあまり意味のない話を書いておきます。

LaTeX と pLaTeX では以下の結果が異なります。

\documentclass{article}
\begin{document}
\ref{a}\label{a}
\end{document}

pLaTeX では「相互参照が収束しないケース」に該当し,奇数回コンパイルすると Output written on sheors.dvi (1 page, 212 bytes). ですが,偶数回コンパイルすると No pages of output. になるので

Latexmk: Did not finish processing file 'test':
   'latex' needed too many passes

ということになります。上は \ref の前にそれが参照すべきカウンタがなくて「空」になる例ですが,\pageref も \thepage の定義次第で「空」になり得るので

\documentclass{article}
\pagenumbering{gobble}
\begin{document}
\pageref{a}\label{a}
\end{document}

でも同じような結果になります。

\def\@setref@{\ifhmode\spacefactor\@m\else\null\fi}

ならば LaTeX に近づきますが,今のところは別にわざわざ入れるほどのことはないと思っています。

aminophen commented 1 year ago

情報:ここの冒頭のコード

本質的には TeX Q&A 45421 にある次のソースで確認できます。

は最新の LaTeX では通らなくなっている。

! Missing number, treated as zero.
          \xparse function is not expandable 

\pageref\NewDocumentCommandで定義されるようになっている、からかな ltnews35の項目だと: Starred command version for \ref, \Ref and \pageref

他にも,エラーが出ないけど処理結果が LaTeX の版によって変わる例もあるので注意。

%#!pdflatex
%\RequirePackage[2022/05/01]{latexrelease}
\documentclass{article}
\begin{document}

\section{First}\label{sec}

% \ref / \pageref で数字が取得できるとは限らない
% LaTeX2e 2022-11-15: EVEN (!!)
% LaTeX2e 2022-05-01: ODD (expected)
\ifodd0\pageref{sec}-ODD-\else-EVEN-\fi

\end{document}