diff --git a/src/children.rs b/src/children.rs index 13aa837..51f6620 100644 --- a/src/children.rs +++ b/src/children.rs @@ -9,10 +9,16 @@ pub struct Children { current_index: usize, } +pub enum DrainCommentOrNewline { + Comment(String), + Newline(usize), +} + impl Children { - pub fn new( + pub fn new_with_configuration( build_ctx: &crate::builder::BuildCtx, node: &rnix::SyntaxNode, + with_newlines: bool, ) -> Children { let mut children = Vec::new(); @@ -29,7 +35,21 @@ impl Children { } rnix::SyntaxElement::Token(token) => { match token.kind() { - rnix::SyntaxKind::TOKEN_WHITESPACE => {} + rnix::SyntaxKind::TOKEN_WHITESPACE => { + if with_newlines + && token + .text() + .chars() + .filter(|c| *c == '\n') + .count() + > 0 + { + children.push(Child { + element: token.clone().into(), + pos: pos.clone(), + }); + } + } _ => { children.push(Child { element: token.clone().into(), @@ -46,6 +66,13 @@ impl Children { Children { children, current_index: 0 } } + pub fn new( + build_ctx: &crate::builder::BuildCtx, + node: &rnix::SyntaxNode, + ) -> Children { + Children::new_with_configuration(build_ctx, node, false) + } + pub fn get(&mut self, index: usize) -> Option { if index + 1 > self.children.len() { None @@ -92,6 +119,47 @@ impl Children { }) } + pub fn has_newlines(&self) -> bool { + self.children.iter().any(|child| { + child.element.kind() == rnix::SyntaxKind::TOKEN_WHITESPACE + && child + .element + .clone() + .into_token() + .unwrap() + .text() + .chars() + .filter(|c| *c == '\n') + .count() + > 0 + }) + } + + pub fn drain_newlines(&mut self, mut callback: F) { + let mut newlines = 0; + + while let Some(child) = self.peek_next() { + match child.element.kind() { + rnix::SyntaxKind::TOKEN_WHITESPACE => { + newlines += child + .element + .into_token() + .unwrap() + .text() + .chars() + .filter(|c| *c == '\n') + .count(); + self.move_next(); + } + _ => { + break; + } + } + } + + callback(newlines) + } + pub fn drain_comment(&mut self, mut callback: F) { if let Some(child) = self.peek_next() { match child.element.kind() { @@ -123,6 +191,42 @@ impl Children { } } } + + pub fn drain_comments_and_newlines( + &mut self, + mut callback: F, + ) { + while let Some(child) = self.peek_next() { + match child.element.kind() { + rnix::SyntaxKind::TOKEN_COMMENT => { + callback(DrainCommentOrNewline::Comment(dedent_comment( + &child.pos, + child.element.into_token().unwrap().text(), + ))); + self.move_next(); + } + rnix::SyntaxKind::TOKEN_WHITESPACE => { + let count = child + .element + .clone() + .into_token() + .unwrap() + .text() + .chars() + .filter(|c| *c == '\n') + .count(); + + if count > 1 { + callback(DrainCommentOrNewline::Newline(count)); + } + self.move_next(); + } + _ => { + break; + } + } + } + } } fn dedent_comment(pos: &crate::position::Position, text: &str) -> String { diff --git a/src/rules/attr_set.rs b/src/rules/attr_set.rs index fd5eb2b..4504185 100644 --- a/src/rules/attr_set.rs +++ b/src/rules/attr_set.rs @@ -4,20 +4,25 @@ pub fn rule( ) -> std::collections::LinkedList { let mut steps = std::collections::LinkedList::new(); - let mut children = crate::children::Children::new(build_ctx, node); + let mut children = crate::children::Children::new_with_configuration( + build_ctx, node, true, + ); - let layout = if children.has_comments() { - &crate::config::Layout::Tall - } else if node + let items_count = node .children() - .filter(|element| match element.kind() { - rnix::SyntaxKind::NODE_KEY_VALUE - | rnix::SyntaxKind::NODE_INHERIT - | rnix::SyntaxKind::NODE_INHERIT_FROM => true, - _ => false, + .filter(|element| { + matches!( + element.kind(), + rnix::SyntaxKind::NODE_KEY_VALUE + | rnix::SyntaxKind::NODE_INHERIT + | rnix::SyntaxKind::NODE_INHERIT_FROM + ) }) - .count() - > 1 + .count(); + + let layout = if items_count > 1 + || children.has_comments() + || children.has_newlines() { &crate::config::Layout::Tall } else { @@ -28,10 +33,29 @@ pub fn rule( let child = children.peek_next().unwrap(); if let rnix::SyntaxKind::TOKEN_REC = child.element.kind() { steps.push_back(crate::builder::Step::Format(child.element)); - steps.push_back(crate::builder::Step::Whitespace); children.move_next(); + + if let rnix::SyntaxKind::TOKEN_COMMENT + | rnix::SyntaxKind::TOKEN_WHITESPACE = + children.peek_next().unwrap().element.kind() + { + steps.push_back(crate::builder::Step::NewLine); + steps.push_back(crate::builder::Step::Pad); + } else { + steps.push_back(crate::builder::Step::Whitespace); + } } + // /**/ + children.drain_comments_and_newlines(|element| match element { + crate::children::DrainCommentOrNewline::Comment(text) => { + steps.push_back(crate::builder::Step::Comment(text)); + steps.push_back(crate::builder::Step::NewLine); + steps.push_back(crate::builder::Step::Pad); + } + crate::children::DrainCommentOrNewline::Newline(_) => {} + }); + // { let child = children.get_next().unwrap(); steps.push_back(crate::builder::Step::Format(child.element)); @@ -42,24 +66,41 @@ pub fn rule( crate::config::Layout::Wide => {} } - loop { - // /**/ - children.drain_comments(|text| { + // /**/ + children.drain_comments_and_newlines(|element| match element { + crate::children::DrainCommentOrNewline::Comment(text) => { steps.push_back(crate::builder::Step::NewLine); steps.push_back(crate::builder::Step::Pad); steps.push_back(crate::builder::Step::Comment(text)); + } + crate::children::DrainCommentOrNewline::Newline(_) => {} + }); + + let mut item_index: usize = 0; + + loop { + // /**/ + children.drain_comments_and_newlines(|element| match element { + crate::children::DrainCommentOrNewline::Comment(text) => { + steps.push_back(crate::builder::Step::NewLine); + steps.push_back(crate::builder::Step::Pad); + steps.push_back(crate::builder::Step::Comment(text)); + } + crate::children::DrainCommentOrNewline::Newline(_) => { + if item_index > 0 && item_index < items_count { + steps.push_back(crate::builder::Step::NewLine); + } + } }); if let Some(child) = children.peek_next() { - let kind = child.element.kind(); - - if let rnix::SyntaxKind::TOKEN_COMMENT - | rnix::SyntaxKind::TOKEN_CURLY_B_CLOSE = kind + if let rnix::SyntaxKind::TOKEN_CURLY_B_CLOSE = child.element.kind() { break; } // item + item_index += 1; match layout { crate::config::Layout::Tall => { steps.push_back(crate::builder::Step::NewLine); @@ -76,18 +117,9 @@ pub fn rule( } children.move_next(); - } else { - break; } } - // /**/ - children.drain_comments(|text| { - steps.push_back(crate::builder::Step::NewLine); - steps.push_back(crate::builder::Step::Pad); - steps.push_back(crate::builder::Step::Comment(text)); - }); - // } let child = children.get_next().unwrap(); match layout { diff --git a/tests/cases/attr_set/in b/tests/cases/attr_set/in index 7f82e77..2a42177 100644 --- a/tests/cases/attr_set/in +++ b/tests/cases/attr_set/in @@ -2,6 +2,20 @@ {} {/*a*/} {a=1;} - {/*a*/b=1;/*c*/} + + { b=1; } + { b=1; /*c*/ } + { /*a*/ b=1; } + { /*a*/ b=1; /*c*/ } + + rec { c=1; } + rec { c=1; /*d*/ } + rec { /*b*/ c=1; } + rec { /*b*/ c=1; /*d*/ } + rec /*a*/ { c=1; } + rec /*a*/ { c=1; /*d*/ } + rec /*a*/ { /*b*/ c=1; } + rec /*a*/ { /*b*/ c=1; /*d*/ } + {a=rec {a={a=rec {a={a=rec {a={a=rec {a={a=rec {a={};};};};};};};};};};} ] diff --git a/tests/cases/attr_set/out b/tests/cases/attr_set/out index b3636aa..5d8211e 100644 --- a/tests/cases/attr_set/out +++ b/tests/cases/attr_set/out @@ -6,6 +6,19 @@ */ } { a = 1; } + { b = 1; } + { + b = 1; + /* + c + */ + } + { + /* + a + */ + b = 1; + } { /* a @@ -15,6 +28,68 @@ c */ } + rec { c = 1; } + rec { + c = 1; + /* + d + */ + } + rec { + /* + b + */ + c = 1; + } + rec { + /* + b + */ + c = 1; + /* + d + */ + } + rec + /* + a + */ + { + c = 1; + } + rec + /* + a + */ + { + c = 1; + /* + d + */ + } + rec + /* + a + */ + { + /* + b + */ + c = 1; + } + rec + /* + a + */ + { + /* + b + */ + c = 1; + /* + d + */ + } { a = rec { a = { diff --git a/tests/cases/key_value/in b/tests/cases/key_value/in index 61911b9..8fb4ca1 100644 --- a/tests/cases/key_value/in +++ b/tests/cases/key_value/in @@ -1,6 +1,11 @@ -{ +rec /**/ { + a = {a = 1 ;}; + + b = {a = 1/*d*/;}; + + c = {a =/*c*/1 ;}; d = {a =/*c*/1/*d*/;}; e = {a/*b*/= 1 ;}; @@ -15,6 +20,10 @@ o = { pkgs , ... }: { }; + + p = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa { } a; + + } diff --git a/tests/cases/key_value/out b/tests/cases/key_value/out index cdabc02..c19c974 100644 --- a/tests/cases/key_value/out +++ b/tests/cases/key_value/out @@ -1,5 +1,8 @@ +rec +/**/ { a = { a = 1; }; + b = { a = 1 @@ -8,6 +11,7 @@ */ ; }; + c = { a = /* @@ -96,6 +100,7 @@ , ... }: { }; + p = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa { } a; }