パソコンでプログラミングしよう ウィンドウズC++プログラミング環境の構築
1.6.3.6(15)
Doxygenのマークダウン形式ファイル

DoxygenのHTML出力の原稿としてマークダウン形式ファイルを用いる方法を説明する。

ドキュメンテーションツールであるDoxygenは修飾機能が豊富で本来のソースコード解析を目的としなくてもリッチなドキュメントを作成できる。本サイトもDoxygen修飾を付加したプレーンテキストとして原稿を作成し、マークダウン形式(拡張子*.md)ファイルとしてDoxygenに処理させたHTML出力を用いている。しかしDoxygenのマークダウン形式の処理には不具合も多く、安定した運用にはいくつかの注意を必要とする。

本サイトでの"マークダウン形式ファイル"はDoxygenの読み込むファイル形式に限定する。独自拡張したコマンドを持ち、他形式コマンドが混在し、厳密に定義される"マークダウン形式ファイル"から恐らく大きくかけ離れる。

なぜマークダウン形式か

Doxygenはプログラミングのソースコード解析が本来の目的で、Doxygen書式のコメント行に各種コマンドを挿入して出力をコントロールする。マークダウン形式ファイルだけが各種コマンドをコメント行でなくプレーンテキストに置くことができる。

Doxygenの豊富な機能を用いれば一般のHTMLドキュメント生成ツールとしても利用できるが、コメント行に長文作成すれば原稿の見通しを悪夢的に損なう。

/**
* \page nakajima_atsushi 中島敦
*
* \section nakajima_atsushi_sangetsuki 山月記
*
* 隴西の李徴は博学才穎、天宝の末年、若くして名を虎榜に連ね、ついで江南尉に補せられたが、性、狷介、自ら恃むところ頗る厚く、賤吏に甘んずるを潔しとしなかった。いくばくもなく官を退いた後は、故山、虢略に帰臥し、人と交を絶って、ひたすら詩作に耽った。下吏となって長く膝を俗悪な大官の前に屈するよりは、詩家としての名を死後百年に遺そうとしたのである。(https://www.aozora.gr.jp/cards/000119/card624.html)
*
* \section nakajima_atsushi_riryou 李陵
*
* 漢の武帝の天漢二年秋九月、騎都尉・李陵は歩卒五千を率い、辺塞遮虜鄣を発して北へ向かった。阿爾泰山脈の東南端が戈壁沙漠に没せんとする辺の磽确たる丘陵地帯を縫って北行すること三十日。朔風は戎衣を吹いて寒く、いかにも万里孤軍来たるの感が深い。漠北・浚稽山の麓に至って軍はようやく止営した。すでに敵匈奴の勢力圏に深く進み入っているのである。(https://www.aozora.gr.jp/cards/000119/card1737.html)
*/

こういった場合、分かち書きの英語なら単語間で改行だが日本語は向かない。そこで山月記を一定カラムで改行してみるが、半角スペースで連結され不自然である。

/**
* \page nakajima_atsushi
*
* 隴西の李徴は博学才穎、天宝の末年、若くして名を虎榜に連ね、ついで江南尉に補
* せられたが、性、狷介、自ら恃むところ頗る厚く、賤吏に甘んずるを潔しとしなか
* った。いくばくもなく官を退いた後は、故山、虢略に帰臥し、人と交を絶って、ひ
* たすら詩作に耽った。下吏となって長く膝を俗悪な大官の前に屈するよりは、詩家
* としての名を死後百年に遺そうとしたのである。
*/

隴西の李徴は博学才穎、天宝の末年、若くして名を虎榜に連ね、ついで江南尉に補 せられたが、性、狷介、自ら恃むところ頗る厚く、賤吏に甘んずるを潔しとしなか った。いくばくもなく官を退いた後は、故山、虢略に帰臥し、人と交を絶って、ひ たすら詩作に耽った。下吏となって長く膝を俗悪な大官の前に屈するよりは、詩家 としての名を死後百年に遺そうとしたのである。

HTMLドキュメント作成に使うコマンド

Doxygenは四つの修飾方法(コマンド)を同一ファイルの中で利用できる。マークダウン形式はMARKDOWN_SUPPORTオプションをYES(デフォルト)とする必要がある。マークダウン形式ファイル(拡張子*.md)でもマークダウン以外の形式が使える。

