1use std::{env, error::Error};
3type DynError = Box<dyn Error>;
6 use std::path::{Path, PathBuf};
9 use helix_core::syntax::Configuration as LangConfig;
10 use helix_term::health::TsFeature;
12 /// Get the list of languages that support a particular tree-sitter
14 pub fn ts_lang_support(feat: TsFeature) -> Vec<String> {
15 let queries_dir = path::ts_queries();
17 find_files(&queries_dir, feat.runtime_filename())
20 // .../helix/runtime/queries/python/highlights.scm
21 let tail = f.strip_prefix(&queries_dir).unwrap(); // python/highlights.scm
22 let lang = tail.components().next().unwrap(); // python
23 lang.as_os_str().to_string_lossy().to_string()
28 /// Get the list of languages that have any form of tree-sitter
29 /// queries defined in the runtime directory.
30 pub fn langs_with_ts_queries() -> Vec<String> {
31 std::fs::read_dir(path::ts_queries())
34 let entry = entry.ok()?;
39 .then(|| entry.file_name().to_string_lossy().to_string())
44 // naive implementation, but suffices for our needs
45 pub fn find_files(dir: &Path, filename: &str) -> Vec<PathBuf> {
46 std::fs::read_dir(dir)
49 let path = entry.ok()?.path();
51 Some(find_files(&path, filename))
53 (path.file_name()?.to_string_lossy() == filename).then(|| vec![path])
60 pub fn lang_config() -> LangConfig {
61 let bytes = std::fs::read(path::lang_config()).unwrap();
62 toml::from_slice(&bytes).unwrap()
71 use helix_term::commands::TYPABLE_COMMAND_LIST;
72 use helix_term::health::TsFeature;
75 pub const TYPABLE_COMMANDS_MD_OUTPUT: &str = "typable-cmd.md";
76 pub const LANG_SUPPORT_MD_OUTPUT: &str = "lang-support.md";
78 fn md_table_heading(cols: &[String]) -> String {
79 let mut header = String::new();
80 header += &md_table_row(cols);
81 header += &md_table_row(&vec!["---".to_string(); cols.len()]);
85 fn md_table_row(cols: &[String]) -> String {
86 format!("| {} |\n", cols.join(" | "))
89 fn md_mono(s: &str) -> String {
93 pub fn typable_commands() -> Result<String, DynError> {
94 let mut md = String::new();
95 md.push_str(&md_table_heading(&[
97 "Description".to_owned(),
100 let cmdify = |s: &str| format!("`:{}`", s);
102 for cmd in TYPABLE_COMMAND_LIST {
103 let names = std::iter::once(&cmd.name)
104 .chain(cmd.aliases.iter())
109 let doc = cmd.doc.replace('\n', "<br>");
111 md.push_str(&md_table_row(&[names.to_owned(), doc.to_owned()]));
117 pub fn lang_features() -> Result<String, DynError> {
118 let mut md = String::new();
119 let ts_features = TsFeature::all();
121 let mut cols = vec!["Language".to_owned()];
125 .map(|t| t.long_title().to_string())
126 .collect::<Vec<_>>(),
128 cols.push("Default LSP".to_owned());
130 md.push_str(&md_table_heading(&cols));
131 let config = helpers::lang_config();
133 let mut langs = config
136 .map(|l| l.language_id.clone())
137 .collect::<Vec<_>>();
138 langs.sort_unstable();
140 let mut ts_features_to_langs = Vec::new();
141 for &feat in ts_features {
142 ts_features_to_langs.push((feat, helpers::ts_lang_support(feat)));
145 let mut row = Vec::new();
150 .find(|l| l.language_id == lang)
151 .unwrap(); // lang comes from config
152 row.push(lc.language_id.clone());
154 for (_feat, support_list) in &ts_features_to_langs {
156 if support_list.contains(&lang) {
167 .map(|s| s.command.clone())
168 .map(|c| md_mono(&c))
169 .unwrap_or_default(),
172 md.push_str(&md_table_row(&row));
179 pub fn write(filename: &str, data: &str) {
180 let error = format!("Could not write to {}", filename);
181 let path = path::book_gen().join(filename);
182 fs::write(path, data).expect(&error);
187 use std::path::{Path, PathBuf};
189 pub fn project_root() -> PathBuf {
190 Path::new(env!("CARGO_MANIFEST_DIR"))
196 pub fn book_gen() -> PathBuf {
197 project_root().join("book/src/generated/")
200 pub fn ts_queries() -> PathBuf {
201 project_root().join("runtime/queries")
204 pub fn lang_config() -> PathBuf {
205 project_root().join("languages.toml")
213 pub fn docgen() -> Result<(), DynError> {
215 write(TYPABLE_COMMANDS_MD_OUTPUT, &typable_commands()?);
216 write(LANG_SUPPORT_MD_OUTPUT, &lang_features()?);
220 pub fn print_help() {
223Usage: Run with `cargo xtask <task>`, eg. `cargo xtask docgen`.
226 docgen: Generate files to be included in the mdbook output.
232fn main() -> Result<(), DynError> {
233 let task = env::args().nth(1);
235 None => tasks::print_help(),
236 Some(t) => match t.as_str() {
237 "docgen" => tasks::docgen()?,
238 invalid => return Err(format!("Invalid task name: {}", invalid).into()),
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list