Markdownのコードブロックを実行するツールです。
これを使うことで、READMEに書かれたサンプルが動作することをCIで保証することなどができます。
サンプルリポジトリ: https://github.com/lempiji/sandbox-vuepress
dub fetch md
および dub run md -- README.md
といったコマンドで実行できます。
この README.md
も実行可能となっています。
なお、 md
にコマンドライン引数を渡すことで、生成した D ソースファイルをどのように実行するか設定することもできます。
ヘルプの参照方法
dub run md -- --help
言語に d
または D
と指定されているコードブロックが実行されます。
以下のように複数のブロックがある場合、それらが結合されて実行されます。
1ブロック目
import std;
auto message = "Hello, " ~ "Markdown!";
2ブロック目
writeln(message); // Hello, Markdown!
以下のように disabled
と指定したコードブロックは実行されません。
```d disabled
```
実行されないブロック
throw new Exception("disabled");
コードブロックに対して、以下のような名前を指定することで独立したスコープを与えることができます。 離れた位置に書かれていても、同じ名前を与えると1つのブロックとして結合されます。
```d name=test
```
import std;
auto buf = iota(10).array();
writeln(buf);
name
指定がない場合は main
という名前として扱われます。
1つのコードブロックを他のブロックと結合せず、独立して実行させるためには single
という属性を付与します。
```d single
```
他のブロックと結合しない例
import std;
auto message = "single code block";
writeln(message);
ツールによる実行(dub run
)に渡すことができるいくつかのオプションをサポートしています。
これらのオプションは、指定された値をそのまま dub run
の引数として渡します。
--build
--compiler
--arch
例
dub run md -- README.md --build=release --compiler=ldc2 --arch=x86_64
ライブラリのREADMEなどをサポートするため、実行時のカレントディレクトリがdubパッケージであった場合、自動的に dub
プロジェクトとしての依存関係が追加されます。(これは dub.sdl
に path
ベースの dependency
が追加されます)
たとえば、 dub.sdl
と同じディレクトリにある本READMEの場合、内部で使っている commands.main
を import
することができます。
import commands.main;
import std.stdio;
writeln("current package: ", loadCurrentProjectName());
-d <pakageName>
や -d <pakageName>@<versionString>
(-d mir-ion@~>2.0.16
など)の指定によって追加の依存関係を設定することもできます。(-d
の正式名は --dependency
です)
--dubsdl <instruction>
を指定すると、生成されるファイルに dub.sdl の行を直接追加することができます。このオプションは複数回指定することで複数の行を追加することもできます。
このオプションを指定した場合、上記の「既定のパッケージ参照機能」が無効化され、参照が追加されなくなります。
通常のコードブロックはサンプル用の記述を想定し、 void main() {}
の中に書かれたものとして実行されます。(前後に void main() {
と }
が補われたソースが生成されます)
コードブロックを1つのソースファイルとして解釈させる場合、コードブロックに global
という設定を追加します。これは single
を指定した場合と同様、他のコードブロックとは結合されません。
```d global
```
1つのソースとして実行される例
import std;
void main()
{
writeln("Hello, Markdown!");
}
tempディレクトリに .md
ディレクトリを作り、dubのシングルファイル形式のソースを生成、 dub run --single md_xxx.md
といったコマンドで実行します。
また、既定のパッケージ参照を実現するため、ソースの先頭に以下のようなコメントを自動的に付与します。
/+ dub.sdl:
dependency "md" path="C:\\work\md"
+/
通常のコードブロックでは、 void main() {}
で囲んだソースを生成します。
関数定義がグローバル関数ではないため、UFCSは動作しません
UFCSが解決されず動かない例
auto sum(R)(R range)
{
import std.range : ElementType;
alias E = ElementType!R;
auto result = E(0);
foreach (x; range)
{
result += x;
}
return result;
}
auto arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
auto result = arr.sum();
global設定を行い、main関数を適切に書くことで動作します。
UFCSのためglobal指定を追加した例
auto sum(R)(R range)
{
import std.range : ElementType;
alias E = ElementType!R;
auto result = E(0);
foreach (x; range)
{
result += x;
}
return result;
}
void main()
{
auto arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
auto result = arr.sum();
}