Re:VIEW(EPUB)でコードリストをシンタックスハイライトする方法

Re:VIEW シンタックスハイライト

Re:VIEW シンタックスハイライト

rougeでシンタックスハイライト

2018年8月、Re:VIEWのEPUB生成でrougeを使用してコードリストをシンタックスハイライトにしました。

Re:VIEWのバージョンは2.5.0です。

>review version
2.5.0

rougeのバージョンは3.2.0です。

>rougify version
3.2.0

Windows10に書籍執筆支援システム「Re:VIEW」をインストールして使用しています。

Windows10に Re:VIEW 執筆支援システムをインストールする方法

ソースコードリスト

Re:VIEW フォーマットガイドによると、原稿にソースコードを入れるには、4種類の方法があります。

連番 行番号 コマンド
あり なし //list[識別子][キャプション][言語指定]{ ~ //}
あり あり //listnum[識別子][キャプション][言語指定]{ ~ //}
なし なし //emlist[キャプション][言語指定]{ ~ //}
なし あり //emlistnum[キャプション][言語指定]{ ~ //}
  • 識別子 : リストを参照するときのID
  • キャプション : リストのタイトル
  • 言語指定 : ソースコードの言語(省略可能)

ソースコードを参照するときは、@<list>{識別子}と記述します。

Re:VIEWテスト原稿

下記のようなテスト原稿(sample6.re)を作成します。
C++言語のソースコードリストを行番号付きで入れます。言語指定はどのように記述するか不明ですが、取りあえず「cpp」としました。

= ソースコードリスト

C++言語で書いたプログラムコードを@<list>{sample}に示します。

//listnum[sample][ラスタースキャン・ループ][cpp]{
void Image_process( ImageFunc efunc ,int iw ,int ih ,const uchar *pucSrc ,uchar *pucDst )
{
    for(int iy=1; iy<ih-1; iy++)
    {
        for(int ix=1; ix<iw-1; ix++)
        {
            uchar uc = pucSrc[ (iy+0)*iw + (ix+0) ];    // 中央
            uchar ua = pucSrc[ (iy-1)*iw + (ix+0) ];    // 上
            uchar ub = pucSrc[ (iy+1)*iw + (ix+0) ];    // 下
            uchar ul = pucSrc[ (iy+0)*iw + (ix-1) ];    // 左
            uchar ur = pucSrc[ (iy+0)*iw + (ix+1) ];    // 右
            //
            uchar ux = Func_dilation(uc ,ua ,ub ,ul ,ur); 
            pucDst[ iy*iw + ix ] = ux;
        }
    }
}
//}

EPUB生成

生成したEPUBを確認します。

EPUB コードリスト

EPUB コードリスト

すっきりしたコードリストですが、少々不満があります。

  • 等幅フォントでないのでリストが見づらい
  • コードリストの背景に薄い色があったほうがよい

PDF生成

生成したPDFを確認します。

PDF コードリスト

PDF コードリスト

TeXらしく美しいコードリストです。等幅フォントでリストは見やすいです。

コードリストの改善

Re:VIEWで生成したEPUBの内容を解析してみます。EPUBをzip解凍して、コードを確認します。(OEBPS>sample6.xhtml)

<div id="sample" class="code">
<p class="caption">リスト1.1: ラスタースキャン・ループ</p>
<pre class="list language-cpp">
 1: void Image_process( ImageFunc efunc ,int iw ,int ih ,const uchar *pucSrc ,uchar *pucDst )
 2: {
 3:     for(int iy=1; iy&lt;ih-1; iy++)
 4:     {
     ・・・ 省略
16:     }
17: }
</pre>
</div>

codeクラスの<DIV>タグで全体を囲み、list language-cppクラスの<PRE>タグでソースコードを囲んでいます。

スタイルシートの変更で解決できそうです。

スタイルシートは、config.ymlで指定します。

# CSSファイル(配列で複数指定可)
stylesheet: ["style.css"]

スタイルシートstyle.cssの定義を確認します。

pre.emlist, pre.source, pre.list {
    margin: 0;
    padding: 5px;
    border: 1px #aaa solid;
    background-color: gainsboro;
    font-family: monospace ;
}

listクラスの<PRE>タグに、背景色(background-color:)とフォントファミリー(font-family: monospace )を追加します。

生成したEPUBを確認します。

EPUB コードリストの改善

EPUB コードリストの改善

等幅フォントでコードリストがそろい、またコードリストの背景に色がつきました。

rougeでシンタックスハイライト

listコマンドの言語指定は省略可能ですが、どのような意味を持つのでしょうか。

Re:VIEW フォーマットガイドに次のように記載があるだけで詳細は不明です。

