注意
(2022/09/08 追記)この記事にある switchkutoten パッケージはこちらのツイートで触れられているように"3000や"FF00のブロックの文字を丸ごと欧文扱いにするものなので、使う場合はその意味を把握した上でお使いください。 doraTeX さんのupLaTeX文書の句読点を置き換えるや、私がこの記事の後に書いた【LaTeX】句読点をdviの時点で置き換える方法 の方法の方が TeX 的には安全だと思います。
面白いんだけど、ただこの
— 某ZR(ざんねん🙃) (@zr_tex8r) September 7, 2022
「"3000や"FF00のブロックを欧文扱いにする」
というギミックについては
「根本的に危険であって、完璧にする(完全に副作用をなくす)ことはまず無理」
ということを、使う人が確実に把握しておくべきだとも思う🙂#TeX #TeX言語
はじめに
自分は文書を作る時にupLaTeXを使っていますが、ふと句読点に、。ではなく,.を使いたくなるときがあります(このページは、。で書いていますが…)。upLaTeXで句読点を,.にするには以下の方法が考えられます。
- IMEの設定で句読点を,.に変更
- コンパイルのタイミングでそのtexファイル中の、。を,.に変更
- フォントマップを変更
-
newunicodechar
パッケージを使って、。を,.に再定義する。
上の3つはそれぞれ
- IMEの設定を変更するのはメール等ふと、。を使いたくなる状況があるので怖い
- コンパイルのレシピとして変更するのは、他人のファイルの内容を改変してしまう危険がある
- フォントマップの変更がそもそも(LaTeXのフォント周りの知識が少ない自分には)ハードルが高いのと個別のフォントごとにしなくてはならないのが面倒、新しくフォントを増やしたら忘れそう
というデメリットがあるのと、そもそも文書単位で句読点を変えたいというのが自分の希望なので4つ目の方法、newunicodechar
を使う方法を採用します。
再定義の方法
newunicodechar
はplatexでは使えません。upLaTeXでは使えます。LuaLaTeXでも使えます。
LuaLaTeXの場合
プレアンブルに以下を追加。
\usepackage{newunicodechar}
\newunicodechar{、}{,}
\newunicodechar{。}{.}
これだけです。「、」を「,」に「。」を「.」に置き換える前提で書きました。違う組み合わせにしたい場合は適宜置き換えてください。副作用は自分が見たところありません。
upLaTeXの場合
upLaTeXでは和文文字は\newunicodechar
できないという制限があるので一旦「、」(U+3001)「。」(U+3002)が含まれるunicodeブロックの文字のkcatcode
を15
、すなわち欧文扱いとします(ブロック単位でしか変えられません)。このためブロックに含まれる文字(括弧類も含む)を全て再定義する必要があります。
「、」を「,」に「。」を「.」に置き換える場合は
\usepackage{newunicodechar}
\kcatcode"3000=15
\newunicodechar{、}{,}
\newunicodechar{。}{.}
と行きたいところですが、こうすると副作用があります。
例えば次の文書を出力したいとします。
\documentclass[a4j,12pt,uplatex,dvipdfmx]{jsarticle}
\parindent=0em
\pagestyle{empty}
\renewcommand{\baselinestretch}{0}
\begin{document}
普通の文; です.そこで
合字; ...
直後に数字; .1
改行を挟む; です.
あれは
\end{document}
\documentclass[a4j,12pt,uplatex,dvipdfmx]{jsarticle}
\parindent=0em
\pagestyle{empty}
\renewcommand{\baselinestretch}{0}
\usepackage{newunicodechar}
\kcatcode"3000=15
\newunicodechar{、}{,}
\newunicodechar{。}{.}
\begin{document}
普通の文; です。そこで
合字; 。。。
直後に数字; 。1
改行を挟む; です。
あれは
\end{document}
。の後に改行を挟んだときに「.」と「あ」の間に半角スペースが入ってしまいます。
\newunicodechar
の2行を修正してみます。
\newunicodechar{、}{\char"FF0C}
\newunicodechar{。}{\char"FF0E}
今度は直後に数字があると文字化けしてしまいました。これはchar
が"FF0E1
という16進法の数字と勘違いしたからです。直後に数字またはAからFまでのアルファベットを入れても同じことが起こります。
今度は後ろに空白を入れてみましょう。
\newunicodechar{、}{\char"FF0C }
\newunicodechar{。}{\char"FF0E }
spaceを強制的に無視するignorespaces
を入れてみましょう。
\newunicodechar{、}{\char"FF0C\ignorespaces}
\newunicodechar{。}{\char"FF0E\ignorespaces}
合字がダメになってしまいました。合字が使えないと何が困るのかというと例えば(いささか強引な文ですが)
彼は「『やる!僕も。』」と言った。
のような文章を出力したときにこうなります。上が合字ありの出力、下が合字なしの出力です。
\kcatcode
でカギ括弧類と普通の括弧も定義しなおされてしまう(定義しなければならない)のでignorespacesすると下のようになってしまう欠点があります。ということでこの手は使えません。
結局色々試行錯誤したのですが、合字できない、直後の数字で文字化け、改行が空白になる、の3つの副作用はどうしてもどれか1つ残ってしまうことがわかりました。ちなみに試したものは以下です。
後ろに代入したもの
\relax
\empty
\space
-
\@ifnextchar
による条件分岐 -
\@ifx\@nextchar=\par
による条件分岐 {}
- よくわからないけど
\expandafter
\char
の代わりに使ったもの
\UTF
\Uchar
\CID
\symbol
\Ucharcat
その他
- expl3文法 なんかエラーが出た
-
xparse
パッケージの\DeclareDocumentCommand
そもそも\char
がどこまで数字とみなすかをはっきりさせることができれば済む話なのですが…なんでこんなひどい仕様になっているのかがわかりません。
switchkutoten パッケージ
switchkutoten パッケージを作ってみました。このパッケージを読み込むとupLaTeXでも3つの副作用のいずれか付きではありますが、句読点を自由に変換できます。あと警告がうるさいので\newunicodechar
ではなくその元の定義になっている\@namedef
を使用しています。ちなみに途中で
-
\char
が"をつけなければ10進数のunicodeを出すこと -
\Ucharcat 10進数コード 文字コード
で出力すると「直後に数字」の文字化けが起こらない代わりにコンパイルエラーで済む(自分の中でも文字化けとコンパイルエラーのどちらがいいのか賛否両論ありますが…)
という事情から\Ucharcat
を使用しています。
パッケージオプションには以下があります。
- nothing 句読点の組み合わせを変更しない
- cp 「。」「、」を「.」「,」に変更
- cmaru 「.」「、」を「。」「,」に変更
- tenmaru 「.」「,」を「。」「、」に変更
- tenp 「。」「,」を「.」「、」に変更
- empty 直後に何も入れない(。とかの直後に数字があるとエラーになる)
- forcezenkaku 直後に
\ignorespaces
挿入(合字なし) - space 直後にスペース挿入(「。」「.」直後の改行が空白)
があります。デフォルトではnothing
、empty
になっているので「forcezenkaku
またはspace
なしでコンパイルできる」ならば「余計な空白、文字化け等入らず正しい出力になっている」ようになっています。
なお自分は〜です。1日目は…
みたいなのが出てくる文章ではspace
にして。
の次に改行が出たらシンタックスハイライトするようにVSCodeを設定して、そうでない数学とかのレポートではempty
にしています。
誰か副作用なく(u)pLaTeXの中でパッケージとして変換する方法がわかる方がいらっしゃればご教示いただけると幸いです。
(追記 2022/09/08)CMapファイルから置き換える方法
doraTeX さんの記事で本記事を紹介していただきました! ありがとうございます!
上の記事の方法を使うとCMapファイルから、本記事のような副作用なしで[、。]を[,.]に置き換えることができました。
(さらに追記 2022/09/08)dvi の時点で置き換える方法
doraTeX さんの記事と前後するタイミングで「pLaTeX と upLaTeX で置き換えられればよいのだから dvi の段階で置き換えればよいのでは」と思い、【LaTeX】句読点をdviの時点で置き換える方法 を投稿しました。こちらは latexmkrc を使う方法です。こちらも本記事のような副作用なしで[、。]を[,.]に置き換えることができる方法だと思うのでぜひご覧ください。
コードハイライトでミスを減らす(一応)
switchkutoten パッケージのspace
オプションを使うときは「。」の直後に改行してスペースを空けてしまう「ミス」を減らすために特にVSCodeを使用している人であれば次のようなコードハイライトをするといいと思います。VSCodeのHighlight
という拡張機能を使っています。
{
"highlight.regexes": {
"(。\n)": [
{
"border": "1px solid red"
}
],
"(。\n\n)": [
{
"border": "1px solid #1E1E1E"
}
],
"(。\n\\\\begin)": [
{
"border": "2px solid #1E1E1E"
}
],
"(。\n\\\\end)": [
{
"border": "2px solid #1E1E1E"
}
],
"(。\n\\\\item)": [
{
"border": "2px solid #1E1E1E"
}
],
},
}
長く書きましたが要は「。」の後の改行直後にbegin
\end
\item
\n
(改行)のいずれかがこなければ文字を赤い枠で囲むというだけのものです。結構使えます。正規表現を使います。
本当は下の4つは「または」の正規表現を使って一つにまとめたかったのですが、いじっていたら何回かVSCodeが落ちたのでできませんでした。