rust: Include pattern indices when iterating query captures

This commit is contained in:
Max Brunsfeld 2019-09-18 14:22:55 -07:00
parent 186b08381c
commit d9b8bae629
4 changed files with 74 additions and 50 deletions

View file

@ -84,7 +84,8 @@ fn run() -> error::Result<()> {
.multiple(true)
.required(true),
)
.arg(Arg::with_name("scope").long("scope").takes_value(true)),
.arg(Arg::with_name("scope").long("scope").takes_value(true))
.arg(Arg::with_name("captures").long("captures").short("c")),
)
.subcommand(
SubCommand::with_name("test")
@ -210,6 +211,7 @@ fn run() -> error::Result<()> {
return Error::err(String::new());
}
} else if let Some(matches) = matches.subcommand_matches("query") {
let ordered_captures = matches.values_of("captures").is_some();
let paths = matches
.values_of("path")
.unwrap()
@ -224,7 +226,7 @@ fn run() -> error::Result<()> {
matches.value_of("scope"),
)?;
let query_path = Path::new(matches.value_of("query-path").unwrap());
query::query_files_at_paths(language, paths, query_path)?;
query::query_files_at_paths(language, paths, query_path, ordered_captures)?;
} else if let Some(matches) = matches.subcommand_matches("highlight") {
let paths = matches.values_of("path").unwrap().into_iter();
let html_mode = matches.is_present("html");

View file

@ -2,12 +2,13 @@ use super::error::{Error, Result};
use std::fs;
use std::io::{self, Write};
use std::path::Path;
use tree_sitter::{Language, Parser, Query, QueryCursor};
use tree_sitter::{Language, Node, Parser, Query, QueryCursor};
pub fn query_files_at_paths(
language: Language,
paths: Vec<&Path>,
query_path: &Path,
ordered_captures: bool,
) -> Result<()> {
let stdout = io::stdout();
let mut stdout = stdout.lock();
@ -29,19 +30,33 @@ pub fn query_files_at_paths(
let source_code = fs::read(path).map_err(Error::wrap(|| {
format!("Error reading source file {:?}", path)
}))?;
let text_callback = |n: Node| &source_code[n.byte_range()];
let tree = parser.parse(&source_code, None).unwrap();
for mat in query_cursor.matches(&query, tree.root_node(), |n| &source_code[n.byte_range()]) {
writeln!(&mut stdout, " pattern: {}", mat.pattern_index())?;
for (capture_id, node) in mat.captures() {
if ordered_captures {
for (pattern_index, capture) in query_cursor.captures(&query, tree.root_node(), text_callback) {
writeln!(
&mut stdout,
" {}: {:?}",
&query.capture_names()[capture_id],
node.utf8_text(&source_code).unwrap_or("")
" pattern: {}, capture: {}, row: {}, text: {:?}",
pattern_index,
&query.capture_names()[capture.index],
capture.node.start_position().row,
capture.node.utf8_text(&source_code).unwrap_or("")
)?;
}
} else {
for m in query_cursor.matches(&query, tree.root_node(), text_callback) {
writeln!(&mut stdout, " pattern: {}", m.pattern_index)?;
for capture in m.captures() {
writeln!(
&mut stdout,
" capture: {}, row: {}, text: {:?}",
&query.capture_names()[capture.index],
capture.node.start_position().row,
capture.node.utf8_text(&source_code).unwrap_or("")
)?;
}
}
}
}

View file

@ -1,6 +1,6 @@
use super::helpers::allocations;
use super::helpers::fixtures::get_language;
use tree_sitter::{Node, Parser, Query, QueryCursor, QueryError, QueryMatch};
use tree_sitter::{Node, Parser, Query, QueryCapture, QueryCursor, QueryError, QueryMatch};
use std::fmt::Write;
#[test]
@ -797,22 +797,22 @@ fn collect_matches<'a>(
matches
.map(|m| {
(
m.pattern_index(),
collect_captures(m.captures(), query, source),
m.pattern_index,
collect_captures(m.captures().map(|c| (m.pattern_index, c)), query, source),
)
})
.collect()
}
fn collect_captures<'a, 'b>(
captures: impl Iterator<Item = (usize, Node<'a>)>,
captures: impl Iterator<Item = (usize, QueryCapture<'a>)>,
query: &'b Query,
source: &'b str,
) -> Vec<(&'b str, &'b str)> {
captures
.map(|(capture_id, node)| {
.map(|(_, QueryCapture { index, node })| {
(
query.capture_names()[capture_id].as_str(),
query.capture_names()[index].as_str(),
node.utf8_text(source.as_bytes()).unwrap(),
)
})