言語指定は、ハイライトを有効にしたときに利用されます。

Re:VIEWでハイライトができそうです。しかし、方法がわかりません。Re:VIEWは素晴らしいツールなのですが、情報が少なくて苦労します。

調べてみると、config.ymlにハイライトの設定がありました。

# ソースコードハイライトを利用する (rouge,pygmentsには外部gemが必要)
# highlight:
#   html: "rouge"
#   latex: "listings"

知ってる人は当たり前のことなのでしょうが、私はrougeやpygmentsは何なのかわかりません。rougeについて調べてみると、RougeはRubyで書いたシンタックスハイライトのようです。

An elegant, extendable code highlighter written in pure Ruby.
純粋なRubyで書かれたエレガントで拡張可能なコードハイライター。

デフォルトでは、コメントアウトになっていたので highlight:を有効にしてhtml: “rouge”を選びます。

# ソースコードハイライトを利用する (rouge,pygmentsには外部gemが必要)
highlight:
     html: "rouge"
#   latex: "listings"

外部gemが必要と書いてあるので、別途インストールが必要です。

>gem install rouge
Fetching: rouge-3.2.0.gem (100%)
Successfully installed rouge-3.2.0
Parsing documentation for rouge-3.2.0
Installing ri documentation for rouge-3.2.0
Done installing documentation for rouge after 13 seconds
1 gem installed

>rougify version
3.2.0

生成したEPUBを確認すると、少しだけシンタックスハイライトになりました。

EPUB コードリスト rouge組み込み

EPUB コードリスト rouge組み込み

想像していたハイライトとは違って少し地味です。

CSS定義で改善

Re:VIEWで生成したEPUBの内容を解析してみます。EPUBをzip解凍して、コードを確認します。(OEBPS>sample6.xhtml)

<div id="sample" class="code">
<p class="caption">リスト1.1: ラスタースキャン・ループ</p>
<table class="highlight rouge-table">
<tbody>
 <tr>
  <td class="rouge-gutter gl">
     <pre class="lineno">1…</pre>
  </td>
  <td class="rouge-code">
     <pre><span class="kt">void</span> <span class="nf">Image_process</span>
       ・・・・
     </pre>
  </td>
 </tr>
</tbody>
</table>

codeクラスの<DIV>タグで全体を囲み、テーブルで行番号とコード本体を分離し、rouge-codeクラスの<PRE>タグでソースコードがわからないぐらい<span>による装飾をしています。

rouge用のスタイルシートが必要みたいです。調べてみると、rougeはスタイルシートを生成できるみたいです。

>rougify
usage: rougify [command] [args...]

where <command> is one of:
        highlight       highlight code
        help            print help info
        style           print CSS styles
        list            list available lexers
        guess           guess the languages of file
        version         print the rouge version number

See `rougify help <command>` for more info.

>rougify style > rouge.css

スタイルシートをリダイレクトしてrouge.cssに出力します。

スタイルシートは、config.ymlで指定しています。

# CSSファイル(配列で複数指定可)
stylesheet: ["style.css"]

rouge.cssも追加します。

# CSSファイル(配列で複数指定可)
stylesheet: ["style.css" ,"rouge.css"]

生成したEPUBを確認します。

EPUB コードリスト rouge+CSS

EPUB コードリスト rouge+CSS

とてもカラフルなシンタックスハイライトになりました。

rougeの言語指定

//listコマンドの言語指定は、rougeに渡されるわけです。rougeが認識する言語指定について調べてみます。

>rougify
usage: rougify [command] [args...]

where <command> is one of:
        highlight       highlight code
        help            print help info
        style           print CSS styles
        list            list available lexers
        guess           guess the languages of file
        version         print the rouge version number

See `rougify help <command>` for more info.

>rougify list
  ・・・
c: The C programming language
  ・・・
cpp: The C++ programming language [aliases: c++]
  ・・・

百種類以上の言語を指定できるようです。C++言語の言語指定は、cppで正解でした。

CSS定義でもう少し改善

等幅フォントではないのでコードリストがそろっていません。スタイルシートをもう少し修正します。

スタイルシートrouge.cssの定義の最後に下記を追加します。

.rouge-code pre{
    font-family: monospace ;
}

生成したEPUBを確認します。

EPUB コードリスト rouge+CSS 等幅フォント

等幅フォントになりコードリストがそろいました。

まとめ

書籍執筆支援システム「Re:VIEW(EPUB)」でrougeを使用してコードリストをシンタックスハイライトにしました。

Re:VIEW(EPUB)は、外部ツールで拡張してスタイル変更により見え方を変更できるのでとても便利です。