ト部蛸焼のブログ

日頃知ったことをアウトプットするためのブログ

自作コマンドが作る快適なLaTeX環境

こんにちは。ト部蛸焼です。「今回からはアウトプットもしていこう」ということで,今回はLaTeXに関してです。


LaTeXのコマンド

「\hoge」という形をしているコマンドは,LaTeXの様々な機能を呼び出すために使われます。例えば,

\int_{- \infty}^{+ \infty} \frac{1}{\sqrt{2 \pi \sigma^{2}}} \exp \left( - \frac{(x - \mu)^{2}}{2 \sigma^{2}} \right) \mathrm{d}x = 1

と入力すると
\begin{equation}
\int_{- \infty}^{+ \infty} \frac{1}{\sqrt{2 \pi σ^{2}}} \exp \left( - \frac{(x - \mu)^{2}}{2 σ^{2}} \right) \mathrm{d}x = 1
\end{equation}
と出力されます*1

私は,より効率的に綺麗なLaTeX文書を作成する鍵は,コマンドを自分流に洗練させて巧みに用いることだと思います。つまり……

LaTeXは「コマンド育成ゲー」

ということです!(あくまで個人的な意見です。)
……ということで,以下ではコマンドの育成に便利な「コマンドの作成とその管理」について紹介します。


\newcommandと\def

コマンドは\newcommandまたは\defによって作成できます。この2つの役割は基本的には似ていますが,コマンド名が衝突したとき,つまり,既存のコマンド名と同名のコマンドを定義しようとする際には大きな違いを生じます*2。具体的には,\newcommandでは既存のコマンド名と同名のコマンドを作成できず,\defでは従前の定義を上書きして更新します

\defを使ってコマンドを定義していると,意図せず既存のコマンドの定義を破壊してしまう可能性があるので,なるべくなら\newcommandを用いるべきでしょう。ちなみに,\newcommandに対して,既存の定義の書き換えを行う\renewcommandというコマンドがあります。

まとめ
newcommand系でコマンド名の衝突には慎重に


演算子を作る\DeclareMathOperator

\newcommandのほかに\DeclareMathOperatorも覚えておくと便利です。数式には,\sin (\omega t + \varphi)\sin\operatorname{GCD}(m,n)\operatorname{GCD}のように,ある種の演算子が存在します。このような記号を定義する場合,\newcommandよりも\DeclareMathOperatorのほうが簡単に綺麗な見栄えに仕上がります。これを次に示すコードで確認してみます。

\documentclass[uplatex,dvipdfmx]{jsarticle}
\usepackage{amsmath} % DeclareMathOperatorの利用のために必要
\newcommand{\commandrank}{\mathrm{rank}}  % newcommandを用いた定義
\DeclareMathOperator{\operatorrank}{rank} % DeclareMathOperatorを用いた定義
%
\begin{document}
\begin{table}[htbp]
  \centering
  \caption{newcommandとDeclareMathOperatorの比較}
  \begin{tabular}{ll} \hline
    newcommand版 & $\commandrank A$ \\ \hline
    DeclareMathOperator版 & $\operatorrank A$ \\ \hline
  \end{tabular}
\end{table}
\end{document}

実際の出力は次のようになります。

f:id:tobetakoyaki:20190707181642p:plain:w600
newcommandとDeclareMathOperatorの比較

この表によれば,\newcommandだと「rank」と「A」の間が詰まっているものの,\DeclareMathOperatorだとほどよくスペースが挿入されることが分かります*3

「\newcommandが行うことは文字列の置き換えなのでこのような出力になっている」と分かれば\newcommandでもほどよい空隙を挿入することはできますが,手軽に同じことが可能であるというのが,\DeclareMathOperatorの強みでしょう。


コマンドの無効化

しかし,演算子コマンドの定義を修正したい場合には少し注意が必要です。なぜなら\newcommandのときに見たような「\DeclareMathOperatorで定義の上書き」や「\reDeclareMathOperator*4で再定義」といった方法が通用しないからです。実は,\DeclareMathOperatorの場合には,一度コマンドを無効にして新たに定義し直すという方法を採る必要があるようです。具体的に方法を見ていきましょう。ここでは,「デフォルトで設定されている\gcdというコマンド(出力はgcdという演算子)の表記をキャピタライズする」状況を想定します。これを実現するコードは以下の通りです。

\let\gcd\relax % 一度定義を``無効化''
\DeclareMathOperator{\gcd}{GCD}

