-
Notifications
You must be signed in to change notification settings - Fork 0
/
rmd2md.d
121 lines (101 loc) · 3.81 KB
/
rmd2md.d
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
module rmd2md;
import std.algorithm;
import std.stdio;
import file = std.file;
import std.conv;
import std.regex;
import std.getopt;
import std.path;
import std.datetime;
import std.parallelism;
import std.range;
void main(string[] args)
{
// Set variables for the main program
string programName = "Rmd2md";
// Setup Regex for capturing Rmd code snippet header
Regex!char re = regex(r"`{3}\{r[a-zA-Z0-9= ]*\}", "g");
// Set default values for the arguments
string inputPath = file.getcwd();
string fileEndsWith = ".Rmd";
string outputPath = file.getcwd();
// Set GetOpt variables
auto helpInformation = getopt(
args,
"path|p", "Path of Rmd files. Default: current working directory.", &inputPath,
"fext|e", "Extension of Rmd files. Default: `.Rmd`", &fileEndsWith,
"fout|o", "Output folder to save the MD files. Default: current working directory.", &outputPath
);
if (helpInformation.helpWanted)
{
defaultGetoptPrinter("Rmd to Markdown (md) file converter.",
helpInformation.options);
return;
}
// is the path valid?
if (!std.path.isValidPath(inputPath))
{
writeln(programName ~ ": invalid input path");
return;
}
// is output path valid?
if (!std.path.isValidPath(outputPath))
{
writeln(programName ~ ": invalid output path");
return;
}
// is file extension valid?
if (!startsWith(fileEndsWith, "."))
{
writeln(programName ~ ": invalid extension given");
return;
}
writeln(programName ~ ": input directory is " ~ inputPath);
writeln(programName ~ ": output directory is " ~ outputPath);
writeln(programName ~ ": ---");
// Get no files in specified inputPath variable with a specific extension
auto rmdFiles_for_counting = file.dirEntries(inputPath, file.SpanMode.shallow)
.filter!(f => f.isFile)
.filter!(f => f.name.endsWith(fileEndsWith));
writeln(programName ~ ": found - " ~ to!string(rmdFiles_for_counting.walkLength) ~ fileEndsWith ~ " file(s)");
writeln(programName ~ ": ---");
// Get start time
auto stattime = Clock.currTime();
// Process each Rmd file
int fileWrittenCount = 0;
// Get files in specified inputPath variable with a specific extension
auto rmdFiles = file.dirEntries(inputPath, file.SpanMode.shallow)
.filter!(f => f.isFile)
.filter!(f => f.name.endsWith(fileEndsWith));
foreach (file.DirEntry item; parallel(rmdFiles))
{
writeln(Clock.currTime().toISOExtString, ": processing " ~ item.name);
try
{
// Read content as string
string content = file.readText(item.name);
// Replace ```{r} or ```{r option1=value} with ```R
string modified = replaceAll(content, re, "```R");
// Set the Markdown output file
string outputFile = replaceAll(baseName(item.name), regex(r".Rmd"), ".md");
// Build an output path, using output path and baseName(item.name)
string outputFilenamePath = buildPath(outputPath, outputFile);
// Save output Markdown file
file.write(outputFilenamePath, modified);
writeln(Clock.currTime().toISOExtString, ": written " ~ outputFilenamePath);
// Increase counter to indicate number of files processed
fileWrittenCount++;
}
catch (file.FileException e)
{
writeln(programName ~ ": " ~ e.msg);
}
}
writeln(programName ~ ": ---");
// Gett end clock
auto endttime = Clock.currTime();
auto duration = endttime - stattime;
writeln(programName ~ ": duration - ", duration);
// Console output a summary
writeln(programName ~ ": written " ~ to!string(fileWrittenCount) ~ " file(s)");
}