Skip to content

Commit f313a01

Browse files
authored
Merge pull request #1796 from rust-lang/TC/refactor-with-renderctx
Refactor rendering with `RenderCtx`
2 parents 7fdb38f + 57ea6a8 commit f313a01

File tree

3 files changed

+71
-110
lines changed

3 files changed

+71
-110
lines changed

mdbook-spec/src/grammar.rs

+15-20
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,13 @@ enum Characters {
8888
Range(char, char),
8989
}
9090

91+
#[derive(Debug)]
92+
pub struct RenderCtx {
93+
md_link_map: HashMap<String, String>,
94+
rr_link_map: HashMap<String, String>,
95+
for_summary: bool,
96+
}
97+
9198
impl Grammar {
9299
fn visit_nt(&self, callback: &mut dyn FnMut(&str)) {
93100
for p in self.productions.values() {
@@ -301,7 +308,7 @@ fn render_names(
301308
output.push_str("<br>\n");
302309

303310
// Convert the link map to add the id.
304-
let updated_link_map = |get_id: fn(&str, bool) -> String| -> HashMap<String, String> {
311+
let update_link_map = |get_id: fn(&str, bool) -> String| -> HashMap<String, String> {
305312
link_map
306313
.iter()
307314
.map(|(name, path)| {
@@ -316,19 +323,13 @@ fn render_names(
316323
.collect()
317324
};
318325

319-
let markdown_link_map = updated_link_map(render_markdown::markdown_id);
320-
// Modify the link map so that it contains the exact destination needed to
321-
// link to the railroad productions, and to accommodate the summary
322-
// chapter.
323-
let railroad_link_map = updated_link_map(render_railroad::railroad_id);
324-
325-
if let Err(e) = grammar.render_markdown(
326-
&names,
327-
&markdown_link_map,
328-
&railroad_link_map,
329-
&mut output,
326+
let render_ctx = RenderCtx {
327+
md_link_map: update_link_map(render_markdown::markdown_id),
328+
rr_link_map: update_link_map(render_railroad::railroad_id),
330329
for_summary,
331-
) {
330+
};
331+
332+
if let Err(e) = grammar.render_markdown(&render_ctx, &names, &mut output) {
332333
warn_or_err!(
333334
diag,
334335
"grammar failed in chapter {:?}: {e}",
@@ -348,13 +349,7 @@ fn render_names(
348349
\n",
349350
);
350351

351-
if let Err(e) = grammar.render_railroad(
352-
&names,
353-
&railroad_link_map,
354-
&markdown_link_map,
355-
&mut output,
356-
for_summary,
357-
) {
352+
if let Err(e) = grammar.render_railroad(&render_ctx, &names, &mut output) {
358353
warn_or_err!(
359354
diag,
360355
"grammar failed in chapter {:?}: {e}",

mdbook-spec/src/grammar/render_markdown.rs

+26-44
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,26 @@
11
//! Renders the grammar to markdown.
22
3-
use super::{Characters, Expression, ExpressionKind, Production};
3+
use super::{Characters, Expression, ExpressionKind, Production, RenderCtx};
44
use crate::grammar::Grammar;
55
use anyhow::bail;
66
use regex::Regex;
77
use std::borrow::Cow;
8-
use std::collections::HashMap;
98
use std::fmt::Write;
109
use std::sync::LazyLock;
1110

1211
impl Grammar {
1312
pub fn render_markdown(
1413
&self,
14+
cx: &RenderCtx,
1515
names: &[&str],
16-
link_map: &HashMap<String, String>,
17-
rr_link_map: &HashMap<String, String>,
1816
output: &mut String,
19-
for_summary: bool,
2017
) -> anyhow::Result<()> {
2118
let mut iter = names.into_iter().peekable();
2219
while let Some(name) = iter.next() {
2320
let Some(prod) = self.productions.get(*name) else {
2421
bail!("could not find grammar production named `{name}`");
2522
};
26-
prod.render_markdown(link_map, rr_link_map, output, for_summary);
23+
prod.render_markdown(cx, output);
2724
if iter.peek().is_some() {
2825
output.push_str("\n");
2926
}
@@ -42,14 +39,9 @@ pub fn markdown_id(name: &str, for_summary: bool) -> String {
4239
}
4340

4441
impl Production {
45-
fn render_markdown(
46-
&self,
47-
link_map: &HashMap<String, String>,
48-
rr_link_map: &HashMap<String, String>,
49-
output: &mut String,
50-
for_summary: bool,
51-
) {
52-
let dest = rr_link_map
42+
fn render_markdown(&self, cx: &RenderCtx, output: &mut String) {
43+
let dest = cx
44+
.rr_link_map
5345
.get(&self.name)
5446
.map(|path| path.to_string())
5547
.unwrap_or_else(|| format!("missing"));
@@ -60,12 +52,11 @@ impl Production {
6052
>\
6153
[{name}]({dest})\
6254
</span> → ",
63-
id = markdown_id(&self.name, for_summary),
55+
id = markdown_id(&self.name, cx.for_summary),
6456
name = self.name,
6557
)
6658
.unwrap();
67-
self.expression
68-
.render_markdown(link_map, output, for_summary);
59+
self.expression.render_markdown(cx, output);
6960
output.push('\n');
7061
}
7162
}
@@ -92,16 +83,11 @@ impl Expression {
9283
}
9384
}
9485

95-
fn render_markdown(
96-
&self,
97-
link_map: &HashMap<String, String>,
98-
output: &mut String,
99-
for_summary: bool,
100-
) {
86+
fn render_markdown(&self, cx: &RenderCtx, output: &mut String) {
10187
match &self.kind {
10288
ExpressionKind::Grouped(e) => {
10389
output.push_str("( ");
104-
e.render_markdown(link_map, output, for_summary);
90+
e.render_markdown(cx, output);
10591
if !matches!(e.last(), ExpressionKind::Break(_)) {
10692
output.push(' ');
10793
}
@@ -110,7 +96,7 @@ impl Expression {
11096
ExpressionKind::Alt(es) => {
11197
let mut iter = es.iter().peekable();
11298
while let Some(e) = iter.next() {
113-
e.render_markdown(link_map, output, for_summary);
99+
e.render_markdown(cx, output);
114100
if iter.peek().is_some() {
115101
if !matches!(e.last(), ExpressionKind::Break(_)) {
116102
output.push(' ');
@@ -122,34 +108,34 @@ impl Expression {
122108
ExpressionKind::Sequence(es) => {
123109
let mut iter = es.iter().peekable();
124110
while let Some(e) = iter.next() {
125-
e.render_markdown(link_map, output, for_summary);
111+
e.render_markdown(cx, output);
126112
if iter.peek().is_some() && !matches!(e.last(), ExpressionKind::Break(_)) {
127113
output.push(' ');
128114
}
129115
}
130116
}
131117
ExpressionKind::Optional(e) => {
132-
e.render_markdown(link_map, output, for_summary);
118+
e.render_markdown(cx, output);
133119
output.push_str("<sup>?</sup>");
134120
}
135121
ExpressionKind::Repeat(e) => {
136-
e.render_markdown(link_map, output, for_summary);
122+
e.render_markdown(cx, output);
137123
output.push_str("<sup>\\*</sup>");
138124
}
139125
ExpressionKind::RepeatNonGreedy(e) => {
140-
e.render_markdown(link_map, output, for_summary);
126+
e.render_markdown(cx, output);
141127
output.push_str("<sup>\\* (non-greedy)</sup>");
142128
}
143129
ExpressionKind::RepeatPlus(e) => {
144-
e.render_markdown(link_map, output, for_summary);
130+
e.render_markdown(cx, output);
145131
output.push_str("<sup>+</sup>");
146132
}
147133
ExpressionKind::RepeatPlusNonGreedy(e) => {
148-
e.render_markdown(link_map, output, for_summary);
134+
e.render_markdown(cx, output);
149135
output.push_str("<sup>+ (non-greedy)</sup>");
150136
}
151137
ExpressionKind::RepeatRange(e, a, b) => {
152-
e.render_markdown(link_map, output, for_summary);
138+
e.render_markdown(cx, output);
153139
write!(
154140
output,
155141
"<sup>{}..{}</sup>",
@@ -159,7 +145,7 @@ impl Expression {
159145
.unwrap();
160146
}
161147
ExpressionKind::Nt(nt) => {
162-
let dest = link_map.get(nt).map_or("missing", |d| d.as_str());
148+
let dest = cx.md_link_map.get(nt).map_or("missing", |d| d.as_str());
163149
write!(output, "<span class=\"grammar-text\">[{nt}]({dest})</span>").unwrap();
164150
}
165151
ExpressionKind::Terminal(t) => {
@@ -177,10 +163,10 @@ impl Expression {
177163
output.push_str("\\\n");
178164
output.push_str(&"&nbsp;".repeat(*indent));
179165
}
180-
ExpressionKind::Charset(set) => charset_render_markdown(set, link_map, output),
166+
ExpressionKind::Charset(set) => charset_render_markdown(cx, set, output),
181167
ExpressionKind::NegExpression(e) => {
182168
output.push('~');
183-
e.render_markdown(link_map, output, for_summary);
169+
e.render_markdown(cx, output);
184170
}
185171
ExpressionKind::Unicode(s) => {
186172
output.push_str("U+");
@@ -190,7 +176,7 @@ impl Expression {
190176
if let Some(suffix) = &self.suffix {
191177
write!(output, "<sub class=\"grammar-text\">{suffix}</sub>").unwrap();
192178
}
193-
if !for_summary {
179+
if !cx.for_summary {
194180
if let Some(footnote) = &self.footnote {
195181
// The `ZeroWidthSpace` is to avoid conflicts with markdown link
196182
// references.
@@ -200,15 +186,11 @@ impl Expression {
200186
}
201187
}
202188

203-
fn charset_render_markdown(
204-
set: &[Characters],
205-
link_map: &HashMap<String, String>,
206-
output: &mut String,
207-
) {
189+
fn charset_render_markdown(cx: &RenderCtx, set: &[Characters], output: &mut String) {
208190
output.push_str("\\[");
209191
let mut iter = set.iter().peekable();
210192
while let Some(chars) = iter.next() {
211-
chars.render_markdown(link_map, output);
193+
chars.render_markdown(cx, output);
212194
if iter.peek().is_some() {
213195
output.push(' ');
214196
}
@@ -217,10 +199,10 @@ fn charset_render_markdown(
217199
}
218200

219201
impl Characters {
220-
fn render_markdown(&self, link_map: &HashMap<String, String>, output: &mut String) {
202+
fn render_markdown(&self, cx: &RenderCtx, output: &mut String) {
221203
match self {
222204
Characters::Named(s) => {
223-
let dest = link_map.get(s).map_or("missing", |d| d.as_str());
205+
let dest = cx.md_link_map.get(s).map_or("missing", |d| d.as_str());
224206
write!(output, "[{s}]({dest})").unwrap();
225207
}
226208
Characters::Terminal(s) => write!(

0 commit comments

Comments
 (0)