ruff/crates/ruff_python_formatter/src/options.rs
Micha Reiser 313711aaf9
Prefer the configured quote style
<!--
Thank you for contributing to Ruff! To help us out with reviewing, please consider the following:

- Does this pull request include a summary of the change? (See below.)
- Does this pull request include a descriptive title?
- Does this pull request include references to any relevant issues?
-->

## Summary

This PR extends the string formatting to respect the configured quote style.

<!-- What's the purpose of the change? What does it do, and why? -->

## Test Plan

Extended the string test with new cases and set it up to run twice: Once with the `quote_style: Doube`, and once with `quote_style: Single` single and double quotes. 

<!-- How was it tested? -->
2023-06-26 14:24:25 +02:00

148 lines
3.6 KiB
Rust

use ruff_formatter::printer::{LineEnding, PrinterOptions};
use ruff_formatter::{FormatOptions, IndentStyle, LineWidth};
#[derive(Clone, Debug)]
#[cfg_attr(
feature = "serde",
derive(serde::Serialize, serde::Deserialize),
serde(default)
)]
pub struct PyFormatOptions {
/// Specifies the indent style:
/// * Either a tab
/// * or a specific amount of spaces
indent_style: IndentStyle,
/// The preferred line width at which the formatter should wrap lines.
#[cfg_attr(feature = "serde", serde(default = "default_line_width"))]
line_width: LineWidth,
/// The preferred quote style to use (single vs double quotes).
quote_style: QuoteStyle,
/// Whether to expand lists or elements if they have a trailing comma such as `(a, b,)`
magic_trailing_comma: MagicTrailingComma,
}
fn default_line_width() -> LineWidth {
LineWidth::try_from(88).unwrap()
}
impl PyFormatOptions {
pub fn magic_trailing_comma(&self) -> MagicTrailingComma {
self.magic_trailing_comma
}
pub fn quote_style(&self) -> QuoteStyle {
self.quote_style
}
pub fn with_quote_style(&mut self, style: QuoteStyle) -> &mut Self {
self.quote_style = style;
self
}
pub fn with_magic_trailing_comma(&mut self, trailing_comma: MagicTrailingComma) -> &mut Self {
self.magic_trailing_comma = trailing_comma;
self
}
pub fn with_indent_style(&mut self, indent_style: IndentStyle) -> &mut Self {
self.indent_style = indent_style;
self
}
pub fn with_line_width(&mut self, line_width: LineWidth) -> &mut Self {
self.line_width = line_width;
self
}
}
impl FormatOptions for PyFormatOptions {
fn indent_style(&self) -> IndentStyle {
self.indent_style
}
fn line_width(&self) -> LineWidth {
self.line_width
}
fn as_print_options(&self) -> PrinterOptions {
PrinterOptions {
tab_width: 4,
print_width: self.line_width.into(),
line_ending: LineEnding::LineFeed,
indent_style: self.indent_style,
}
}
}
impl Default for PyFormatOptions {
fn default() -> Self {
Self {
indent_style: IndentStyle::Space(4),
line_width: LineWidth::try_from(88).unwrap(),
quote_style: QuoteStyle::default(),
magic_trailing_comma: MagicTrailingComma::default(),
}
}
}
#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
#[cfg_attr(
feature = "serde",
derive(serde::Serialize, serde::Deserialize),
serde(rename_all = "kebab-case")
)]
pub enum QuoteStyle {
Single,
#[default]
Double,
}
impl QuoteStyle {
pub const fn as_char(self) -> char {
match self {
QuoteStyle::Single => '\'',
QuoteStyle::Double => '"',
}
}
#[must_use]
pub const fn invert(self) -> QuoteStyle {
match self {
QuoteStyle::Single => QuoteStyle::Double,
QuoteStyle::Double => QuoteStyle::Single,
}
}
}
impl TryFrom<char> for QuoteStyle {
type Error = ();
fn try_from(value: char) -> std::result::Result<Self, Self::Error> {
match value {
'\'' => Ok(QuoteStyle::Single),
'"' => Ok(QuoteStyle::Double),
_ => Err(()),
}
}
}
#[derive(Copy, Clone, Debug, Default)]
#[cfg_attr(
feature = "serde",
derive(serde::Serialize, serde::Deserialize),
serde(rename_all = "kebab-case")
)]
pub enum MagicTrailingComma {
#[default]
Respect,
Ignore,
}
impl MagicTrailingComma {
pub const fn is_respect(self) -> bool {
matches!(self, Self::Respect)
}
}