From 8d163eb099418a8709732cb60a8474bd92f7a18a Mon Sep 17 00:00:00 2001 From: Lennart Spitzner Date: Mon, 6 Mar 2017 15:58:57 +0100 Subject: [PATCH] Improve layouting for equations with multiple clauses e.g. func x | x = simple expression | otherwise = 0 This fixes part of #7 --- src-literatetests/tests.blt | 36 ++++++-- .../Haskell/Brittany/Layouters/Decl.hs | 82 +++++++++++++++++++ src/Language/Haskell/Brittany/Types.hs | 5 ++ 3 files changed, 116 insertions(+), 7 deletions(-) diff --git a/src-literatetests/tests.blt b/src-literatetests/tests.blt index b22afe9..a49e1dc 100644 --- a/src-literatetests/tests.blt +++ b/src-literatetests/tests.blt @@ -443,6 +443,31 @@ func = do stmt x +############################################################################### +############################################################################### +############################################################################### +#group equations +############################################################################### +############################################################################### +############################################################################### + +#test multiple-clauses-1 +func x | x = simple expression + | otherwise = 0 + +#test multiple-clauses-2 +func x + | a somewhat longer guard x = "and a somewhat longer expession that does not" + | otherwise = "fit without putting the guards in new lines" + +#test multiple-clauses-3 +func x + | very long guard, another rather long guard that refers to x + = nontrivial expression foo bar alsdkjlasdjlasj + | otherwise + = 0 + + ############################################################################### ############################################################################### ############################################################################### @@ -673,6 +698,10 @@ showPackageDetailedInfo pkginfo = $+$ nest 4 (vcat (map disp . sort . modules $ pkginfo)) ] +#test issue 7a +isValidPosition position | validX && validY = Just position + | otherwise = Nothing + ############################################################################### ############################################################################### @@ -682,13 +711,6 @@ showPackageDetailedInfo pkginfo = ############################################################################### ############################################################################### -#test issue 7a -#pending - -isValidPosition :: Position -> Maybe Position -isValidPosition position - | validX && validY = Just position - | otherwise = Nothing ## this testcase is not about idempotency, but about _how_ the output differs diff --git a/src/Language/Haskell/Brittany/Layouters/Decl.hs b/src/Language/Haskell/Brittany/Layouters/Decl.hs index 2acccd0..565869a 100644 --- a/src/Language/Haskell/Brittany/Layouters/Decl.hs +++ b/src/Language/Haskell/Brittany/Layouters/Decl.hs @@ -292,6 +292,88 @@ layoutPatternBindFinal alignmentToken binderDoc mPatDoc clauseDocs mWhereDocs = | [(guards, body, _)] <- [clauseDocs] , let guardPart = singleLineGuardsDoc guards ] + ++ -- multiple clauses added in-paragraph, each in a single line + -- example: foo | bar = baz + -- | lll = asd + [ docLines + $ [ docSeq + [ appSep $ docForceSingleline $ return patDoc + , docSetBaseY + $ docLines + $ clauseDocs + <&> \(guardDocs, bodyDoc, _) -> do + let guardPart = singleLineGuardsDoc guardDocs + -- the docForceSingleline might seems superflous, but it + -- helps the alternative resolving impl. + docForceSingleline $ docCols + ColGuardedBody + [ guardPart + , docSeq + [ appSep $ return binderDoc + , docForceSingleline $ return bodyDoc + -- i am not sure if there is a benefit to using + -- docForceParSpacing additionally here: + -- , docAddBaseY BrIndentRegular $ return bodyDoc + ] + ] + ] + ] + ++ wherePartMultiLine + | Just patDoc <- [mPatDoc] + ] + ++ -- multiple clauses, each in a separate, single line + [ docLines + $ [ patPartParWrap + $ docEnsureIndent BrIndentRegular + $ docLines + $ clauseDocs + <&> \(guardDocs, bodyDoc, _) -> do + let guardPart = singleLineGuardsDoc guardDocs + -- the docForceSingleline might seems superflous, but it + -- helps the alternative resolving impl. + docForceSingleline $ docCols + ColGuardedBody + [ guardPart + , docSeq + [ appSep $ return binderDoc + , docForceSingleline $ return bodyDoc + -- i am not sure if there is a benefit to using + -- docForceParSpacing additionally here: + -- , docAddBaseY BrIndentRegular $ return bodyDoc + ] + ] + ] + ++ wherePartMultiLine + ] + ++ -- multiple clauses, each with the guard(s) in a single line, body + -- as a paragraph + [ docLines + $ [ patPartParWrap + $ docEnsureIndent BrIndentRegular + $ docLines + $ clauseDocs + >>= \(guardDocs, bodyDoc, _) -> + ( case guardDocs of + [] -> [] + [g] -> + [docSeq [appSep $ docLit $ Text.pack "|", return g]] + gs -> + [ docSeq + $ [appSep $ docLit $ Text.pack "|"] + ++ List.intersperse docCommaSep (return <$> gs) + ] + ) + ++ [ docCols + ColOpPrefix + [ appSep $ return binderDoc + , docForceParSpacing + $ docAddBaseY BrIndentRegular + $ return bodyDoc + ] + ] + ] + ++ wherePartMultiLine + ] ++ -- conservative approach: everything starts on the left. [ docLines $ [ patPartParWrap diff --git a/src/Language/Haskell/Brittany/Types.hs b/src/Language/Haskell/Brittany/Types.hs index 3f15427..ae7ddd1 100644 --- a/src/Language/Haskell/Brittany/Types.hs +++ b/src/Language/Haskell/Brittany/Types.hs @@ -158,6 +158,11 @@ data ColSig -- or "pat | cond1, cond2 -> ..." -- 1111222222222222222 -- expected to have exactly two columns + | ColGuardedBody + -- e.g. | foofoo = 1 + -- | bar = 2 + -- 111111111222 + -- expected to have exactly two columns | ColBindStmt | ColDoLet -- the non-indented variant | ColRecUpdate