📖

Linux でも日本語の man page を印刷したい!

2024/11/04に公開

概要

Ubuntu にデフォルトでインストールされている man コマンド、あるいは、そのための最小限の groff システムでは、日本語を含む man page を PostScript に出力することができません。 この記事では、Ubuntu に groff をインストールし、さらに groff のための日本語フォントをインストールすることによって、日本語の man page を PostScript 経由で印刷できるようにするまでの過程を説明します。

環境について

以下の環境で動作を確認しています。 この環境はコンテナの上に作られていますが、通常のインストールでも問題ないはずです。 また、シェルとして bash を利用していることを想定しています。

$ uname -a
Linux alumikan 6.8.12-2-pve #1 SMP PREEMPT_DYNAMIC PMX 6.8.12-2 (2024-09-05T10:03Z) x86_64 x86_64 x86_64 GNU/Linux
$ cat /etc/os-release 
PRETTY_NAME="Ubuntu 24.04.1 LTS"
NAME="Ubuntu"
VERSION_ID="24.04"
VERSION="24.04.1 LTS (Noble Numbat)"
VERSION_CODENAME=noble
ID=ubuntu
ID_LIKE=debian
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
UBUNTU_CODENAME=noble
LOGO=ubuntu-logo

はじめに

Unix な世界にいると、コマンド操作によって何らかの処理をしたり、プログラミング言語 C を用いてプログラムを書いたりする場面に多く遭遇します。 そのような場面で、それらのコマンドの使い方がわからなくなったり、C の関数の機能や振舞いを思い出せなくなったりした場合、どのようにしてそれらを調べますか? 確かに、現代のウェブ検索エンジンは大いに発展していますから、大変よく仕事をしてくれます。 また、近年では ChatGPT をはじめとする生成系 AI などの技術を利用することで、ユーザが望んでいる情報まで対話的に導いてくれるサービスまで登場しています。 しかし、Unix な世界には、創世して間も無い頃からの伝統であるマニュアルページman page)の文化があります[1]。 通常、man page はシステムにインストールされ、実際に利用されているコマンドやライブラリ、カーネルのバージョンと一致しています。 そのため、man page を読むことで、ウェブ上の情報を検索するよりも実際的な情報を得られることもあります。

Man page を読む

Man page を読むには man コマンドを実行します。 最も簡単な方法は、調べたいコマンドや関数の名前などを引数として指定して man コマンドを実行することです。 例えば、cat コマンドについて調べるには man cat のように実行し、C の sin 関数について調べるには man sin のように実行します。 このとき、man page を表示するために適当なページャが起動するかもしれません(Ubuntu では less が起動するようです)。 これを終了するためにはキーボードの q のキーを押下します。

 を実行し、 コマンドの man page を表示している様子
man cat を実行し、cat コマンドの man page を表示している様子

日本語の man page が表示されない

日本語の man page が表示されない場合は、以下のように実行してみてください。

日本語のマニュアルを表示する
$ LANG=ja_JP.UTF-8 man cat	# man は LANG で言語を切り替える

それでも表示されない場合は、日本語の man page がインストールされていないのかもしれません。 以下のように実行することで、日本語の man page をインストールできます。

日本語の man page をインストールする
$ sudo apt update
$ sudo apt upgrade
$ sudo apt install manpages-ja		# 通常のコマンドなどの man page
$ sudo apt install manpages-ja-dev	# C の関数など開発者用の man page

あるいは、ロカールが正しく設定されていないのかもしれません。 その場合、以下のように表示されるはずです。

ロカールが正しく設定されていない
$ LANG=ja_JP.UTF-8 man cat
man: can't set the locale; make sure $LC_* and $LANG are correct

この場合、以下のように実行して日本語のロカール情報を生成することで解決します。

日本語のロカール情報を生成する
$ sudo locale-gen $(cut -d' ' -f1 /usr/share/i18n/SUPPORTED | grep ja_JP)
Generating locales (this might take a while)...
  ja_JP.EUC-JP... done
  ja_JP.UTF-8... done
Generation complete.

Man page のセクション

Man page はいくつかのセクションに分かれて構成されています。 通常は以下の表のように分類されています。

セクションの番号 セクションの内容
1 ユーザコマンド(通常のプログラム)
2 システムコール
3 C ライブラリ関数、サブルーチン
4 スペシャルファイル、デバイスドライバ
5 ファイルフォーマット
6 ゲーム、ユーザによって管理されるコマンド
7 その他の雑多なこと(歴史や標準など)
8 (主に root 用の)システム管理用コマンド
9(非標準) カーネルルーチン

