Introduce IndentWidth (#7301)
This commit is contained in:
@@ -361,7 +361,7 @@ where
|
||||
|
||||
f.write_element(FormatElement::Text {
|
||||
text: self.text.to_string().into_boxed_str(),
|
||||
text_width: TextWidth::from_text(self.text, f.options().tab_width()),
|
||||
text_width: TextWidth::from_text(self.text, f.options().indent_width()),
|
||||
});
|
||||
|
||||
Ok(())
|
||||
@@ -393,8 +393,10 @@ where
|
||||
let slice = source_code.slice(self.range);
|
||||
debug_assert_no_newlines(slice.text(source_code));
|
||||
|
||||
let text_width =
|
||||
TextWidth::from_text(slice.text(source_code), f.context().options().tab_width());
|
||||
let text_width = TextWidth::from_text(
|
||||
slice.text(source_code),
|
||||
f.context().options().indent_width(),
|
||||
);
|
||||
|
||||
f.write_element(FormatElement::SourceCodeSlice { slice, text_width });
|
||||
|
||||
@@ -917,8 +919,10 @@ where
|
||||
/// use ruff_formatter::prelude::*;
|
||||
///
|
||||
/// # fn main() -> FormatResult<()> {
|
||||
/// use ruff_formatter::IndentWidth;
|
||||
/// let context = SimpleFormatContext::new(SimpleFormatOptions {
|
||||
/// indent_style: IndentStyle::Space(4),
|
||||
/// indent_style: IndentStyle::Space,
|
||||
/// indent_width: IndentWidth::try_from(4).unwrap(),
|
||||
/// ..SimpleFormatOptions::default()
|
||||
/// });
|
||||
///
|
||||
|
||||
@@ -10,7 +10,7 @@ use unicode_width::UnicodeWidthChar;
|
||||
|
||||
use crate::format_element::tag::{GroupMode, LabelId, Tag};
|
||||
use crate::source_code::SourceCodeSlice;
|
||||
use crate::{TabWidth, TagKind};
|
||||
use crate::{IndentWidth, TagKind};
|
||||
use ruff_text_size::TextSize;
|
||||
|
||||
/// Language agnostic IR for formatting source code.
|
||||
@@ -432,12 +432,12 @@ pub enum TextWidth {
|
||||
}
|
||||
|
||||
impl TextWidth {
|
||||
pub fn from_text(text: &str, tab_width: TabWidth) -> TextWidth {
|
||||
pub fn from_text(text: &str, indent_width: IndentWidth) -> TextWidth {
|
||||
let mut width = 0u32;
|
||||
|
||||
for c in text.chars() {
|
||||
let char_width = match c {
|
||||
'\t' => tab_width.value(),
|
||||
'\t' => indent_width.value(),
|
||||
'\n' => return TextWidth::Multiline,
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
c => c.width().unwrap_or(0) as u32,
|
||||
|
||||
@@ -9,7 +9,7 @@ use crate::prelude::*;
|
||||
use crate::source_code::SourceCode;
|
||||
use crate::{
|
||||
format, write, BufferExtensions, Format, FormatContext, FormatElement, FormatOptions,
|
||||
FormatResult, Formatter, IndentStyle, LineWidth, PrinterOptions, TabWidth,
|
||||
FormatResult, Formatter, IndentStyle, IndentWidth, LineWidth, PrinterOptions,
|
||||
};
|
||||
|
||||
use super::tag::Tag;
|
||||
@@ -213,11 +213,11 @@ struct IrFormatOptions;
|
||||
|
||||
impl FormatOptions for IrFormatOptions {
|
||||
fn indent_style(&self) -> IndentStyle {
|
||||
IndentStyle::Space(2)
|
||||
IndentStyle::Space
|
||||
}
|
||||
|
||||
fn tab_width(&self) -> TabWidth {
|
||||
TabWidth::default()
|
||||
fn indent_width(&self) -> IndentWidth {
|
||||
IndentWidth::default()
|
||||
}
|
||||
|
||||
fn line_width(&self) -> LineWidth {
|
||||
@@ -227,7 +227,7 @@ impl FormatOptions for IrFormatOptions {
|
||||
fn as_print_options(&self) -> PrinterOptions {
|
||||
PrinterOptions {
|
||||
line_width: self.line_width(),
|
||||
indent_style: IndentStyle::Space(2),
|
||||
indent_style: IndentStyle::Space,
|
||||
..PrinterOptions::default()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,23 +52,20 @@ pub use crate::diagnostics::{ActualStart, FormatError, InvalidDocumentError, Pri
|
||||
pub use format_element::{normalize_newlines, FormatElement, LINE_TERMINATORS};
|
||||
pub use group_id::GroupId;
|
||||
use ruff_text_size::{TextRange, TextSize};
|
||||
use std::str::FromStr;
|
||||
|
||||
#[derive(Debug, Eq, PartialEq, Clone, Copy, Hash)]
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
#[derive(Default)]
|
||||
pub enum IndentStyle {
|
||||
/// Tab
|
||||
/// Use tabs to indent code.
|
||||
#[default]
|
||||
Tab,
|
||||
/// Space, with its quantity
|
||||
Space(u8),
|
||||
/// Use [`IndentWidth`] spaces to indent code.
|
||||
Space,
|
||||
}
|
||||
|
||||
impl IndentStyle {
|
||||
pub const DEFAULT_SPACES: u8 = 2;
|
||||
|
||||
/// Returns `true` if this is an [`IndentStyle::Tab`].
|
||||
pub const fn is_tab(&self) -> bool {
|
||||
matches!(self, IndentStyle::Tab)
|
||||
@@ -76,58 +73,42 @@ impl IndentStyle {
|
||||
|
||||
/// Returns `true` if this is an [`IndentStyle::Space`].
|
||||
pub const fn is_space(&self) -> bool {
|
||||
matches!(self, IndentStyle::Space(_))
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for IndentStyle {
|
||||
type Err = &'static str;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
match s {
|
||||
"tab" | "Tabs" => Ok(Self::Tab),
|
||||
"space" | "Spaces" => Ok(Self::Space(IndentStyle::DEFAULT_SPACES)),
|
||||
// TODO: replace this error with a diagnostic
|
||||
v => {
|
||||
let v = v.strip_prefix("Spaces, size: ").unwrap_or(v);
|
||||
|
||||
u8::from_str(v)
|
||||
.map(Self::Space)
|
||||
.map_err(|_| "Value not supported for IndentStyle")
|
||||
}
|
||||
}
|
||||
matches!(self, IndentStyle::Space)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for IndentStyle {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
IndentStyle::Tab => std::write!(f, "Tab"),
|
||||
IndentStyle::Space(size) => std::write!(f, "Spaces, size: {size}"),
|
||||
IndentStyle::Tab => std::write!(f, "tab"),
|
||||
IndentStyle::Space => std::write!(f, "space"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The visual width of a `\t` character.
|
||||
/// The visual width of a indentation.
|
||||
///
|
||||
/// Determines the visual width of a tab character (`\t`) and the number of
|
||||
/// spaces per indent when using [`IndentStyle::Space`].
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
pub struct TabWidth(NonZeroU8);
|
||||
pub struct IndentWidth(NonZeroU8);
|
||||
|
||||
impl TabWidth {
|
||||
impl IndentWidth {
|
||||
/// Return the numeric value for this [`LineWidth`]
|
||||
pub const fn value(&self) -> u32 {
|
||||
self.0.get() as u32
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for TabWidth {
|
||||
impl Default for IndentWidth {
|
||||
fn default() -> Self {
|
||||
Self(NonZeroU8::new(2).unwrap())
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<u8> for TabWidth {
|
||||
impl TryFrom<u8> for IndentWidth {
|
||||
type Error = TryFromIntError;
|
||||
|
||||
fn try_from(value: u8) -> Result<Self, Self::Error> {
|
||||
@@ -196,16 +177,8 @@ pub trait FormatOptions {
|
||||
/// The indent style.
|
||||
fn indent_style(&self) -> IndentStyle;
|
||||
|
||||
/// The visual width of a tab character.
|
||||
fn tab_width(&self) -> TabWidth;
|
||||
|
||||
/// The visual width of an indent
|
||||
fn indent_width(&self) -> u32 {
|
||||
match self.indent_style() {
|
||||
IndentStyle::Tab => self.tab_width().value(),
|
||||
IndentStyle::Space(spaces) => u32::from(spaces),
|
||||
}
|
||||
}
|
||||
fn indent_width(&self) -> IndentWidth;
|
||||
|
||||
/// What's the max width of a line. Defaults to 80.
|
||||
fn line_width(&self) -> LineWidth;
|
||||
@@ -250,6 +223,7 @@ impl FormatContext for SimpleFormatContext {
|
||||
#[derive(Debug, Default, Eq, PartialEq, Clone)]
|
||||
pub struct SimpleFormatOptions {
|
||||
pub indent_style: IndentStyle,
|
||||
pub indent_width: IndentWidth,
|
||||
pub line_width: LineWidth,
|
||||
}
|
||||
|
||||
@@ -258,8 +232,8 @@ impl FormatOptions for SimpleFormatOptions {
|
||||
self.indent_style
|
||||
}
|
||||
|
||||
fn tab_width(&self) -> TabWidth {
|
||||
TabWidth::default()
|
||||
fn indent_width(&self) -> IndentWidth {
|
||||
self.indent_width
|
||||
}
|
||||
|
||||
fn line_width(&self) -> LineWidth {
|
||||
@@ -270,6 +244,7 @@ impl FormatOptions for SimpleFormatOptions {
|
||||
PrinterOptions {
|
||||
line_width: self.line_width,
|
||||
indent_style: self.indent_style,
|
||||
indent_width: self.indent_width,
|
||||
source_map_generation: SourceMapGeneration::Enabled,
|
||||
..PrinterOptions::default()
|
||||
}
|
||||
|
||||
@@ -367,7 +367,7 @@ impl<'a> Printer<'a> {
|
||||
if !self.state.pending_indent.is_empty() {
|
||||
let (indent_char, repeat_count) = match self.options.indent_style() {
|
||||
IndentStyle::Tab => ('\t', 1),
|
||||
IndentStyle::Space(count) => (' ', count),
|
||||
IndentStyle::Space => (' ', self.options.indent_width()),
|
||||
};
|
||||
|
||||
let indent = std::mem::take(&mut self.state.pending_indent);
|
||||
@@ -764,7 +764,7 @@ impl<'a> Printer<'a> {
|
||||
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
let char_width = if char == '\t' {
|
||||
self.options.tab_width.value()
|
||||
self.options.indent_width.value()
|
||||
} else {
|
||||
// SAFETY: A u32 is sufficient to represent the width of a file <= 4GB
|
||||
char.width().unwrap_or(0) as u32
|
||||
@@ -1347,7 +1347,7 @@ impl<'a, 'print> FitsMeasurer<'a, 'print> {
|
||||
} else {
|
||||
for c in text.chars() {
|
||||
let char_width = match c {
|
||||
'\t' => self.options().tab_width.value(),
|
||||
'\t' => self.options().indent_width.value(),
|
||||
'\n' => {
|
||||
if self.must_be_flat {
|
||||
return Fits::No;
|
||||
@@ -1501,7 +1501,7 @@ mod tests {
|
||||
use crate::printer::{LineEnding, Printer, PrinterOptions};
|
||||
use crate::source_code::SourceCode;
|
||||
use crate::{
|
||||
format_args, write, Document, FormatState, IndentStyle, LineWidth, Printed, TabWidth,
|
||||
format_args, write, Document, FormatState, IndentStyle, IndentWidth, LineWidth, Printed,
|
||||
VecBuffer,
|
||||
};
|
||||
|
||||
@@ -1509,7 +1509,7 @@ mod tests {
|
||||
format_with_options(
|
||||
root,
|
||||
PrinterOptions {
|
||||
indent_style: IndentStyle::Space(2),
|
||||
indent_style: IndentStyle::Space,
|
||||
..PrinterOptions::default()
|
||||
},
|
||||
)
|
||||
@@ -1653,7 +1653,7 @@ two lines`,
|
||||
fn it_use_the_indent_character_specified_in_the_options() {
|
||||
let options = PrinterOptions {
|
||||
indent_style: IndentStyle::Tab,
|
||||
tab_width: TabWidth::try_from(4).unwrap(),
|
||||
indent_width: IndentWidth::try_from(4).unwrap(),
|
||||
line_width: LineWidth::try_from(19).unwrap(),
|
||||
..PrinterOptions::default()
|
||||
};
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
use crate::{FormatOptions, IndentStyle, LineWidth, TabWidth};
|
||||
use crate::{FormatOptions, IndentStyle, IndentWidth, LineWidth};
|
||||
|
||||
/// Options that affect how the [`crate::Printer`] prints the format tokens
|
||||
#[derive(Clone, Debug, Eq, PartialEq, Default)]
|
||||
pub struct PrinterOptions {
|
||||
/// Width of a single tab character (does it equal 2, 4, ... spaces?)
|
||||
pub tab_width: TabWidth,
|
||||
pub indent_width: IndentWidth,
|
||||
|
||||
/// Whether the printer should use tabs or spaces to indent code.
|
||||
pub indent_style: IndentStyle,
|
||||
|
||||
/// What's the max width of a line. Defaults to 80
|
||||
pub line_width: LineWidth,
|
||||
@@ -12,9 +15,6 @@ pub struct PrinterOptions {
|
||||
/// The type of line ending to apply to the printed input
|
||||
pub line_ending: LineEnding,
|
||||
|
||||
/// Whether the printer should use tabs or spaces to indent code and if spaces, by how many.
|
||||
pub indent_style: IndentStyle,
|
||||
|
||||
/// Whether the printer should build a source map that allows mapping positions in the source document
|
||||
/// to positions in the formatted document.
|
||||
pub source_map_generation: SourceMapGeneration,
|
||||
@@ -46,8 +46,8 @@ impl PrinterOptions {
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn with_tab_width(mut self, width: TabWidth) -> Self {
|
||||
self.tab_width = width;
|
||||
pub fn with_tab_width(mut self, width: IndentWidth) -> Self {
|
||||
self.indent_width = width;
|
||||
|
||||
self
|
||||
}
|
||||
@@ -58,10 +58,7 @@ impl PrinterOptions {
|
||||
|
||||
/// Width of an indent in characters.
|
||||
pub(super) const fn indent_width(&self) -> u32 {
|
||||
match self.indent_style {
|
||||
IndentStyle::Tab => self.tab_width.value(),
|
||||
IndentStyle::Space(count) => count as u32,
|
||||
}
|
||||
self.indent_width.value()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
{
|
||||
"tab_width": 8
|
||||
"indent_width": 4
|
||||
}
|
||||
|
||||
@@ -1,22 +1,18 @@
|
||||
[
|
||||
{
|
||||
"indent_style": {
|
||||
"Space": 4
|
||||
},
|
||||
"tab_width": 8
|
||||
"indent_style": "Space",
|
||||
"indent_width": 4
|
||||
},
|
||||
{
|
||||
"indent_style": {
|
||||
"Space": 2
|
||||
},
|
||||
"tab_width": 8
|
||||
"indent_style": "Space",
|
||||
"indent_width": 2
|
||||
},
|
||||
{
|
||||
"indent_style": "Tab",
|
||||
"tab_width": 8
|
||||
"indent_width": 8
|
||||
},
|
||||
{
|
||||
"indent_style": "Tab",
|
||||
"tab_width": 4
|
||||
"indent_width": 4
|
||||
}
|
||||
]
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
[
|
||||
{
|
||||
"indent_style": { "Space": 4 }
|
||||
"indent_style": "Space",
|
||||
"indent_width": 4
|
||||
},
|
||||
{
|
||||
"indent_style": { "Space": 2 }
|
||||
"indent_style": "Space",
|
||||
"indent_width": 2
|
||||
}
|
||||
]
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
[
|
||||
{
|
||||
"indent_style": { "Space": 4 }
|
||||
"indent_style": "Space",
|
||||
"indent_width": 4
|
||||
},
|
||||
{
|
||||
"indent_style": { "Space": 1 }
|
||||
"indent_style": "Space",
|
||||
"indent_width": 1
|
||||
},
|
||||
{
|
||||
"indent_style": "Tab"
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
[
|
||||
{
|
||||
"indent_style": { "Space": 4 }
|
||||
"indent_style": "Space",
|
||||
"indent_width": 4
|
||||
},
|
||||
{
|
||||
"indent_style": { "Space": 2 }
|
||||
"indent_style": "Space",
|
||||
"indent_width": 2
|
||||
},
|
||||
{
|
||||
"indent_style": "Tab"
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
[
|
||||
{
|
||||
"tab_width": 2
|
||||
"indent_width": 2
|
||||
},
|
||||
{
|
||||
"tab_width": 4
|
||||
"indent_width": 4
|
||||
},
|
||||
{
|
||||
"indent_width": 8
|
||||
}
|
||||
]
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
# Fits with tab width 2
|
||||
1 + " 012345678901234567890123456789012345678901234567890123456789012345678901234567890"
|
||||
(1 + " 012345678901234567890123456789012345678901234567890123456789012345678901234567")
|
||||
|
||||
# Fits with tab width 4
|
||||
1 + " 0123456789012345678901234567890123456789012345678901234567890123456789012345678"
|
||||
(1 + " 0123456789012345678901234567890123456789012345678901234567890123456789012345")
|
||||
|
||||
# Fits with tab width 8
|
||||
1 + " 012345678901234567890123456789012345678901234567890123456789012345678901234"
|
||||
(1 + " 012345678901234567890123456789012345678901234567890123456789012345678901")
|
||||
|
||||
@@ -353,7 +353,7 @@ impl Format<PyFormatContext<'_>> for FormatTrailingEndOfLineComment<'_> {
|
||||
} else {
|
||||
// Start with 2 because of the two leading spaces.
|
||||
let width = 2u32.saturating_add(
|
||||
TextWidth::from_text(&normalized_comment, f.options().tab_width())
|
||||
TextWidth::from_text(&normalized_comment, f.options().indent_width())
|
||||
.width()
|
||||
.expect("Expected comment not to contain any newlines")
|
||||
.value(),
|
||||
|
||||
@@ -47,7 +47,7 @@ where
|
||||
text_len > 5
|
||||
&& text_len
|
||||
<= context.options().line_width().value() as usize
|
||||
- context.options().indent_width() as usize
|
||||
- context.options().indent_width().value() as usize
|
||||
}
|
||||
|
||||
pub(crate) trait NeedsParentheses {
|
||||
|
||||
@@ -2,7 +2,7 @@ use std::borrow::Cow;
|
||||
|
||||
use bitflags::bitflags;
|
||||
|
||||
use ruff_formatter::{format_args, write, FormatError, FormatOptions, TabWidth};
|
||||
use ruff_formatter::{format_args, write, FormatError};
|
||||
use ruff_python_ast::node::AnyNodeRef;
|
||||
use ruff_python_ast::{self as ast, Constant, ExprConstant, ExprFString, ExpressionRef};
|
||||
use ruff_python_parser::lexer::{lex_starts_at, LexicalError, LexicalErrorType};
|
||||
@@ -727,22 +727,20 @@ fn normalize_string(input: &str, quotes: StringQuotes, is_raw: bool) -> Cow<str>
|
||||
/// For docstring indentation, black counts spaces as 1 and tabs by increasing the indentation up
|
||||
/// to the next multiple of 8. This is effectively a port of
|
||||
/// [`str.expandtabs`](https://docs.python.org/3/library/stdtypes.html#str.expandtabs),
|
||||
/// which black [calls with the default tab width of 8](https://github.com/psf/black/blob/c36e468794f9256d5e922c399240d49782ba04f1/src/black/strings.py#L61)
|
||||
fn count_indentation_like_black(line: &str, tab_width: TabWidth) -> TextSize {
|
||||
let mut indentation = TextSize::default();
|
||||
/// which black [calls with the default tab width of 8](https://github.com/psf/black/blob/c36e468794f9256d5e922c399240d49782ba04f1/src/black/strings.py#L61).
|
||||
fn indentation_length(line: &str) -> TextSize {
|
||||
let mut indentation = 0u32;
|
||||
for char in line.chars() {
|
||||
if char == '\t' {
|
||||
// Pad to the next multiple of tab_width
|
||||
indentation += TextSize::from(
|
||||
tab_width.value() - (indentation.to_u32().rem_euclid(tab_width.value())),
|
||||
);
|
||||
indentation += 8 - (indentation.rem_euclid(8));
|
||||
} else if char.is_whitespace() {
|
||||
indentation += char.text_len();
|
||||
indentation += u32::from(char.text_len());
|
||||
} else {
|
||||
return indentation;
|
||||
break;
|
||||
}
|
||||
}
|
||||
indentation
|
||||
TextSize::new(indentation)
|
||||
}
|
||||
|
||||
/// Format a docstring by trimming whitespace and adjusting the indentation.
|
||||
@@ -910,7 +908,7 @@ fn format_docstring(normalized: &NormalizedString, f: &mut PyFormatter) -> Forma
|
||||
.clone()
|
||||
// We don't want to count whitespace-only lines as miss-indented
|
||||
.filter(|line| !line.trim().is_empty())
|
||||
.map(|line| count_indentation_like_black(line, f.options().tab_width()))
|
||||
.map(indentation_length)
|
||||
.min()
|
||||
.unwrap_or_default();
|
||||
|
||||
@@ -952,7 +950,7 @@ fn format_docstring_line(
|
||||
line: &str,
|
||||
is_last: bool,
|
||||
offset: TextSize,
|
||||
stripped_indentation: TextSize,
|
||||
stripped_indentation_length: TextSize,
|
||||
already_normalized: bool,
|
||||
f: &mut PyFormatter,
|
||||
) -> FormatResult<()> {
|
||||
@@ -979,21 +977,20 @@ fn format_docstring_line(
|
||||
// overindented, in which case we strip the additional whitespace (see example in
|
||||
// [`format_docstring`] doc comment). We then prepend the in-docstring indentation to the
|
||||
// string.
|
||||
let indent_len =
|
||||
count_indentation_like_black(trim_end, f.options().tab_width()) - stripped_indentation;
|
||||
let in_docstring_indent = " ".repeat(indent_len.to_usize()) + trim_end.trim_start();
|
||||
let indent_len = indentation_length(trim_end) - stripped_indentation_length;
|
||||
let in_docstring_indent = " ".repeat(usize::from(indent_len)) + trim_end.trim_start();
|
||||
text(&in_docstring_indent, Some(offset)).fmt(f)?;
|
||||
} else {
|
||||
// Take the string with the trailing whitespace removed, then also skip the leading
|
||||
// whitespace
|
||||
let trimmed_line_range =
|
||||
TextRange::at(offset, trim_end.text_len()).add_start(stripped_indentation);
|
||||
TextRange::at(offset, trim_end.text_len()).add_start(stripped_indentation_length);
|
||||
if already_normalized {
|
||||
source_text_slice(trimmed_line_range).fmt(f)?;
|
||||
} else {
|
||||
// All indents are ascii spaces, so the slicing is correct
|
||||
text(
|
||||
&trim_end[stripped_indentation.to_usize()..],
|
||||
&trim_end[usize::from(stripped_indentation_length)..],
|
||||
Some(trimmed_line_range.start()),
|
||||
)
|
||||
.fmt(f)?;
|
||||
@@ -1012,25 +1009,14 @@ fn format_docstring_line(
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use ruff_formatter::TabWidth;
|
||||
|
||||
use crate::expression::string::count_indentation_like_black;
|
||||
use crate::expression::string::indentation_length;
|
||||
use ruff_text_size::TextSize;
|
||||
|
||||
#[test]
|
||||
fn test_indentation_like_black() {
|
||||
let tab_width = TabWidth::try_from(8).unwrap();
|
||||
assert_eq!(
|
||||
count_indentation_like_black("\t \t \t", tab_width).to_u32(),
|
||||
24
|
||||
);
|
||||
assert_eq!(
|
||||
count_indentation_like_black("\t \t", tab_width).to_u32(),
|
||||
24
|
||||
);
|
||||
assert_eq!(
|
||||
count_indentation_like_black("\t\t\t", tab_width).to_u32(),
|
||||
24
|
||||
);
|
||||
assert_eq!(count_indentation_like_black(" ", tab_width).to_u32(), 4);
|
||||
assert_eq!(indentation_length("\t \t \t"), TextSize::new(24));
|
||||
assert_eq!(indentation_length("\t \t"), TextSize::new(24));
|
||||
assert_eq!(indentation_length("\t\t\t"), TextSize::new(24));
|
||||
assert_eq!(indentation_length(" "), TextSize::new(4));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use ruff_formatter::printer::{LineEnding, PrinterOptions, SourceMapGeneration};
|
||||
use ruff_formatter::{FormatOptions, IndentStyle, LineWidth, TabWidth};
|
||||
use ruff_formatter::{FormatOptions, IndentStyle, IndentWidth, LineWidth};
|
||||
use ruff_python_ast::PySourceType;
|
||||
use std::path::Path;
|
||||
use std::str::FromStr;
|
||||
@@ -25,8 +25,8 @@ pub struct PyFormatOptions {
|
||||
line_width: LineWidth,
|
||||
|
||||
/// The visual width of a tab character.
|
||||
#[cfg_attr(feature = "serde", serde(default = "default_tab_width"))]
|
||||
tab_width: TabWidth,
|
||||
#[cfg_attr(feature = "serde", serde(default = "default_indent_width"))]
|
||||
indent_width: IndentWidth,
|
||||
|
||||
line_ending: LineEnding,
|
||||
|
||||
@@ -49,11 +49,11 @@ fn default_line_width() -> LineWidth {
|
||||
}
|
||||
|
||||
fn default_indent_style() -> IndentStyle {
|
||||
IndentStyle::Space(4)
|
||||
IndentStyle::Space
|
||||
}
|
||||
|
||||
fn default_tab_width() -> TabWidth {
|
||||
TabWidth::try_from(4).unwrap()
|
||||
fn default_indent_width() -> IndentWidth {
|
||||
IndentWidth::try_from(4).unwrap()
|
||||
}
|
||||
|
||||
impl Default for PyFormatOptions {
|
||||
@@ -62,7 +62,7 @@ impl Default for PyFormatOptions {
|
||||
source_type: PySourceType::default(),
|
||||
indent_style: default_indent_style(),
|
||||
line_width: default_line_width(),
|
||||
tab_width: default_tab_width(),
|
||||
indent_width: default_indent_width(),
|
||||
quote_style: QuoteStyle::default(),
|
||||
line_ending: LineEnding::default(),
|
||||
magic_trailing_comma: MagicTrailingComma::default(),
|
||||
@@ -110,8 +110,8 @@ impl PyFormatOptions {
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn with_tab_width(mut self, tab_width: TabWidth) -> Self {
|
||||
self.tab_width = tab_width;
|
||||
pub fn with_indent_width(mut self, indent_width: IndentWidth) -> Self {
|
||||
self.indent_width = indent_width;
|
||||
self
|
||||
}
|
||||
|
||||
@@ -157,8 +157,8 @@ impl FormatOptions for PyFormatOptions {
|
||||
self.indent_style
|
||||
}
|
||||
|
||||
fn tab_width(&self) -> TabWidth {
|
||||
self.tab_width
|
||||
fn indent_width(&self) -> IndentWidth {
|
||||
self.indent_width
|
||||
}
|
||||
|
||||
fn line_width(&self) -> LineWidth {
|
||||
@@ -167,7 +167,7 @@ impl FormatOptions for PyFormatOptions {
|
||||
|
||||
fn as_print_options(&self) -> PrinterOptions {
|
||||
PrinterOptions {
|
||||
tab_width: self.tab_width,
|
||||
indent_width: self.indent_width,
|
||||
line_width: self.line_width,
|
||||
line_ending: self.line_ending,
|
||||
indent_style: self.indent_style,
|
||||
|
||||
@@ -253,11 +253,11 @@ impl fmt::Display for DisplayPyOptions<'_> {
|
||||
f,
|
||||
r#"indent-style = {indent_style}
|
||||
line-width = {line_width}
|
||||
tab-width = {tab_width}
|
||||
indent-width = {indent_width}
|
||||
quote-style = {quote_style:?}
|
||||
magic-trailing-comma = {magic_trailing_comma:?}"#,
|
||||
indent_style = self.0.indent_style(),
|
||||
tab_width = self.0.tab_width().value(),
|
||||
indent_width = self.0.indent_width().value(),
|
||||
line_width = self.0.line_width().value(),
|
||||
quote_style = self.0.quote_style(),
|
||||
magic_trailing_comma = self.0.magic_trailing_comma()
|
||||
|
||||
@@ -111,9 +111,9 @@ class TabbedIndent:
|
||||
## Outputs
|
||||
### Output 1
|
||||
```
|
||||
indent-style = Spaces, size: 4
|
||||
indent-style = space
|
||||
line-width = 88
|
||||
tab-width = 8
|
||||
indent-width = 4
|
||||
quote-style = Double
|
||||
magic-trailing-comma = Respect
|
||||
```
|
||||
@@ -224,9 +224,9 @@ class TabbedIndent:
|
||||
|
||||
### Output 2
|
||||
```
|
||||
indent-style = Spaces, size: 2
|
||||
indent-style = space
|
||||
line-width = 88
|
||||
tab-width = 8
|
||||
indent-width = 2
|
||||
quote-style = Double
|
||||
magic-trailing-comma = Respect
|
||||
```
|
||||
@@ -337,9 +337,9 @@ class TabbedIndent:
|
||||
|
||||
### Output 3
|
||||
```
|
||||
indent-style = Tab
|
||||
indent-style = tab
|
||||
line-width = 88
|
||||
tab-width = 8
|
||||
indent-width = 8
|
||||
quote-style = Double
|
||||
magic-trailing-comma = Respect
|
||||
```
|
||||
@@ -450,9 +450,9 @@ class TabbedIndent:
|
||||
|
||||
### Output 4
|
||||
```
|
||||
indent-style = Tab
|
||||
indent-style = tab
|
||||
line-width = 88
|
||||
tab-width = 4
|
||||
indent-width = 4
|
||||
quote-style = Double
|
||||
magic-trailing-comma = Respect
|
||||
```
|
||||
@@ -556,7 +556,7 @@ class TabbedIndent:
|
||||
"""check for correct tabbed formatting
|
||||
^^^^^^^^^^
|
||||
Normal indented line
|
||||
- autor
|
||||
- autor
|
||||
"""
|
||||
```
|
||||
|
||||
|
||||
@@ -129,9 +129,9 @@ test_particular = [
|
||||
## Outputs
|
||||
### Output 1
|
||||
```
|
||||
indent-style = Spaces, size: 4
|
||||
indent-style = space
|
||||
line-width = 88
|
||||
tab-width = 4
|
||||
indent-width = 4
|
||||
quote-style = Double
|
||||
magic-trailing-comma = Respect
|
||||
```
|
||||
@@ -277,9 +277,9 @@ test_particular = [
|
||||
|
||||
### Output 2
|
||||
```
|
||||
indent-style = Spaces, size: 4
|
||||
indent-style = space
|
||||
line-width = 88
|
||||
tab-width = 4
|
||||
indent-width = 4
|
||||
quote-style = Single
|
||||
magic-trailing-comma = Respect
|
||||
```
|
||||
|
||||
@@ -141,9 +141,9 @@ x = (b"""aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa""" b"""bbbbbbbbbbbbbbbbbbbbbbbbbbb
|
||||
## Outputs
|
||||
### Output 1
|
||||
```
|
||||
indent-style = Spaces, size: 4
|
||||
indent-style = space
|
||||
line-width = 88
|
||||
tab-width = 4
|
||||
indent-width = 4
|
||||
quote-style = Double
|
||||
magic-trailing-comma = Respect
|
||||
```
|
||||
@@ -310,9 +310,9 @@ x = (
|
||||
|
||||
### Output 2
|
||||
```
|
||||
indent-style = Spaces, size: 4
|
||||
indent-style = space
|
||||
line-width = 88
|
||||
tab-width = 4
|
||||
indent-width = 4
|
||||
quote-style = Single
|
||||
magic-trailing-comma = Respect
|
||||
```
|
||||
|
||||
@@ -28,9 +28,9 @@ def test():
|
||||
## Outputs
|
||||
### Output 1
|
||||
```
|
||||
indent-style = Spaces, size: 4
|
||||
indent-style = space
|
||||
line-width = 88
|
||||
tab-width = 4
|
||||
indent-width = 4
|
||||
quote-style = Double
|
||||
magic-trailing-comma = Respect
|
||||
```
|
||||
@@ -60,9 +60,9 @@ def test():
|
||||
|
||||
### Output 2
|
||||
```
|
||||
indent-style = Spaces, size: 2
|
||||
indent-style = space
|
||||
line-width = 88
|
||||
tab-width = 4
|
||||
indent-width = 2
|
||||
quote-style = Double
|
||||
magic-trailing-comma = Respect
|
||||
```
|
||||
|
||||
@@ -9,9 +9,9 @@ input_file: crates/ruff_python_formatter/resources/test/fixtures/ruff/fmt_on_off
|
||||
## Outputs
|
||||
### Output 1
|
||||
```
|
||||
indent-style = Spaces, size: 4
|
||||
indent-style = space
|
||||
line-width = 88
|
||||
tab-width = 4
|
||||
indent-width = 4
|
||||
quote-style = Double
|
||||
magic-trailing-comma = Respect
|
||||
```
|
||||
@@ -22,9 +22,9 @@ magic-trailing-comma = Respect
|
||||
|
||||
### Output 2
|
||||
```
|
||||
indent-style = Spaces, size: 1
|
||||
indent-style = space
|
||||
line-width = 88
|
||||
tab-width = 4
|
||||
indent-width = 1
|
||||
quote-style = Double
|
||||
magic-trailing-comma = Respect
|
||||
```
|
||||
@@ -35,9 +35,9 @@ magic-trailing-comma = Respect
|
||||
|
||||
### Output 3
|
||||
```
|
||||
indent-style = Tab
|
||||
indent-style = tab
|
||||
line-width = 88
|
||||
tab-width = 4
|
||||
indent-width = 4
|
||||
quote-style = Double
|
||||
magic-trailing-comma = Respect
|
||||
```
|
||||
|
||||
@@ -24,9 +24,9 @@ not_fixed
|
||||
## Outputs
|
||||
### Output 1
|
||||
```
|
||||
indent-style = Spaces, size: 4
|
||||
indent-style = space
|
||||
line-width = 88
|
||||
tab-width = 4
|
||||
indent-width = 4
|
||||
quote-style = Double
|
||||
magic-trailing-comma = Respect
|
||||
```
|
||||
@@ -53,9 +53,9 @@ not_fixed
|
||||
|
||||
### Output 2
|
||||
```
|
||||
indent-style = Spaces, size: 2
|
||||
indent-style = space
|
||||
line-width = 88
|
||||
tab-width = 4
|
||||
indent-width = 2
|
||||
quote-style = Double
|
||||
magic-trailing-comma = Respect
|
||||
```
|
||||
@@ -82,9 +82,9 @@ not_fixed
|
||||
|
||||
### Output 3
|
||||
```
|
||||
indent-style = Tab
|
||||
indent-style = tab
|
||||
line-width = 88
|
||||
tab-width = 4
|
||||
indent-width = 4
|
||||
quote-style = Double
|
||||
magic-trailing-comma = Respect
|
||||
```
|
||||
|
||||
@@ -42,9 +42,9 @@ with (a,): # magic trailing comma
|
||||
## Outputs
|
||||
### Output 1
|
||||
```
|
||||
indent-style = Spaces, size: 4
|
||||
indent-style = space
|
||||
line-width = 88
|
||||
tab-width = 4
|
||||
indent-width = 4
|
||||
quote-style = Double
|
||||
magic-trailing-comma = Respect
|
||||
```
|
||||
@@ -94,9 +94,9 @@ with (
|
||||
|
||||
### Output 2
|
||||
```
|
||||
indent-style = Spaces, size: 4
|
||||
indent-style = space
|
||||
line-width = 88
|
||||
tab-width = 4
|
||||
indent-width = 4
|
||||
quote-style = Double
|
||||
magic-trailing-comma = Ignore
|
||||
```
|
||||
|
||||
@@ -5,45 +5,42 @@ input_file: crates/ruff_python_formatter/resources/test/fixtures/ruff/tab_width.
|
||||
## Input
|
||||
```py
|
||||
# Fits with tab width 2
|
||||
1 + " 012345678901234567890123456789012345678901234567890123456789012345678901234567890"
|
||||
(1 + " 012345678901234567890123456789012345678901234567890123456789012345678901234567")
|
||||
|
||||
# Fits with tab width 4
|
||||
1 + " 0123456789012345678901234567890123456789012345678901234567890123456789012345678"
|
||||
(1 + " 0123456789012345678901234567890123456789012345678901234567890123456789012345")
|
||||
|
||||
# Fits with tab width 8
|
||||
1 + " 012345678901234567890123456789012345678901234567890123456789012345678901234"
|
||||
(1 + " 012345678901234567890123456789012345678901234567890123456789012345678901")
|
||||
```
|
||||
|
||||
## Outputs
|
||||
### Output 1
|
||||
```
|
||||
indent-style = Spaces, size: 4
|
||||
indent-style = space
|
||||
line-width = 88
|
||||
tab-width = 2
|
||||
indent-width = 2
|
||||
quote-style = Double
|
||||
magic-trailing-comma = Respect
|
||||
```
|
||||
|
||||
```py
|
||||
# Fits with tab width 2
|
||||
(
|
||||
1
|
||||
+ " 012345678901234567890123456789012345678901234567890123456789012345678901234567890"
|
||||
)
|
||||
(1 + " 012345678901234567890123456789012345678901234567890123456789012345678901234567")
|
||||
|
||||
# Fits with tab width 4
|
||||
1 + " 0123456789012345678901234567890123456789012345678901234567890123456789012345678"
|
||||
(1 + " 0123456789012345678901234567890123456789012345678901234567890123456789012345")
|
||||
|
||||
# Fits with tab width 8
|
||||
1 + " 012345678901234567890123456789012345678901234567890123456789012345678901234"
|
||||
(1 + " 012345678901234567890123456789012345678901234567890123456789012345678901")
|
||||
```
|
||||
|
||||
|
||||
### Output 2
|
||||
```
|
||||
indent-style = Spaces, size: 4
|
||||
indent-style = space
|
||||
line-width = 88
|
||||
tab-width = 4
|
||||
indent-width = 4
|
||||
quote-style = Double
|
||||
magic-trailing-comma = Respect
|
||||
```
|
||||
@@ -52,17 +49,41 @@ magic-trailing-comma = Respect
|
||||
# Fits with tab width 2
|
||||
(
|
||||
1
|
||||
+ " 012345678901234567890123456789012345678901234567890123456789012345678901234567890"
|
||||
+ " 012345678901234567890123456789012345678901234567890123456789012345678901234567"
|
||||
)
|
||||
|
||||
# Fits with tab width 4
|
||||
(1 + " 0123456789012345678901234567890123456789012345678901234567890123456789012345")
|
||||
|
||||
# Fits with tab width 8
|
||||
(1 + " 012345678901234567890123456789012345678901234567890123456789012345678901")
|
||||
```
|
||||
|
||||
|
||||
### Output 3
|
||||
```
|
||||
indent-style = space
|
||||
line-width = 88
|
||||
indent-width = 8
|
||||
quote-style = Double
|
||||
magic-trailing-comma = Respect
|
||||
```
|
||||
|
||||
```py
|
||||
# Fits with tab width 2
|
||||
(
|
||||
1
|
||||
+ " 012345678901234567890123456789012345678901234567890123456789012345678901234567"
|
||||
)
|
||||
|
||||
# Fits with tab width 4
|
||||
(
|
||||
1
|
||||
+ " 0123456789012345678901234567890123456789012345678901234567890123456789012345678"
|
||||
1
|
||||
+ " 0123456789012345678901234567890123456789012345678901234567890123456789012345"
|
||||
)
|
||||
|
||||
# Fits with tab width 8
|
||||
1 + " 012345678901234567890123456789012345678901234567890123456789012345678901234"
|
||||
(1 + " 012345678901234567890123456789012345678901234567890123456789012345678901")
|
||||
```
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user