Skip to content

Commit 222cfbe

Browse files
committed
rustdoc: Add command line option parsing and a config record
1 parent 21650d0 commit 222cfbe

File tree

2 files changed

+258
-0
lines changed

2 files changed

+258
-0
lines changed

src/rustdoc/config.rs

Lines changed: 257 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,257 @@
1+
import std::getopts;
2+
3+
export output_format::{};
4+
export output_style::{};
5+
export config;
6+
export parse_config;
7+
8+
#[doc = "The type of document to output"]
9+
enum output_format {
10+
#[doc = "Markdown"]
11+
markdown,
12+
#[doc = "HTML, via markdown and pandoc"]
13+
pandoc_html
14+
}
15+
16+
#[doc = "How to organize the output"]
17+
enum output_style {
18+
#[doc = "All in a single document"]
19+
doc_per_crate,
20+
#[doc = "Each module in its own document"]
21+
doc_per_mod
22+
}
23+
24+
#[doc = "The configuration for a rustdoc session"]
25+
type config = {
26+
input_crate: str,
27+
output_dir: str,
28+
output_format: output_format,
29+
output_style: output_style,
30+
pandoc_cmd: option<str>
31+
};
32+
33+
fn opt_output_dir() -> str { "output-dir" }
34+
fn opt_output_format() -> str { "output-format" }
35+
fn opt_output_style() -> str { "output-style" }
36+
fn opt_pandoc_cmd() -> str { "pandoc-cmd" }
37+
38+
fn opts() -> [(getopts::opt, str)] {
39+
[
40+
(getopts::optopt(opt_output_dir()),
41+
"put documents here"),
42+
(getopts::optopt(opt_output_format()),
43+
"either 'markdown' or 'html'"),
44+
(getopts::optopt(opt_output_style()),
45+
"either 'doc-per-crate' or 'doc-per-mod'"),
46+
(getopts::optopt(opt_pandoc_cmd()),
47+
"the command for running pandoc")
48+
]
49+
}
50+
51+
fn default_config(input_crate: str) -> config {
52+
{
53+
input_crate: input_crate,
54+
output_dir: ".",
55+
output_format: pandoc_html,
56+
output_style: doc_per_mod,
57+
pandoc_cmd: none
58+
}
59+
}
60+
61+
fn parse_config(args: [str]) -> result::t<config, str> {
62+
let args = vec::tail(args);
63+
let opts = tuple::first(vec::unzip(opts()));
64+
alt getopts::getopts(args, opts) {
65+
result::ok(match) {
66+
if vec::len(match.free) == 1u {
67+
let input_crate = vec::head(match.free);
68+
config_from_opts(input_crate, match)
69+
} else if vec::is_empty(match.free) {
70+
result::err("no crates specified")
71+
} else {
72+
result::err("multiple crates specified")
73+
}
74+
}
75+
result::err(f) {
76+
result::err(getopts::fail_str(f))
77+
}
78+
}
79+
}
80+
81+
fn config_from_opts(
82+
input_crate: str,
83+
match: getopts::match
84+
) -> result::t<config, str> {
85+
86+
let config = default_config(input_crate);
87+
let result = result::ok(config);
88+
let result = result::chain(result) {|config|
89+
let output_dir = getopts::opt_maybe_str(match, opt_output_dir());
90+
result::ok({
91+
output_dir: option::from_maybe(config.output_dir, output_dir)
92+
with config
93+
})
94+
};
95+
let result = result::chain(result) {|config|
96+
let output_format = getopts::opt_maybe_str(
97+
match, opt_output_format());
98+
option::maybe(result::ok(config), output_format) {|output_format|
99+
result::chain(parse_output_format(output_format)) {|output_format|
100+
result::ok({
101+
output_format: output_format
102+
with config
103+
})
104+
}
105+
}
106+
};
107+
let result = result::chain(result) {|config|
108+
let output_style = getopts::opt_maybe_str(match, opt_output_style());
109+
option::maybe(result::ok(config), output_style) {|output_style|
110+
result::chain(parse_output_style(output_style)) {|output_style|
111+
result::ok({
112+
output_style: output_style
113+
with config
114+
})
115+
}
116+
}
117+
};
118+
let result = result::chain(result) {|config|
119+
let pandoc_cmd = getopts::opt_maybe_str(match, opt_pandoc_cmd());
120+
let pandoc_cmd = maybe_find_pandoc(config, pandoc_cmd);
121+
result::chain(pandoc_cmd) {|pandoc_cmd|
122+
result::ok({
123+
pandoc_cmd: pandoc_cmd
124+
with config
125+
})
126+
}
127+
};
128+
ret result;
129+
}
130+
131+
fn parse_output_format(output_format: str) -> result::t<output_format, str> {
132+
alt output_format {
133+
"markdown" { result::ok(markdown) }
134+
"html" { result::ok(pandoc_html) }
135+
_ { result::err(#fmt("unknown output format '%s'", output_format)) }
136+
}
137+
}
138+
139+
fn parse_output_style(output_style: str) -> result::t<output_style, str> {
140+
alt output_style {
141+
"doc-per-crate" { result::ok(doc_per_crate) }
142+
"doc-per-mod" { result::ok(doc_per_mod) }
143+
_ { result::err(#fmt("unknown output style '%s'", output_style)) }
144+
}
145+
}
146+
147+
fn maybe_find_pandoc(
148+
_config: config,
149+
maybe_pandoc_cmd: option<str>
150+
) -> result::t<option<str>, str> {
151+
// FIXME: When we actually need pandoc then look for it first
152+
// on the path, then in cabal; test to make sure pandoc works
153+
alt maybe_pandoc_cmd {
154+
some(pandoc_cmd) { result::ok(some(pandoc_cmd)) }
155+
none { result::ok(some("pandoc")) }
156+
}
157+
}
158+
159+
#[test]
160+
fn should_error_with_no_crates() {
161+
let config = parse_config(["rustdoc"]);
162+
assert result::get_err(config) == "no crates specified";
163+
}
164+
165+
#[test]
166+
fn should_error_with_multiple_crates() {
167+
let config = parse_config(["rustdoc", "crate1.rc", "crate2.rc"]);
168+
assert result::get_err(config) == "multiple crates specified";
169+
}
170+
171+
#[test]
172+
fn should_set_output_dir_to_cwd_if_not_provided() {
173+
let config = parse_config(["rustdoc", "crate.rc"]);
174+
assert result::get(config).output_dir == ".";
175+
}
176+
177+
#[test]
178+
fn should_set_output_dir_if_provided() {
179+
let config = parse_config([
180+
"rustdoc", "crate.rc", "--output-dir", "snuggles"
181+
]);
182+
assert result::get(config).output_dir == "snuggles";
183+
}
184+
185+
#[test]
186+
fn should_set_output_format_to_pandoc_html_if_not_provided() {
187+
let config = parse_config(["rustdoc", "crate.rc"]);
188+
assert result::get(config).output_format == pandoc_html;
189+
}
190+
191+
#[test]
192+
fn should_set_output_format_to_markdown_if_requested() {
193+
let config = parse_config([
194+
"rustdoc", "crate.rc", "--output-format", "markdown"
195+
]);
196+
assert result::get(config).output_format == markdown;
197+
}
198+
199+
#[test]
200+
fn should_set_output_format_to_pandoc_html_if_requested() {
201+
let config = parse_config([
202+
"rustdoc", "crate.rc", "--output-format", "html"
203+
]);
204+
assert result::get(config).output_format == pandoc_html;
205+
}
206+
207+
#[test]
208+
fn should_error_on_bogus_format() {
209+
let config = parse_config([
210+
"rustdoc", "crate.rc", "--output-format", "bogus"
211+
]);
212+
assert result::get_err(config) == "unknown output format 'bogus'";
213+
}
214+
215+
#[test]
216+
fn should_set_output_style_to_doc_per_mod_by_default() {
217+
let config = parse_config(["rustdoc", "crate.rc"]);
218+
assert result::get(config).output_style == doc_per_mod;
219+
}
220+
221+
#[test]
222+
fn should_set_output_style_to_one_doc_if_requested() {
223+
let config = parse_config([
224+
"rustdoc", "crate.rc", "--output-style", "doc-per-crate"
225+
]);
226+
assert result::get(config).output_style == doc_per_crate;
227+
}
228+
229+
#[test]
230+
fn should_set_output_style_to_doc_per_mod_if_requested() {
231+
let config = parse_config([
232+
"rustdoc", "crate.rc", "--output-style", "doc-per-mod"
233+
]);
234+
assert result::get(config).output_style == doc_per_mod;
235+
}
236+
237+
#[test]
238+
fn should_error_on_bogus_output_style() {
239+
let config = parse_config([
240+
"rustdoc", "crate.rc", "--output-style", "bogus"
241+
]);
242+
assert result::get_err(config) == "unknown output style 'bogus'";
243+
}
244+
245+
#[test]
246+
fn should_set_pandoc_command_if_requested() {
247+
let config = parse_config([
248+
"rustdoc", "crate.rc", "--pandoc-cmd", "panda-bear-doc"
249+
]);
250+
assert result::get(config).pandoc_cmd == some("panda-bear-doc");
251+
}
252+
253+
#[test]
254+
fn should_set_pandoc_command_when_using_pandoc() {
255+
let config = parse_config(["rustdoc", "crate.rc"]);
256+
assert result::get(config).pandoc_cmd == some("pandoc");
257+
}

src/rustdoc/rustdoc.rc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
use std;
1313
use rustc;
1414

15+
mod config;
1516
mod parse;
1617
mod extract;
1718
mod attr_parser;

0 commit comments

Comments
 (0)