on master help sign in
Auto generate docs for language support
commita78b7894066b6ccf56c404b7543b45e2dfd99982 authorGokul Soumya <gokulps15@gmail.com> dateMon 22 Nov 2021, 00:25 (5 years ago) parent71292f9
11 files changed+311−22
Cargo.lock+2 book/src/SUMMARY.md+1 book/src/generated/lang-support.md+41 book/src/generated/typable-cmd.md+1−1 book/src/lang-support.md+10 docs/CONTRIBUTING.md+1−1 helix-core/src/indent.rs+1 helix-core/src/syntax.rs+2−1 languages.toml+40 xtask/Cargo.toml+2 xtask/src/main.rs+210−19
Cargo.lock+2
@@ -1264,5 +1264,7 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
12641264name = "xtask"
12651265version = "0.5.0"
12661266dependencies = [
1267+ "helix-core",
12671268 "helix-term",
1269+ "toml",
12681270]
book/src/SUMMARY.md+1
@@ -4,6 +4,7 @@
44- [Usage](./usage.md)
55 - [Keymap](./keymap.md)
66 - [Commands](./commands.md)
7+ - [Language Support](./lang-support.md)
78- [Migrating from Vim](./from-vim.md)
89- [Configuration](./configuration.md)
910 - [Themes](./themes.md)
book/src/generated/lang-support.mdnew file+41
@@ -0,0 +1,41 @@
1+| Language | Syntax Highlighting | Treesitter Textobjects | Auto Indent | Default LSP |
2+| --- | --- | --- | --- | --- |
3+| Bash | ✓ | | | `bash-language-server` |
4+| C | ✓ | | | `clangd` |
5+| C# | ✓ | | | |
6+| CMake | ✓ | | | `cmake-language-server` |
7+| C++ | ✓ | | | `clangd` |
8+| CSS | ✓ | | | |
9+| Elixir | ✓ | | | `elixir-ls` |
10+| GLSL | ✓ | | ✓ | |
11+| Go | ✓ | ✓ | ✓ | `gopls` |
12+| HTML | ✓ | | | |
13+| Java | ✓ | | | |
14+| JavaScript | ✓ | | ✓ | |
15+| JSON | ✓ | | ✓ | |
16+| Julia | ✓ | | | `julia` |
17+| LaTeX | ✓ | | | |
18+| Ledger | ✓ | | | |
19+| LLVM | ✓ | | | |
20+| Lua | ✓ | | ✓ | |
21+| Mint | | | | `mint` |
22+| Nix | ✓ | | ✓ | `rnix-lsp` |
23+| OCaml | ✓ | | ✓ | |
24+| OCaml-Interface | ✓ | | | |
25+| Perl | ✓ | ✓ | | |
26+| PHP | ✓ | | ✓ | |
27+| Prolog | | | | `swipl` |
28+| Protobuf | ✓ | | ✓ | |
29+| Python | ✓ | ✓ | ✓ | `pylsp` |
30+| Racket | | | | `racket` |
31+| Ruby | ✓ | | | `solargraph` |
32+| Rust | ✓ | ✓ | ✓ | `rust-analyzer` |
33+| Svelte | ✓ | | ✓ | `svelteserver` |
34+| TOML | ✓ | | | |
35+| TSQ | ✓ | | | |
36+| TSX | ✓ | | | `typescript-language-server` |
37+| TypeScript | ✓ | | ✓ | `typescript-language-server` |
38+| Vue | ✓ | | | |
39+| WGSL | ✓ | | | |
40+| YAML | ✓ | | ✓ | |
41+| Zig | ✓ | | ✓ | `zls` |
book/src/generated/typable-cmd.md+1−1
@@ -1,5 +1,5 @@
11| Name | Description |
2−| --- | --- |
2+| --- | --- |
33| `:quit`, `:q` | Close the current view. |
44| `:quit!`, `:q!` | Close the current view forcefully (ignoring unsaved changes). |
55| `:open`, `:o` | Open a file from disk into the current view. |
book/src/lang-support.mdnew file+10
@@ -0,0 +1,10 @@
1+# Language Support
2+
3+For more information like arguments passed to default LSP server,
4+extensions assosciated with a filetype, custom LSP settings, filetype
5+specific indent settings, etc see the default
6+[`languages.toml`][languages.toml] file.
7+
8+{{#include ./generated/lang-support.md}}
9+
10+[languages.toml]: https://github.com/helix-editor/helix/blob/master/languages.toml
docs/CONTRIBUTING.md+1−1
@@ -23,7 +23,7 @@ like the list of `:commands` and supported languages. To generate these
2323files, run
2424
2525```shell
26−cargo xtask bookgen
26+cargo xtask docgen
2727```
2828
2929inside the project. We use [xtask][xtask] as an ad-hoc task runner and
helix-core/src/indent.rs+1
@@ -452,6 +452,7 @@ where
452452 file_types: vec!["rs".to_string()],
453453 shebangs: vec![],
454454 language_id: "Rust".to_string(),
455+ display_name: "Rust".to_string(),
455456 highlight_config: OnceCell::new(),
456457 config: None,
457458 //
helix-core/src/syntax.rs+2−1
@@ -50,7 +50,8 @@ pub struct Configuration {
5050#[serde(rename_all = "kebab-case", deny_unknown_fields)]
5151pub struct LanguageConfiguration {
5252 #[serde(rename = "name")]
53− pub language_id: String,
53+ pub language_id: String, // c-sharp, rust
54+ pub display_name: String, // C#, Rust
5455 pub scope: String, // source.rust
5556 pub file_types: Vec<String>, // filename ends_with? <Gemfile, rb, etc>
5657 #[serde(default)]
languages.toml+40
@@ -1,5 +1,6 @@
11[[language]]
22name = "rust"
3+display-name = "Rust"
34scope = "source.rust"
45injection-regex = "rust"
56file-types = ["rs"]
@@ -14,6 +15,7 @@ procMacro = { enable = false }
1415
1516[[language]]
1617name = "toml"
18+display-name = "TOML"
1719scope = "source.toml"
1820injection-regex = "toml"
1921file-types = ["toml"]
@@ -24,6 +26,7 @@ indent = { tab-width = 2, unit = " " }
2426
2527[[language]]
2628name = "protobuf"
29+display-name = "Protobuf"
2730scope = "source.proto"
2831injection-regex = "protobuf"
2932file-types = ["proto"]
@@ -34,6 +37,7 @@ indent = { tab-width = 2, unit = " " }
3437
3538[[language]]
3639name = "elixir"
40+display-name = "Elixir"
3741scope = "source.elixir"
3842injection-regex = "elixir"
3943file-types = ["ex", "exs"]
@@ -46,6 +50,7 @@ indent = { tab-width = 2, unit = " " }
4650
4751[[language]]
4852name = "mint"
53+display-name = "Mint"
4954scope = "source.mint"
5055injection-regex = "mint"
5156file-types = ["mint"]
@@ -58,6 +63,7 @@ indent = { tab-width = 2, unit = " " }
5863
5964[[language]]
6065name = "json"
66+display-name = "JSON"
6167scope = "source.json"
6268injection-regex = "json"
6369file-types = ["json"]
@@ -67,6 +73,7 @@ indent = { tab-width = 2, unit = " " }
6773
6874[[language]]
6975name = "c"
76+display-name = "C"
7077scope = "source.c"
7178injection-regex = "c"
7279file-types = ["c"] # TODO: ["h"]
@@ -78,6 +85,7 @@ indent = { tab-width = 2, unit = " " }
7885
7986[[language]]
8087name = "cpp"
88+display-name = "C++"
8189scope = "source.cpp"
8290injection-regex = "cpp"
8391file-types = ["cc", "hh", "cpp", "hpp", "h", "ipp", "tpp", "cxx", "hxx", "ixx", "txx", "ino"]
@@ -89,6 +97,7 @@ indent = { tab-width = 2, unit = " " }
8997
9098[[language]]
9199name = "c-sharp"
100+display-name = "C#"
92101scope = "source.csharp"
93102injection-regex = "c-?sharp"
94103file-types = ["cs"]
@@ -99,6 +108,7 @@ indent = { tab-width = 4, unit = "\t" }
99108
100109[[language]]
101110name = "go"
111+display-name = "Go"
102112scope = "source.go"
103113injection-regex = "go"
104114file-types = ["go"]
@@ -112,6 +122,7 @@ indent = { tab-width = 4, unit = "\t" }
112122
113123[[language]]
114124name = "javascript"
125+display-name = "JavaScript"
115126scope = "source.js"
116127injection-regex = "^(js|javascript)$"
117128file-types = ["js", "mjs"]
@@ -124,6 +135,7 @@ indent = { tab-width = 2, unit = " " }
124135
125136[[language]]
126137name = "typescript"
138+display-name = "TypeScript"
127139scope = "source.ts"
128140injection-regex = "^(ts|typescript)$"
129141file-types = ["ts"]
@@ -136,6 +148,7 @@ indent = { tab-width = 2, unit = " " }
136148
137149[[language]]
138150name = "tsx"
151+display-name = "TSX"
139152scope = "source.tsx"
140153injection-regex = "^(tsx)$" # |typescript
141154file-types = ["tsx"]
@@ -147,6 +160,7 @@ indent = { tab-width = 2, unit = " " }
147160
148161[[language]]
149162name = "css"
163+display-name = "CSS"
150164scope = "source.css"
151165injection-regex = "css"
152166file-types = ["css"]
@@ -156,6 +170,7 @@ indent = { tab-width = 2, unit = " " }
156170
157171[[language]]
158172name = "html"
173+display-name = "HTML"
159174scope = "text.html.basic"
160175injection-regex = "html"
161176file-types = ["html"]
@@ -165,6 +180,7 @@ indent = { tab-width = 2, unit = " " }
165180
166181[[language]]
167182name = "python"
183+display-name = "Python"
168184scope = "source.python"
169185injection-regex = "python"
170186file-types = ["py"]
@@ -178,6 +194,7 @@ indent = { tab-width = 4, unit = " " }
178194
179195[[language]]
180196name = "nix"
197+display-name = "Nix"
181198scope = "source.nix"
182199injection-regex = "nix"
183200file-types = ["nix"]
@@ -190,6 +207,7 @@ indent = { tab-width = 2, unit = " " }
190207
191208[[language]]
192209name = "ruby"
210+display-name = "Ruby"
193211scope = "source.ruby"
194212injection-regex = "ruby"
195213file-types = ["rb"]
@@ -202,6 +220,7 @@ indent = { tab-width = 2, unit = " " }
202220
203221[[language]]
204222name = "bash"
223+display-name = "Bash"
205224scope = "source.bash"
206225injection-regex = "bash"
207226file-types = ["sh", "bash"]
@@ -214,6 +233,7 @@ indent = { tab-width = 2, unit = " " }
214233
215234[[language]]
216235name = "php"
236+display-name = "PHP"
217237scope = "source.php"
218238injection-regex = "php"
219239file-types = ["php"]
@@ -224,6 +244,7 @@ indent = { tab-width = 4, unit = " " }
224244
225245[[language]]
226246name = "latex"
247+display-name = "LaTeX"
227248scope = "source.tex"
228249injection-regex = "tex"
229250file-types = ["tex"]
@@ -234,6 +255,7 @@ indent = { tab-width = 4, unit = "\t" }
234255
235256[[language]]
236257name = "julia"
258+display-name = "Julia"
237259scope = "source.julia"
238260injection-regex = "julia"
239261file-types = ["jl"]
@@ -259,6 +281,7 @@ indent = { tab-width = 2, unit = " " }
259281
260282[[language]]
261283name = "java"
284+display-name = "Java"
262285scope = "source.java"
263286injection-regex = "java"
264287file-types = ["java"]
@@ -267,6 +290,7 @@ indent = { tab-width = 4, unit = " " }
267290
268291[[language]]
269292name = "ledger"
293+display-name = "Ledger"
270294scope = "source.ledger"
271295injection-regex = "ledger"
272296file-types = ["ldg", "ledger", "journal"]
@@ -276,6 +300,7 @@ indent = { tab-width = 4, unit = " " }
276300
277301[[language]]
278302name = "ocaml"
303+display-name = "OCaml"
279304scope = "source.ocaml"
280305injection-regex = "ocaml"
281306file-types = ["ml"]
@@ -286,6 +311,7 @@ indent = { tab-width = 2, unit = " " }
286311
287312[[language]]
288313name = "ocaml-interface"
314+display-name = "OCaml-Interface"
289315scope = "source.ocaml.interface"
290316file-types = ["mli"]
291317shebangs = []
@@ -295,6 +321,7 @@ indent = { tab-width = 2, unit = " "}
295321
296322[[language]]
297323name = "lua"
324+display-name = "Lua"
298325scope = "source.lua"
299326file-types = ["lua"]
300327shebangs = ["lua"]
@@ -304,6 +331,7 @@ indent = { tab-width = 2, unit = " " }
304331
305332[[language]]
306333name = "svelte"
334+display-name = "Svelte"
307335scope = "source.svelte"
308336injection-regex = "svelte"
309337file-types = ["svelte"]
@@ -314,6 +342,7 @@ language-server = { command = "svelteserver", args = ["--stdio"] }
314342
315343[[language]]
316344name = "vue"
345+display-name = "Vue"
317346scope = "source.vue"
318347injection-regex = "vue"
319348file-types = ["vue"]
@@ -322,6 +351,7 @@ indent = { tab-width = 2, unit = " " }
322351
323352[[language]]
324353name = "yaml"
354+display-name = "YAML"
325355scope = "source.yaml"
326356file-types = ["yml", "yaml"]
327357roots = []
@@ -330,6 +360,7 @@ indent = { tab-width = 2, unit = " " }
330360
331361# [[language]]
332362# name = "haskell"
363+# display-name = "Haskell"
333364# scope = "source.haskell"
334365# injection-regex = "haskell"
335366# file-types = ["hs"]
@@ -340,6 +371,7 @@ indent = { tab-width = 2, unit = " " }
340371
341372[[language]]
342373name = "zig"
374+display-name = "Zig"
343375scope = "source.zig"
344376injection-regex = "zig"
345377file-types = ["zig"]
@@ -352,6 +384,7 @@ indent = { tab-width = 4, unit = " " }
352384
353385[[language]]
354386name = "prolog"
387+display-name = "Prolog"
355388scope = "source.prolog"
356389roots = []
357390file-types = ["pl", "prolog"]
@@ -365,6 +398,7 @@ language-server = { command = "swipl", args = [
365398
366399[[language]]
367400name = "tsq"
401+display-name = "TSQ"
368402scope = "source.tsq"
369403file-types = ["scm"]
370404roots = []
@@ -373,6 +407,7 @@ indent = { tab-width = 2, unit = " " }
373407
374408[[language]]
375409name = "cmake"
410+display-name = "CMake"
376411scope = "source.cmake"
377412file-types = ["cmake", "CMakeLists.txt"]
378413roots = []
@@ -382,6 +417,7 @@ language-server = { command = "cmake-language-server" }
382417
383418[[language]]
384419name = "glsl"
420+display-name = "GLSL"
385421scope = "source.glsl"
386422file-types = ["glsl", "vert", "tesc", "tese", "geom", "frag", "comp" ]
387423roots = []
@@ -390,6 +426,7 @@ indent = { tab-width = 4, unit = " " }
390426
391427[[language]]
392428name = "perl"
429+display-name = "Perl"
393430scope = "source.perl"
394431file-types = ["pl", "pm"]
395432shebangs = ["perl"]
@@ -399,6 +436,7 @@ indent = { tab-width = 2, unit = " " }
399436
400437[[language]]
401438name = "racket"
439+display-name = "Racket"
402440scope = "source.rkt"
403441roots = []
404442file-types = ["rkt"]
@@ -408,6 +446,7 @@ language-server = { command = "racket", args = ["-l", "racket-langserver"] }
408446
409447[[language]]
410448name = "wgsl"
449+display-name = "WGSL"
411450scope = "source.wgsl"
412451file-types = ["wgsl"]
413452roots = []
@@ -416,6 +455,7 @@ indent = { tab-width = 4, unit = " " }
416455
417456[[language]]
418457name = "llvm"
458+display-name = "LLVM"
419459scope = "source.llvm"
420460roots = []
421461file-types = ["ll"]
xtask/Cargo.toml+2
@@ -7,3 +7,5 @@ edition = "2021"
77
88[dependencies]
99helix-term = { version = "0.5", path = "../helix-term" }
10+helix-core = { version = "0.5", path = "../helix-core" }
11+toml = "0.5"
xtask/src/main.rs+210−19
@@ -1,17 +1,138 @@
1−use std::env;
1+use std::{env, error::Error};
2+
3+type DynError = Box<dyn Error>;
4+
5+pub mod helpers {
6+ use std::{
7+ fmt::Display,
8+ path::{Path, PathBuf},
9+ };
10+
11+ use crate::path;
12+ use helix_core::syntax::Configuration as LangConfig;
13+
14+ #[derive(Copy, Clone)]
15+ pub enum TsFeature {
16+ Highlight,
17+ TextObjects,
18+ AutoIndent,
19+ }
20+
21+ impl TsFeature {
22+ pub fn all() -> &'static [Self] {
23+ &[Self::Highlight, Self::TextObjects, Self::AutoIndent]
24+ }
25+
26+ pub fn runtime_filename(&self) -> &'static str {
27+ match *self {
28+ Self::Highlight => "highlights.scm",
29+ Self::TextObjects => "textobjects.scm",
30+ Self::AutoIndent => "indents.toml",
31+ }
32+ }
33+ }
34+
35+ impl Display for TsFeature {
36+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
37+ write!(
38+ f,
39+ "{}",
40+ match *self {
41+ Self::Highlight => "Syntax Highlighting",
42+ Self::TextObjects => "Treesitter Textobjects",
43+ Self::AutoIndent => "Auto Indent",
44+ }
45+ )
46+ }
47+ }
48+
49+ /// Get the list of languages that support a particular tree-sitter
50+ /// based feature.
51+ pub fn ts_lang_support(feat: TsFeature) -> Vec<String> {
52+ let queries_dir = path::ts_queries();
53+
54+ find_files(&queries_dir, feat.runtime_filename())
55+ .iter()
56+ .map(|f| {
57+ // .../helix/runtime/queries/python/highlights.scm
58+ let tail = f.strip_prefix(&queries_dir).unwrap(); // python/highlights.scm
59+ let lang = tail.components().next().unwrap(); // python
60+ lang.as_os_str().to_string_lossy().to_string()
61+ })
62+ .collect()
63+ }
64+
65+ /// Get the list of languages that have any form of tree-sitter
66+ /// queries defined in the runtime directory.
67+ pub fn langs_with_ts_queries() -> Vec<String> {
68+ std::fs::read_dir(path::ts_queries())
69+ .unwrap()
70+ .filter_map(|entry| {
71+ let entry = entry.ok()?;
72+ entry
73+ .file_type()
74+ .ok()?
75+ .is_dir()
76+ .then(|| entry.file_name().to_string_lossy().to_string())
77+ })
78+ .collect()
79+ }
80+
81+ // naive implementation, but suffices for our needs
82+ pub fn find_files(dir: &Path, filename: &str) -> Vec<PathBuf> {
83+ std::fs::read_dir(dir)
84+ .unwrap()
85+ .filter_map(|entry| {
86+ let path = entry.ok()?.path();
87+ if path.is_dir() {
88+ Some(find_files(&path, filename))
89+ } else {
90+ (path.file_name()?.to_string_lossy() == filename).then(|| vec![path])
91+ }
92+ })
93+ .flatten()
94+ .collect()
95+ }
96+
97+ pub fn lang_config() -> LangConfig {
98+ let bytes = std::fs::read(path::lang_config()).unwrap();
99+ toml::from_slice(&bytes).unwrap()
100+ }
101+}
2102
3103pub mod md_gen {
4− use super::path;
104+ use crate::DynError;
105+
106+ use crate::helpers;
107+ use crate::path;
5108 use std::fs;
6109
7110 use helix_term::commands::cmd::TYPABLE_COMMAND_LIST;
8111
9112 pub const TYPABLE_COMMANDS_MD_OUTPUT: &str = "typable-cmd.md";
113+ pub const LANG_SUPPORT_MD_OUTPUT: &str = "lang-support.md";
114+
115+ fn md_table_heading(cols: &[String]) -> String {
116+ let mut header = String::new();
117+ header += &md_table_row(cols);
118+ header += &md_table_row(&vec!["---".to_string(); cols.len()]);
119+ header
120+ }
121+
122+ fn md_table_row(cols: &[String]) -> String {
123+ "| ".to_owned() + &cols.join(" | ") + " |\n"
124+ }
125+
126+ fn md_mono(s: &str) -> String {
127+ format!("`{}`", s)
128+ }
10129
11− pub fn typable_commands() -> String {
130+ pub fn typable_commands() -> Result<String, DynError> {
12131 let mut md = String::new();
13− md.push_str("| Name | Description |\n");
14− md.push_str("| --- | --- |\n");
132+ md.push_str(&md_table_heading(&[
133+ "Name".to_owned(),
134+ "Description".to_owned(),
135+ ]));
15136
16137 let cmdify = |s: &str| format!("`:{}`", s);
17138
@@ -22,11 +143,72 @@ pub mod md_gen {
22143 .collect::<Vec<_>>()
23144 .join(", ");
24145
25− let entry = format!("| {} | {} |\n", names, cmd.doc);
26− md.push_str(&entry);
146+ md.push_str(&md_table_row(&[names.to_owned(), cmd.doc.to_owned()]));
147+ }
148+
149+ Ok(md)
150+ }
151+
152+ pub fn lang_features() -> Result<String, DynError> {
153+ let mut md = String::new();
154+ let ts_features = helpers::TsFeature::all();
155+
156+ let mut cols = vec!["Language".to_owned()];
157+ cols.append(
158+ &mut ts_features
159+ .iter()
160+ .map(|t| t.to_string())
161+ .collect::<Vec<_>>(),
162+ );
163+ cols.push("Default LSP".to_owned());
164+
165+ md.push_str(&md_table_heading(&cols));
166+ let config = helpers::lang_config();
167+
168+ let mut langs = config
169+ .language
170+ .iter()
171+ .map(|l| l.language_id.clone())
172+ .collect::<Vec<_>>();
173+ langs.sort_unstable();
174+
175+ let mut ts_features_to_langs = Vec::new();
176+ for &feat in ts_features {
177+ ts_features_to_langs.push((feat, helpers::ts_lang_support(feat)));
27178 }
28179
29− md
180+ let mut row = Vec::new();
181+ for lang in langs {
182+ let lc = config
183+ .language
184+ .iter()
185+ .find(|l| l.language_id == lang)
186+ .unwrap(); // lang comes from config
187+ row.push(lc.display_name.clone());
188+
189+ for (_feat, support_list) in &ts_features_to_langs {
190+ row.push(
191+ if support_list.contains(&lang) {
192+ "✓"
193+ } else {
194+ ""
195+ }
196+ .to_owned(),
197+ );
198+ }
199+ row.push(
200+ lc.language_server
201+ .as_ref()
202+ .map(|s| s.command.clone())
203+ .map(|c| md_mono(&c))
204+ .unwrap_or_default(),
205+ );
206+
207+ md.push_str(&md_table_row(&row));
208+ row.clear();
209+ }
210+
211+ Ok(md)
30212 }
31213
32214 pub fn write(filename: &str, data: &str) {
@@ -49,37 +231,46 @@ pub mod path {
49231 pub fn book_gen() -> PathBuf {
50232 project_root().join("book/src/generated/")
51233 }
234+
235+ pub fn ts_queries() -> PathBuf {
236+ project_root().join("runtime/queries")
237+ }
238+
239+ pub fn lang_config() -> PathBuf {
240+ project_root().join("languages.toml")
241+ }
52242}
53243
54244pub mod tasks {
55− use super::md_gen;
245+ use crate::md_gen;
246+ use crate::DynError;
56247
57− pub fn bookgen() {
58− md_gen::write(
59− md_gen::TYPABLE_COMMANDS_MD_OUTPUT,
60− &md_gen::typable_commands(),
61− );
248+ pub fn docgen() -> Result<(), DynError> {
249+ use md_gen::*;
250+ write(TYPABLE_COMMANDS_MD_OUTPUT, &typable_commands()?);
251+ write(LANG_SUPPORT_MD_OUTPUT, &lang_features()?);
252+ Ok(())
62253 }
63254
64255 pub fn print_help() {
65256 println!(
66257 "
67−Usage: Run with `cargo xtask <task>`, eg. `cargo xtask bookgen`.
258+Usage: Run with `cargo xtask <task>`, eg. `cargo xtask docgen`.
68259
69260 Tasks:
70− bookgen: Generate files to be included in the mdbook output.
261+ docgen: Generate files to be included in the mdbook output.
71262"
72263 );
73264 }
74265}
75266
76−fn main() -> Result<(), String> {
267+fn main() -> Result<(), DynError> {
77268 let task = env::args().nth(1);
78269 match task {
79270 None => tasks::print_help(),
80271 Some(t) => match t.as_str() {
81− "bookgen" => tasks::bookgen(),
82− invalid => return Err(format!("Invalid task name: {}", invalid)),
272+ "docgen" => tasks::docgen()?,
273+ invalid => return Err(format!("Invalid task name: {}", invalid).into()),
83274 },
84275 };
85276 Ok(())