Doxygen形式

HTMLドキュメント作成において文書の構成要素(ページ、セクション、サブセクションなど)を示すコマンドを構成要素コマンドと定義する。Doxygen形式の構成要素コマンドを示す。

Doxygen形式 概略
\mainpage [(title)] HTMLトップページ(index.html)
\page <name> (title) HTMLページ(*.html)
\section <name> (title) セクションレベル1、章
\subsection <name> (title) サブセクションレベル2、節
\subsubsection <name> (title) サブセクションレベル3、項

ページ相互は\subpageコマンドで上下関係を付ける。トップページを祖とするツリー構造とするのが自然だが、本サイトのセットアップ用語などのようにトップページに並列させる事もできる。並列配置されたページはRelated Pageページに表示される。構成要素は\refコマンドで参照できる。

覚え書き
"Related Page"は本サイトではDoxygenカスタマイズファイルmy_layout.xmlで"記事"というタイトルに変更している。
Doxygen形式 概略
\subpage <name> ["(text)"] ページを参照し上下関係を定義する
\ref <name> ["(text)"] ページやセクションを参照する

\subpageコマンドによるページ間構成と\sectionコマンドなどによるページ内構成を合わせて目次(Table Of Contents)が作成され、GENERATE_TREEVIEWオプションが画面左に表示するツリービューなどに反映される。

マークダウン形式

マークダウン形式のヘッダは構成要素コマンドとして機能する。

覚え書き
マニュアルのDoxygen形式コマンドとマークダウン形式の記述方法と用語が統一されていない。以下の対比ではマニュアルがDoxygen形式の説明に用いるプレースホルダーを概ね踏襲する。
プレースホルダー 意味
<sharp> 単語、空白を含めない
(round) 行末あるいは次の制御文字までの文字列、空白を含める
{curly} { }を含め実際の文字列として扱う
[square] 省略可能なオプション
マークダウン形式のヘッダID文字列(マニュアルの"header id")はDoxygen形式の名前(マニュアルの"name")と機能上差異が無く、以降は<name>で統一する。

等価となるDoxygen形式コマンドと対比する。

