後続の文字に応じて自動的に和欧文間空白か欧文間空白を挿入する方法

後続の文字に応じて自動的に和欧文間空白か欧文間空白を挿入する方法

- yudai-nkt の投稿
返信数: 4
tcolorbox パッケージの theorems ライブラリを利用しているのですが,和欧文間空白 \xkanjiskip が本来挿入されるべき箇所に欧文間空白 \ が挿入されてしまいます。

% uplatex + dvipdfmx
\documentclass[dvipdfmx,uplatex]{jsarticle}
\usepackage{tcolorbox}
\tcbuselibrary{theorems}
\newcommand*{\fermatlast}{%<br /> 3以上の自然数$n$について$x^n + y^n = z^n$となる自然数$(x, y, z)$の組は存在しない.<br />}
\newtcbtheorem{theorem}{定理}{}{theo}
\begin{document}
\begin{theorem}{フェルマーの最終定理}{}
\fermatlast
\end{theorem}
\begingroup
\xkanjiskip=1zw
\begin{theorem}{フェルマーの最終定理}{}
\fermatlast
\end{theorem}
\endgroup
\end{document}


上のソースにおける定理2では「理」と「2」および「:」と「フ」の間が欧文間空白になっています。

次のような theorem1 環境にすれば,これらの空白は適切に和欧文間空白になりますが,その代わりに今度は定理名が欧文文字から始まるときにもコロンと当該欧文文字の間に和欧文間空白が挿入されてしまいます。

\makeatletter
\newtcbtheorem{theorem1}{定理\@gobble}{separator sign={:\hspace{\xkanjiskip}\@gobble}}{theo1}
\makeatother
\begingroup
\xkanjiskip=1zw
\begin{theorem1}{フェルマーの最終定理}{}
\fermatlast
\end{theorem1}
\begin{theorem1}{Fermatの最終定理}{}
\fermatlast
\end{theorem1}
\endgroup

定理番号は欧文文字であることが(デフォルトから変更しなければ)保証されているので,
定理\@gobbleはつねに意図通りに挙動してくれますが,定理名は「Fermatの最終定理」のように欧文文字が含まれることは十分に考えられます。定理の名称の一文字目が和文文字か欧文文字かに応じてコロンとの間に和欧文間空白か欧文間空白のいずれかを適切に挿入できるようにしたいのですが,欧文間空白を挿入するには \(x)kanjiskip とは異なりソース中に明示的に書く必要があるためか両者を適切に挿入することができません。

定理名が和文文字で始まるか欧文文字で始まるかに応じて挿入する空白量を切り替える方法がもしあれば,ご教授いただけますと幸いです。

yudai-nkt への返信

Re: 後続の文字に応じて自動的に和欧文間空白か欧文間空白を挿入する方法

- Dora TeX の投稿
開発版jsclassesでの \everyparhook の改良に用いた手法を応用して,次のようにして実現してみました。 これでいかがでしょうか。
% uplatex + dvipdfmx
\documentclass[dvipdfmx,uplatex]{jsarticle}
\usepackage{tcolorbox}
\tcbuselibrary{theorems}

\makeatletter

%% 直後のトークンが和文文字なら和欧文間空白 \xkanjiskip を,欧文文字なら欧文間空白 \ を挿入する命令 \@hoge を定義
\def\@hoge{\futurelet\@let@token\@@hoge}
\edef\kanji@character{\detokenize{kanji character }}
\def\@@hoge{\expandafter\expandafter\expandafter\@@@hoge\expandafter\meaning\expandafter\@let@token\kanji@character\relax\@fuga}
\expandafter\def\expandafter\@@@hoge\expandafter#\expandafter1\kanji@character#2#3\@fuga{%
  \def\@tempa{#1}%
  \ifx\@tempa\@empty
    \hskip\xkanjiskip\relax
  \else
    \ 
  \fi}

%%% tcbtheorems.code.tex の定義を改変

