様々な言語に対応したシンタックスハイライトツールHighlightについて。
ソースからのビルド・インストール
LuaおよびBoostに依存するため、あらかじめインストールしておく。
sudo apt install liblua5.3-0 liblua5.3-dev libboost-dev
ソースのダウンロード、展開。
curl http://www.andre-simon.de/zip/highlight-3.56.tar.bz2 -o highlight-3.56.tar.bz2
tar -xvf highlight-3.56.tar.bz2
cd highlight-3.56/
パッケージにはconfigureは含まれておらず、標準では/usr
にインストールされる。 /usr
以外にインストールする場合は、以下のようにmakefileを直接編集する。
11c11
< PREFIX = /usr
---
> PREFIX = /usr/local
Ubuntu 18.04+liblua5.2では、makeしようとした際にLuaライブラリのパス取得で失敗したため、src/makefile
の次の箇所を編集する必要があった。
36c36
41c41
< LUA_CFLAGS=$(shell pkg-config --cflags lua) -DUSE_LUA52
---
> LUA_CFLAGS=$(shell pkg-config --cflags lua5.2) -DUSE_LUA52
44c44
< LUA_LIBS=$(shell pkg-config --libs lua)
---
> LUA_LIBS=$(shell pkg-config --libs lua5.2)
make, make installする。
make
sudo make install
参考までに、Intel Core i5-6402Pを積んだマシンでの所要時間は以下のとおり。
$ time make -j4 real 0m22.300s user 1m17.202s sys 0m4.161s
インストールできたら、確認をかねて--list-scripts=langs
でハイライトできる言語の一覧を表示する。
$ highlight --list-scripts=langs Installed langDefs (located in /usr/local/share/highlight/langDefs/): ABAP/4 : abap4 ( abp ) ABC : abc Advanced Backus-Naur Form : abnf ActionScript : actionscript ( as ) ADA95 : ada ( a adb ads gnad ) Agda : agda ALAN Interactive Fiction Language: alan ( alan i ) ALGOL 68 : algol ( alg ) : :
ここまでの操作ではコマンドラインインターフェイスのみしかビルドされない。 GUIが必要な場合は、以下のコマンドでビルドする。
make gui
sudo make install-gui
SWIGでC#用バインディングを作成する
extras/swig/highlight.i
にSWIGのインターフェイス定義ファイルが用意されているので、これを使ってC#用バインディングを作成する。 なお、ここで使用したSWIGのバージョンは3.0.12である。
ビルド済みのC#バインディングを含むラッパーライブラリをSmdn.LibHighlightSharpで公開しています。
用意されているmakefileはPython, Perl用のバインディングを作成するようにしか書かれていないので、これに追記してC#用バインディングを作成するmakefileを書く。 追記する内容は以下の通り。
3c3,4
< CFLAGS=-g -O2 -fPIC
---
> CFLAGS=-g -O2 -fPIC -std=c++0x
> CSC=mcs
8,9c9,10
< LUA_CFLAGS=$(shell pkg-config --cflags lua)
< LUA_LIBS=$(shell pkg-config --libs lua)
---
> LUA_CFLAGS=$(shell pkg-config --cflags lua5.2)
> LUA_LIBS=$(shell pkg-config --libs lua5.2)
34c35,41
< clean: python-clean perl-clean php-clean
---
> csharp: lib-stamp
> swig -c++ -csharp -o highlight_wrap.cpp -dllimport libhighlight -namespace highlight highlight.i
> ${CXX} ${CFLAGS} -c highlight_wrap.cpp ${LUA_CFLAGS} -I${HL_INC}
> ${CXX} -shared -s highlight_wrap.o -L${HL_SRC} -lhighlight ${LUA_LIBS} -o libhighlight.so
> ${CSC} /t:library /out:highlight.dll *.cs
>
> clean: python-clean perl-clean php-clean csharp-clean
48c55,58
< .PHONY: python python-clean perl perl-clean php php-clean clean
---
> csharp-clean:
> rm -f highlight.so highlight_wrap.cpp *.cs *.o
>
> .PHONY: python python-clean perl perl-clean php php-clean csharp csharp-clean clean
ここでswigに渡しているオプションの詳細は次の通り。
- -dllimport libhighlight
- 参照するライブラリのファイル名(DllImport属性で指定される)をlibhighlightに指定
- -namespace highlight
- 生成されるアセンブリのルート名前空間をhighlightに指定
makefileへの追記が済んだらmake csharpでmakeする。
$ make csharp : : swig -c++ -csharp -o highlight_wrap.cpp -dllimport libhighlight -namespace highlight highlight.i ../../src/include/codegenerator.h:86: Warning 503: Can't wrap 'operator =' unless renamed to a valid identifier. g++ -g -O2 -fPIC -std=c++0x -c highlight_wrap.cpp -I/usr/include/lua5.3 -I../../src/include/ g++ -shared -s highlight_wrap.o -L../../src/ -lhighlight -llua5.3 -o libhighlight.so mcs /t:library /out:highlight.dll *.cs
これでライブラリhighlight.soおよびラッパhighlight.dllが作成される。 作成したラッパが動作するかテストコードを作ってテストしてみる。
using System;
using highlight;
class testmod {
static void Main(string[] args)
{
var gen = CodeGenerator.getInstance(OutputType.HTML);
var input =
@"public class Test {
static void Main(string[] args)
{
Console.WriteLine(""Hello, world!"");
}
}";
gen.initTheme("/usr/local/share/highlight/themes/edit-msvs2008.theme");
gen.loadLanguage("/usr/local/share/highlight/langDefs/csharp.lang");
gen.setIncludeStyle(true);
gen.setEncoding("UTF-8");
Console.WriteLine(gen.generateString(input));
CodeGenerator.deleteInstance(gen);
}
}
上記のコードをコンパイル・実行すると、HTMLでマークアップされたハイライト済みのテキストが出力される。
$ mcs -r:./highlight.dll testmod.cs && mono testmod.exe > test.html
public class Test { static void Main(string[] args) { Console.WriteLine("Hello, world!"); } }
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Source file</title> <style type="text/css"> /* highlight theme: Visual Studio IDE */ body.hl { background-color:#ffffff; } pre.hl { color:#000000; background-color:#ffffff; font-size:10pt; font-family:'Courier New',monospace;} .hl.num { color:#000000; } .hl.esc { color:#a31515; } .hl.str { color:#a31515; } .hl.pps { color:#0000ff; } .hl.slc { color:#008000; } .hl.com { color:#008000; } .hl.ppc { color:#0000ff; } .hl.opt { color:#000000; } .hl.ipl { color:#a31515; } .hl.lin { color:#2b91af; } .hl.kwa { color:#0000ff; } .hl.kwb { color:#0000ff; } .hl.kwc { color:#2b91af; } .hl.kwd { color:#000000; } </style> </head> <body class="hl"> <pre class="hl"><span class="hl kwa">public class</span> Test <span class="hl opt">{</span> <span class="hl kwa">static void</span> <span class="hl kwd">Main</span><span class="hl opt">(</span><span class="hl kwa">string</span><span class="hl opt">[]</span> args<span class="hl opt">)</span> <span class="hl opt">{</span> Console<span class="hl opt">.</span><span class="hl kwd">WriteLine</span><span class="hl opt">(</span><span class="hl str">"Hello, world!"</span><span class="hl opt">);</span> <span class="hl opt">}</span> <span class="hl opt">}</span> </pre> </body> </html> <!--HTML generated by highlight 3.56, http://www.andre-simon.de/-->