From ff2436a6f8639b290e4395ca2b44491472647a2b Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Tue, 14 Feb 2023 14:41:25 -0800 Subject: [PATCH] Add --row-range, --quiet, and --time flags to query subcommand --- cli/src/main.rs | 30 ++++++++++++++++--- cli/src/query.rs | 77 +++++++++++++++++++++++++++++------------------- 2 files changed, 73 insertions(+), 34 deletions(-) diff --git a/cli/src/main.rs b/cli/src/main.rs index 47e7597b..fb2a6327 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -3,6 +3,7 @@ use clap::{App, AppSettings, Arg, SubCommand}; use glob::glob; use std::path::{Path, PathBuf}; use std::{env, fs, u64}; +use tree_sitter::Point; use tree_sitter_cli::parse::ParseOutput; use tree_sitter_cli::{ generate, highlight, logger, parse, playground, query, tags, test, test_highlight, test_tags, @@ -173,6 +174,8 @@ fn run() -> Result<()> { .index(1) .required(true), ) + .arg(&time_arg) + .arg(&quiet_arg) .arg(&paths_file_arg) .arg(&paths_arg.clone().index(2)) .arg( @@ -181,6 +184,12 @@ fn run() -> Result<()> { .long("byte-range") .takes_value(true), ) + .arg( + Arg::with_name("row-range") + .help("The range of rows in which the query will be executed") + .long("row-range") + .takes_value(true), + ) .arg(&scope_arg) .arg(Arg::with_name("captures").long("captures").short("c")) .arg(Arg::with_name("test").long("test")), @@ -456,6 +465,8 @@ fn run() -> Result<()> { ("query", Some(matches)) => { let ordered_captures = matches.values_of("captures").is_some(); + let quiet = matches.values_of("quiet").is_some(); + let time = matches.values_of("time").is_some(); let paths = collect_paths(matches.value_of("paths-file"), matches.values_of("paths"))?; let loader_config = config.get()?; loader.find_all_languages(&loader_config)?; @@ -465,9 +476,17 @@ fn run() -> Result<()> { matches.value_of("scope"), )?; let query_path = Path::new(matches.value_of("query-path").unwrap()); - let range = matches.value_of("byte-range").map(|br| { - let r: Vec<&str> = br.split(":").collect(); - r[0].parse().unwrap()..r[1].parse().unwrap() + let byte_range = matches.value_of("byte-range").and_then(|arg| { + let mut parts = arg.split(":"); + let start = parts.next()?.parse().ok()?; + let end = parts.next().unwrap().parse().ok()?; + Some(start..end) + }); + let point_range = matches.value_of("row-range").and_then(|arg| { + let mut parts = arg.split(":"); + let start = parts.next()?.parse().ok()?; + let end = parts.next().unwrap().parse().ok()?; + Some(Point::new(start, 0)..Point::new(end, 0)) }); let should_test = matches.is_present("test"); query::query_files_at_paths( @@ -475,8 +494,11 @@ fn run() -> Result<()> { paths, query_path, ordered_captures, - range, + byte_range, + point_range, should_test, + quiet, + time, )?; } diff --git a/cli/src/query.rs b/cli/src/query.rs index 73d6dd28..fc24cb05 100644 --- a/cli/src/query.rs +++ b/cli/src/query.rs @@ -5,16 +5,20 @@ use std::{ io::{self, Write}, ops::Range, path::Path, + time::Instant, }; -use tree_sitter::{Language, Parser, Query, QueryCursor}; +use tree_sitter::{Language, Parser, Point, Query, QueryCursor}; pub fn query_files_at_paths( language: Language, paths: Vec, query_path: &Path, ordered_captures: bool, - range: Option>, + byte_range: Option>, + point_range: Option>, should_test: bool, + quiet: bool, + print_time: bool, ) -> Result<()> { let stdout = io::stdout(); let mut stdout = stdout.lock(); @@ -24,9 +28,12 @@ pub fn query_files_at_paths( let query = Query::new(language, &query_source).with_context(|| "Query compilation failed")?; let mut query_cursor = QueryCursor::new(); - if let Some(range) = range { + if let Some(range) = byte_range { query_cursor.set_byte_range(range); } + if let Some(range) = point_range { + query_cursor.set_point_range(range); + } let mut parser = Parser::new(); parser.set_language(language)?; @@ -40,22 +47,25 @@ pub fn query_files_at_paths( fs::read(&path).with_context(|| format!("Error reading source file {:?}", path))?; let tree = parser.parse(&source_code, None).unwrap(); + let start = Instant::now(); if ordered_captures { for (mat, capture_index) in query_cursor.captures(&query, tree.root_node(), source_code.as_slice()) { let capture = mat.captures[capture_index]; let capture_name = &query.capture_names()[capture.index as usize]; - writeln!( - &mut stdout, - " pattern: {:>2}, capture: {} - {}, start: {}, end: {}, text: `{}`", - mat.pattern_index, - capture.index, - capture_name, - capture.node.start_position(), - capture.node.end_position(), - capture.node.utf8_text(&source_code).unwrap_or("") - )?; + if !quiet { + writeln!( + &mut stdout, + " pattern: {:>2}, capture: {} - {}, start: {}, end: {}, text: `{}`", + mat.pattern_index, + capture.index, + capture_name, + capture.node.start_position(), + capture.node.end_position(), + capture.node.utf8_text(&source_code).unwrap_or("") + )?; + } results.push(query_testing::CaptureInfo { name: capture_name.to_string(), start: capture.node.start_position(), @@ -64,27 +74,31 @@ pub fn query_files_at_paths( } } else { for m in query_cursor.matches(&query, tree.root_node(), source_code.as_slice()) { - writeln!(&mut stdout, " pattern: {}", m.pattern_index)?; + if !quiet { + writeln!(&mut stdout, " pattern: {}", m.pattern_index)?; + } for capture in m.captures { let start = capture.node.start_position(); let end = capture.node.end_position(); let capture_name = &query.capture_names()[capture.index as usize]; - if end.row == start.row { - writeln!( - &mut stdout, - " capture: {} - {}, start: {}, end: {}, text: `{}`", - capture.index, - capture_name, - start, - end, - capture.node.utf8_text(&source_code).unwrap_or("") - )?; - } else { - writeln!( - &mut stdout, - " capture: {}, start: {}, end: {}", - capture_name, start, end, - )?; + if !quiet { + if end.row == start.row { + writeln!( + &mut stdout, + " capture: {} - {}, start: {}, end: {}, text: `{}`", + capture.index, + capture_name, + start, + end, + capture.node.utf8_text(&source_code).unwrap_or("") + )?; + } else { + writeln!( + &mut stdout, + " capture: {}, start: {}, end: {}", + capture_name, start, end, + )?; + } } results.push(query_testing::CaptureInfo { name: capture_name.to_string(), @@ -103,6 +117,9 @@ pub fn query_files_at_paths( if should_test { query_testing::assert_expected_captures(results, path, &mut parser, language)? } + if print_time { + writeln!(&mut stdout, "{:?}", start.elapsed())?; + } } Ok(())