%% 「定理」と定理番号との間に強制的に挿入されていた欧文間空白を削除し,pTeXによる和欧文間空白挿入に任せる
\def\tcb@theo@form#1#2{\hbox{#1#2}}

%% 定理名の出力処理を改変
\def\tcb@theo@title#1#2#3{%
  \ifdefempty{#2}{\setbox\z@=\color@hbox#1\color@endbox}{\setbox\z@=\tcb@theo@form{#1}{#2}}%
  \def\temp@a{#3}%
  \ifx\temp@a\@empty\relax%
    \unhbox\z@\kvtcb@terminatorsign%
  \else%
    \setbox\z@=\hbox{\unhbox\z@\kvtcb@separatorsign}% ここに強制挿入されていた欧文間空白を削除
    \hangindent\wd\z@%
    \hangafter=1%
    \mbox{\unhbox\z@}{\tcb@theo@desc@form{\@hoge#3}}\kvtcb@terminatorsign% ここに \@hoge を挿入することで定理名冒頭文字の種類に応じた空白を挿入
  \fi%
}
\makeatother

\newcommand*{\fermatlast}{%
3以上の自然数$n$について$x^n + y^n = z^n$となる自然数$(x, y, z)$の組は存在しない.
}
\newtcbtheorem{theorem}{定理}{}{theo}

\begin{document}
\begin{theorem}{フェルマーの最終定理}{}
\fermatlast
\end{theorem}

\begin{theorem}{Fermatの最終定理}{}
\fermatlast
\end{theorem}

\begingroup
\xkanjiskip=1zw
\begin{theorem}{フェルマーの最終定理}{}
\fermatlast
\end{theorem}

\begin{theorem}{Fermatの最終定理}{}
\fermatlast
\end{theorem}
\endgroup

\end{document}
Dora TeX への返信

Re: 後続の文字に応じて自動的に和欧文間空白か欧文間空白を挿入する方法

- yudai-nkt の投稿

doraTeX さん,ありがとうございます。 \tcb@theo@form を決め打ちで再定義せず theorem name and number ja などのように keyval オプションで変更できるよう改変させていただきましたが,ご提案いただいたコードで本来希望していた通りの出力が得られました。

ここでの \edef\detokenize の必要性などまだ完全には理解していないところもありますが,\meaning <和文文字>kanji character が現れるのを \def のパターンマッチに利用する手法は自分ではぜったい辿りつかなかったので,非常に助かりました。

yudai-nkt への返信

Re: 後続の文字に応じて自動的に和欧文間空白か欧文間空白を挿入する方法

- Dora TeX の投稿
ここでの \edef や \detokenize の必要性などまだ完全には理解していないところもありますが,
\meaning による出力は,通常の文字ではなく,「\the-文字列」と呼ばれる特殊な文字列になります。\the-文字列では空白文字以外のカテゴリーコードが全て12になります(解説)。
\def によるパターンマッチは,カテゴリーコードも含めて照合対象となるので,単に
\def\@@@hoge#1kanji character #2#3\@fuga{...}
のように定義してしまうと,定義時とパターン照合時で kanji character の部分のカテゴリーコードが一致せずマッチしません。 e-TeX の追加プリミティブである \detokenize による出力は \the-文字列になるので,それを \edef で実行させることで,\the-文字列である "kanji character " という文字列を得ています。これにより,\meaning による出力とパターンマッチさせることができます。

e-TeX 拡張の存在が仮定できないような状況下では,一文字ごとのカテゴリーコードを変更する処理が必要です。その際は,カテゴリーコード12に変更してしまった文字は以降通常使用ができなくなることに注意が必要です。その場合のトリックはこちらのサンプルをご参照ください。
Dora TeX への返信

Re: 後続の文字に応じて自動的に和欧文間空白か欧文間空白を挿入する方法

- yudai-nkt の投稿

\the-文字列では空白文字以外のカテゴリーコードが全て12になります

\def によるパターンマッチは,カテゴリーコードも含めて照合対象となる

の二点を今回はじめて知りました。重ねてありがとうございました。