mirror of
https://github.com/astral-sh/ruff
synced 2026-01-22 14:00:51 -05:00
This commit greatly simplifies the implementation of the CLI,
as well as the user expierence (since --help no longer lists all
options even though many of them are in fact incompatible).
To preserve backwards-compatability as much as possible aliases have
been added for the new subcommands, so for example the following two
commands are equivalent:
ruff explain E402 --format json
ruff --explain E402 --format json
However for this to work the legacy-format double-dash command has to
come first, i.e. the following no longer works:
ruff --format json --explain E402
Since ruff previously had an implicitly default subcommand,
this is preserved for backwards compatibility, i.e. the following two
commands are equivalent:
ruff .
ruff check .
Previously ruff didn't complain about several argument combinations that
should have never been allowed, e.g:
ruff --explain RUF001 --line-length 33
previously worked but now rightfully fails since the explain command
doesn't support a `--line-length` option.
104 lines
2.7 KiB
Rust
104 lines
2.7 KiB
Rust
use anyhow::Result;
|
|
use fern;
|
|
|
|
#[macro_export]
|
|
macro_rules! warn_user_once {
|
|
($($arg:tt)*) => {
|
|
use colored::Colorize;
|
|
static WARNED: std::sync::atomic::AtomicBool = std::sync::atomic::AtomicBool::new(false);
|
|
if !WARNED.swap(true, std::sync::atomic::Ordering::SeqCst) {
|
|
let message = format!("{}", format_args!($($arg)*));
|
|
eprintln!(
|
|
"{}{} {}",
|
|
"warning".yellow().bold(),
|
|
":".bold(),
|
|
message.bold(),
|
|
);
|
|
}
|
|
};
|
|
}
|
|
|
|
#[macro_export]
|
|
macro_rules! warn_user {
|
|
($($arg:tt)*) => {
|
|
use colored::Colorize;
|
|
let message = format!("{}", format_args!($($arg)*));
|
|
eprintln!(
|
|
"{}{} {}",
|
|
"warning".yellow().bold(),
|
|
":".bold(),
|
|
message.bold(),
|
|
);
|
|
};
|
|
}
|
|
|
|
#[macro_export]
|
|
macro_rules! notify_user {
|
|
($($arg:tt)*) => {
|
|
println!(
|
|
"[{}] {}",
|
|
chrono::Local::now()
|
|
.format("%H:%M:%S %p")
|
|
.to_string()
|
|
.dimmed(),
|
|
format_args!($($arg)*)
|
|
)
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Default, PartialOrd, Ord, PartialEq, Eq, Copy, Clone)]
|
|
pub enum LogLevel {
|
|
// No output (+ `log::LevelFilter::Off`).
|
|
Silent,
|
|
// Only show lint violations, with no decorative output (+ `log::LevelFilter::Off`).
|
|
Quiet,
|
|
// All user-facing output (+ `log::LevelFilter::Info`).
|
|
#[default]
|
|
Default,
|
|
// All user-facing output (+ `log::LevelFilter::Debug`).
|
|
Verbose,
|
|
}
|
|
|
|
impl LogLevel {
|
|
#[allow(clippy::trivially_copy_pass_by_ref)]
|
|
fn level_filter(&self) -> log::LevelFilter {
|
|
match self {
|
|
LogLevel::Default => log::LevelFilter::Info,
|
|
LogLevel::Verbose => log::LevelFilter::Debug,
|
|
LogLevel::Quiet => log::LevelFilter::Off,
|
|
LogLevel::Silent => log::LevelFilter::Off,
|
|
}
|
|
}
|
|
}
|
|
|
|
pub fn set_up_logging(level: &LogLevel) -> Result<()> {
|
|
fern::Dispatch::new()
|
|
.format(|out, message, record| {
|
|
out.finish(format_args!(
|
|
"{}[{}][{}] {}",
|
|
chrono::Local::now().format("[%Y-%m-%d][%H:%M:%S]"),
|
|
record.target(),
|
|
record.level(),
|
|
message
|
|
));
|
|
})
|
|
.level(level.level_filter())
|
|
.chain(std::io::stderr())
|
|
.apply()?;
|
|
Ok(())
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use crate::logging::LogLevel;
|
|
|
|
#[test]
|
|
fn ordering() {
|
|
assert!(LogLevel::Default > LogLevel::Silent);
|
|
assert!(LogLevel::Default >= LogLevel::Default);
|
|
assert!(LogLevel::Quiet > LogLevel::Silent);
|
|
assert!(LogLevel::Verbose > LogLevel::Default);
|
|
assert!(LogLevel::Verbose > LogLevel::Silent);
|
|
}
|
|
}
|