feat(cli): rework tags to use new input handler
Co-authored-by: Will Lillis <will.lillis24@gmail.com>
This commit is contained in:
parent
55fda55b9b
commit
16be945cdd
2 changed files with 187 additions and 88 deletions
141
cli/src/main.rs
141
cli/src/main.rs
|
|
@ -420,11 +420,18 @@ struct Tags {
|
|||
long = "paths",
|
||||
help = "The path to a file with paths to source file(s)"
|
||||
)]
|
||||
pub paths_file: Option<String>,
|
||||
pub paths_file: Option<PathBuf>,
|
||||
#[arg(num_args = 1.., help = "The source file(s) to use")]
|
||||
pub paths: Option<Vec<String>>,
|
||||
pub paths: Option<Vec<PathBuf>>,
|
||||
#[arg(long, help = "The path to an alternative config.json file")]
|
||||
pub config_path: Option<PathBuf>,
|
||||
#[arg(
|
||||
long,
|
||||
short = 'n',
|
||||
help = "Generate tags from the contents of a specific test"
|
||||
)]
|
||||
#[clap(conflicts_with = "paths", conflicts_with = "paths_file")]
|
||||
pub test_number: Option<u32>,
|
||||
}
|
||||
|
||||
#[derive(Args)]
|
||||
|
|
@ -1434,15 +1441,127 @@ impl Tags {
|
|||
let config = Config::load(self.config_path)?;
|
||||
let loader_config = config.get()?;
|
||||
loader.find_all_languages(&loader_config)?;
|
||||
let paths = collect_paths(self.paths_file.as_deref(), self.paths)?;
|
||||
tags::generate_tags(
|
||||
&loader,
|
||||
&config.get()?,
|
||||
self.scope.as_deref(),
|
||||
&paths,
|
||||
self.quiet,
|
||||
self.time,
|
||||
|
||||
let cancellation_flag = util::cancel_on_signal();
|
||||
|
||||
let (mut language, mut language_configuration) = (None, None);
|
||||
if let Some(scope) = self.scope.as_deref() {
|
||||
if let Some((lang, lang_config)) = loader.language_configuration_for_scope(scope)? {
|
||||
language = Some(lang);
|
||||
language_configuration = Some(lang_config);
|
||||
};
|
||||
if language.is_none() {
|
||||
return Err(anyhow!("Unknown scope '{scope}'"));
|
||||
}
|
||||
}
|
||||
|
||||
let options = TagsOptions {
|
||||
scope: self.scope,
|
||||
quiet: self.quiet,
|
||||
print_time: self.time,
|
||||
cancellation_flag: cancellation_flag.clone(),
|
||||
};
|
||||
|
||||
let input = get_input(
|
||||
self.paths_file.as_deref(),
|
||||
self.paths,
|
||||
self.test_number,
|
||||
&cancellation_flag,
|
||||
)?;
|
||||
match input {
|
||||
CliInput::Paths(paths) => {
|
||||
let indent = paths.len() > 1;
|
||||
for path in paths {
|
||||
let (language, language_config) =
|
||||
match (language.clone(), language_configuration) {
|
||||
(Some(l), Some(lc)) => (l, lc),
|
||||
_ => {
|
||||
if let Some((lang, lang_config)) =
|
||||
loader.language_configuration_for_file_name(&path)?
|
||||
{
|
||||
(lang, lang_config)
|
||||
} else {
|
||||
eprintln!(
|
||||
"{}",
|
||||
util::lang_not_found_for_path(&path, &loader_config)
|
||||
);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if let Some(tags_config) = language_config.tags_config(language)? {
|
||||
tags::generate_tags(
|
||||
&path,
|
||||
&path.display().to_string(),
|
||||
tags_config,
|
||||
indent,
|
||||
&options,
|
||||
)?;
|
||||
} else {
|
||||
eprintln!("No tags config found for path {}", path.display());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CliInput::Test {
|
||||
name,
|
||||
contents,
|
||||
languages: language_names,
|
||||
} => {
|
||||
let path = get_tmp_source_file(&contents)?;
|
||||
|
||||
let languages = loader.languages_at_path(current_dir)?;
|
||||
let language = languages
|
||||
.iter()
|
||||
.find(|(_, n)| language_names.contains(&Box::from(n.as_str())))
|
||||
.or_else(|| languages.first())
|
||||
.map(|(l, _)| l.clone())
|
||||
.ok_or_else(|| anyhow!("No language found in current path"))?;
|
||||
let language_config = loader
|
||||
.get_language_configuration_in_current_path()
|
||||
.ok_or_else(|| anyhow!("No language configuration found in current path"))?;
|
||||
|
||||
if let Some(tags_config) = language_config.tags_config(language)? {
|
||||
tags::generate_tags(&path, &name, tags_config, false, &options)?;
|
||||
} else {
|
||||
eprintln!("No tags config found for test {name}");
|
||||
}
|
||||
fs::remove_file(path)?;
|
||||
}
|
||||
|
||||
CliInput::Stdin(contents) => {
|
||||
// Place user input and tags output on separate lines
|
||||
println!();
|
||||
|
||||
let path = get_tmp_source_file(&contents)?;
|
||||
|
||||
let (language, language_config) =
|
||||
if let (Some(l), Some(lc)) = (language.clone(), language_configuration) {
|
||||
(l, lc)
|
||||
} else {
|
||||
let languages = loader.languages_at_path(current_dir)?;
|
||||
let language = languages
|
||||
.first()
|
||||
.map(|(l, _)| l.clone())
|
||||
.ok_or_else(|| anyhow!("No language found in current path"))?;
|
||||
let language_configuration = loader
|
||||
.get_language_configuration_in_current_path()
|
||||
.ok_or_else(|| {
|
||||
anyhow!("No language configuration found in current path")
|
||||
})?;
|
||||
(language, language_configuration)
|
||||
};
|
||||
|
||||
if let Some(tags_config) = language_config.tags_config(language)? {
|
||||
tags::generate_tags(&path, "stdin", tags_config, false, &options)?;
|
||||
} else {
|
||||
eprintln!("No tags config found for path {}", current_dir.display());
|
||||
}
|
||||
fs::remove_file(path)?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
@ -1565,7 +1684,7 @@ fn run() -> Result<()> {
|
|||
Commands::Fuzz(fuzz_options) => fuzz_options.run(loader, ¤t_dir)?,
|
||||
Commands::Query(query_options) => query_options.run(loader, ¤t_dir)?,
|
||||
Commands::Highlight(highlight_options) => highlight_options.run(loader, ¤t_dir)?,
|
||||
Commands::Tags(tags_options) => tags_options.run(loader)?,
|
||||
Commands::Tags(tags_options) => tags_options.run(loader, ¤t_dir)?,
|
||||
Commands::Playground(playground_options) => playground_options.run(¤t_dir)?,
|
||||
Commands::DumpLanguages(dump_options) => dump_options.run(loader)?,
|
||||
Commands::Complete(complete_options) => complete_options.run(&mut cli),
|
||||
|
|
|
|||
134
cli/src/tags.rs
134
cli/src/tags.rs
|
|
@ -3,95 +3,75 @@ use std::{
|
|||
io::{self, Write},
|
||||
path::Path,
|
||||
str,
|
||||
sync::{atomic::AtomicUsize, Arc},
|
||||
time::Instant,
|
||||
};
|
||||
|
||||
use anyhow::{anyhow, Result};
|
||||
use tree_sitter_loader::{Config, Loader};
|
||||
use tree_sitter_tags::TagsContext;
|
||||
use anyhow::Result;
|
||||
use tree_sitter_tags::{TagsConfiguration, TagsContext};
|
||||
|
||||
use super::util;
|
||||
pub struct TagsOptions {
|
||||
pub scope: Option<String>,
|
||||
pub quiet: bool,
|
||||
pub print_time: bool,
|
||||
pub cancellation_flag: Arc<AtomicUsize>,
|
||||
}
|
||||
|
||||
pub fn generate_tags(
|
||||
loader: &Loader,
|
||||
loader_config: &Config,
|
||||
scope: Option<&str>,
|
||||
paths: &[String],
|
||||
quiet: bool,
|
||||
time: bool,
|
||||
path: &Path,
|
||||
name: &str,
|
||||
config: &TagsConfiguration,
|
||||
indent: bool,
|
||||
opts: &TagsOptions,
|
||||
) -> Result<()> {
|
||||
let mut lang = None;
|
||||
if let Some(scope) = scope {
|
||||
lang = loader.language_configuration_for_scope(scope)?;
|
||||
if lang.is_none() {
|
||||
return Err(anyhow!("Unknown scope '{scope}'"));
|
||||
}
|
||||
}
|
||||
|
||||
let mut context = TagsContext::new();
|
||||
let cancellation_flag = util::cancel_on_signal();
|
||||
let stdout = io::stdout();
|
||||
let mut stdout = stdout.lock();
|
||||
|
||||
for path in paths {
|
||||
let path = Path::new(&path);
|
||||
let (language, language_config) = match lang.clone() {
|
||||
Some(v) => v,
|
||||
None => {
|
||||
if let Some(v) = loader.language_configuration_for_file_name(path)? {
|
||||
v
|
||||
} else {
|
||||
eprintln!("{}", util::lang_not_found_for_path(path, loader_config));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if let Some(tags_config) = language_config.tags_config(language)? {
|
||||
let indent = if paths.len() > 1 {
|
||||
if !quiet {
|
||||
writeln!(&mut stdout, "{}", path.to_string_lossy())?;
|
||||
}
|
||||
"\t"
|
||||
} else {
|
||||
""
|
||||
};
|
||||
|
||||
let source = fs::read(path)?;
|
||||
let t0 = Instant::now();
|
||||
for tag in context
|
||||
.generate_tags(tags_config, &source, Some(&cancellation_flag))?
|
||||
.0
|
||||
{
|
||||
let tag = tag?;
|
||||
if !quiet {
|
||||
write!(
|
||||
&mut stdout,
|
||||
"{indent}{:<10}\t | {:<8}\t{} {} - {} `{}`",
|
||||
str::from_utf8(&source[tag.name_range]).unwrap_or(""),
|
||||
&tags_config.syntax_type_name(tag.syntax_type_id),
|
||||
if tag.is_definition { "def" } else { "ref" },
|
||||
tag.span.start,
|
||||
tag.span.end,
|
||||
str::from_utf8(&source[tag.line_range]).unwrap_or(""),
|
||||
)?;
|
||||
if let Some(docs) = tag.docs {
|
||||
if docs.len() > 120 {
|
||||
write!(&mut stdout, "\t{:?}...", docs.get(0..120).unwrap_or(""))?;
|
||||
} else {
|
||||
write!(&mut stdout, "\t{:?}", &docs)?;
|
||||
}
|
||||
}
|
||||
writeln!(&mut stdout)?;
|
||||
}
|
||||
}
|
||||
|
||||
if time {
|
||||
writeln!(&mut stdout, "{indent}time: {}ms", t0.elapsed().as_millis(),)?;
|
||||
}
|
||||
} else {
|
||||
eprintln!("No tags config found for path {path:?}");
|
||||
let indent_str = if indent {
|
||||
if !opts.quiet {
|
||||
writeln!(&mut stdout, "{name}")?;
|
||||
}
|
||||
"\t"
|
||||
} else {
|
||||
""
|
||||
};
|
||||
|
||||
let source = fs::read(path)?;
|
||||
let start = Instant::now();
|
||||
for tag in context
|
||||
.generate_tags(config, &source, Some(&opts.cancellation_flag))?
|
||||
.0
|
||||
{
|
||||
let tag = tag?;
|
||||
if !opts.quiet {
|
||||
write!(
|
||||
&mut stdout,
|
||||
"{indent_str}{:<10}\t | {:<8}\t{} {} - {} `{}`",
|
||||
str::from_utf8(&source[tag.name_range]).unwrap_or(""),
|
||||
&config.syntax_type_name(tag.syntax_type_id),
|
||||
if tag.is_definition { "def" } else { "ref" },
|
||||
tag.span.start,
|
||||
tag.span.end,
|
||||
str::from_utf8(&source[tag.line_range]).unwrap_or(""),
|
||||
)?;
|
||||
if let Some(docs) = tag.docs {
|
||||
if docs.len() > 120 {
|
||||
write!(&mut stdout, "\t{:?}...", docs.get(0..120).unwrap_or(""))?;
|
||||
} else {
|
||||
write!(&mut stdout, "\t{:?}", &docs)?;
|
||||
}
|
||||
}
|
||||
writeln!(&mut stdout)?;
|
||||
}
|
||||
}
|
||||
|
||||
if opts.print_time {
|
||||
writeln!(
|
||||
&mut stdout,
|
||||
"{indent_str}time: {}ms",
|
||||
start.elapsed().as_millis(),
|
||||
)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue