Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,23 @@ If not found, we search for an `.editorconfig` file, otherwise fall back to the
This feature can be disabled using `--no-editorconfig`.
See [EditorConfig](https://editorconfig.org/) for more details.

The following EditorConfig properties are supported:

| EditorConfig Property | Maps to |
| --------------------------------- | ---------------------------- |
| `end_of_line` | `line_endings` |
| `indent_style` | `indent_type` |
| `indent_size` | `indent_width` |
| `max_line_length` | `column_width` |
| `quote_type` | `quote_style` |
| `call_parentheses` | `call_parentheses` |
| `space_after_function_names` | `space_after_function_names` |
| `collapse_simple_statement` | `collapse_simple_statement` |
| `sort_requires` | `sort_requires.enabled` |
| `stylua_syntax` | `syntax` |
| `stylua_block_newline_gaps` | `block_newline_gaps` |
| `stylua_trailing_comment_spacing` | `trailing_comment_spacing` |

Use `--config-path <path>` to provide a custom path to the configuration.
If the file provided is not found/malformed, StyLua will exit with an error.

Expand Down Expand Up @@ -319,6 +336,7 @@ StyLua only offers the following options:
| `call_parentheses` | `Always` | Whether parentheses should be applied on function calls with a single string/table argument. Possible options: `Always`, `NoSingleString`, `NoSingleTable`, `None`, `Input`. `Always` applies parentheses in all cases. `NoSingleString` omits parentheses on calls with a single string argument. Similarly, `NoSingleTable` omits parentheses on calls with a single table argument. `None` omits parentheses in both cases. Note: parentheses are still kept in situations where removal can lead to obscurity (e.g. `foo "bar".setup -> foo("bar").setup`, since the index is on the call result, not the string). `Input` removes all automation and preserves parentheses only if they were present in input code: consistency is not enforced. |
| `space_after_function_names` | `Never` | Specify whether to add a space between the function name and parentheses. Possible options: `Never`, `Definitions`, `Calls`, or `Always` |
| `block_newline_gaps` | `Never` | Specify whether to preserve leading and trailing newline gaps for blocks. Possible options: `Never`, `Preserve` |
| `trailing_comment_spacing` | `Compress` | Specify whether to preserve the original spacing before trailing inline comments. Possible options: `Compress` (always use a single space), `Preserve` (keep original spacing) |
| `collapse_simple_statement` | `Never` | Specify whether to collapse simple statements. Possible options: `Never`, `FunctionOnly`, `ConditionalOnly`, or `Always` |

Default `stylua.toml`, note you do not need to explicitly specify each option if you want to use the defaults:
Expand All @@ -334,6 +352,7 @@ call_parentheses = "Always"
collapse_simple_statement = "Never"
space_after_function_names = "Never"
block_newline_gaps = "Never"
trailing_comment_spacing = "Compress"

[sort_requires]
enabled = false
Expand Down
3 changes: 3 additions & 0 deletions src/cli/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,9 @@ fn load_overrides(config: Config, opt: &Opt) -> Config {
if let Some(preserve_block_newline_gaps) = opt.format_opts.preserve_block_newline_gaps {
new_config.block_newline_gaps = preserve_block_newline_gaps.into();
};
if let Some(trailing_comment_spacing) = opt.format_opts.trailing_comment_spacing {
new_config.trailing_comment_spacing = trailing_comment_spacing.into();
};
if opt.format_opts.sort_requires {
new_config.sort_requires = SortRequiresConfig { enabled: true }
}
Expand Down
10 changes: 9 additions & 1 deletion src/cli/opt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use clap::{ArgEnum, StructOpt};
use std::path::PathBuf;
use stylua_lib::{
BlockNewlineGaps, CallParenType, CollapseSimpleStatement, IndentType, LineEndings, LuaVersion,
QuoteStyle, SpaceAfterFunctionNames,
QuoteStyle, SpaceAfterFunctionNames, TrailingCommentSpacing,
};

lazy_static::lazy_static! {
Expand Down Expand Up @@ -202,6 +202,9 @@ pub struct FormatOpts {
pub sort_requires: bool,
#[structopt(long, arg_enum, ignore_case = true)]
pub space_after_function_names: Option<ArgSpaceAfterFunctionNames>,
/// Specify whether to preserve spacing before trailing comments.
#[structopt(long, arg_enum, ignore_case = true)]
pub trailing_comment_spacing: Option<ArgTrailingCommentSpacing>,
}

// Convert [`stylua_lib::Config`] enums into clap-friendly enums
Expand Down Expand Up @@ -295,6 +298,11 @@ convert_enum!(SpaceAfterFunctionNames, ArgSpaceAfterFunctionNames, {
Always,
});

convert_enum!(TrailingCommentSpacing, ArgTrailingCommentSpacing, {
Compress,
Preserve,
});

#[cfg(test)]
mod tests {
use super::Opt;
Expand Down
14 changes: 13 additions & 1 deletion src/editorconfig.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::{
BlockNewlineGaps, CallParenType, CollapseSimpleStatement, Config, IndentType, LineEndings,
LuaVersion, QuoteStyle, SortRequiresConfig, SpaceAfterFunctionNames,
LuaVersion, QuoteStyle, SortRequiresConfig, SpaceAfterFunctionNames, TrailingCommentSpacing,
};
use ec4rs::{
properties_of,
Expand Down Expand Up @@ -106,6 +106,12 @@ property_choice! {
(Preserve, "preserve")
}

property_choice! {
StyluaTrailingCommentSpacingChoice, "stylua_trailing_comment_spacing";
(Compress, "compress"),
(Preserve, "preserve")
}

// Override StyLua config with EditorConfig properties
fn load(mut config: Config, properties: &Properties) -> Config {
if let Ok(end_of_line) = properties.get::<EndOfLine>() {
Expand Down Expand Up @@ -202,6 +208,12 @@ fn load(mut config: Config, properties: &Properties) -> Config {
StyluaBlockNewlineGapsChoice::Preserve => BlockNewlineGaps::Preserve,
};
}
if let Ok(trailing_comment_spacing) = properties.get::<StyluaTrailingCommentSpacingChoice>() {
config.trailing_comment_spacing = match trailing_comment_spacing {
StyluaTrailingCommentSpacingChoice::Compress => TrailingCommentSpacing::Compress,
StyluaTrailingCommentSpacingChoice::Preserve => TrailingCommentSpacing::Preserve,
};
}

config
}
Expand Down
39 changes: 30 additions & 9 deletions src/formatters/general.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use crate::{
},
},
shape::Shape,
QuoteStyle,
QuoteStyle, TrailingCommentSpacing,
};
use full_moon::node::Node;
use full_moon::tokenizer::{StringLiteralQuoteType, Token, TokenKind, TokenReference, TokenType};
Expand Down Expand Up @@ -236,8 +236,10 @@ pub fn format_token(
trailing_trivia = Some(vec![create_newline_trivia(ctx)]);
}
FormatTokenType::TrailingTrivia => {
// Add a space before the comment
leading_trivia = Some(vec![Token::new(TokenType::spaces(1))]);
// Add a space before the comment (unless preserving original spacing)
if ctx.config().trailing_comment_spacing == TrailingCommentSpacing::Compress {
leading_trivia = Some(vec![Token::new(TokenType::spaces(1))]);
}
}
_ => (),
}
Expand Down Expand Up @@ -308,12 +310,31 @@ fn load_token_trivia(
}
}
FormatTokenType::TrailingTrivia => {
// If the next trivia is a MultiLineComment, and this whitespace is just spacing, then we
// will preserve a single space
if let Some(next_trivia) = trivia_iter.peek() {
if let TokenType::MultiLineComment { .. } = next_trivia.token_type() {
if !characters.contains('\n') {
token_trivia.push(Token::new(TokenType::spaces(1)))
// If the next trivia is a comment, preserve original spacing if configured
if ctx.config().trailing_comment_spacing == TrailingCommentSpacing::Preserve
{
if let Some(next_trivia) = trivia_iter.peek() {
match next_trivia.token_type() {
TokenType::SingleLineComment { .. }
| TokenType::MultiLineComment { .. } => {
if !characters.contains('\n') {
token_trivia.push(Token::new(TokenType::Whitespace {
characters: characters.to_owned(),
}));
}
}
_ => (),
}
}
} else {
// If the next trivia is a MultiLineComment, and this whitespace is just spacing, then we
// will preserve a single space
if let Some(next_trivia) = trivia_iter.peek() {
if let TokenType::MultiLineComment { .. } = next_trivia.token_type()
{
if !characters.contains('\n') {
token_trivia.push(Token::new(TokenType::spaces(1)))
}
}
}
}
Expand Down
18 changes: 18 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,19 @@ pub enum BlockNewlineGaps {
Preserve,
}

/// How to handle spacing before trailing inline comments.
#[derive(Debug, Default, 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 TrailingCommentSpacing {
/// Always use a single space before trailing comments
#[default]
Compress,
/// Preserve the original spacing before trailing comments
Preserve,
}

/// 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.
Expand Down Expand Up @@ -279,6 +292,10 @@ pub struct Config {
/// * if space_after_function_names is set to [`SpaceAfterFunctionNames::Calls`] a space is used only for calls.
/// * if space_after_function_names is set to [`SpaceAfterFunctionNames::Always`] a space is used for both definitions and calls.
pub space_after_function_names: SpaceAfterFunctionNames,
/// How to handle spacing before trailing inline comments.
/// * if set to [`TrailingCommentSpacing::Compress`] a single space is always used before trailing comments.
/// * if set to [`TrailingCommentSpacing::Preserve`] the original spacing before trailing comments is preserved.
pub trailing_comment_spacing: TrailingCommentSpacing,
}

#[cfg_attr(all(target_arch = "wasm32", feature = "wasm-bindgen"), wasm_bindgen)]
Expand All @@ -305,6 +322,7 @@ impl Default for Config {
sort_requires: SortRequiresConfig::default(),
space_after_function_names: SpaceAfterFunctionNames::default(),
block_newline_gaps: BlockNewlineGaps::default(),
trailing_comment_spacing: TrailingCommentSpacing::default(),
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
local x = 1 -- x value
local y = 2 -- y value
local longname = 3 -- long name
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
local a = 1 -- single space
local b = 2 -- two spaces
local c = 3 -- four spaces
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
source: tests/tests.rs
assertion_line: 140
expression: "format_code(&contents, Config\n{\n trailing_comment_spacing: TrailingCommentSpacing::Preserve,\n ..Config::default()\n}, None, OutputVerification::None).unwrap()"
input_file: tests/inputs-preserve-trailing-comment-spacing/aligned-comments.lua
---
local x = 1 -- x value
local y = 2 -- y value
local longname = 3 -- long name

Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
source: tests/tests.rs
assertion_line: 140
expression: "format_code(&contents, Config\n{\n trailing_comment_spacing: TrailingCommentSpacing::Preserve,\n ..Config::default()\n}, None, OutputVerification::None).unwrap()"
input_file: tests/inputs-preserve-trailing-comment-spacing/varying-spacing.lua
---
local a = 1 -- single space
local b = 2 -- two spaces
local c = 3 -- four spaces

19 changes: 18 additions & 1 deletion tests/tests.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use stylua_lib::{
format_code, BlockNewlineGaps, CollapseSimpleStatement, Config, LuaVersion, OutputVerification,
SortRequiresConfig,
SortRequiresConfig, TrailingCommentSpacing,
};

fn format(input: &str, syntax: LuaVersion) -> String {
Expand Down Expand Up @@ -133,6 +133,23 @@ fn test_preserve_block_newline_gaps() {
})
}

#[test]
fn test_preserve_trailing_comment_spacing() {
insta::glob!("inputs-preserve-trailing-comment-spacing/*.lua", |path| {
let contents = std::fs::read_to_string(path).unwrap();
insta::assert_snapshot!(format_code(
&contents,
Config {
trailing_comment_spacing: TrailingCommentSpacing::Preserve,
..Config::default()
},
None,
OutputVerification::None
)
.unwrap());
})
}

// Collapse simple statement for goto
#[test]
#[cfg(feature = "lua52")]
Expand Down