新たに\GCDという演算子を定義すると大文字の入力が面倒ですが,これだと小文字のまま楽に入力できます。やったね。


コマンドの輸入

LaTeXをある程度使うと,いつも使う「馴染みのコマンド」ができてくると思います。そのようなコマンドを毎回プリアンブル*5で定義するのは非常に面倒です。また,簡単に綺麗な文書を作成するために,先人の積み上げてきた「パッケージ」を拝借しますが,これも次第に「馴染みのパッケージ」ができてくるもので,いちいちプリアンブルに\usepackage{amsmath}などと何行も書くのは非常に面倒です。このようなときには,「普段使うコマンドの定義やパッケージの呼び出しだけを記述した別のファイルを用意して,それを最初に読み込む」という方法が非常に楽です。この方法について説明します。
まず,普段よく使うコマンドやパッケージの呼び出しを行うファイルを用意します。中身は単純で,以下のように(ほとんどは)ただ必要な定義を書き連ねるだけです。

\newcounter{toinum}
\newcommand{\toi}{\refstepcounter{toinum}\sukima\omidashi{問題\thetoinum.}}
\DeclareMathOperator{\lcm}{LCM}

\ProvidesPackage{mypackage}
\usepackage[top=20truemm,bottom=20truemm,left=20truemm,right=20truemm]{geometry}
\usepackage{amsmath,amssymb,amsfonts}
\usepackage{fancybox,ascmac}
\usepackage[dvipdfmx]{graphicx,xcolor}
\usepackage{tikz}
\usepackage[framemethod=tikz]{mdframed}
\usepackage{array,booktabs}
\newcommand{\midashi}[1]{\noindent\textbf{#1}\par}
\newcommand{\omidashi}[1]{\noindent\textbf{\large #1}\par}
\newcommand{\sukima}{\vspace{\baselineskip}}
\DeclareMathOperator{\ordO}{O}
\DeclareMathOperator{\ordTheta}{\Theta}
\DeclareMathOperator{\ordOmega}{\Omega}
\DeclareMathOperator{\conv}{conv}
\DeclareMathOperator{\diag}{diag}
\DeclareMathOperator{\Image}{Im}
\DeclareMathOperator{\Kernel}{Ker}
\DeclareMathOperator{\rank}{rank}

ファイルの拡張子についてですが,1つ目は「.tex」,2つ目は「.sty」にしています。「違いは……?」と聞かれると,今の2つの例に関しては違いは全くもってありません。コマンドの定義をするときに「@」を使う場合は後者のほうが便利なようです(cf. packages - Why use .sty files? - TeX - LaTeX Stack Exchange*6

さて,この2つのファイルを今から新規に作成する文書「newdocument.tex」に輸入してみましょう*7。そのためには\usepackageや\inputを使います

% newdocument.tex
\documentclass[uplatex]{jsarticle}
\usepackage{mypackage} % styファイル向け
\input{newcommand} % texファイル向け
\begin{document}
hogehoge
\end{document}

単純でした。こうしてみると,プリアンブルもすっきりしますし,新しくコマンドを定義するときに「わざわざプリアンブルに戻って定義を追加してまた本文に戻ってくる」なんてことをする必要はなくなります*8。別のファイルの画面に切り替えて編集すればいいだけですから。これで快適な\LaTeX入力が(少しくらいは)可能になることでしょう……!

*1:はてなブログの環境の都合上,このブログ上では\sigmaではなくσと打っています。

*2:そのほかにも「@」を用いることができるか否かといった問題がありますが,少し面倒なので割愛します。

*3:\DeclareMathOperatorでは定義されたコマンドが演算子扱いとなり,演算子用のスペース幅が前後に適用されます。

*4:そもそも見たことありませんが……。

*5:texファイルの中で,文頭から\begin{document}の前までの部分を指します。

*6:この記事を執筆するまで,私はこの違いをあまり意識していませんでした。今まではファイルごとに行う(この意味で局所的な)定義をtexファイルに,全文書に共通して使う(この意味で大域的な)コマンドやパッケージの呼び出しをstyファイルで行っていました。styファイルを使う利点は他にもあるようなので,是非本文中のリンクを参考にしてみてください。

*7:pythonの気持ちで輸入(import)という言葉を使いましたが,LaTeXの文脈では誤りでしょう。

*8:\newcommandに関しては本文中でも定義ができますが,\DeclareMathOperatorや\usepackageはプリアンブルでしか機能しません。