Doxygen形式 マークダウン形式1 マークダウン形式2 備考
\mainpage [(title)] (title) {#mainpage}
=======
# (title) # {#mainpage} ファイル先頭の場合
\refからはindexで参照
\page <name> (title) (title) [{#<name>}]
=======
# (title) # [{#<name>}] ファイル先頭の場合
\section <name> (title) (title) [{#<name>}]
=======
# (title) # [{#<name>}] ファイル先頭以外の場合、レベル1
\subsection <name> (title) (title) [{#<name>}]
-------
## (title) ## [{#<name>}] レベル2
\subsubsection <name> (title) - ### (title) ### [{#<name>}] レベル3
- - #### (title) #### [{#<name>}] レベル4
- - ##### (title) ##### [{#<name>}] レベル5、\refで参照できない
- - ###### (title) ###### [{#<name>}] レベル6、\refで参照できない

マークダウン形式1の2行目は=または-のみからなる文字列で、その文字数は2個以上任意である。マークダウン形式2の(title)直後の#文字数は0個以上任意である。マークダウン形式2は最大6レベルのサブセクションを作れるが、\refで参照できるのはレベル4までに限定される。\mainpageを除きDoxygen形式で<name>は必須だがマークダウン形式では省略できる。マークダウン形式は\page(および\mainpage)と\sectionが同一構文で混乱するものの、開発者は"Note that the subsequent sections have to be at the same level as the title in order for them to be rendered as sections within the page (you can call this a bug)"と居直る。

\subpageに対応するマークダウン形式は存在しないが、\refへの対応は存在する。Doxygen形式には外部ウェブページを参照するコマンドが無く、HTLM形式アンカー要素かマークダウン形式を用いる。

Doxygen形式 HTML形式 マークダウン形式 備考
\subpage <name> ["(text)"] - - -
\ref <name> ["(text)"] - [(text)](\ref <name>) マークダウン形式の[ ]はプレースホルダーの記号ではなくて実際の文字
- <a href="<web-address>">(text)</a> [(text)](<web-address>) HTML型式< >は<web-address>を除きタグを表す実際の文字
マークダウン形式の[ ]は実際の文字

マークダウン形式ファイルの先頭に\page(または\mainpage)あるいは対応するマークダウン形式コマンドが無い場合、あるいは先頭のマークダウン形式コマンドが<name>を省略する場合、マニュアルはタイトル((text))とラベル(<name>)をファイル名から作成するとしている。マニュアルに記載は無いがラベルはmd_<page-base-name>の形式で、<page-base-name>はDoxygen実行ディレクトリからファイルまでの相対パスを構成するディレクトリ名と、拡張子を除いたファイル名をアンダースコアで連結する。相対パスが親ディレクトリを含む場合に<page-base-name>がどうなるかは全く不明にある。マニュアルはまた\refコマンドにマークダウン形式ファイル名を直接参照できるとするが、相対パスの影響を受け理解に苦しむ挙動を示す。

以下にマークダウン形式ファイルを実行ディレクトリから異なる相対位置(上位、同じ、下位)として、トップページから\subpageで参照した場合の挙動をまとめる。ファイルが置かれるディレクトリは全てINPUTオプションに指定して、ファイル名にディレクトリは含まない。

ディレクトリ 参照方法 \subpageの参照先 ツリービュー(トップとの関係) Related Page
上位 先頭コマンド<name> HTML表示 子ノードで参照先はHTML表示 表示されない
md_<page-base-name> <page-base-name>が不明
ファイル名 ソースコード表示 兄弟ノードで参照先はHTML表示 参照先はHTML表示
同じ 先頭コマンド<name> HTML表示 子ノードで参照先はHTML表示 表示されない
md_<page-base-name> HTML表示 子ノードで参照先はHTML表示 表示されない
ファイル名 HTML表示 兄弟ノードで参照先はHTML表示 参照先はHTML表示
下位 先頭コマンド<name> HTML表示 子ノードで参照先はHTML表示 表示されない
md_<page-base-name> HTML表示 子ノードで参照先はHTML表示 表示されない
ファイル名 ソースコード表示 兄弟ノードで参照先はHTML表示 参照先はHTML表示

\subpageによる参照なのでトップページの子ノードでRelated Pageに表示されないはずだが、整合性は乏しく過去のバージョンでは異なるケースもある。結論として、ラベルを先頭コマンド<name>で明示するのが最も確実で安定している。

どのコマンド形式を使うべきか

Doxygenが1.8.15にバージョンアップした際にマークダウン形式1はバグを抱えたため現時点では利用を避ける。

Doxygen形式は<name>を必須とする。<name>は全ドキュメント(全原稿)ユニークなID文字列で、ファイル数が多くなるとその管理は負担となる。サイト作成者だけかもしれないが<name>を忘れて(title)のみを与えるミスが多く、その場合(title)として与えたつもりの文字列の最初の空白文字までが<name>と解釈され、以降が(title)となる。(title)が空文字列なら<name>が代わりにラベル表示されるのため、このミスは発見しづらい。他と重複する<name>を持つ構成要素は目次に登録されずツリービューなどに表示されない。一方、マークダウン形式は<name>を省略できる。<name>を持たない構成要素はTOC_INCLUDE_HEADINGSオプション値のレベルまで目次に登録されツリービューなどに表示される。TOC_INCLUDE_HEADINGS値デフォルトをマニュアルは5とするがDoxygen(バージョン1.8.15)生成テンプレートファイルでは0なのでDoxyfileで明示的に設定する。なお<name>を持つ構成要素はTOC_INCLUDE_HEADINGS値と無関係に目次に登録される。

TOC_INCLUDE_HEADINGS値を1以上として、二つのファイルでそれぞれが同じタイトルを持つセクションを定義してみる。Doxygen形式はあえて<name>を忘れるミスを犯す。

\page markdown_file_1 マークダウン形式ファイルその1
\section Doxygen形式のセクション
# マークダウン形式2のセクション #
\page markdown_file_2 マークダウン形式ファイルその2
\section Doxygen形式のセクション
# マークダウン形式2のセクション #

Doxygen形式は二つのセクションでID文字列が衝突し、ツリービューなどに片方しか表示されない。マークダウン形式は両方とも表示される。マークダウン形式(現状では形式2に限定される)の方が<name>の自由度が高くDoxygen形式より優れると結論付けられよう。

検索ボックス

DoxyfileのSEARCHENGINEオプション(デフォルトはYES)でHTML出力に検索ボックスを追加できる。これはソースコード解析ならクラス名、ファイル名、関数名を検索できて有益であるが、ソースコード以外ではページラベルしか検索できない上に日本語による検索に不具合がある。ソースコード解析を含まない一般的なドキュメントならこのオプションをNOとした方が安心できる。

マークダウン形式ファイル

作成の指針

DoxygenによるHTML出力の原稿となるマークダウン形式ファイルを作成する場合の指針を示す。

  1. 原稿はマークダウン形式ファイル(*.md)として作成する。
  2. 文字コードはUTF-8とする。
  3. 長文は不要な改行をせずに打ち続ける。エディタは折り返し表示設定とする。
  4. 一つのファイルで一つのHTMLページを作成する。
  5. ファイル先頭にはマークダウン形式2でページタイトル((title))とユニークなID文字列(<name>)を定義する。
  6. トップページのID文字列はmainpageとする。
  7. セクション、サブセクションはマークダウン形式2でセクションタイトル((title))を定義する。
  8. セクションレベル1の構文がファイル先頭ページタイトルの構文と同じである事に慣れる。
  9. 他から参照するセクション、サブセクションにはユニークなID文字列(<name>)を定義する。
  10. サブセクションの最大深さレベルは4とする。
  11. DoxyfileのTOC_INCLUDE_HEADINGSオプションにID文字列(<name>)を持たないセクション、サブセクションの目次登録レベルを設定する。
  12. ページ、セクション、サブセクションへの参照はID文字列(<name>)を使う。
  13. トップページを参照するときのID文字列はmainpageではなくindexとする。
  14. ページ見出し書式はDoxygenカスタマイズファイルmy_customdoxygen.cssでtitleクラスに設定する。
  15. 各セクション見出しの書式はmy_customdoxygen.cssのh1要素(セクションレベル1)、h2要素(サブセクションレベル2)、h3要素(サブセクションレベル3)、h4要素(サブセクションレベル4)で設定する。
  16. DoxyfileのSEARCHENGINEオプションをNOとして検索ボックスを表示しない。

一つのファイルで一つのHTMLページを作成するとしたが、ファイル途中にDoxygen形式の\pageコマンドを挿入すれば一つのファイルで二つ以上のHTMLページを作成できる。しかし構成要素コマンドをマークダウン形式2に統一する観点から好ましくなく、また一つのファイル一つのページを原則としたほうが管理がたやすい。Doxygenの以前のバージョンで一ファイルから複数ページを作成させていたところサイズ拡大と共に不可解なエラーの発生を経験したこともあり、避けるに越したことはない。

Doxygenは4種類のコマンド形式を同時解釈するためかそれぞれの形式で期待する動作とならない場合があり、特にマークダウン形式にはバグと呼びたい不具合が多い。各形式が干渉し、例えばある形式の制御文字に一致する文字のエスケープ要否がケースバイケースで異なる。トライアンドエラーは避け得ないものとして覚悟する。

サンプル

本サイトトップページの原稿をサンプルとして示す。

# 緒言 # {#mainpage}
\tableofcontents
\head_inserter
<meta name="description" content="N-BASICで初めてプログラミングに触れた世代に属する者として、ウィンドウズパソコンにC++プログラミング環境を金をかけずに構築します。ツールとして、MSYS2、mingw-w64、Code::Blocks、Git for Windows、GNU gettext、Doxygen、Inno Setupを利用します。">
\endhead_inserter
[__プログラミング教育__](http://www.mext.go.jp/a_menu/shotou/zyouhou/detail/1375607.htm)が世間を賑わす。タッチパネルで[__ブロックを組み合わせる__](https://scratch.mit.edu/about)小学生、彼らは[__プログラミング__](https://ja.wikipedia.org/wiki/%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0_(%E3%82%B3%E3%83%B3%E3%83%94%E3%83%A5%E3%83%BC%E3%82%BF))していると言う。我々のプログラミングはしかし、英数字を[__パソコン__](https://ja.wikipedia.org/wiki/%E3%83%91%E3%83%BC%E3%82%BD%E3%83%8A%E3%83%AB%E3%82%B3%E3%83%B3%E3%83%94%E3%83%A5%E3%83%BC%E3%82%BF)に打ち込む作業だった。<a href="https://zatsuneta.com/archives/109281.html"><b id="pc8001-age"></b></a>に[__PC-8001__](https://ja.wikipedia.org/wiki/PC-8000%E3%82%B7%E3%83%AA%E3%83%BC%E3%82%BA)は輝き、パソコンの使用はプログラミングと等価だった。[__ブラウン管__](https://ja.wikipedia.org/wiki/%E3%83%96%E3%83%A9%E3%82%A6%E3%83%B3%E7%AE%A1)に映る[__N-BASIC__](https://ja.wikipedia.org/wiki/N-BASIC)は滲んでいたが、いかなる詩文散文にも増して我らが世代を象徴した。
パソコンはかつてプログラミングする道具だったが、それは今も変わらない。そう、[パソコンでプログラミングしよう](\ref index)。
\htmlonly
<!-- https://momentjs.com/ -->
<!-- https://www.htmlgoodies.com/beyond/javascript/js-ref/formatting-javascript-date-intervals-into-years-months-weeks-and-days.html -->
<script type="text/javascript" src="moment.js" defer></script>
<script>
document.addEventListener('DOMContentLoaded',function()
{
function elapsed_years(since,units)
{
var d=moment(since),d_now=moment();
return units.reduce(function(out,unit){var diff=d_now.diff(d,unit[0]);d.add(diff,unit[0]);return out+diff+unit[1];},'');
}
document.getElementById('pc8001-age').innerHTML=elapsed_years('28 Sep, 1979',[['years','年'],['months','ヶ月と'],['days','日前']]);
})
</script>
\endhtmlonly
# 方針 #
- ハードウェア、消費電力、通信を除き金をかけない。
- ターゲットは[ウィンドウズ](\ref terms_windows)の[32ビット/64ビット](\ref terms_architecture)、[プログラミング言語](\ref terms_programming_language)は[C++](\ref terms_c_plusplus)。
- なるべく具体的な[セットアップ](\ref setup)を示す。深いカスタマイズを目指し[ディープなセットアップ](\ref deepsetup)を試みる。
- プログラミングサンプルとして[簡単なテキストエディタ](\ref texteditor)を作る。これをベースに[高機能化に挑む](\ref texteditor2)。
- [用語](\ref terms)は外部の説明リンク先を示してから本サイトでの解釈を要約する。その際に英語情報の利用をためらわない。
- 説明が[詳細](\ref details)に立ち入る場合は別項目とする。
# 対象とするパソコン #
本サイトの記述は大まかに以下のパソコンを対象とする。
- 64ビットアーキテクチャ
- 64ビットウィンドウズ
- インターネット接続
検証はレノボThinkPad L430で行った。2018年11月に通販購入した中古品でおよそ2万円を出費した。
- Core i5-3210M(2.50GHz)
- 8GiB/SSD125GiB/DVD MULTI
- Win10-Home-64bit
# 著作権表示 #
Copyright © 2019-2024 Takeshi Kodama All Rights Reserved.
<DIV style="color:gray;font:normal 12px Roboto,sans-serif;">
本サイトを利用したウェブサイトの閲覧や情報収集については、情報がユーザーの需要に適合するものか否か、情報の保存や複製その他ユーザーによる任意の利用方法により必要な法的権利を有しているか否か、著作権、秘密保持、名誉毀損、品位保持および輸出に関する法規その他法令上の義務に従うことなど、ユーザーご自身の責任において行っていただきますようお願いいたします。本サイトのご利用につき、何らかのトラブルや損失・損害等につきましては一切責任を問わないものとします。本サイトが紹介しているウェブサイトやソフトウェア・アプリケーション・ツールの合法性、正確性、道徳性、最新性、適切性、著作権の許諾や有無など、その内容については一切の保証を致しかねます。
</DIV>