Skip to content

Commit 91ef535

Browse files
authored
Merge pull request #2060 from wilzbach/header-gen2
Add header TOC generation merged-on-behalf-of: Vladimir Panteleev <github@thecybershadow.net>
2 parents f281b49 + c340573 commit 91ef535

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+294
-58
lines changed

ddoc.d

Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
#!/usr/bin/env rdmd
2+
/**
3+
A wrapper around DDoc to allow custom extensions
4+
5+
Copyright: D Language Foundation 2018
6+
7+
License: $(WEB boost.org/LICENSE_1_0.txt, Boost License 1.0).
8+
9+
Example usage:
10+
11+
---
12+
./ddoc --compiler=<path-to-dmd> --output=out.html myfile.dd
13+
---
14+
15+
Author: Sebastian Wilzbach
16+
*/
17+
import std.algorithm, std.array, std.ascii, std.conv, std.file, std.functional,
18+
std.meta, std.path, std.range, std.string, std.typecons;
19+
import std.stdio : writeln, writefln;
20+
21+
struct Config
22+
{
23+
string dmdBinPath = "dmd";
24+
string outputFile;
25+
}
26+
Config config;
27+
28+
int main(string[] args)
29+
{
30+
import std.getopt;
31+
auto helpInformation = getopt(
32+
args,
33+
"compiler", "Compiler to use", &config.dmdBinPath,
34+
"o|output", "Output file", &config.outputFile,
35+
);
36+
37+
assert(config.outputFile, "An output file is required.");
38+
assert(args.length > 1, "An input file is required.");
39+
40+
if (helpInformation.helpWanted)
41+
{
42+
`DDoc wrapper
43+
./ddoc <file>...
44+
`.defaultGetoptPrinter(helpInformation.options);
45+
return 1;
46+
}
47+
48+
import std.file : readText;
49+
auto text = args[$ - 1].readText;
50+
51+
// transform and extend the ddoc page
52+
text = genHeader(text);
53+
54+
return compile(text, args[1 .. $ - 1]);
55+
}
56+
57+
auto compile(R)(R buffer, string[] arguments)
58+
{
59+
import std.process : pipeProcess, Redirect, wait;
60+
auto args = [config.dmdBinPath, "-c", "-Df"~config.outputFile, "-o-"] ~ arguments;
61+
args ~= "-";
62+
auto pipes = pipeProcess(args, Redirect.stdin);
63+
pipes.stdin.write(buffer);
64+
pipes.stdin.close;
65+
return wait(pipes.pid);
66+
}
67+
68+
// replaces the content of a DDoc macro call
69+
auto updateDdocTag(string fileText, string ddocKey, string newContent)
70+
{
71+
auto pos = fileText.representation.countUntil(ddocKey);
72+
if (pos < 0)
73+
return fileText;
74+
const ddocStartLength = ddocKey.representation.until('(', No.openRight).count;
75+
auto len = fileText[pos .. $].representation.drop(ddocStartLength).untilClosingParentheses.walkLength;
76+
return fileText.replace(fileText[pos .. pos + len + ddocStartLength + 1], newContent);
77+
}
78+
79+
// a range until the next ')', nested () are ignored
80+
auto untilClosingParentheses(R)(R rs)
81+
{
82+
return rs.cumulativeFold!((count, r){
83+
switch(r)
84+
{
85+
case '(':
86+
count++;
87+
break;
88+
case ')':
89+
count--;
90+
break;
91+
default:
92+
}
93+
return count;
94+
})(1).zip(rs).until!(e => e[0] == 0).map!(e => e[1]);
95+
}
96+
97+
unittest
98+
{
99+
import std.algorithm.comparison : equal;
100+
assert("aa $(foo $(bar)foobar)".untilClosingParentheses.equal("aa $(foo $(bar)foobar)"));
101+
assert("$(FOO a, b, $(ARGS e, f)))".untilClosingParentheses.equal("$(FOO a, b, $(ARGS e, f))"));
102+
}
103+
104+
// parse the ddoc file for H2 and H3 items
105+
// H3 items are listed as subitems
106+
auto parseToc(string text)
107+
{
108+
alias TocEntry = Tuple!(string, "id", string, "name");
109+
alias TocTopEntry = Tuple!(TocEntry, "main", TocEntry[], "children");
110+
TocTopEntry[] toc;
111+
112+
bool isH2 = true;
113+
void append(string id, string name)
114+
{
115+
auto entry = TocEntry(id, name);
116+
if (isH2)
117+
toc ~= TocTopEntry(entry, null);
118+
else
119+
toc.back.children ~= entry;
120+
}
121+
while (!text.empty)
122+
{
123+
enum needles = AliasSeq!("$(H2 ", "$(SECTION2 ", "$(H3", "$(SECTION3");
124+
auto res = text.find(needles);
125+
if (res[0].empty)
126+
break;
127+
128+
isH2 = res[1] <= 2;
129+
text = res[0].drop(needles.only[res[1] - 1].length);
130+
text.skipOver!isWhite;
131+
132+
enum gname = "$(GNAME ";
133+
enum lNameNeedles = AliasSeq!("$(LNAME2", "$(LEGACY_LNAME2");
134+
if (text.startsWith(gname))
135+
{
136+
auto name = text.drop(gname.length).untilClosingParentheses.to!string.strip;
137+
append(name, name);
138+
}
139+
else if (auto idx = text.startsWith(lNameNeedles))
140+
{
141+
auto arr = text.drop(lNameNeedles.only[idx - 1].length).splitter(",");
142+
if (idx == 2)
143+
arr.popFront;
144+
append(arr.front.strip, arr.dropOne.joiner(",").untilClosingParentheses.to!string.strip);
145+
}
146+
}
147+
return toc;
148+
}
149+
150+
// Ddoc splits arguments by commas
151+
auto escapeDdoc(string s)
152+
{
153+
return s.replace(",", "$(COMMA)");
154+
}
155+
156+
// generated a SPEC_HEADERNAV_TOC Ddoc macro with the parsed H2/H3 entries
157+
auto genHeader(string fileText)
158+
{
159+
enum ddocKey = "$(SPEC_HEADERNAV_TOC";
160+
auto newContent = ddocKey ~ "\n";
161+
enum indent = " ";
162+
foreach (entry; fileText.parseToc)
163+
{
164+
if (entry.children)
165+
{
166+
newContent ~= "%s$(SPEC_HEADERNAV_SUBITEMS %s, %s,\n".format(indent, entry.main.id, entry.main.name.escapeDdoc);
167+
foreach (child; entry.children)
168+
newContent ~= "%s$(SPEC_HEADERNAV_ITEM %s, %s)\n".format(indent.repeat(2).joiner, child.id, child.name.escapeDdoc);
169+
newContent ~= indent;
170+
newContent ~= ")\n";
171+
}
172+
else
173+
{
174+
newContent ~= "%s$(SPEC_HEADERNAV_ITEM %s, %s)\n".format(indent, entry.main.id, entry.main.name.escapeDdoc);
175+
}
176+
}
177+
newContent ~= ")";
178+
return updateDdocTag(fileText, ddocKey, newContent);
179+
}
180+

