Skip to content

Commit c0a9eeb

Browse files
committed
feat: shorten output for grammar fetching and building
New look: ``` ./target/debug/hx --grammar build Building 102 grammars ... done 100 grammars already built 02 grammars built now ["bash", "rust"] ```
1 parent d773a6e commit c0a9eeb

File tree

1 file changed

+151
-28
lines changed

1 file changed

+151
-28
lines changed

helix-loader/src/grammar.rs

+151-28
Original file line numberDiff line numberDiff line change
@@ -89,15 +89,106 @@ pub fn fetch_grammars() -> Result<()> {
8989
let mut grammars = get_grammar_configs()?;
9090
grammars.retain(|grammar| !matches!(grammar.source, GrammarSource::Local { .. }));
9191

92-
run_parallel(grammars, fetch_grammar, "fetch")
92+
print!("Fetching {} grammars", grammars.len());
93+
let results = run_parallel(grammars, fetch_grammar);
94+
println!(" ... done");
95+
96+
let mut errors = Vec::new();
97+
let mut git_updated = Vec::new();
98+
let mut git_up_to_date = Vec::new();
99+
let mut non_git = Vec::new();
100+
101+
for res in results {
102+
match res {
103+
Ok(FetchSuccess {
104+
grammar_id,
105+
action: FetchAction::GitUpdated { revision },
106+
}) => git_updated.push(format!("{grammar_id}->{revision}")),
107+
Ok(FetchSuccess {
108+
grammar_id,
109+
action: FetchAction::GitUpToDate,
110+
}) => git_up_to_date.push(grammar_id),
111+
Ok(FetchSuccess {
112+
grammar_id,
113+
action: FetchAction::NonGit,
114+
}) => non_git.push(grammar_id),
115+
Err(e) => errors.push(e),
116+
}
117+
}
118+
119+
// People will easily find the grammar they want that way
120+
git_updated.sort_unstable();
121+
git_up_to_date.sort_unstable();
122+
non_git.sort_unstable();
123+
124+
if !git_up_to_date.is_empty() {
125+
println!("{:02} up to date git grammars", git_up_to_date.len());
126+
}
127+
if !non_git.is_empty() {
128+
println!("{:02} non git grammars", non_git.len());
129+
println!(" {:?}", non_git);
130+
}
131+
132+
if !git_updated.is_empty() {
133+
println!("{:02} updated grammars", git_updated.len());
134+
println!(" {:?}", git_updated);
135+
}
136+
if !errors.is_empty() {
137+
let len = errors.len();
138+
println!("{len:02} grammars failed to fetch");
139+
for (i, error) in errors.into_iter().enumerate() {
140+
println!(" Failure {i:02}/{len:02}: {error}")
141+
}
142+
}
143+
144+
Ok(())
93145
}
94146

95147
pub fn build_grammars(target: Option<String>) -> Result<()> {
96-
run_parallel(
97-
get_grammar_configs()?,
98-
move |grammar| build_grammar(grammar, target.as_deref()),
99-
"build",
100-
)
148+
let grammars = get_grammar_configs()?;
149+
print!("Building {} grammars", grammars.len());
150+
let results = run_parallel(grammars, move |grammar| {
151+
build_grammar(grammar, target.as_deref())
152+
});
153+
println!(" ... done");
154+
155+
let mut errors = Vec::new();
156+
let mut built = Vec::new();
157+
let mut already_built = Vec::new();
158+
159+
for res in results {
160+
match res {
161+
Ok(BuildSuccess {
162+
grammar_id,
163+
action: BuildAction::Built,
164+
}) => built.push(grammar_id),
165+
Ok(BuildSuccess {
166+
grammar_id,
167+
action: BuildAction::AlreadyBuilt,
168+
}) => already_built.push(grammar_id),
169+
Err(e) => errors.push(e),
170+
}
171+
}
172+
173+
built.sort_unstable();
174+
already_built.sort_unstable();
175+
176+
if !already_built.is_empty() {
177+
println!("{:02} grammars already built", already_built.len());
178+
}
179+
if !built.is_empty() {
180+
println!("{:02} grammars built now", built.len());
181+
println!(" {:?}", built);
182+
}
183+
if !errors.is_empty() {
184+
let len = errors.len();
185+
println!("{len:02} grammars failed to build");
186+
for (i, error) in errors.into_iter().enumerate() {
187+
println!(" Failure {i:02}/{len:02}: {error}")
188+
}
189+
}
190+
191+
Ok(())
101192
}
102193

103194
// Returns the set of grammar configurations the user requests.
@@ -126,9 +217,10 @@ fn get_grammar_configs() -> Result<Vec<GrammarConfiguration>> {
126217
Ok(grammars)
127218
}
128219

