Skip to content

Commit 47a253f

Browse files
authored
Add PreviewMode option to formatter
## Summary This PR adds the `--preview` and `--no-preview` options to the `format` command (hidden) and passes it through to the formatte. ## Test Plan I added the `dbg(f.options().preview())` statement in `FormatNodeRule::fmt` and verified that the option gets correctly passed to the formatter.
1 parent d9544a2 commit 47a253f

File tree

7 files changed

+54
-7
lines changed

7 files changed

+54
-7
lines changed

Cargo.lock

-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/ruff_cli/src/args.rs

+7
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,12 @@ pub struct FormatCommand {
368368
/// The name of the file when passing it through stdin.
369369
#[arg(long, help_heading = "Miscellaneous")]
370370
pub stdin_filename: Option<PathBuf>,
371+
372+
/// Enable preview mode; checks will include unstable rules and fixes.
373+
#[arg(long, overrides_with("no_preview"), hide = true)]
374+
preview: bool,
375+
#[clap(long, overrides_with("preview"), hide = true)]
376+
no_preview: bool,
371377
}
372378

373379
#[derive(Debug, Clone, Copy, clap::ValueEnum)]
@@ -496,6 +502,7 @@ impl FormatCommand {
496502
self.respect_gitignore,
497503
self.no_respect_gitignore,
498504
),
505+
preview: resolve_bool_arg(self.preview, self.no_preview).map(PreviewMode::from),
499506
force_exclude: resolve_bool_arg(self.force_exclude, self.no_force_exclude),
500507
// Unsupported on the formatter CLI, but required on `Overrides`.
501508
..Overrides::default()

crates/ruff_cli/src/commands/format.rs

+8-1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ use tracing::{debug, warn};
1313

1414
use ruff::fs;
1515
use ruff::logging::LogLevel;
16+
use ruff::settings::types::PreviewMode;
1617
use ruff::warn_user_once;
1718
use ruff_formatter::LineWidth;
1819
use ruff_python_ast::{PySourceType, SourceType};
@@ -72,9 +73,15 @@ pub(crate) fn format(
7273
return None;
7374
};
7475

76+
let preview = match pyproject_config.settings.lib.preview {
77+
PreviewMode::Enabled => ruff_python_formatter::PreviewMode::Enabled,
78+
PreviewMode::Disabled => ruff_python_formatter::PreviewMode::Disabled,
79+
};
80+
7581
let line_length = resolver.resolve(path, &pyproject_config).line_length;
7682
let options = PyFormatOptions::from_source_type(source_type)
77-
.with_line_width(LineWidth::from(NonZeroU16::from(line_length)));
83+
.with_line_width(LineWidth::from(NonZeroU16::from(line_length)))
84+
.with_preview(preview);
7885
debug!("Formatting {} with {:?}", path.display(), options);
7986
Some(format_path(path, options, mode))
8087
}

crates/ruff_python_formatter/Cargo.toml

-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ anyhow = { workspace = true }
2323
bitflags = { workspace = true }
2424
clap = { workspace = true }
2525
countme = "3.0.1"
26-
is-macro = { workspace = true }
2726
itertools = { workspace = true }
2827
memchr = { workspace = true }
2928
once_cell = { workspace = true }

crates/ruff_python_formatter/src/expression/mod.rs

+9-3
Original file line numberDiff line numberDiff line change
@@ -388,10 +388,10 @@ fn can_omit_optional_parentheses(expr: &Expr, context: &PyFormatContext) -> bool
388388
// Only use the layout if the first or last expression has parentheses of some sort, and
389389
// those parentheses are non-empty.
390390
let first_parenthesized = visitor.first.is_some_and(|first| {
391-
has_parentheses(first, context).is_some_and(|parentheses| parentheses.is_non_empty())
391+
has_parentheses(first, context).is_some_and(OwnParentheses::is_non_empty)
392392
});
393393
let last_parenthesized = visitor.last.is_some_and(|last| {
394-
has_parentheses(last, context).is_some_and(|parentheses| parentheses.is_non_empty())
394+
has_parentheses(last, context).is_some_and(OwnParentheses::is_non_empty)
395395
});
396396
first_parenthesized || last_parenthesized
397397
}
@@ -706,14 +706,20 @@ impl CallChainLayout {
706706
}
707707
}
708708

709-
#[derive(Debug, Copy, Clone, PartialEq, Eq, is_macro::Is)]
709+
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
710710
pub(crate) enum OwnParentheses {
711711
/// The node has parentheses, but they are empty (e.g., `[]` or `f()`).
712712
Empty,
713713
/// The node has parentheses, and they are non-empty (e.g., `[1]` or `f(1)`).
714714
NonEmpty,
715715
}
716716

717+
impl OwnParentheses {
718+
const fn is_non_empty(self) -> bool {
719+
matches!(self, OwnParentheses::NonEmpty)
720+
}
721+
}
722+
717723
/// Returns the [`OwnParentheses`] value for a given [`Expr`], to indicate whether it has its
718724
/// own parentheses or is itself parenthesized.
719725
///

crates/ruff_python_formatter/src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use crate::comments::{
1414
dangling_comments, leading_comments, trailing_comments, Comments, SourceComment,
1515
};
1616
pub use crate::context::PyFormatContext;
17-
pub use crate::options::{MagicTrailingComma, PyFormatOptions, QuoteStyle};
17+
pub use crate::options::{MagicTrailingComma, PreviewMode, PyFormatOptions, QuoteStyle};
1818
use crate::verbatim::suppressed_node;
1919

2020
pub(crate) mod builders;

crates/ruff_python_formatter/src/options.rs

+29
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@ pub struct PyFormatOptions {
3939
/// Should the formatter generate a source map that allows mapping source positions to positions
4040
/// in the formatted document.
4141
source_map_generation: SourceMapGeneration,
42+
43+
/// Whether preview style formatting is enabled or not
44+
preview: PreviewMode,
4245
}
4346

4447
fn default_line_width() -> LineWidth {
@@ -64,6 +67,7 @@ impl Default for PyFormatOptions {
6467
line_ending: LineEnding::default(),
6568
magic_trailing_comma: MagicTrailingComma::default(),
6669
source_map_generation: SourceMapGeneration::default(),
70+
preview: PreviewMode::default(),
6771
}
6872
}
6973
}
@@ -101,6 +105,10 @@ impl PyFormatOptions {
101105
self.line_ending
102106
}
103107

108+
pub fn preview(&self) -> PreviewMode {
109+
self.preview
110+
}
111+
104112
#[must_use]
105113
pub fn with_tab_width(mut self, tab_width: TabWidth) -> Self {
106114
self.tab_width = tab_width;
@@ -136,6 +144,12 @@ impl PyFormatOptions {
136144
self.line_ending = line_ending;
137145
self
138146
}
147+
148+
#[must_use]
149+
pub fn with_preview(mut self, preview: PreviewMode) -> Self {
150+
self.preview = preview;
151+
self
152+
}
139153
}
140154

141155
impl FormatOptions for PyFormatOptions {
@@ -246,3 +260,18 @@ impl FromStr for MagicTrailingComma {
246260
}
247261
}
248262
}
263+
264+
#[derive(Copy, Clone, Debug, Eq, PartialEq, Default)]
265+
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
266+
pub enum PreviewMode {
267+
#[default]
268+
Disabled,
269+
270+
Enabled,
271+
}
272+
273+
impl PreviewMode {
274+
pub const fn is_enabled(self) -> bool {
275+
matches!(self, PreviewMode::Enabled)
276+
}
277+
}

0 commit comments

Comments
 (0)