例えば、単に printf といった場合には、ユーザコマンドの printf を指しているのか C ライブラリ関数の printf を指しているのか不明確になってしまいます。 そのため、Unix な世界ではしばしば printf(1)printf(3) のように該当するセクションの番号を添えることがあります。 この記法は man コマンドに対してセクションを指定する場合にも利用できます。 ただし、括弧がシェルによって解釈されることを避けるため、適切にエスケープする必要があります(例えば、man 'printf(3)' のように)。 あるいは、man 3 printf のようにセクション番号を先に渡し、その後に項目の名前を渡すことであったり、man printf.3 のように man page の名前とセクション番号をピリオド(.)で区切ることでもセクション番号を指定できます。

Man page を探す

システムには膨大な量の man page がインストールされていますから、その中から目的の項目を探し出すことはとても難しいことであると思われるかもしれません。 しかし、man コマンドの姉妹コマンドを活用することでその労力を低減できます。 それぞれの man page の冒頭には、その項目の内容を短く説明した要約文が含まれています。 ここで紹介する man コマンドの姉妹コマンドは、この情報を元にシステム上の man page を横断検索してくれます。

要約文を一覧表示する

whatis コマンドは指定された名前にマッチする項目の要約文を一覧表示します。 このコマンドは、調べたい項目がどのセクションに含まれているのかを調べるために有用です。 man コマンドにオプション -f を添えた場合も同様の動作をします。

man に一致する項目の要約文を一覧表示する
$ whatis man
man (1)              - an interface to the system reference manuals
man (7)              - man ページを整形するマクロ
man (1posix)         - display system documentation

要約文からキーワード検索する

apropos コマンドは指定されたキーワードが項目名や要約文に含まれる項目を一覧表示します。 このコマンドは、調べたい内容に関連する項目を見つけるために有用です。 man コマンドにオプション -k を添えた場合も同様の動作をします。

manual に関連する項目を一覧表示する
$ apropos manual
man (1)              - an interface to the system reference manuals
man-recode (1)       - convert manual pages to another encoding
whatis (1)           - display one-line manual page descriptions
apropos (1)          - search the manual page names and descriptions
catman (8)           - create or update the pre-formatted manual pages
manconv (1)          - convert manual page from one encoding to another
mandb (8)            - create or update the manual page index caches
manpath (1)          - determine search path for manual pages
whereis (1)          - locate the binary, source, and manual page files for a...
xman (1)             - Manual page display program for the X Window System
zenity (1)           - manual page for zenity 4.0.1

Man page を印刷用に出力してみる

さて、man コマンドを使って man コマンドの man page を読んでみると、オプション -t を添えることで groff を利用してマニュアルページを整形してくれるとあります[2]。 通常、groff はデフォルトで PostScript を出力します。 この出力を PostScript に対応したプリンタに送信することで man page を紙に印刷できます。

まずは、このコマンドの出力を適当なファイルに保存し、適当なヴューワで眺めてみましょう。 以下のように実行すると、cat コマンドの英語の man page が cat.1.ps に保存されます。

cat コマンドの英語の man page を cat.1.ps に保存する
$ LANG=C man -t cat >cat.1.ps	# LANC=C で英語版になる

出力された PostScript ファイル **cat.1.ps** の描画イメージ
出力された PostScript ファイル cat.1.ps の描画イメージ

しかし、これと同じことを日本語の man page に対して行うと、出力は残念な結果になります。 先ほどと同じように実行すると数多の警告メッセージが表示され、出力結果からは日本語の表示されるべきところが全て抜け落ちてしまいます。 これを印刷した暁には目も当てられない無駄紙ができあがるでしょう。

cat コマンドの日本語の man page を cat.1.ja.ps に保存する
$ LANG=ja_JP.UTF-8 man -t cat >cat.1.ja.ps
troff:<standard input>:2: warning: special character 'u5E74' not defined
troff:<standard input>:2: warning: special character 'u6708' not defined
troff:<standard input>:2: warning: special character 'u30E6' not defined
troff:<standard input>:2: warning: special character 'u30FC' not defined
troff:<standard input>:2: warning: special character 'u30B5_3099' not defined
... (snip) ...