129-
fn run_parallel<F>(grammars: Vec<GrammarConfiguration>, job: F, action: &'static str) -> Result<()>
220+
fn run_parallel<F, Res>(grammars: Vec<GrammarConfiguration>, job: F) -> Vec<Result<Res>>
130221
where
131-
F: Fn(GrammarConfiguration) -> Result<()> + std::marker::Send + 'static + Clone,
222+
F: Fn(GrammarConfiguration) -> Result<Res> + Send + 'static + Clone,
223+
Res: Send + 'static,
132224
{
133225
let pool = threadpool::Builder::new().build();
134226
let (tx, rx) = channel();
@@ -146,14 +238,21 @@ where
146238

147239
drop(tx);
148240

149-
// TODO: print all failures instead of the first one found.
150-
rx.iter()
151-
.find(|result| result.is_err())
152-
.map(|err| err.with_context(|| format!("Failed to {} some grammar(s)", action)))
153-
.unwrap_or(Ok(()))
241+
rx.iter().collect()
154242
}
155243

156-
fn fetch_grammar(grammar: GrammarConfiguration) -> Result<()> {
244+
struct FetchSuccess {
245+
grammar_id: String,
246+
action: FetchAction,
247+
}
248+
249+
enum FetchAction {
250+
GitUpdated { revision: String },
251+
GitUpToDate,
252+
NonGit,
253+
}
254+
255+
fn fetch_grammar(grammar: GrammarConfiguration) -> Result<FetchSuccess> {
157256
if let GrammarSource::Git {
158257
remote, revision, ..
159258
} = grammar.source
@@ -189,16 +288,27 @@ fn fetch_grammar(grammar: GrammarConfiguration) -> Result<()> {
189288
)?;
190289
git(&grammar_dir, ["checkout", &revision])?;
191290

192-
println!(
193-
"Grammar '{}' checked out at '{}'.",
194-
grammar.grammar_id, revision
195-
);
291+
Ok(FetchSuccess {
292+
grammar_id: grammar.grammar_id,
293+
action: FetchAction::GitUpdated { revision },
294+
})
295+
// println!(
296+
// "Grammar '{}' checked out at '{}'.",
297+
// grammar.grammar_id, revision
298+
// );
196299
} else {
197-
println!("Grammar '{}' is already up to date.", grammar.grammar_id);
300+
Ok(FetchSuccess {
301+
grammar_id: grammar.grammar_id,
302+
action: FetchAction::GitUpToDate,
303+
})
304+
// println!("Grammar '{}' is already up to date.", grammar.grammar_id);
198305
}
306+
} else {
307+
Ok(FetchSuccess {
308+
grammar_id: grammar.grammar_id,
309+
action: FetchAction::NonGit,
310+
})
199311
}
200-
201-
Ok(())
202312
}
203313

204314
// Sets the remote for a repository to the given URL, creating the remote if
@@ -245,7 +355,17 @@ where
245355
}
246356
}
247357

248-
fn build_grammar(grammar: GrammarConfiguration, target: Option<&str>) -> Result<()> {
358+
struct BuildSuccess {
359+
grammar_id: String,
360+
action: BuildAction,
361+
}
362+
363+
enum BuildAction {
364+
Built,
365+
AlreadyBuilt,
366+
}
367+
368+
fn build_grammar(grammar: GrammarConfiguration, target: Option<&str>) -> Result<BuildSuccess> {
249369
let grammar_dir = if let GrammarSource::Local { path } = &grammar.source {
250370
PathBuf::from(&path)
251371
} else {
@@ -285,7 +405,7 @@ fn build_tree_sitter_library(
285405
src_path: &Path,
286406
grammar: GrammarConfiguration,
287407
target: Option<&str>,
288-
) -> Result<()> {
408+
) -> Result<BuildSuccess> {
289409
let header_path = src_path;
290410
let parser_path = src_path.join("parser.c");
291411
let mut scanner_path = src_path.join("scanner.c");
@@ -308,12 +428,12 @@ fn build_tree_sitter_library(
308428
.context("Failed to compare source and binary timestamps")?;
309429

310430
if !recompile {
311-
println!("Grammar '{}' is already built.", grammar.grammar_id);
312-
return Ok(());
431+
return Ok(BuildSuccess {
432+
grammar_id: grammar.grammar_id,
433+
action: BuildAction::AlreadyBuilt,
434+
});
313435
}
314436

315-
println!("Building grammar '{}'", grammar.grammar_id);
316-
317437
let mut config = cc::Build::new();
318438
config
319439
.cpp(true)
@@ -381,7 +501,10 @@ fn build_tree_sitter_library(
381501
));
382502
}
383503

384-
Ok(())
504+
Ok(BuildSuccess {
505+
grammar_id: grammar.grammar_id,
506+
action: BuildAction::Built,
507+
})
385508
}
386509

387510
fn needs_recompile(

0 commit comments

Comments
 (0)