はじめに
WinMergeのソースコードに手を加え、D言語のシンタックスハイライト機能を追加しました。
WinMergeのビルド方法や追加した機能ついて、書いてみたいと思います。
※v2.16.17以降に組み込まれる予定です。
WinMergeとは
詳細な説明は公式サイトを参照してください。私は普段からソースコードの修正時に愛用しています。
開発環境
WinMergeの実行モジュールであるWinMergeU.exe
をビルドする際に必要なアプリケーションと、参考までに、私の開発環境のバージョンを紹介します。
インストーラを含む全体のビルドを行いたい方は、WinMerge GitHubのページを確認してください。
- Windows 10 (バージョン 2004)
- Visual C++ ビルドツール 2019 (v16.11.5) → インストール手順
- MSVC v142 Buildtools
- C++ MFC for v142 Buildtools
- Windows SDK (10.0.19041.0)
- Git (version 2.24.1.windows.2)
- 7-Zip (Ver 19.00)
参考:Visual Studio Build Tools 2019 インストール対象
WinMergeのビルド
GitHubから WinMergeのソースコードを取得し、ビルドを行います。
WinMergeの実行モジュールであるWinMergeU.exe
がD:\Dev\winmerge\Build\x64\Release
に作成されました。
D:\Dev> git clone https://github.com/winmerge/winmerge
Cloning into 'winmerge'...
remote: Enumerating objects: 124830, done.
remote: Counting objects: 100% (1119/1119), done.
remote: Compressing objects: 100% (484/484), done.
remote: Total 124830 (delta 729), reused 933 (delta 626), pack-reused 123711
Receiving objects: 100% (124830/124830), 442.15 MiB | 1.21 MiB/s, done.
Resolving deltas: 100% (54763/54763), done.
Updating files: 100% (6731/6731), done.
D:\Dev> cd winmerge
D:\Dev\winmerge> git submodule init
Submodule 'Externals/freeimage' (https://github.com/WinMerge/freeimage.git) registered for path 'Externals/freeimage'
Submodule 'Externals/frhed' (https://github.com/WinMerge/frhed.git) registered for path 'Externals/frhed'
Submodule 'Externals/jq' (https://github.com/stedolan/jq) registered for path 'Externals/jq'
Submodule 'Externals/patch' (https://github.com/WinMerge/patch.git) registered for path 'Externals/patch'
Submodule 'Externals/sevenzip' (https://github.com/WinMerge/sevenzip.git) registered for path 'Externals/sevenzip'
Submodule 'Externals/tidy-html5' (https://github.com/htacg/tidy-html5) registered for path 'Externals/tidy-html5'
Submodule 'Externals/wil' (https://github.com/microsoft/wil) registered for path 'Externals/wil'
Submodule 'Externals/winimerge' (https://github.com/WinMerge/winimerge.git) registered for path 'Externals/winimerge'
D:\Dev\winmerge> git submodule update
Cloning into 'D:/Dev/winmerge/Externals/freeimage'...
Cloning into 'D:/Dev/winmerge/Externals/frhed'...
Cloning into 'D:/Dev/winmerge/Externals/jq'...
Cloning into 'D:/Dev/winmerge/Externals/patch'...
Cloning into 'D:/Dev/winmerge/Externals/sevenzip'...
Cloning into 'D:/Dev/winmerge/Externals/tidy-html5'...
Cloning into 'D:/Dev/winmerge/Externals/wil'...
Cloning into 'D:/Dev/winmerge/Externals/winimerge'...
Submodule path 'Externals/freeimage': checked out '111502a59d938d476ebb5a975ccf0cadd14e1cab'
Submodule path 'Externals/frhed': checked out '50590011df95cac36aa5fd800d3d2653fc16e410'
Submodule path 'Externals/jq': checked out 'e73951f3d1928591b3a9a60de11ae975a21e621f'
Submodule path 'Externals/patch': checked out 'a44c7a2921d52b274ab33900a3f49e6b02a5a95f'
Submodule path 'Externals/sevenzip': checked out 'cff58f15205a4e45343a5ed9214059162039e6c0'
Submodule path 'Externals/tidy-html5': checked out '0016e0083505ccee25a5c76dcf64cfe336765128'
Submodule path 'Externals/wil': checked out '209ff9c7e30e71bf6d1405557bf78544920f8157'
Submodule path 'Externals/winimerge': checked out '7b751b2342e2bb2924df53e13b93c92a21d35632'
D:\Dev\winmerge> path="C:\Program Files\7-Zip";%PATH%
D:\Dev\winmerge> DownloadDeps.cmd
・・・省略・・・
D:\Dev\winmerge> BuildBin.vs2019.cmd x64
・・・省略・・・
開発にチャレンジ
WinMergeを使っていて、D言語のシンタックスハイライト機能が欲しいと思い、開発にチャレンジしました。
D言語向け機能の実装を行った中で、以下がメインの作業となりました。
ソースコードでの実装方法に選択肢が多いのは、ソースコードを書く側としてありがたいのですが、今回ソースコードを解析する側に立つと、大変だなと思いました。
D言語の特徴1:コメントのネスト(入れ子)構造
D言語は、コメント行の書き方を3種類提供しています。
// 一行コメント
/+
string s = "ここは、コメント行1";
/+
string s = "ここは、コメント行2";
+/
string s = "ここは、コメント行3";
+/
/*
string s = "ここは、コメント行4";
/*
string s = "ここは、コメント行5";
*/
string s = "ここは、コメント行ではない";
D言語のブロックコメント/+ +/
は、ネストに対応しています。
/* */
は、C言語と言語仕様に合わせて、ネストに対応していません。
Rust
はブロックコメント/* */
がネストに対応しているそうで、実装での参考にしました。
D言語の特徴2:文字列の表現
D言語は、文字列リテラルの表現方法がたくさん用意されています。
import std.stdio;
void main()
{
string[] arr = [
"string
1\\\"",
r"string
2\"c,
`"string
3\"`,
q"(string
4a\")",
q"[string
4b\"]",
q"{string
4c\"}",
q"<string
4d\">",
q"/string
4e\"/"
];
foreach( i, s; arr ){
writefln("-----arr[%s]-----\n%s", i, s);
}
}
arr[0]
は C言語と同じ文字列表現です。
arr[1]
以降はWysiwyg Stringsでエスケープシーケンスを使わずにダブルクォーテーション"
やバックスラッシュ(円マーク)\
を表現できます。ただし、arr[1]
ではダブルクォーテーション"
自体を文字列に含めることができません。
また、文字列中に改行があると、改行文字\n
として扱われます。
-----arr[0]-----
string
1\"
-----arr[1]-----
string
2\
-----arr[2]-----
"string
3\"
-----arr[3]-----
string
4a\"
-----arr[4]-----
string
4b\"
-----arr[5]-----
string
4c\"
-----arr[6]-----
string
4d\"
-----arr[7]-----
string
4e\"
WinMergeでの実装が難しく、以下の文字列は未対応(断念)としました。
"EOS
とEOS"
の間にあるのが文字列になります。
以下の例のEOS
に限らず、D言語では任意の文字列を区切り文字(デリミタ)にできます。
import std.stdio;
string s =
q"EOS
This
is a multi-line
heredoc string
EOS";
void main()
{
writeln(s);
}
This
is a multi-line
heredoc string
D言語の特徴3:文字列のネスト(入れ子)構造
D言語では、文字列の区切り文字(デリミタ)のネストを許容するパターンがあります。Token strings
import std.stdio;
void main()
{
string s =
q{string
5 q{string 5+} };
writeln(s);
}
QiitaのMarkdown カラー表示が、少しわかりにくいですが、
q{
と}
の間が文字列になります。ネストが許容されるので、内側のq{
と}
は文字列に含まれます。
以下にコンパイル実行結果を記載します。表示されている部分が文字列です。
string
5 q{string 5+}
WinMerge実装結果
完成したD言語シンタックスハイライト機能のイメージです。
おわりに
私なんかが、いきなりプルリクエストして採用されるのだろうか・・・
と、ちょっと心配でしたが、v2.16.17の追加機能として、無事マージされました。
WinMergeのマイルストーンを見ると、
v2.16.17(ベータ版)は2021/12/19リリース予定、v2.16.18(安定版)は2022/1/27リリース予定となっています。
みなさまのD言語開発に活用していただければと思います。
参考情報