出力された PostScript ファイル **cat.1.ja.ps** の描画イメージ
出力された PostScript ファイル cat.1.ja.ps の描画イメージ

日本語を出力できるようにする

日本語を含む man page を正しく PostScript に出力するためには、groff 上で PostScript を出力する grops システムに日本語フォントをインストールする必要があります。 ここで、groff とは roff と呼ばれる言語で記述された文書をタイプセット(組版)するシステムであり、man コマンドが内部で利用しているものです[3]。 フォントをインストールする方法は grops(1) の man page で詳しく述べられています。 一般によく用いられているフォントの形式として TrueType や OpenType などが挙げられますが、grops は TrueType フォントを変換することで得られる Type 42 形式のフォントを扱います。

ここでは、システムに各種ファイルをインストールし、日本語を含む man page を印刷できる環境を整えます。

下準備

日本語フォントをインストールするために必要な各種コマンドをインストールする必要があります。 以下のように実行します。

必要な各種コマンドをインストールする
$ sudo apt update
$ sudo apt upgrade
$ sudo apt install groff		# 完全版の groff
$ sudo apt install fontforge-nox	# フォント変換コマンド

TrueType フォントのインストール

まずは適当な TrueType フォントをインストールします。 いくつかのフォントを試してみましたが、grops で利用できる形式に正しく変換できるものは多くない印象を受けました。 ここでは、apt 経由でインストールできるさわらび明朝及びさわらびゴシックを利用します。 以下のように実行して、インストールします。

さわらび明朝及びさわらびゴシックをインストールする
$ sudo apt update
$ sudo apt upgrade
$ sudo apt install fonts-sawarabi-gothic fonts-sawarabi-mincho

あるいは、Google Fonts からダウンロードしてきたフォントファイルを手動でインストールすることもできます。

変換用スクリプト

TrueType フォントを grops で利用できる形式に変換するための小さなスクリプトを用意します。 以下の内容を font-install.sh などのように名付けて保存し、実行権限を与えておきます。 このスクリプトは grops(1) のマニュアルページに掲載されているスクリプトを一部修正したものです。

このスクリプトでは、FontForge を利用して TrueType ファイルから PostScript Font ASCII(PFA)形式のフォントと Adobe Font Metrics(AFM)形式の文字情報を生成しています。 また、AFM 形式の文字情報を grops で用いる形式に変換し、フォントの一覧に登録しています。

font-install.sh
#! /bin/sh

set -ex

if [ "$#" -ne "2" -o "$(whoami)" != "root" ]
then
	echo "usage: sudo $0 TTF GFN" 1>&2
	exit 1
fi

MAP="/usr/share/groff/current/font/devps/generate/text.map"
TTF="$1"

BASE="$(basename "$TTF")"
INT="${BASE%.ttf}"
PFA="$INT.pfa"
AFM="$INT.afm"
GFN="$2"

DIR="/usr/share/groff/site-font"
mkdir -p "$DIR/devps"

fontforge -lang=ff -c "Open(\"$TTF\"); Generate(\"$DIR/devps/$PFA\");"
afmtodit "$DIR/devps/$AFM" "$MAP" "$DIR/devps/$GFN"
printf "$BASE\t$PFA\n" >>"$DIR/devps/download"

このスクリプトは以下のような書式で実行されます。 ここで、TTF には TrueType フォントのファイルパスを、GFN には grops におけるフォントの名前を指定します。

font-install.sh の使いかた
$ sudo ./font-install.sh TTF GFN

閑話: Groff におけるフォントの名前

Grops におけるフォントのほとんどは一定の規則に基づいて名付けられます。 フォントには、スタイル(style)と呼ばれる RIB、そして BI の 4 種類の分類があり、これらの 4 種類のスタイルを持つようなファミリ(family)と呼ばれる大分類があります。 例えば、Times ファミリ(T)の Roman スタイル(R)は TR と名付けられ、Helvetica Narrow ファミリ(HN)の BoldOblique スタイル(BI)は HNBI と名付けられます。 ここで、一般的な組版の分野で用いられるようなファミリという語と groff のフォントにおけるファミリという語との間に違いがあることに注意が必要です。 例えば、一般に Helvetica ファミリといった場合には Helvetica や Helvetica Bold、Helvetica Narrow Oblique、そして Helvetica Narrow Bold などがこれに含まれますが、groff においては Helvetica ファミリと Helvetica Narrow ファミリとは異なるファミリとして扱われ、Helvetica ファミリ(H)には Helvetica(HR)や Helvetica Bold(HB)が、Helvetica Narrow ファミリ(HN)には Helvetica Narrow Oblique(HNI)や Helvetica Narrow Bold(NHB)が含まれます。

一方で、例外もいくつか見受けられます。 例えば、ファミリを構成していないフォント ZapfChancery MediumItalic(ZCMI)や、特殊文字を含む Zapf Dingbats(ZD)などです。

日本語フォントのインストール

上で用意したスクリプトを用いて、日本語の文字を持つフォントを grops にインストールします。 ここでは、明朝フォント(M)及びゴシックフォント(G)を作成します。 利用する日本語フォントであるさわらび明朝さわらびゴシックはそれぞれスタイルを 1 種類しか持たず、ファミリを構成できないため、上で紹介した命名規則に従うことを諦めます。 以下のように実行すると、/usr/share/groff/site-font の配下に変換された日本語フォントがインストールされます。

日本語のフォントファミリを grops にインストールする
$ sudo ./font-install.sh /usr/share/fonts/truetype/sawarabi-mincho/sawarabi-mincho-medium.ttf M
$ sudo ./font-install.sh /usr/share/fonts/truetype/sawarabi-gothic/sawarabi-gothic-medium.ttf G

日本語フォントが正しくインストールされたことを確認するには、以下のような内容のファイルを用意します。 適当に check.roff のように名付けておきます。

check.roff
.ft M
明朝体でこんにちは
Hello, world!
.ft G
ゴシック体でこんにちは
Hello, world!

そして、以下のように実行して check.ps を確認します。

check.ps を作成
$ groff -k check.roff >test.ps

明朝体とゴシック体とが日本語で挨拶していれば正しくインストールできています。

明朝体とゴシック体が日本語で挨拶している
明朝体とゴシック体とが日本語で挨拶している

PostScript フォントと日本語フォントとの紐付け

PostScript フォントと日本語フォントとを紐付ける設定を記述します。 以下の内容を記述したファイルを /usr/share/groff/site-tmac/ps.tmac と名付けて保存します。

/usr/share/groff/site-tmac/ps.tmac
.\" -*- nroff -*-
.
.fspecial AR G
.fspecial AI G
.fspecial AB G
.fspecial ABI G
.fspecial BMR M
.fspecial BMI M
.fspecial BMB G
.fspecial BMBI G
.fspecial CR M
.fspecial CI M
.fspecial CB G
.fspecial CBI G
.fspecial HR G
.fspecial HI G
.fspecial HB G
.fspecial HBI G
.fspecial HNR G
.fspecial HNI G
.fspecial HNB G
.fspecial HNBI G
.fspecial NR M
.fspecial NI M
.fspecial NB G
.fspecial NBI G
.fspecial PR M
.fspecial PI M
.fspecial PB G
.fspecial PBI G
.fspecial TR M
.fspecial TI M
.fspecial TB G
.fspecial TBI G
.fspecial ZCMI M
.fspecial S M
.fspecial ZD M
.fspecial SS M
.fspecial EURO M
.fspecial ZDR M

以上で日本語の man page を PostScript に出力できるようになっているはずです。

日本語の man page を印刷用に出力してみる

日本語の man page を PostScript に出力し、適当なヴューワで眺めてみると、英語の man page と同様に正しく表示されることを確認できるはずです。 改めて以下のコマンドを実行すると、cat コマンドの日本語の man page が cat.1.ja.ps に保存されます。

cat コマンドの日本語の man page を cat.1.ja.ps に保存する
$ LANG=ja_JP.UTF-8 man -t cat >cat.1.ja.ps

出力された PostScript ファイル **cat.1.ja.ps** の描画イメージ
出力された PostScript ファイル cat.1.ja.ps の描画イメージ

よくある警告

上で説明した方法で、ほとんどの日本語の man page を PostScript に出力し、綺麗に印刷できるようになります。 しかし、いくつかの警告が表示される場合があります。 ここでは、それらの警告について説明します。

行揃えに失敗

長い行を含む man page を扱う場合、以下のような警告が表示されることがあります。

