mirror of https://github.com/astral-sh/ruff
Adding flag and logic for different output format (#185)
This commit is contained in:
parent
85dcaa8d3c
commit
bda34945a5
|
|
@ -10,6 +10,7 @@ pub mod fs;
|
||||||
pub mod linter;
|
pub mod linter;
|
||||||
pub mod logging;
|
pub mod logging;
|
||||||
pub mod message;
|
pub mod message;
|
||||||
|
pub mod printer;
|
||||||
mod pyproject;
|
mod pyproject;
|
||||||
mod python;
|
mod python;
|
||||||
pub mod settings;
|
pub mod settings;
|
||||||
|
|
|
||||||
|
|
@ -3,15 +3,16 @@ use fern;
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! tell_user {
|
macro_rules! tell_user {
|
||||||
($($arg:tt)*) => {
|
($writer:expr,$($arg:tt)*) => {
|
||||||
println!(
|
writeln!(
|
||||||
|
$writer,
|
||||||
"[{}] {}",
|
"[{}] {}",
|
||||||
chrono::Local::now()
|
chrono::Local::now()
|
||||||
.format("%H:%M:%S %p")
|
.format("%H:%M:%S %p")
|
||||||
.to_string()
|
.to_string()
|
||||||
.dimmed(),
|
.dimmed(),
|
||||||
format_args!($($arg)*)
|
format_args!($($arg)*)
|
||||||
)
|
)?
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
65
src/main.rs
65
src/main.rs
|
|
@ -1,3 +1,4 @@
|
||||||
|
use std::io::{stdout, BufWriter, Write};
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::process::ExitCode;
|
use std::process::ExitCode;
|
||||||
use std::sync::mpsc::channel;
|
use std::sync::mpsc::channel;
|
||||||
|
|
@ -18,6 +19,7 @@ use ::ruff::fs::iter_python_files;
|
||||||
use ::ruff::linter::lint_path;
|
use ::ruff::linter::lint_path;
|
||||||
use ::ruff::logging::set_up_logging;
|
use ::ruff::logging::set_up_logging;
|
||||||
use ::ruff::message::Message;
|
use ::ruff::message::Message;
|
||||||
|
use ::ruff::printer::{Printer, SerializationFormat};
|
||||||
use ::ruff::settings::Settings;
|
use ::ruff::settings::Settings;
|
||||||
use ::ruff::tell_user;
|
use ::ruff::tell_user;
|
||||||
|
|
||||||
|
|
@ -57,6 +59,9 @@ struct Cli {
|
||||||
/// List of file and/or directory patterns to exclude from checks.
|
/// List of file and/or directory patterns to exclude from checks.
|
||||||
#[clap(long, multiple = true)]
|
#[clap(long, multiple = true)]
|
||||||
exclude: Vec<Pattern>,
|
exclude: Vec<Pattern>,
|
||||||
|
/// Output formatting of linting messages
|
||||||
|
#[clap(long, arg_enum, default_value_t=SerializationFormat::Text)]
|
||||||
|
format: SerializationFormat,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "update-informer")]
|
#[cfg(feature = "update-informer")]
|
||||||
|
|
@ -130,60 +135,14 @@ fn run_once(
|
||||||
Ok(messages)
|
Ok(messages)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn report_once(messages: &[Message]) -> Result<()> {
|
|
||||||
let (fixed, outstanding): (Vec<&Message>, Vec<&Message>) =
|
|
||||||
messages.iter().partition(|message| message.fixed);
|
|
||||||
let num_fixable = outstanding
|
|
||||||
.iter()
|
|
||||||
.filter(|message| message.kind.fixable())
|
|
||||||
.count();
|
|
||||||
|
|
||||||
if !outstanding.is_empty() {
|
|
||||||
for message in &outstanding {
|
|
||||||
println!("{}", message);
|
|
||||||
}
|
|
||||||
println!();
|
|
||||||
}
|
|
||||||
|
|
||||||
if !fixed.is_empty() {
|
|
||||||
println!(
|
|
||||||
"Found {} error(s) ({} fixed).",
|
|
||||||
outstanding.len(),
|
|
||||||
fixed.len()
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
println!("Found {} error(s).", outstanding.len());
|
|
||||||
}
|
|
||||||
|
|
||||||
if num_fixable > 0 {
|
|
||||||
println!("{num_fixable} potentially fixable with the --fix option.");
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn report_continuously(messages: &[Message]) -> Result<()> {
|
|
||||||
tell_user!(
|
|
||||||
"Found {} error(s). Watching for file changes.",
|
|
||||||
messages.len(),
|
|
||||||
);
|
|
||||||
|
|
||||||
if !messages.is_empty() {
|
|
||||||
println!();
|
|
||||||
for message in messages {
|
|
||||||
println!("{}", message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn inner_main() -> Result<ExitCode> {
|
fn inner_main() -> Result<ExitCode> {
|
||||||
let cli = Cli::parse();
|
let cli = Cli::parse();
|
||||||
|
|
||||||
set_up_logging(cli.verbose)?;
|
set_up_logging(cli.verbose)?;
|
||||||
|
|
||||||
let mut settings = Settings::from_paths(&cli.files);
|
let mut settings = Settings::from_paths(&cli.files);
|
||||||
|
let mut printer = Printer::new(BufWriter::new(stdout()), cli.format);
|
||||||
|
|
||||||
if !cli.select.is_empty() {
|
if !cli.select.is_empty() {
|
||||||
settings.select(cli.select);
|
settings.select(cli.select);
|
||||||
}
|
}
|
||||||
|
|
@ -201,11 +160,11 @@ fn inner_main() -> Result<ExitCode> {
|
||||||
|
|
||||||
// Perform an initial run instantly.
|
// Perform an initial run instantly.
|
||||||
clearscreen::clear()?;
|
clearscreen::clear()?;
|
||||||
tell_user!("Starting linter in watch mode...\n");
|
tell_user!(printer.writer, "Starting linter in watch mode...\n");
|
||||||
|
|
||||||
let messages = run_once(&cli.files, &settings, !cli.no_cache, false)?;
|
let messages = run_once(&cli.files, &settings, !cli.no_cache, false)?;
|
||||||
if !cli.quiet {
|
if !cli.quiet {
|
||||||
report_continuously(&messages)?;
|
printer.write_continuously(&messages)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Configure the file watcher.
|
// Configure the file watcher.
|
||||||
|
|
@ -221,11 +180,11 @@ fn inner_main() -> Result<ExitCode> {
|
||||||
if let Some(path) = e.path {
|
if let Some(path) = e.path {
|
||||||
if path.to_string_lossy().ends_with(".py") {
|
if path.to_string_lossy().ends_with(".py") {
|
||||||
clearscreen::clear()?;
|
clearscreen::clear()?;
|
||||||
tell_user!("File change detected...\n");
|
tell_user!(printer.writer, "File change detected...\n");
|
||||||
|
|
||||||
let messages = run_once(&cli.files, &settings, !cli.no_cache, false)?;
|
let messages = run_once(&cli.files, &settings, !cli.no_cache, false)?;
|
||||||
if !cli.quiet {
|
if !cli.quiet {
|
||||||
report_continuously(&messages)?;
|
printer.write_continuously(&messages)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -236,7 +195,7 @@ fn inner_main() -> Result<ExitCode> {
|
||||||
} else {
|
} else {
|
||||||
let messages = run_once(&cli.files, &settings, !cli.no_cache, cli.fix)?;
|
let messages = run_once(&cli.files, &settings, !cli.no_cache, cli.fix)?;
|
||||||
if !cli.quiet {
|
if !cli.quiet {
|
||||||
report_once(&messages)?;
|
printer.write_once(&messages)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "update-informer")]
|
#[cfg(feature = "update-informer")]
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,82 @@
|
||||||
|
use colored::Colorize;
|
||||||
|
use std::io::Write;
|
||||||
|
|
||||||
|
use anyhow::Result;
|
||||||
|
use clap::ValueEnum;
|
||||||
|
|
||||||
|
use crate::message::Message;
|
||||||
|
use crate::tell_user;
|
||||||
|
|
||||||
|
#[derive(Clone, ValueEnum, PartialEq, Eq, Debug)]
|
||||||
|
pub enum SerializationFormat {
|
||||||
|
Text,
|
||||||
|
Json,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Printer<W> {
|
||||||
|
pub writer: W,
|
||||||
|
format: SerializationFormat,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<W: Write> Printer<W> {
|
||||||
|
pub fn new(writer: W, format: SerializationFormat) -> Self {
|
||||||
|
Self { writer, format }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn write_once(&mut self, messages: &[Message]) -> Result<()> {
|
||||||
|
let (fixed, outstanding): (Vec<&Message>, Vec<&Message>) =
|
||||||
|
messages.iter().partition(|message| message.fixed);
|
||||||
|
let num_fixable = outstanding
|
||||||
|
.iter()
|
||||||
|
.filter(|message| message.kind.fixable())
|
||||||
|
.count();
|
||||||
|
|
||||||
|
match self.format {
|
||||||
|
SerializationFormat::Json => {
|
||||||
|
writeln!(self.writer, "{}", serde_json::to_string_pretty(&messages)?)?
|
||||||
|
}
|
||||||
|
SerializationFormat::Text => {
|
||||||
|
if !fixed.is_empty() {
|
||||||
|
writeln!(
|
||||||
|
self.writer,
|
||||||
|
"Found {} error(s) ({} fixed).",
|
||||||
|
outstanding.len(),
|
||||||
|
fixed.len()
|
||||||
|
)?
|
||||||
|
} else {
|
||||||
|
writeln!(self.writer, "Found {} error(s).", outstanding.len())?
|
||||||
|
}
|
||||||
|
|
||||||
|
for message in outstanding {
|
||||||
|
writeln!(self.writer, "{}", message)?
|
||||||
|
}
|
||||||
|
|
||||||
|
if num_fixable > 0 {
|
||||||
|
writeln!(
|
||||||
|
self.writer,
|
||||||
|
"{num_fixable} potentially fixable with the --fix option."
|
||||||
|
)?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn write_continuously(&mut self, messages: &[Message]) -> Result<()> {
|
||||||
|
tell_user!(
|
||||||
|
self.writer,
|
||||||
|
"Found {} error(s). Watching for file changes.",
|
||||||
|
messages.len(),
|
||||||
|
);
|
||||||
|
|
||||||
|
if !messages.is_empty() {
|
||||||
|
writeln!(self.writer, "\n")?;
|
||||||
|
for message in messages {
|
||||||
|
writeln!(self.writer, "{}", message)?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue