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
28 changes: 27 additions & 1 deletion bin/src/Bin/FormatOptions.purs
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,15 @@ import Data.Argonaut.Encode (assoc, encodeJson, extend)
import Data.Either (Either)
import Data.Maybe (Maybe(..), fromMaybe, maybe)
import Data.Traversable (traverse)
import Tidy (ImportSortOption(..), ImportWrapOption(..), TypeArrowOption(..), UnicodeOption(..))
import Tidy (ImportSortOption(..), ImportWrapOption(..), ThenPlacementOption(..), TypeArrowOption(..), UnicodeOption(..))

type FormatOptions =
{ importSort :: ImportSortOption
, importWrap :: ImportWrapOption
, indent :: Int
, operatorsFile :: Maybe String
, ribbon :: Number
, thenPlacement :: ThenPlacementOption
, typeArrowPlacement :: TypeArrowOption
, unicode :: UnicodeOption
, width :: Maybe Int
Expand All @@ -33,6 +34,7 @@ defaults =
, indent: 2
, operatorsFile: Nothing
, ribbon: 1.0
, thenPlacement: ThenSameLine
, typeArrowPlacement: TypeArrowFirst
, unicode: UnicodeSource
, width: Nothing
Expand Down Expand Up @@ -76,6 +78,16 @@ formatOptions =
"The ratio of printable width to maximum width.\nFrom 0 to 1. Defaults to 1."
# Arg.number
# Arg.default defaults.ribbon
, thenPlacement:
Arg.choose "then placement"
[ Arg.flag [ "--then-same-line", "-tsl" ]
"Then keyword is placed on the same line as the if condition.\nDefault."
$> ThenSameLine
, Arg.flag [ "--then-new-line", "-tnl" ]
"Then keyword is placed on a new line."
$> ThenNewLine
]
# Arg.default defaults.thenPlacement
, typeArrowPlacement:
Arg.choose "type arrow placement"
[ Arg.flag [ "--arrow-first", "-af" ]
Expand Down Expand Up @@ -117,6 +129,7 @@ fromJson json = do
indent <- obj .:? "indent"
operatorsFile <- obj .:? "operatorsFile"
ribbon <- obj .:? "ribbon"
thenPlacement <- traverse thenPlacementFromString =<< obj .:? "thenPlacement"
typeArrowPlacement <- traverse typeArrowPlacementFromString =<< obj .:? "typeArrowPlacement"
unicode <- traverse unicodeFromString =<< obj .:? "unicode"
width <- obj .:? "width"
Expand All @@ -126,6 +139,7 @@ fromJson json = do
, indent: fromMaybe defaults.indent indent
, operatorsFile: operatorsFile <|> defaults.operatorsFile
, ribbon: fromMaybe defaults.ribbon ribbon
, thenPlacement: fromMaybe defaults.thenPlacement thenPlacement
, typeArrowPlacement: fromMaybe defaults.typeArrowPlacement typeArrowPlacement
, unicode: fromMaybe defaults.unicode unicode
, width: width <|> defaults.width
Expand All @@ -139,10 +153,22 @@ toJson options =
# extend (assoc "indent" options.indent)
# extend (assoc "operatorsFile" (maybe jsonNull encodeJson options.operatorsFile))
# extend (assoc "ribbon" options.ribbon)
# extend (assoc "thenPlacement" (thenPlacementToString options.thenPlacement))
# extend (assoc "typeArrowPlacement" (typeArrowPlacementToString options.typeArrowPlacement))
# extend (assoc "unicode" (unicodeToString options.unicode))
# extend (assoc "width" (maybe jsonNull encodeJson options.width))

thenPlacementFromString :: String -> Either JsonDecodeError ThenPlacementOption
thenPlacementFromString = case _ of
"same-line" -> pure ThenSameLine
"new-line" -> pure ThenNewLine
other -> throwError $ UnexpectedValue (Json.fromString other)

thenPlacementToString :: ThenPlacementOption -> String
thenPlacementToString = case _ of
ThenSameLine -> "same-line"
ThenNewLine -> "new-line"

typeArrowPlacementFromString :: String -> Either JsonDecodeError TypeArrowOption
typeArrowPlacementFromString = case _ of
"first" -> pure TypeArrowFirst
Expand Down
6 changes: 6 additions & 0 deletions bin/src/Bin/Worker.purs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ type WorkerConfig =
, indent :: Int
, operatorsFile :: String
, ribbon :: Number
, thenPlacement :: String
, typeArrowPlacement :: String
, unicode :: String
, width :: Int
Expand All @@ -49,6 +50,7 @@ toWorkerConfig options =
, indent: options.indent
, operatorsFile: fromMaybe ".tidyoperators.default" options.operatorsFile
, ribbon: options.ribbon
, thenPlacement: FormatOptions.thenPlacementToString options.thenPlacement
, typeArrowPlacement: FormatOptions.typeArrowPlacementToString options.typeArrowPlacement
, unicode: FormatOptions.unicodeToString options.unicode
, width: fromMaybe top options.width
Expand Down Expand Up @@ -88,6 +90,7 @@ formatCommand args operators contents = do
{ importSort = args.importSort
, importWrap = args.importWrap
, operators = remapOperators operators ok
, thenPlacement = args.thenPlacement
, typeArrowPlacement = args.typeArrowPlacement
, unicode = args.unicode
}
Expand Down Expand Up @@ -115,6 +118,9 @@ formatInPlaceCommand shouldCheck operators { filePath, config } = do
, indent: config.indent
, operatorsFile: Nothing
, ribbon: config.ribbon
, thenPlacement:
fromRight' (\_ -> unsafeCrashWith "Unknown thenPlacement value") do
FormatOptions.thenPlacementFromString config.thenPlacement
, typeArrowPlacement:
fromRight' (\_ -> unsafeCrashWith "Unknown typeArrowPlacement value") do
FormatOptions.typeArrowPlacementFromString config.typeArrowPlacement
Expand Down
51 changes: 39 additions & 12 deletions src/Tidy.purs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ module Tidy
( FormatOptions
, defaultFormatOptions
, TypeArrowOption(..)
, ThenPlacementOption(..)
, ImportSortOption(..)
, ImportWrapOption(..)
, Format
Expand Down Expand Up @@ -50,6 +51,12 @@ data TypeArrowOption

derive instance eqTypeArrowOption :: Eq TypeArrowOption

data ThenPlacementOption
= ThenSameLine
| ThenNewLine

derive instance eqThenPlacementOption :: Eq ThenPlacementOption

data ImportWrapOption
= ImportWrapSource
| ImportWrapAuto
Expand All @@ -66,6 +73,7 @@ type FormatOptions e a =
{ formatError :: e -> FormatDoc a
, unicode :: UnicodeOption
, typeArrowPlacement :: TypeArrowOption
, thenPlacement :: ThenPlacementOption
, operators :: PrecedenceMap
, importSort :: ImportSortOption
, importWrap :: ImportWrapOption
Expand All @@ -76,6 +84,7 @@ defaultFormatOptions =
{ formatError
, unicode: UnicodeSource
, typeArrowPlacement: TypeArrowFirst
, thenPlacement: ThenSameLine
, operators: Map.empty
, importSort: ImportSortSource
, importWrap: ImportWrapSource
Expand Down Expand Up @@ -991,19 +1000,37 @@ toElseIfChain ifte = go (pure (IfThen ifte.keyword ifte.cond ifte.then ifte.true
formatElseIfChain :: forall e a. Format (NonEmptyArray (ElseIfChain e)) e a
formatElseIfChain conf = flexGroup <<< joinWithMap spaceBreak case _ of
IfThen kw1 cond kw2 expr ->
formatToken conf kw1
`flexSpaceBreak`
indent (anchor (flexGroup (formatExpr conf cond)))
`space`
Hang.toFormatDoc (anchor (formatToken conf kw2) `hang` formatHangingExpr conf expr)
case conf.thenPlacement of
ThenSameLine ->
formatToken conf kw1
`flexSpaceBreak`
indent (anchor (flexGroup (formatExpr conf cond)))
`space`
Hang.toFormatDoc (anchor (formatToken conf kw2) `hang` formatHangingExpr conf expr)
ThenNewLine ->
formatToken conf kw1
`flexSpaceBreak`
indent (anchor (flexGroup (formatExpr conf cond)))
`break`
Hang.toFormatDoc (anchor (formatToken conf kw2) `hang` formatHangingExpr conf expr)
ElseIfThen kw1 kw2 cond kw3 expr ->
formatToken conf kw1
`space`
indent (anchor (formatToken conf kw2))
`flexSpaceBreak`
indent (anchor (flexGroup (formatExpr conf cond)))
`space`
Hang.toFormatDoc (anchor (formatToken conf kw3) `hang` formatHangingExpr conf expr)
case conf.thenPlacement of
ThenSameLine ->
formatToken conf kw1
`space`
indent (anchor (formatToken conf kw2))
`flexSpaceBreak`
indent (anchor (flexGroup (formatExpr conf cond)))
`space`
Hang.toFormatDoc (anchor (formatToken conf kw3) `hang` formatHangingExpr conf expr)
ThenNewLine ->
formatToken conf kw1
`space`
indent (anchor (formatToken conf kw2))
`flexSpaceBreak`
indent (anchor (flexGroup (formatExpr conf cond)))
`break`
Hang.toFormatDoc (anchor (formatToken conf kw3) `hang` formatHangingExpr conf expr)
Else kw1 expr ->
Hang.toFormatDoc (formatToken conf kw1 `hang` formatHangingExpr conf expr)

Expand Down
1 change: 1 addition & 0 deletions test/FormatDirective.purs
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ parseDirectivesFromModule (Module { header: ModuleHeader header, body }) =
{ formatError: default.formatError
, operators: default.operators
, unicode: opts.unicode
, thenPlacement: opts.thenPlacement
, typeArrowPlacement: opts.typeArrowPlacement
, importSort: opts.importSort
, importWrap: opts.importWrap
Expand Down
16 changes: 16 additions & 0 deletions test/snapshots/ThenPlacementComparison.input
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
-- @format --then-same-line --width 40
module ThenPlacementComparison where

-- This should trigger the difference with narrow width
test1 =
if someVeryLongConditionExpressionThatWillDefinitelyWrap
then shortResult
else alternativeValue

-- This should also show the difference
test2 =
if firstLongCondition
then if secondLongCondition
then result1
else result2
else alternativeResult
29 changes: 29 additions & 0 deletions test/snapshots/ThenPlacementComparison.output
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
module ThenPlacementComparison where

-- This should trigger the difference with narrow width
test1 =
if someVeryLongConditionExpressionThatWillDefinitelyWrap then shortResult
else alternativeValue

-- This should also show the difference
test2 =
if firstLongCondition then
if secondLongCondition then result1
else result2
else alternativeResult
-- @format --then-same-line --width 40
module ThenPlacementComparison where

-- This should trigger the difference with narrow width
test1 =
if
someVeryLongConditionExpressionThatWillDefinitelyWrap then
shortResult
else alternativeValue

-- This should also show the difference
test2 =
if firstLongCondition then
if secondLongCondition then result1
else result2
else alternativeResult
16 changes: 16 additions & 0 deletions test/snapshots/ThenPlacementDifference.input
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
-- @format --then-new-line --width 40
module ThenPlacementDifference where

-- This should trigger the difference with narrow width
test1 =
if someVeryLongConditionExpressionThatWillDefinitelyWrap
then shortResult
else alternativeValue

-- This should also show the difference
test2 =
if firstLongCondition
then if secondLongCondition
then result1
else result2
else alternativeResult
31 changes: 31 additions & 0 deletions test/snapshots/ThenPlacementDifference.output
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
module ThenPlacementDifference where

-- This should trigger the difference with narrow width
test1 =
if someVeryLongConditionExpressionThatWillDefinitelyWrap then shortResult
else alternativeValue

-- This should also show the difference
test2 =
if firstLongCondition then
if secondLongCondition then result1
else result2
else alternativeResult
-- @format --then-new-line --width 40
module ThenPlacementDifference where

-- This should trigger the difference with narrow width
test1 =
if
someVeryLongConditionExpressionThatWillDefinitelyWrap
then shortResult
else alternativeValue

-- This should also show the difference
test2 =
if firstLongCondition
then
if secondLongCondition
then result1
else result2
else alternativeResult
56 changes: 56 additions & 0 deletions test/snapshots/ThenPlacementNewLine.input
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
-- @format --then-new-line
module ThenPlacementNewLine where

-- Simple if-then-else
simple = if condition then result else alternative

-- Nested if-then-else
nested = if a then b else if x then y else z

-- Multi-line condition
multilineCondition =
if someVeryLongConditionThatSpansMultipleLinesAndNeedsToWrap
then shortResult
else alternativeResult

-- Multi-line then/else branches
multilineBranches =
if condition
then do
action1
action2
result
else do
alternativeAction1
alternativeAction2
alternativeResult

-- Complex nested case
complexNested =
if firstCondition
then if secondCondition
then firstResult
else if thirdCondition
then secondResult
else thirdResult
else if fourthCondition
then fourthResult
else finalResult

-- With guards
withGuards x y
| condition = if guard then guardedResult else defaultResult
| otherwise = if alternativeGuard then alternativeResult else fallback

-- In do blocks
inDoBlock = do
value <- computation
if isValid value
then pure value
else throwError "Invalid value"

-- With complex expressions
complexExpressions =
if (someFunction arg1 arg2 >>= anotherFunction)
then (complexResult >>= transform >>= validate)
else (fallbackComputation >>= handleError)
Loading