cannot adjust line の警告が表示される例
$ LANG=ja_JP.UTF-8 man -t 2 open >open.2.ja.ps
troff:<standard input>:204: warning [p 2, 4.1i]: cannot adjust line
troff:<standard input>:209: warning [p 2, 5.3i]: cannot adjust line
troff:<standard input>:370: warning [p 4, 7.8i]: cannot adjust line
troff:<standard input>:396: warning [p 5, 2.2i]: cannot adjust line
troff:<standard input>:516: warning [p 6, 6.9i]: cannot adjust line
troff:<standard input>:820: warning [p 11, 4.5i]: cannot adjust line
troff:<standard input>:822: warning [p 11, 5.0i]: cannot adjust line
troff:<standard input>:843: warning [p 11, 8.0i]: cannot adjust line

英文では単語間のアキを伸縮することによって行の両端を揃えられますが、日本語では単語を分かち書きしないため、伸縮させるアキがありません。 このため、仮名や漢字のみで構成される行が現れた場合、その行の両端を揃えられなくなります。 見栄えこそやや劣るものの、本質的な情報が抜け落ちることはないため、些細な問題です。

行揃えを正しく行えなかった箇所
行揃えを正しく行えなかった箇所

フォントが見つからない

指定された名前のフォントが見つからない場合、以下のような警告が表示されることがあります。 特に、表を含む man page にありがちな警告です。

cannot select font の警告が表示される例
$ LANG=ja_JP.UTF-8 man -t 7 vdso >vdso.7.ja.ps
troff:<standard input>:27: warning [p 1, 2.4i]: cannot adjust line
troff:<standard input>:33: warning [p 1, 3.6i]: cannot adjust line
troff:<standard input>:69: warning [p 2, 1.9i]: cannot adjust line
troff:<standard input>:92: warning: cannot select font 'CW'
troff:<standard input>:132: warning: cannot select font 'CW'
troff:<standard input>:160: warning: cannot select font 'CW'
troff:<standard input>:195: warning: cannot select font 'CW'
troff:<standard input>:213: warning: cannot select font 'CW'
troff:<standard input>:235: warning: cannot select font 'CW'
... (SNIP) ...

CW と名付けられたフォントは存在しませんが、多くの文書でそれを指定するように記述されているようです。 CW が指定された部分は、デフォルトのフォント(通常は Times)によって表示されます。 意図された見栄えではないかもしれませんが、本質的な情報が抜け落ちることはないため、些細な問題です。

文字が定義されていない

フォントに含まれていない文字を含む man page を扱う場合、以下のような警告が表示されます。

special character 'XXX' not defined の警告が表示される例
$ cat kanji.6
.TH KANJI 6 "November 4th, 2024"
.SH "名称"
漢字 \- 敢えて難しい漢字を遣ってみます
.SH "解説"
「揺籃期」のランとかが表示されない筈です。
$ LANG=ja_JP.UTF-8 man -t ./kanji.6 >kanji.6.ja.ps
troff:<standard input>:5: warning: special character 'u7C43' not defined

これは大きな問題です。 日本語を含む man page を表示できなかった問題と全く同じであり、情報が抜け落ちます。 しかも、下駄文字や豆腐文字が表示されることもなく元から何も無かったかのように表示されます。 この警告が出た場合には出力結果を注意深く確認する必要があります。

「揺籃期」のランが表示されていない
「揺籃期」のランが表示されていない

mdoc を使った man page

Man page を記述するためのマクロパッケージには man 及び mdoc があります。 man は従来からのパッケージであり、Linux に関連する man page の多くがこれを用いて記述されています。 mdoc は構造化された文書を記述できるように改良されたパッケージであり、BSD に由来する man page の多くがこれを用いて記述されています。

上で説明した方法によって日本語を含む man page の多くを扱えるようになっていますが、mdoc を用いる man page を正しく表示できないかもしれません。 特に、mdoc について解説している groff_mdoc(7) を表示しようとすると悲惨なことになります。

この問題をいくらかだけ改善できる方法を以下に示しておきます(が、これだけでは足りないようです)。

mdoc に対応する方法

FreeBSD の ja-groff パッケージに含まれている EUC-JP 用のファイルを編集したものを利用します。 これは BSD-2-Clause License の下で利用できます。 以下の内容を記述したファイルを /usr/share/groff/site-tmac/mdoc/ja.UTF-8 と名付けて保存します。

