From 256e5e0b0bc1a73f9f9435db67a909adb7ef72ba Mon Sep 17 00:00:00 2001 From: Bertrand Bonnefoy-Claudet Date: Sat, 26 Nov 2022 12:58:03 +0100 Subject: [PATCH] Add `brace_spacing` option Braces, used for table construction, are typically used with spaces inside them: ```lua t = { "content-0" } ``` There can be another style, however, which consists in sticking the braces to the content: ```lua t = {"content-0"} ``` This work adds a configuration parameter `brace_spacing: BraceSpacing` (`Always`, `Never`) to control the spacing inside table constructors and enable the use of the second style. This is similar to [Prettier's bracket spacing option](https://prettier.io/docs/en/options.html#bracket-spacing). Which style is better is debatable, of course. In my quick research, I listed what the formatters I know do: - rustfmt (Rust): space - OCamlFormat (OCaml): space, configurable - Prettier (JavaScript, TypeScript): space, configurable - Black (Python): no space - Clang-Format (C, C++): no space, configurable --- src/cli/opt.rs | 12 +++++++++++- src/context.rs | 8 ++++++-- src/formatters/table.rs | 15 +++++++++++---- src/lib.rs | 33 ++++++++++++++++++++++++++++++++ tests/test_table_spaces.rs | 39 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 100 insertions(+), 7 deletions(-) create mode 100644 tests/test_table_spaces.rs diff --git a/src/cli/opt.rs b/src/cli/opt.rs index c6917814..3b17f96d 100644 --- a/src/cli/opt.rs +++ b/src/cli/opt.rs @@ -1,6 +1,8 @@ use clap::{ArgEnum, StructOpt}; use std::path::PathBuf; -use stylua_lib::{CallParenType, CollapseSimpleStatement, IndentType, LineEndings, QuoteStyle}; +use stylua_lib::{ + BraceSpacing, CallParenType, CollapseSimpleStatement, IndentType, LineEndings, QuoteStyle, +}; lazy_static::lazy_static! { static ref NUM_CPUS: String = num_cpus::get().to_string(); @@ -169,6 +171,9 @@ pub struct FormatOpts { /// Specify whether to collapse simple statements. #[structopt(long, arg_enum, ignore_case = true)] pub collapse_simple_statement: Option, + /// Specify whether to add spacing inside the curly brackets around the content of a table literal. + #[structopt(long, arg_enum, ignore_case = true)] + pub brace_spacing: Option, } // Convert [`stylua_lib::Config`] enums into clap-friendly enums @@ -235,6 +240,11 @@ convert_enum!(CollapseSimpleStatement, ArgCollapseSimpleStatement, { Always, }); +convert_enum!(BraceSpacing, ArgBraceSpacing, { + Never, + Always, +}); + #[cfg(test)] mod tests { use super::Opt; diff --git a/src/context.rs b/src/context.rs index 757c2f86..436d0643 100644 --- a/src/context.rs +++ b/src/context.rs @@ -1,6 +1,6 @@ use crate::{ - shape::Shape, CallParenType, CollapseSimpleStatement, Config, IndentType, LineEndings, - Range as FormatRange, + shape::Shape, BraceSpacing, CallParenType, CollapseSimpleStatement, Config, IndentType, + LineEndings, Range as FormatRange, }; use full_moon::{ node::Node, @@ -152,6 +152,10 @@ impl Context { CollapseSimpleStatement::ConditionalOnly | CollapseSimpleStatement::Always ) } + + pub fn should_add_brace_spacing(&self) -> bool { + matches!(self.config().brace_spacing(), BraceSpacing::Always) + } } /// Returns the relevant line ending string from the [`LineEndings`] enum diff --git a/src/formatters/table.rs b/src/formatters/table.rs index e65d7a59..58e2526e 100644 --- a/src/formatters/table.rs +++ b/src/formatters/table.rs @@ -245,10 +245,17 @@ pub fn create_table_braces( ContainedSpan::new(start_brace_token, end_brace_token) } - TableType::SingleLine => ContainedSpan::new( - fmt_symbol!(ctx, start_brace, "{ ", shape), - fmt_symbol!(ctx, end_brace, " }", shape), - ), + TableType::SingleLine => { + let (start_, end_) = if ctx.should_add_brace_spacing() { + ("{ ", " }") + } else { + ("{", "}") + }; + ContainedSpan::new( + fmt_symbol!(ctx, start_brace, start_, shape), + fmt_symbol!(ctx, end_brace, end_, shape), + ) + } TableType::Empty => { let start_brace = fmt_symbol!(ctx, start_brace, "{", shape); diff --git a/src/lib.rs b/src/lib.rs index 6c744e93..db86cdb1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -113,6 +113,24 @@ impl Default for CollapseSimpleStatement { } } +/// Whether we add spacing inside the curly brackets around the content of a table literal. +#[derive(Debug, Copy, Clone, PartialEq, Eq, Deserialize)] +#[cfg_attr(all(target_arch = "wasm32", feature = "wasm-bindgen"), wasm_bindgen)] +#[cfg_attr(feature = "serialize", derive(serde::Serialize))] +#[cfg_attr(feature = "fromstr", derive(strum::EnumString))] +pub enum BraceSpacing { + /// Never add spaces around content in a table literal + Never, + /// Always add spaces around content in a table literal + Always, +} + +impl Default for BraceSpacing { + fn default() -> Self { + BraceSpacing::Always + } +} + /// An optional formatting range. /// If provided, only content within these boundaries (inclusive) will be formatted. /// Both boundaries are optional, and are given as byte offsets from the beginning of the file. @@ -168,6 +186,8 @@ pub struct Config { /// if set to [`CollapseSimpleStatement::None`] structures are never collapsed. /// if set to [`CollapseSimpleStatement::FunctionOnly`] then simple functions (i.e., functions with a single laststmt) can be collapsed collapse_simple_statement: CollapseSimpleStatement, + /// Whether we add spacing inside the curly brackets around the content of a table literal. + brace_spacing: BraceSpacing, } #[cfg_attr(all(target_arch = "wasm32", feature = "wasm-bindgen"), wasm_bindgen)] @@ -211,6 +231,10 @@ impl Config { self.collapse_simple_statement } + pub fn brace_spacing(&self) -> BraceSpacing { + self.brace_spacing + } + /// Returns a new config with the given column width pub fn with_column_width(self, column_width: usize) -> Self { Self { @@ -275,6 +299,14 @@ impl Config { ..self } } + + /// Returns a new config with the given bracket space configuration + pub fn with_brace_spacing(self, brace_spacing: BraceSpacing) -> Self { + Self { + brace_spacing, + ..self + } + } } impl Default for Config { @@ -288,6 +320,7 @@ impl Default for Config { no_call_parentheses: false, call_parentheses: CallParenType::default(), collapse_simple_statement: CollapseSimpleStatement::default(), + brace_spacing: BraceSpacing::default(), } } } diff --git a/tests/test_table_spaces.rs b/tests/test_table_spaces.rs new file mode 100644 index 00000000..865a3cc8 --- /dev/null +++ b/tests/test_table_spaces.rs @@ -0,0 +1,39 @@ +use stylua_lib::{format_code, BraceSpacing, Config, OutputVerification}; + +fn format(brace_spacing: BraceSpacing, input: &str) -> String { + format_code( + input, + Config::default().with_brace_spacing(brace_spacing), + None, + OutputVerification::None, + ) + .unwrap() +} + +#[test] +fn test_table_oneline_with_internal_spaces() { + insta::assert_snapshot!( + format(BraceSpacing::Always, + r###" +local foo = { "content" } +"### + ), + @r###" + local foo = { "content" } + "### + ); +} + +#[test] +fn test_table_oneline_without_internal_spaces() { + insta::assert_snapshot!( + format(BraceSpacing::Never, + r###" +local foo = { "content" } +"### + ), + @r###" + local foo = {"content"} + "### + ); +}