diff --git a/cli/src/main.rs b/cli/src/main.rs index ff415fbb..21e461cc 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -22,7 +22,7 @@ use tree_sitter_cli::{ init::{generate_grammar_files, get_root_path, JsonConfigOpts}, input::{get_input, get_tmp_source_file, CliInput}, logger, - parse::{self, ParseFileOptions, ParseOutput, ParseTheme}, + parse::{self, ParseDebugType, ParseFileOptions, ParseOutput, ParseTheme}, playground, query, tags::{self, TagsOptions}, test::{self, TestOptions, TestStats}, @@ -171,8 +171,9 @@ struct Parse { #[arg(long)] pub scope: Option, /// Show parsing debug log - #[arg(long, short = 'd')] - pub debug: bool, + #[arg(long, short = 'd')] // TODO: Rework once clap adds `default_missing_value_t` + #[allow(clippy::option_option)] + pub debug: Option>, /// Compile a parser in debug mode #[arg(long, short = '0')] pub debug_build: bool, @@ -877,6 +878,11 @@ impl Parse { let should_track_stats = self.stat; let mut stats = parse::ParseStats::default(); + let debug: ParseDebugType = match self.debug { + None => ParseDebugType::Quiet, + Some(None) => ParseDebugType::Normal, + Some(Some(specifier)) => specifier, + }; let mut options = ParseFileOptions { edits: &edits @@ -887,7 +893,7 @@ impl Parse { print_time: time, timeout, stats: &mut stats, - debug: self.debug, + debug, debug_graph: self.debug_graph, cancellation_flag: Some(&cancellation_flag), encoding, diff --git a/cli/src/parse.rs b/cli/src/parse.rs index 67540cce..bbe971ec 100644 --- a/cli/src/parse.rs +++ b/cli/src/parse.rs @@ -8,6 +8,7 @@ use std::{ use anstyle::{AnsiColor, Color, RgbColor}; use anyhow::{anyhow, Context, Result}; +use clap::ValueEnum; use serde::{Deserialize, Serialize}; use tree_sitter::{ ffi, InputEdit, Language, LogType, ParseOptions, ParseState, Parser, Point, Range, Tree, @@ -224,13 +225,21 @@ pub struct ParseStats { pub cumulative_stats: Stats, } +#[derive(Serialize, ValueEnum, Debug, Clone, Default, Eq, PartialEq)] +pub enum ParseDebugType { + #[default] + Quiet, + Normal, + Pretty, +} + pub struct ParseFileOptions<'a> { pub edits: &'a [&'a str], pub output: ParseOutput, pub stats: &'a mut ParseStats, pub print_time: bool, pub timeout: u64, - pub debug: bool, + pub debug: ParseDebugType, pub debug_graph: bool, pub cancellation_flag: Option<&'a AtomicUsize>, pub encoding: Option, @@ -263,12 +272,43 @@ pub fn parse_file_at_path( _log_session = Some(util::log_graphs(parser, "log.html", opts.open_log)?); } // Log to stderr if `--debug` was passed - else if opts.debug { + else if opts.debug != ParseDebugType::Quiet { + let mut curr_version: usize = 0usize; + let use_color = std::env::var("NO_COLOR").map_or(true, |v| v != "1"); parser.set_logger(Some(Box::new(|log_type, message| { - if log_type == LogType::Lex { - io::stderr().write_all(b" ").unwrap(); + if opts.debug == ParseDebugType::Normal { + if log_type == LogType::Lex { + write!(&mut io::stderr(), " ").unwrap(); + }; + writeln!(&mut io::stderr(), "{message}").unwrap(); + } else { + let colors = &[ + AnsiColor::White, + AnsiColor::Red, + AnsiColor::Blue, + AnsiColor::Green, + AnsiColor::Cyan, + AnsiColor::Yellow, + ]; + if message.starts_with("process version:") { + let comma_idx = message.find(',').unwrap(); + curr_version = message["process version:".len()..comma_idx] + .parse() + .unwrap(); + } + let color = if use_color { + Some(colors[curr_version]) + } else { + None + }; + let mut out = if log_type == LogType::Lex { + " ".to_string() + } else { + String::new() + }; + out += &paint(color, message); + writeln!(&mut io::stderr(), "{out}").unwrap(); } - writeln!(&mut io::stderr(), "{message}").unwrap(); }))); }