ebook.ddoc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,4 +61,7 @@ SPEC_RUNNABLE_EXAMPLE=$0
6161
SPEC_SUBNAV_NEXT=
6262
SPEC_SUBNAV_PREV_NEXT=
6363
SPEC_SUBNAV_PREV=
64+
SPEC_HEADERNAV_TOC=
65+
SPEC_HEADERNAV_ITEM=
66+
SPEC_HEADERNAV_SUBITEMS=
6467
_=

latex.ddoc

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -267,10 +267,10 @@ SPEC_S=$(LAYOUT , $1, $(ARGS $+))
267267
SPEC_SUBNAV_NEXT=
268268
SPEC_SUBNAV_PREV=
269269
SPEC_SUBNAV_PREV_NEXT=
270+
SPEC_HEADERNAV_TOC=
271+
SPEC_HEADERNAV_ITEM=
272+
SPEC_HEADERNAV_SUBITEMS=
270273
SUBSCRIPT=\textsubscript{$0}
271-
SPEC_SUBNAV_PREV=
272-
SPEC_SUBNAV_PREV_NEXT=
273-
SPEC_SUBNAV_NEXT=
274274
SUP=\textsuperscript{$0}
275275
_=
276276

posix.mak

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,12 @@ DDOC_VARS_PRERELEASE_VERBATIM=$(DDOC_VARS_PRERELEASE) \
277277
DOC_OUTPUT_DIR="$W/phobos-prerelease-verbatim" \
278278
STDDOC="$(PWD)/verbatim.ddoc"
279279