/usr/share/groff/site-tmac/mdoc/ja.UTF-8
.lf 1 ja.UTF-8
.\" -*- coding: utf-8; -*-
.\"
.\" Copyright (C) 2001-2003 FreeBSD JPMAN Project, <man-jp@jp.FreeBSD.org>
.\" All rights reserved.
.\" 
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\"    notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\"    notice, this list of conditions and the following disclaimer in the
.\"    documentation and/or other materials provided with the distribution.
.\" 
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\" 
.\" $FreeBSD$
.\"
.nr volume-operating-system-ateol 0
.ds section-name        \[u540D]\[u79F0]
.ds section-synopsis    \[u66F8]\[u5F0F]
.ds section-description \[u89E3]\[u8AAC]
.ds section-see-also    \[u95A2]\[u9023]\[u9805]\[u76EE]
.ds section-files       \[u95A2]\[u9023]\[u30D5]\[u30A1]\[u30A4]\[u30EB]
.ds section-authors     \[u4F5C]\[u8005]
.ds str-Rv-std-prefix "\[u95A2]\[u6570]
.ds str-Rv-std-suffix "\[u306F]\[u3001]\[u51E6]\[u7406]\[u304C]\[u6210]\[u529F]\[u3059]\[u308B]\[u3068]\[u5024] 0 \[u3092]\[u8FD4]\[u3057]\[u307E]\[u3059]\[u3002]
.as str-Rv-std-suffix "\[u305D]\[u3046]\[u3067]\[u306A]\[u3044]\[u5834]\[u5408]\[u3001]\[u5024] -1 \[u304C]\[u8FD4]\[u3055]\[u308C]\[u3001]
.as str-Rv-std-suffix "\[u30B0]\[u30ED]\[u30FC]\[u30D0]\[u30EB]\[u5909]\[u6570] \*[Va-font]errno\f[P] \[u304C]
.as str-Rv-std-suffix "\[u8A2D]\[u5B9A]\[u3055]\[u308C]\[u3066]\[u30A8]\[u30E9]\[u30FC]\[u3092]\[u793A]\[u3057]\[u307E]\[u3059]\[u3002]
.ds str-Rv-stds-prefix "\[u95A2]\[u6570]
.ds str-Rv-stds-and    "\[u304A]\[u3088]\[u3073]
.ds str-Rv-stds-suffix "\[u306F]\[u3001]\[u51E6]\[u7406]\[u304C]\[u6210]\[u529F]\[u3059]\[u308B]\[u3068]\[u5024] 0 \[u3092]\[u8FD4]\[u3057]\[u307E]\[u3059]\[u3002]
.as str-Rv-stds-suffix "\[u305D]\[u3046]\[u3067]\[u306A]\[u3044]\[u5834]\[u5408]\[u3001]\[u5024] -1 \[u304C]\[u8FD4]\[u3055]\[u308C]\[u3001]
.as str-Rv-stds-suffix "\[u30B0]\[u30ED]\[u30FC]\[u30D0]\[u30EB]\[u5909]\[u6570] \*[Va-font]errno\f[P] \[u304C]
.as str-Rv-stds-suffix "\[u8A2D]\[u5B9A]\[u3055]\[u308C]\[u3066]\[u30A8]\[u30E9]\[u30FC]\[u3092]\[u793A]\[u3057]\[u307E]\[u3059]\[u3002]
.ds str-Rv-std0 "\[u6210]\[u529F]\[u3057]\[u3066]\[u7D42]\[u4E86]\[u3057]\[u305F]\[u3068]\[u304D]\[u306B]\[u306F]\[u5024] 0 \[u3092]\[u8FD4]\[u3057]\[u307E]\[u3059]\[u3002]
.as str-Rv-std0 "\[u305D]\[u3046]\[u3067]\[u306A]\[u3044]\[u5834]\[u5408]\[u3001]\[u5024] -1 \[u304C]\[u8FD4]\[u3055]\[u308C]\[u3001]
.as str-Rv-std0 "\[u30B0]\[u30ED]\[u30FC]\[u30D0]\[u30EB]\[u5909]\[u6570] \*[Va-font]errno\f[P] \[u304C]
.as str-Rv-std0 "\[u8A2D]\[u5B9A]\[u3055]\[u308C]\[u3066]\[u30A8]\[u30E9]\[u30FC]\[u3092]\[u793A]\[u3057]\[u307E]\[u3059]\[u3002]
.ds str-Ex-std-prefix "\[u30E6]\[u30FC]\[u30C6]\[u30A3]\[u30EA]\[u30C6]\[u30A3]
.ds str-Ex-std-suffix "\[u306F]\[u3001]\[u6210]\[u529F]\[u3059]\[u308B]\[u3068] 0 \[u3067]\[u3001]
.as str-Ex-std-suffix "\[u30A8]\[u30E9]\[u30FC]\[u304C]\[u3042]\[u3063]\[u305F]\[u5834]\[u5408]\[u306F] >0 \[u3067]\[u7D42]\[u4E86]\[u3057]\[u307E]\[u3059]\[u3002]
.ds str-Ex-stds-prefix "\[u30E6]\[u30FC]\[u30C6]\[u30A3]\[u30EA]\[u30C6]\[u30A3]
.als str-Ex-stds-and str-Rv-stds-and
.ds str-Ex-stds-suffix "\[u306F]\[u3001]\[u6210]\[u529F]\[u3059]\[u308B]\[u3068] 0 \[u3067]\[u3001]
.as str-Ex-stds-suffix "\[u30A8]\[u30E9]\[u30FC]\[u304C]\[u3042]\[u3063]\[u305F]\[u5834]\[u5408]\[u306F] >0 \[u3067]\[u7D42]\[u4E86]\[u3057]\[u307E]\[u3059]\[u3002]
.ds str-Lb-libarm32    ARM32 \[u30A2]\[u30FC]\[u30AD]\[u30C6]\[u30AF]\[u30C1]\[u30E3]\[u30E9]\[u30A4]\[u30D6]\[u30E9]\[u30EA] (libarm32, \-larm32)
.ds str-Lb-libc        \[u6A19]\[u6E96] C \[u30E9]\[u30A4]\[u30D6]\[u30E9]\[u30EA] (libc, \-lc)
.ds str-Lb-libcompat   \[u4E92]\[u63DB]\[u30E9]\[u30A4]\[u30D6]\[u30E9]\[u30EA] (libcompat, \-lcompat)
.ds str-Lb-libcrypt    \[u6697]\[u53F7]\[u30E9]\[u30A4]\[u30D6]\[u30E9]\[u30EA] (libcrypt, \-lcrypt)
.ds str-Lb-libcurses   curses \[u30E9]\[u30A4]\[u30D6]\[u30E9]\[u30EA] (libcurses, \-lcurses)
.ds str-Lb-libedit     \[u30B3]\[u30DE]\[u30F3]\[u30C9]\[u30E9]\[u30A4]\[u30F3]\[u30A8]\[u30C7]\[u30A3]\[u30BF]\[u30E9]\[u30A4]\[u30D6]\[u30E9]\[u30EA] (libedit, \-ledit)
.ds str-Lb-libi386     i386 \[u30A2]\[u30FC]\[u30AD]\[u30C6]\[u30AF]\[u30C1]\[u30E3]\[u30E9]\[u30A4]\[u30D6]\[u30E9]\[u30EA] (libi386, \-li386)
.ds str-Lb-libipsec    IPsec \[u30DD]\[u30EA]\[u30B7]\[u5236]\[u5FA1]\[u30E9]\[u30A4]\[u30D6]\[u30E9]\[u30EA] (libipsec, \-lipsec)
.ds str-Lb-libkvm      \[u30AB]\[u30FC]\[u30CD]\[u30EB]\[u30C7]\[u30FC]\[u30BF]\[u30A2]\[u30AF]\[u30BB]\[u30B9]\[u30E9]\[u30A4]\[u30D6]\[u30E9]\[u30EA] (libkvm, \-lkvm)
.ds str-Lb-libm        \[u6570]\[u5024]\[u8A08]\[u7B97]\[u30E9]\[u30A4]\[u30D6]\[u30E9]\[u30EA] (libm, \-lm)
.ds str-Lb-libmenu     curses \[u30E1]\[u30CB]\[u30E5]\[u30FC]\[u30E9]\[u30A4]\[u30D6]\[u30E9]\[u30EA] (libmenu, \-lmenu)
.ds str-Lb-libossaudio OSS \[u30AA]\[u30FC]\[u30C7]\[u30A3]\[u30AA]\[u30A8]\[u30DF]\[u30E5]\[u30EC]\[u30FC]\[u30B7]\[u30E7]\[u30F3]\[u30E9]\[u30A4]\[u30D6]\[u30E9]\[u30EA] (libossaudio, \-lossaudio)
.ds str-Lb-libposix    \*[Px] \[u4E92]\[u63DB]\[u30E9]\[u30A4]\[u30D6]\[u30E9]\[u30EA] (libposix, \-lposix)
.ds str-Lb-libresolv   DNS \[u30EA]\[u30BE]\[u30EB]\[u30D0]\[u30E9]\[u30A4]\[u30D6]\[u30E9]\[u30EA] (libresolv, \-lresolv)
.ds str-Lb-libtermcap  termcap \[u30A2]\[u30AF]\[u30BB]\[u30B9]\[u30E9]\[u30A4]\[u30D6]\[u30E9]\[u30EA] (libtermcap, \-ltermcap)
.ds str-Lb-libutil     \[u30B7]\[u30B9]\[u30C6]\[u30E0]\[u30E6]\[u30FC]\[u30C6]\[u30A3]\[u30EA]\[u30C6]\[u30A3]\[u30E9]\[u30A4]\[u30D6]\[u30E9]\[u30EA] (libutil, \-lutil)
.ds str-Lb-libz        \[u5727]\[u7E2E]\[u30E9]\[u30A4]\[u30D6]\[u30E9]\[u30EA] (libz, \-lz)
.ds volume-ds-1 \[u4E00]\[u822C]\[u30B3]\[u30DE]\[u30F3]\[u30C9]\[u30DE]\[u30CB]\[u30E5]\[u30A2]\[u30EB]
.ds volume-ds-2 \[u30B7]\[u30B9]\[u30C6]\[u30E0]\[u30B3]\[u30FC]\[u30EB]\[u30DE]\[u30CB]\[u30E5]\[u30A2]\[u30EB]
.ds volume-ds-3 \[u30E9]\[u30A4]\[u30D6]\[u30E9]\[u30EA]\[u95A2]\[u6570]\[u30DE]\[u30CB]\[u30E5]\[u30A2]\[u30EB]
.ds volume-ds-4 \[u30AB]\[u30FC]\[u30CD]\[u30EB]\[u30A4]\[u30F3]\[u30BF]\[u30D5]\[u30A7]\[u30FC]\[u30B9]\[u30DE]\[u30CB]\[u30E5]\[u30A2]\[u30EB]
.ds volume-ds-5 \[u30D5]\[u30A1]\[u30A4]\[u30EB]\[u30D5]\[u30A9]\[u30FC]\[u30DE]\[u30C3]\[u30C8]\[u30DE]\[u30CB]\[u30E5]\[u30A2]\[u30EB]
.ds volume-ds-6 \[u30B2]\[u30FC]\[u30E0]\[u30DE]\[u30CB]\[u30E5]\[u30A2]\[u30EB]
.ds volume-ds-7 \[u591A]\[u65B9]\[u9762]\[u306E]\[u60C5]\[u5831]\[u30DE]\[u30CB]\[u30E5]\[u30A2]\[u30EB]
.ds volume-ds-8 \[u30B7]\[u30B9]\[u30C6]\[u30E0]\[u7BA1]\[u7406]\[u8005]\[u30DE]\[u30CB]\[u30E5]\[u30A2]\[u30EB]
.ds volume-ds-9 \[u30AB]\[u30FC]\[u30CD]\[u30EB]\[u958B]\[u767A]\[u8005]\[u30DE]\[u30CB]\[u30E5]\[u30A2]\[u30EB]

加えて、/usr/share/groff/site-tmac/mdoc.local に以下の内容を追加します。

/usr/share/groff/site-tmac/mdoc.local(追加)
.if "\V[LANG]"ja_JP.UTF-8" .do mso mdoc/ja.UTF-8

おまけ: 文書も書ける話

Groff は man page を整形するためだけのツールではありません。 ms パッケージや mm パッケージなどを用いることで、記事や覚書を書くこともできます。 詳細は groff_ms(7)groff_mm(7) の man page で解説されています。

**ms** パッケージを使った文書の例
ms パッケージを使った文書の例

おわりに

おわりです。

謝辞

この記事をさっさと完成させるように仕向け、唆してくれた yude 氏に熱烈に感謝します。


参考

脚注
  1. man コマンドは 2nd Edition UNIX の時点で登場しています。 ↩︎

  2. 歴史的に、man コマンドにオプション -t を添えた場合、troff コマンドによってタイプセットが行われていました。 オプション文字の t はこの名残です。 ↩︎

  3. Ubuntu の man コマンドは groff を利用していますが、別のいくつかのディスリビューションでは異なるフォーマットシステム(例えば、mandoc)を使っているかもしれません。 ↩︎

Discussion