280+
################################################################################
281+
# Ddoc binaries
282+
################################################################################
283+
284+
DDOC_BIN:=$G/ddoc
285+
280286
################################################################################
281287
# Resources
282288
################################################################################
@@ -460,8 +466,8 @@ $W/changelog/pending.html : changelog/pending.dd $(CHANGELOG_PENDING_DDOC) $(DMD
460466
$W/changelog/%.html : changelog/%.dd $(CHANGELOG_DDOC) $(DMD)
461467
$(DMD) -conf= -c -o- -Df$@ $(CHANGELOG_DDOC) $<
462468

463-
$W/spec/%.html : spec/%.dd $(SPEC_DDOC) $(DMD)
464-
$(DMD) -c -o- -Df$@ $(SPEC_DDOC) $<
469+
$W/spec/%.html : spec/%.dd $(SPEC_DDOC) $(DMD) $(DDOC_BIN)
470+
$(DDOC_BIN) --compiler=$(DMD) -o$@ $(SPEC_DDOC) $<
465471

466472
$W/404.html : 404.dd $(DDOC) $(DMD)
467473
$(DMD) -conf= -c -o- -Df$@ $(DDOC) errorpage.ddoc $<
@@ -947,4 +953,15 @@ $G/contributors_list.ddoc: | $(STABLE_RDMD) $(TOOLS_DIR) $(INSTALLER_DIR)
947953
echo "D_CONTRIBUTORS=" >> $@
948954
cat $G/contributors_list.tmp >> $@
949955

956+
################################################################################
957+
# Custom DDoc wrapper
958+
# ------------------
959+
#
960+
# This allows extending Ddoc files dynamically on-the-fly.
961+
# It is currently only used for the specification pages
962+
################################################################################
963+
964+
$(DDOC_BIN): ddoc.d | $(STABLE_DMD)
965+
$(STABLE_DMD) -of$@ $<
966+
950967
.DELETE_ON_ERROR: # GNU Make directive (delete output files on error)

spec/abi.dd

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ Ddoc
22

33
$(SPEC_S Application Binary Interface,
44

5+
$(SPEC_HEADERNAV_TOC)
6+
57
$(P A D implementation that conforms to the D ABI (Application Binary
68
Interface)
79
will be able to generate libraries, DLL's, etc., that can interoperate

spec/arrays.dd

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ Ddoc
22

33
$(SPEC_S Arrays,
44

5+
$(SPEC_HEADERNAV_TOC)
6+
57
$(H2 $(LNAME2 array-kinds, Kinds))
68

79
$(P There are four kinds of arrays:)

spec/attribute.dd

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ Ddoc
22

33
$(SPEC_S Attributes,
44

5+
$(SPEC_HEADERNAV_TOC)
6+
57
$(GRAMMAR
68
$(GNAME AttributeSpecifier):
79
$(GLINK Attribute) $(D :)

spec/betterc.dd

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ Ddoc
22

33
$(SPEC_S Better C,
44

5+
$(SPEC_HEADERNAV_TOC)
6+
57
`-betterC` is a command-line flag for `dmd`,
68
which restricts the compiler's support of certain runtime features.
79
Notably, D programs or libraries compiled with `betterC` aren't linked with Druntime.

spec/class.dd

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ Ddoc
22

33
$(SPEC_S Classes,
44

5+
$(SPEC_HEADERNAV_TOC)
6+
57
$(P The object-oriented features of D all come from classes. The class
68
hierarchy
79
has as its root the class Object. Object defines a minimum level of functionality

spec/const3.dd

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ Ddoc
22

33
$(D_S Type Qualifiers,
44

5+
$(SPEC_HEADERNAV_TOC)
6+
57
$(P Type qualifiers modify a type by applying a $(GLINK2 declaration, TypeCtor).
68
$(I TypeCtor)s are: $(D const), $(D immutable), $(D shared), and $(D inout).
79
Each applies transitively to all subtypes.

0 commit comments

Comments
 (0)