packages feed

hindent 4.4.1 → 4.4.2

raw patch · 42 files changed

+1238/−256 lines, 42 filesPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

API changes (from Hackage documentation)

+ HIndent: instance Eq CodeBlock
+ HIndent: instance Show CodeBlock
+ HIndent: styleCommentPreprocessor :: Style -> forall s' m. MonadState (PrintState s') m => [Comment] -> m [Comment]
+ HIndent.Styles.Gibiansky: breakCommentLines :: Int -> String -> [String]
+ HIndent.Styles.Gibiansky: commaAfterComment :: ComInfoLocation -> Printer State ()
+ HIndent.Styles.Gibiansky: commentContent :: Comment -> String
+ HIndent.Styles.Gibiansky: commentPreprocessor :: MonadState (PrintState s) m => [Comment] -> m [Comment]
+ HIndent.Styles.Gibiansky: commentSrcSpan :: Comment -> SrcSpan
+ HIndent.Styles.Gibiansky: dropTrailingNewlines :: String -> String
+ HIndent.Styles.Gibiansky: fixSpans :: NodeInfo -> NodeInfo
+ HIndent.Styles.Gibiansky: gibianskyLetBind :: State -> Bool
+ HIndent.Styles.Gibiansky: hasComments :: Foldable ast => ast NodeInfo -> Bool
+ HIndent.Styles.Gibiansky: lineBreakAfterRhs :: NodeInfo -> Exp NodeInfo -> Bool
+ HIndent.Styles.Gibiansky: multiIfExpr :: Exp NodeInfo -> Printer State ()
+ HIndent.Styles.Gibiansky: onSeparateLines' :: Annotated ast => (ast NodeInfo -> Printer State ()) -> [ast NodeInfo] -> Printer State ()
+ HIndent.Styles.Gibiansky: prettyColLength :: (Integral a, Pretty ast) => ast NodeInfo -> Printer State a
+ HIndent.Styles.Gibiansky: prettyCommentCallbacks :: (Pretty ast, MonadState (PrintState s) m) => ast NodeInfo -> (ComInfoLocation -> m ()) -> m ()
+ HIndent.Styles.Gibiansky: qualConDecl :: Extend QualConDecl
+ HIndent.Styles.Gibiansky: skipFollowingNewline :: Decl l -> Bool
+ HIndent.Styles.Gibiansky: stmts :: Extend Stmt
+ HIndent.Styles.Gibiansky: userGets :: (State -> a) -> Printer State a
+ HIndent.Styles.Gibiansky: userModify :: (State -> State) -> Printer State ()
+ HIndent.Styles.JohanTibell: context :: Context NodeInfo -> Printer s ()
+ HIndent.Styles.JohanTibell: typ :: Type NodeInfo -> Printer s ()
+ HIndent.Styles.JohanTibell: unboxParens :: MonadState (PrintState s) m => m a -> m a
+ HIndent.Types: psCommentPreprocessor :: PrintState s -> forall m. MonadState (PrintState s) m => [Comment] -> m [Comment]
+ HIndent.Types: styleCommentPreprocessor :: Style -> forall s' m. MonadState (PrintState s') m => [Comment] -> m [Comment]
- HIndent: Style :: !Text -> !Text -> !Text -> !s -> ![Extender s] -> !Config -> Style
+ HIndent: Style :: !Text -> !Text -> !Text -> !s -> ![Extender s] -> !Config -> (forall s' m. MonadState (PrintState s') m => [Comment] -> m [Comment]) -> Style
- HIndent.Pretty: printComment :: MonadState (PrintState s) m => Maybe SrcSpan -> ComInfo -> m ()
+ HIndent.Pretty: printComment :: MonadState (PrintState s) m => Maybe SrcSpan -> Comment -> m ()
- HIndent.Styles.Gibiansky: State :: Bool -> State
+ HIndent.Styles.Gibiansky: State :: Bool -> Bool -> State
- HIndent.Styles.Gibiansky: recUpdateExpr :: Printer State () -> [FieldUpdate NodeInfo] -> Printer State ()
+ HIndent.Styles.Gibiansky: recUpdateExpr :: Foldable f => [f NodeInfo] -> Printer State () -> [(ComInfoLocation -> Printer State ()) -> Printer State ()] -> Printer State ()
- HIndent.Types: PrintState :: !Int64 -> !Builder -> !Bool -> !Int64 -> !Int64 -> !s -> ![Extender s] -> !Config -> !Bool -> !Bool -> !ParseMode -> PrintState s
+ HIndent.Types: PrintState :: !Int64 -> !Builder -> !Bool -> !Int64 -> !Int64 -> !s -> ![Extender s] -> !Config -> !Bool -> !Bool -> !ParseMode -> (forall m. MonadState (PrintState s) m => [Comment] -> m [Comment]) -> PrintState s
- HIndent.Types: Style :: !Text -> !Text -> !Text -> !s -> ![Extender s] -> !Config -> Style
+ HIndent.Types: Style :: !Text -> !Text -> !Text -> !s -> ![Extender s] -> !Config -> (forall s' m. MonadState (PrintState s') m => [Comment] -> m [Comment]) -> Style

Files

hindent.cabal view
@@ -1,5 +1,5 @@ name:                hindent-version:             4.4.1+version:             4.4.2 synopsis:            Extensible Haskell pretty printer description:         Extensible Haskell pretty printer. Both a library and an executable.                      .
src/HIndent.hs view
@@ -37,26 +37,123 @@ import           Data.Monoid import qualified Data.Text.IO as ST import           Data.Text.Lazy (Text)-import qualified Data.Text.Lazy as T+import qualified Data.Text.Lazy as T hiding (singleton) import           Data.Text.Lazy.Builder (Builder) import qualified Data.Text.Lazy.Builder as T import qualified Data.Text.Lazy.IO as T-import           Language.Haskell.Exts.Annotated hiding (Style,prettyPrint,Pretty,style,parse)+import           Language.Haskell.Exts.Annotated hiding (Style, prettyPrint, Pretty, style, parse)+import           Data.Function (on)+import           Data.List (groupBy, intersperse)+import           Control.Applicative ((<$>)) +data CodeBlock = HaskellSource Text+               | CPPDirectives Text+  deriving (Show, Eq)+ -- | Format the given source. reformat :: Style -> Maybe [Extension] -> Text -> Either String Builder reformat style mexts x =-  case parseModuleWithComments mode'-                               (T.unpack x) of-    ParseOk (m,comments) ->-      prettyPrint mode' style m comments-    ParseFailed _ e -> Left e-  where mode' =-          (case mexts of-             Just exts ->-               parseMode {extensions = exts}-             Nothing -> parseMode)+  mconcat . intersperse "\n" <$> mapM processBlock (cppSplitBlocks x)+  where+    processBlock :: CodeBlock -> Either String Builder+    processBlock (CPPDirectives text) = Right $ T.fromLazyText text+    processBlock (HaskellSource text) =+      let lines = lines' text+          prefix = findPrefix lines+          code = T.unpack $ unlines' $ map (stripPrefix prefix) lines+      in case parseModuleWithComments mode' code of+        ParseOk (m, comments) ->+          T.fromLazyText <$> addPrefix prefix <$> T.toLazyText <$> prettyPrint mode' style m comments+        ParseFailed _ e -> Left e +    lines' = T.split (== '\n')+    unlines' = mconcat . intersperse "\n"++    addPrefix :: Text -> Text -> Text+    addPrefix prefix = unlines' . map (prefix <>) . lines'++    stripPrefix :: Text -> Text -> Text+    stripPrefix prefix line =+      if T.null (T.dropWhile (== '\n') line)+      then line+      else fromMaybe (error "Missing expected prefix") . T.stripPrefix prefix $ line++    findPrefix :: [Text] -> Text+    findPrefix = takePrefix False . findSmallestPrefix . dropNewlines++    dropNewlines :: [Text] -> [Text]+    dropNewlines = filter (not . T.null . T.dropWhile (== '\n'))++    takePrefix :: Bool -> Text -> Text+    takePrefix bracketUsed txt =+      case T.uncons txt of+        Nothing -> ""+        Just ('>', txt') -> if not bracketUsed+                              then T.cons '>' (takePrefix True txt')+                              else ""+        Just (c, txt') -> if c == ' ' || c == '\t'+                            then T.cons c (takePrefix bracketUsed txt')+                            else ""+++    findSmallestPrefix :: [Text] -> Text+    findSmallestPrefix [] = ""+    findSmallestPrefix ("":_) = ""+    findSmallestPrefix (p:ps) = +      let first = T.head p+          startsWithChar c x  = T.length x > 0 && T.head x == c+      in if all (startsWithChar first) ps+           then T.cons first (findSmallestPrefix (T.tail p : map T.tail ps))+           else ""++    mode' =+      case mexts of+        Just exts -> parseMode { extensions = exts }+        Nothing   -> parseMode++-- | Break a Haskell code string into chunks, using CPP as a delimiter.+-- Lines that start with '#if', '#end', or '#else' are their own chunks, and+-- also act as chunk separators. For example, the code+--+-- > #ifdef X+-- > x = X+-- > y = Y+-- > #else+-- > x = Y+-- > y = X+-- > #endif+--+-- will become five blocks, one for each CPP line and one for each pair of declarations.+cppSplitBlocks :: Text -> [CodeBlock]+cppSplitBlocks inp =+  modifyLast (inBlock (`T.append` trailing)) .+  map (classify . mconcat . intersperse "\n") .+  groupBy ((==) `on` cppLine) .+  T.lines $ inp+  where+    cppLine :: Text -> Bool+    cppLine src = any (`T.isPrefixOf` src) ["#if", "#end", "#else", "#define", "#undef"]++    classify :: Text -> CodeBlock+    classify text = if cppLine text+                    then CPPDirectives text+                    else HaskellSource text++    -- Hack to work around some parser issues in haskell-src-exts: Some pragmas+    -- need to have a newline following them in order to parse properly, so we include+    -- the trailing newline in the code block if it existed.+    trailing :: Text+    trailing = if T.isSuffixOf "\n" inp then "\n" else ""++    modifyLast :: (a -> a) -> [a] -> [a]+    modifyLast _ []  = []+    modifyLast f [x] = [f x]+    modifyLast f (x:xs) = x : modifyLast f xs++    inBlock :: (Text -> Text) -> CodeBlock -> CodeBlock+    inBlock f (HaskellSource txt) = HaskellSource (f txt)+    inBlock _ dir = dir+ -- | Print the module. prettyPrint :: ParseMode             -> Style@@ -65,27 +162,29 @@             -> Either a Builder prettyPrint mode' style m comments =   let (cs,ast) =-        annotateComments (fromMaybe m (applyFixities baseFixities m))-                         comments-  in Right (runPrinterStyle-              mode'-              style-              -- For the time being, assume that all "free-floating" comments come at the beginning.-              -- If they were not at the beginning, they would be after some ast node.-              -- Thus, print them before going for the ast.-              (do mapM_ (printComment Nothing)-                        (reverse cs)-                  pretty ast))+        annotateComments (fromMaybe m $ applyFixities baseFixities m) comments+      csComments = map comInfoComment cs+  in case style of+      style@(Style { styleCommentPreprocessor = preprocessor }) ->+        Right (runPrinterStyle+                  mode'+                  style+                  -- For the time being, assume that all "free-floating" comments come at the beginning.+                  -- If they were not at the beginning, they would be after some ast node.+                  -- Thus, print them before going for the ast.+                  (do comments <- preprocessor (reverse csComments)+                      mapM_ (printComment Nothing) comments+                      pretty ast))  -- | Pretty print the given printable thing. runPrinterStyle :: ParseMode -> Style -> (forall s. Printer s ()) -> Builder-runPrinterStyle mode' (Style _name _author _desc st extenders config) m =+runPrinterStyle mode' (Style _name _author _desc st extenders config preprocessor) m =   maybe (error "Printer failed with mzero call.")         psOutput         (runIdentity            (runMaybeT (execStateT                          (runPrinter m)-                         (PrintState 0 mempty False 0 1 st extenders config False False mode'))))+                         (PrintState 0 mempty False 0 1 st extenders config False False mode' preprocessor))))  -- | Parse mode, includes all extensions, doesn't assume any fixities. parseMode :: ParseMode
src/HIndent/Pretty.hs view
@@ -100,12 +100,12 @@            depend              (case listToMaybe (mapMaybe (makePrinter s) es) of                 Just (Printer m) ->-                  modify (\s ->-                            fromMaybe s-                                      (runIdentity (runMaybeT (execStateT m s))))+                  modify (\s' ->+                            fromMaybe s'+                                      (runIdentity (runMaybeT (execStateT m s'))))                 Nothing -> prettyNoExt a)              (printComments After a)-  where makePrinter s (Extender f) =+  where makePrinter _ (Extender f) =           case cast a of             Just v -> Just (f v)             Nothing -> Nothing@@ -121,29 +121,35 @@ -- | Print comments of a node. printComments :: (Pretty ast,MonadState (PrintState s) m)               => ComInfoLocation -> ast NodeInfo -> m ()-printComments loc' ast =-  forM_ comments $ \comment ->-    when (comInfoLocation comment == Just loc') $ do-      -- Preceeding comments must have a newline before them.-      hasNewline <- gets psNewline-      when (not hasNewline && loc' == Before) newline+printComments loc' ast = do+  preprocessor <- gets psCommentPreprocessor -      printComment (Just $ srcInfoSpan $ nodeInfoSpan info) comment+  let correctLocation comment = comInfoLocation comment == Just loc'+      commentsWithLocation = filter correctLocation (nodeInfoComments info)+  comments <- preprocessor $ map comInfoComment commentsWithLocation++  forM_ comments $ \comment -> do+    -- Preceeding comments must have a newline before them.+    hasNewline <- gets psNewline+    when (not hasNewline && loc' == Before) newline++    printComment (Just $ srcInfoSpan $ nodeInfoSpan info) comment   where info = ann ast-        comments = nodeInfoComments info+   -- | Pretty print a comment.-printComment :: MonadState (PrintState s) m => Maybe SrcSpan -> ComInfo -> m ()-printComment mayNodespan (ComInfo (Comment inline cspan str) _) =+printComment :: MonadState (PrintState s) m => Maybe SrcSpan -> Comment -> m ()+printComment mayNodespan (Comment inline cspan str) =   do -- Insert proper amount of space before comment.      -- This maintains alignment. This cannot force comments      -- to go before the left-most possible indent (specified by depends).      case mayNodespan of        Just nodespan ->          do let neededSpaces = srcSpanStartColumn cspan --                               srcSpanEndColumn nodespan+                               max 1 (srcSpanEndColumn nodespan)             replicateM_ neededSpaces space        Nothing -> return ()+      if inline         then do write "{-"                 string str@@ -857,43 +863,16 @@                     (depend (write "=")                             (prefixedLined "|"                                            (map (depend space . pretty) xs)))-decl GDataDecl{} =-  error "FIXME: No implementation for GDataDecl."-decl DataFamDecl{} =-  error "FIXME: No implementation for DataFamDecl."-decl TypeInsDecl{} =-  error "FIXME: No implementation for TypeInsDecl."-decl DataInsDecl{} =-  error "FIXME: No implementation for DataInsDecl."-decl GDataInsDecl{} =-  error "FIXME: No implementation for GDataInsDecl."-decl DerivDecl{} =-  error "FIXME: No implementation for DerivDecl."-decl ForImp{} =-  error "FIXME: No implementation for ForImp."-decl ForExp{} =-  error "FIXME: No implementation for ForExp."-decl RulePragmaDecl{} =-  error "FIXME: No implementation for RulePragmaDecl."-decl DeprPragmaDecl{} =-  error "FIXME: No implementation for DeprPragmaDecl."-decl InlineSig{} =-  error "FIXME: No implementation for InlineSig."-decl InlineConlikeSig{} =-  error "FIXME: No implementation for InlineConlikeSig."-decl SpecSig{} =-  error "FIXME: No implementation for SpecSig."-decl SpecInlineSig{} =-  error "FIXME: No implementation for SpecInlineSig."-decl InstSig{} =-  error "FIXME: No implementation for InstSig."-decl ClosedTypeFamDecl{} =-  error "FIXME: No implementation for ClosedTypeFamDecl."-decl x@WarnPragmaDecl{} = pretty' x-decl x@MinimalPragma{} = pretty' x-decl x@AnnPragma{} = pretty' x-decl x@InfixDecl{} = pretty' x-decl x@DefaultDecl{} = pretty' x++decl (InlineSig _ inline _ name) = do+  write "{-# "++  unless inline $ write "NO"+  write "INLINE "+  pretty name++  write " #-}"+decl x = pretty' x  instance Pretty Deriving where   prettyInternal (Deriving _ heads) =
src/HIndent/Styles/ChrisDone.hs view
@@ -53,7 +53,8 @@            ,Extender decl]         ,styleDefConfig =            defaultConfig {configMaxColumns = 80-                         ,configIndentSpaces = 2}}+                         ,configIndentSpaces = 2}+        ,styleCommentPreprocessor = return}  -------------------------------------------------------------------------------- -- Extenders
src/HIndent/Styles/Fundamental.hs view
@@ -21,4 +21,5 @@         ,styleDescription = "This style adds no extensions to the built-in printer."         ,styleInitialState = State         ,styleExtenders = []-        ,styleDefConfig = def}+        ,styleDefConfig = def+        ,styleCommentPreprocessor = return}
src/HIndent/Styles/Gibiansky.hs view
@@ -5,27 +5,37 @@  import           Data.Foldable import           Control.Applicative ((<$>))-import           Control.Monad (unless, when, replicateM_)-import           Control.Monad.State (gets, get, put)-import           Data.Maybe (isNothing)+import           Data.Maybe+import           Data.List (unfoldr, isPrefixOf)+import           Control.Monad.Trans.Maybe+import           Data.Functor.Identity+import           Control.Monad.State.Strict hiding (state, State, forM_)+import           Data.Typeable  import           HIndent.Pretty import           HIndent.Types  import           Language.Haskell.Exts.Annotated.Syntax import           Language.Haskell.Exts.SrcLoc+import           Language.Haskell.Exts.Pretty (prettyPrint) import           Language.Haskell.Exts.Comments-import           Prelude hiding (exp, all, mapM_, minimum, and, maximum)+import           Prelude hiding (exp, all, mapM_, minimum, and, maximum, concatMap, or, any)  -- | Empty state.-data State = State { gibianskyForceSingleLine :: Bool }+data State = State { gibianskyForceSingleLine :: Bool, gibianskyLetBind :: Bool } +userGets :: (State -> a) -> Printer State a+userGets f = gets (f . psUserState)++userModify :: (State -> State) -> Printer State ()+userModify f = modify (\s -> s { psUserState = f (psUserState s) })+ -- | The printer style. gibiansky :: Style gibiansky = Style { styleName = "gibiansky"                   , styleAuthor = "Andrew Gibiansky"                   , styleDescription = "Andrew Gibiansky's style"-                  , styleInitialState = State { gibianskyForceSingleLine = False }+                  , styleInitialState = State { gibianskyForceSingleLine = False, gibianskyLetBind = False }                   , styleExtenders = [ Extender imp                                      , Extender modl                                      , Extender context@@ -35,6 +45,7 @@                                      , Extender rhss                                      , Extender guardedRhs                                      , Extender decls+                                     , Extender stmts                                      , Extender condecls                                      , Extender alt                                      , Extender moduleHead@@ -42,20 +53,142 @@                                      , Extender fieldUpdate                                      , Extender pragmas                                      , Extender pat+                                     , Extender qualConDecl                                      ]                   , styleDefConfig = defaultConfig { configMaxColumns = 100                                                    , configIndentSpaces = indentSpaces                                                    , configClearEmptyLines = True                                                    }+                  , styleCommentPreprocessor = commentPreprocessor                   } +-- Field accessor for Comment.+commentContent :: Comment -> String+commentContent (Comment _ _ content) = content++-- Field accessor for Comment.+commentSrcSpan :: Comment -> SrcSpan+commentSrcSpan (Comment _ srcSpan _) = srcSpan++commentPreprocessor :: MonadState (PrintState s) m => [Comment] -> m [Comment]+commentPreprocessor cs = do+  config <- gets psConfig+  col <- getColumn+  return $ go (fromIntegral col) config cs+  +  where+   go currentColumn config = concatMap mergeGroup . groupComments Nothing []+    where+      -- Group comments into blocks.+      -- A comment block is the list of comments that are on consecutive lines,+      -- and do not have an empty comment in between them. Empty comments are those with only whitespace.+      -- Empty comments are in their own group.+      groupComments :: Maybe Int -> [Comment] -> [Comment] -> [[Comment]]+      groupComments nextLine accum (comment@(Comment multiline srcSpan str):comments)+        | separateCommentCondition = useAsSeparateCommentGroup+        | beginningOfUnprocessed str =+            let (unprocessedLines, postUnprocessed) = span unprocessed comments+                (endingLine, remLines) = case postUnprocessed of+                    x:xs -> ([x], xs)+                    [] -> ([], [])+                separateCommentGroups = comment : unprocessedLines ++ endingLine+            in currentGroupAsList ++ map (: []) separateCommentGroups ++ groupComments Nothing [] remLines+        | isNothing nextLine || Just (srcSpanStartLine srcSpan) == nextLine = groupComments nextLine' (comment:accum) comments+        | otherwise = currentGroupAsList ++ groupComments (Just $ srcSpanStartLine srcSpan + 1) [comment] comments+        where+          separateCommentCondition = or [multiline, isWhitespace str, "  " `isPrefixOf` str, " >" `isPrefixOf` str]+          useAsSeparateCommentGroup = currentGroupAsList ++ [comment] : groupComments nextLine' [] comments+          nextCommentStartLine = srcSpanStartLine $ commentSrcSpan $ head comments+          currentGroupAsList | null accum = []+                            | otherwise = [reverse accum]+          nextLine' = +            case nextLine of+              Just x -> Just (x + 1)+              Nothing -> Just nextCommentStartLine+      groupComments _ [] [] = []+      groupComments _ accum [] = [reverse accum]++      beginningOfUnprocessed :: String -> Bool+      beginningOfUnprocessed str = any (`isPrefixOf` str) ["@", " @", "  @"]++      unprocessed :: Comment -> Bool+      unprocessed (Comment True _ _) = False+      unprocessed (Comment _ _ str) = not $ beginningOfUnprocessed str++      isWhitespace :: String -> Bool+      isWhitespace = all (\x -> x == ' ' || x == '\t')++      commentLen :: Int+      commentLen = length ("--" :: String)++      -- Merge a group of comments into one comment.+      mergeGroup :: [Comment] -> [Comment]+      mergeGroup [] = error "Empty comment group"+      mergeGroup comments@[Comment True _ _] = comments+      mergeGroup comments = +        let +            firstSrcSpan = commentSrcSpan $ head comments+            firstLine = srcSpanStartLine firstSrcSpan+            firstCol = srcSpanStartColumn firstSrcSpan++            columnDelta = firstCol - currentColumn+            maxStartColumn = maximum (map (srcSpanStartColumn . commentSrcSpan) comments)++            lineLen = fromIntegral (configMaxColumns config) - maxStartColumn - commentLen + columnDelta+            content = breakCommentLines lineLen $ unlines (map commentContent comments)+            srcSpanLines = map (firstLine +) [0 .. length content - 1]+            srcSpans = map (\linum -> firstSrcSpan { srcSpanStartLine = linum, srcSpanEndLine = linum, srcSpanStartColumn = maxStartColumn }) srcSpanLines+        in zipWith (Comment False) srcSpans content+++-- | Break a comment string into lines of a maximum character length.+-- Each line starts with a space, mirroring the traditional way of writing comments:+--+--   -- Hello+--   -- Note the space after the '-'+breakCommentLines :: Int -> String -> [String]+breakCommentLines maxLen str+  -- If there's no way to do this formatting, just give up+  | any ((maxLen <) . length) (words str) = [str]++  -- If we already have a line of the appropriate length, leave it alone. This allows us to format+  -- stuff ourselves in some cases.+  | length (lines str) == 1 && length str <= maxLen = [dropTrailingNewlines str]++  | otherwise = unfoldr unfolder (words str)+  where+    -- Generate successive lines, consuming the words iteratively.+    unfolder :: [String] -> Maybe (String, [String])+    unfolder [] = Nothing+    unfolder ws = Just $ go maxLen [] ws+      where+        go :: Int                -- Characters remaining on the line to be used+           -> [String]           -- Accumulator: The words used so far on this line+           -> [String]           -- Unused words+           -> (String, [String]) -- (Generated line, remaining words)+        go remainingLen taken remainingWords =+          case remainingWords of+            -- If no more words remain, we're done+            [] -> (generatedLine, [])+            word:remWords ->+              -- If the next word doesn't fit on this line, line break+              let nextRemaining = remainingLen - length word - 1+              in if nextRemaining < 0+                   then (generatedLine, remainingWords)+                   else go nextRemaining (word : taken) remWords+          where+            generatedLine = ' ' : unwords (reverse taken)++dropTrailingNewlines :: String -> String+dropTrailingNewlines = reverse . dropWhile (== '\n') . reverse+ -- | Number of spaces to indent by. indentSpaces :: Integral a => a indentSpaces = 2  -- | Printer to indent one level. indentOnce :: Printer s ()-indentOnce = replicateM_ indentSpaces $ write " "+indentOnce = replicateM_ indentSpaces space  -- | How many exports to format in a single line. -- If an export list has more than this, it will be formatted as multiple lines.@@ -100,21 +233,42 @@    onSeparateLines imps   unless (null imps || null decls) (newline >> newline)-  onSeparateLines decls++  unless (null decls) $ do+    forM_ (init decls) $ \decl -> do+      pretty decl+      newline+      unless (skipFollowingNewline decl) newline+    pretty (last decls) modl m = prettyNoExt m +skipFollowingNewline :: Decl l -> Bool+skipFollowingNewline TypeSig{} = True+skipFollowingNewline InlineSig{} = True+skipFollowingNewline AnnPragma{} = True+skipFollowingNewline MinimalPragma{} = True+skipFollowingNewline _ = False+ -- | Format pragmas differently (language pragmas). pragmas :: Extend ModulePragma pragmas (LanguagePragma _ names) = do   write "{-# LANGUAGE "   inter (write ", ") $ map pretty names   write " #-}"+pragmas (OptionsPragma _ mtool opt) = do+  write "{-# OPTIONS"+  forM_ mtool $ \tool -> do+    write "_"+    string $ prettyPrint tool+  string opt+  write "#-}" pragmas p = prettyNoExt p  -- | Format patterns. pat :: Extend Pat pat (PTuple _ boxed pats) = writeTuple boxed pats pat (PList _ pats) = singleLineList pats+pat (PRec _ name fields) = recUpdateExpr fields (pretty name) (map prettyCommentCallbacks fields) pat p = prettyNoExt p  -- | Format import statements.@@ -130,10 +284,36 @@     write " as "     pretty name -  forM_ importSpecs $ \speclist -> do-    write " "-    pretty speclist+  forM_ importSpecs $ \(ImportSpecList _ importHiding specs) -> do+    space+    when importHiding $ write "hiding "+    depend (write "(") $ do+      case specs of+        [] -> return ()+        x:xs -> do+          pretty x+          forM_ xs $ \spec -> do+            write ","+            col <- getColumn+            len <- prettyColLength spec+            maxColumns <- configMaxColumns <$> gets psConfig+            if col + len > maxColumns +              then newline+              else space +            pretty spec+      write ")"++-- | Return the number of columns between the start and end of a printer.+-- Note that if it breaks lines, the line break is not counted; only column is used.+-- So you probably only want to use this for single-line printers.+prettyColLength :: (Integral a, Pretty ast) => ast NodeInfo -> Printer State a+prettyColLength x = fst <$> sandbox (do+  col <- getColumn+  pretty x+  col' <- getColumn+  return $ fromIntegral $ max (col' - col) 0)+ -- | Format contexts with spaces and commas between class constraints. context :: Extend Context context (CxTuple _ asserts) =@@ -222,16 +402,29 @@ exprs exp@Case{} = caseExpr exp exprs exp@LCase{} = lambdaCaseExpr exp exprs exp@If{} = ifExpr exp-exprs (RecUpdate _ exp updates) = recUpdateExpr (pretty exp) updates-exprs (RecConstr _ qname updates) = recUpdateExpr (pretty qname) updates+exprs exp@MultiIf{} = multiIfExpr exp+exprs (RecUpdate _ exp updates) = recUpdateExpr updates (pretty exp) (map prettyCommentCallbacks updates)+exprs (RecConstr _ qname updates) = recUpdateExpr updates (pretty qname) (map prettyCommentCallbacks updates) exprs (Tuple _ _ exps) = parens $ inter (write ", ") $ map pretty exps exprs exp = prettyNoExt exp +multiIfExpr :: Exp NodeInfo -> Printer State ()+multiIfExpr (MultiIf _ alts) =+  withCaseContext True $+    depend (write "if ") $+      onSeparateLines' (depend (write "|") . pretty) alts+multiIfExpr _ = error "Not a multi if"+ letExpr :: Exp NodeInfo -> Printer State () letExpr (Let _ binds result) = do   cols <- depend (write "let ") $ do             col <- getColumn++            oldLetBind <- userGets gibianskyLetBind+            userModify (\s -> s { gibianskyLetBind = True })             writeWhereBinds binds+            userModify (\s -> s { gibianskyLetBind = oldLetBind })+             return $ col - 4   column cols $ do     newline@@ -241,6 +434,8 @@  keepingColumn :: Printer State () -> Printer State () keepingColumn printer = do+  eol <- gets psEolComment+  when eol newline   col <- getColumn   ind <- gets psIndentLevel   column (max col ind) printer@@ -304,7 +499,7 @@ doExpr (Do _ stmts) = do   write "do"   newline-  indented 2 $ onSeparateLines stmts+  indented indentSpaces $ onSeparateLines stmts doExpr _ = error "Not a do"  listExpr :: Exp NodeInfo -> Printer State ()@@ -332,14 +527,16 @@ dollarExpr :: Exp NodeInfo -> Printer State () dollarExpr (InfixApp _ left op right) = do   pretty left-  write " "+  space   pretty op   if needsNewline right     then do       newline-      depend indentOnce $ pretty right+      col <- getColumn+      ind <- gets psIndentLevel+      column (max col ind + indentSpaces) $ pretty right     else do-      write " "+      space       pretty right    where@@ -366,7 +563,7 @@     multiLine :: Exp NodeInfo -> Exp NodeInfo -> [Exp NodeInfo] -> Printer State ()     multiLine first second rest = do       pretty first-      depend (write " ") $ do+      depend space $ do         write "<$> "         pretty second         forM_ rest $ \val -> do@@ -419,10 +616,15 @@   write "\\"   spaced $ map pretty pats   write " ->"-  attemptSingleLine (write " " >> pretty exp) $ do-    newline-    indentOnce-    pretty exp+  if any isBefore $ nodeInfoComments $ ann exp+    then multi+    else attemptSingleLine (space >> pretty exp) multi+      +  where multi = do+         newline+         indented indentSpaces $ pretty exp++        isBefore com = comInfoLocation com == Just Before lambdaExpr _ = error "Not a lambda"  caseExpr :: Exp NodeInfo -> Printer State ()@@ -445,7 +647,7 @@ ifExpr :: Exp NodeInfo -> Printer State () ifExpr (If _ cond thenExpr elseExpr) =   depend (write "if") $ do-    write " "+    space     pretty cond     newline     write "then "@@ -470,10 +672,12 @@       first:rest -> do         printComments Before first         prettyPr first+        printComments After first         forM_ (zip alts rest) $ \(prev, cur) -> do           replicateM_ (max 1 $ lineDelta cur prev) newline           printComments Before cur           prettyPr cur+          printComments After cur    where     isSingle :: Alt NodeInfo -> Printer State Bool@@ -482,11 +686,18 @@                                  line <- gets psLine                                  pretty alt'                                  line' <- gets psLine-                                 return $ line == line')+                                 return $ not (isGuarded (altRhs alt')) && line == line')      altPattern :: Alt l -> Pat l     altPattern (Alt _ p _ _) = p +    altRhs :: Alt l -> Rhs l+    altRhs (Alt _ _ r _) = r++    isGuarded :: Rhs l -> Bool+    isGuarded GuardedRhss{} = True+    isGuarded UnGuardedRhs{} = False+     patternLen :: Pat NodeInfo -> Printer State Int     patternLen pat = fromIntegral <$> fst <$> sandbox                                                 (do@@ -508,51 +719,111 @@        case galts of         UnGuardedRhs{} -> pretty galts-        GuardedRhss{}  -> indented indentSpaces $ pretty galts+        GuardedRhss{}  -> do+          newline+          indented indentSpaces $ pretty galts        --  Optional where clause!       forM_ mbinds $ \binds -> do         newline         indented indentSpaces $ depend (write "where ") (pretty binds) +prettyCommentCallbacks :: (Pretty ast,MonadState (PrintState s) m) => ast NodeInfo -> (ComInfoLocation -> m ()) -> m ()+prettyCommentCallbacks a f =+  do st <- get+     case st of+       PrintState{psExtenders = es,psUserState = s} ->+         do+           printComments Before a+           f Before+           depend+             (case listToMaybe (mapMaybe (makePrinter s) es) of+                Just (Printer m) ->+                  modify (\s' ->+                            fromMaybe s'+                                      (runIdentity (runMaybeT (execStateT m s'))))+                Nothing -> prettyNoExt a)+             (f After >> printComments After a)+  where makePrinter _ (Extender f) =+          case cast a of+            Just v -> Just (f v)+            Nothing -> Nothing+        makePrinter s (CatchAll f) = f s a -recUpdateExpr :: Printer State () -> [FieldUpdate NodeInfo] -> Printer State ()-recUpdateExpr expWriter updates = do-  expWriter-  write " "-  if null updates-    then write "{}"-    else attemptSingleLine single mult +recUpdateExpr :: Foldable f => [f NodeInfo] -> Printer State () -> [(ComInfoLocation -> Printer State ()) -> Printer State ()] -> Printer State ()+recUpdateExpr ast expWriter updates+  | null updates = do+      expWriter+      write "{}"+  | any hasComments ast = mult+  | otherwise = attemptSingleLine single mult+   where     single = do-      write "{ "-      inter (write ", ") $ map pretty updates+      expWriter+      write " { "+      inter (write ", ") updates'       write " }"     mult = do-      col <- getColumn-      column col $ do+      expWriter+      newline+      indented indentSpaces $ keepingColumn $ do         write "{ "-        pretty (head updates)+        head updates'         forM_ (tail updates) $ \update -> do           newline-          write ", "-          pretty update+          update commaAfterComment         newline         write "}" +    updates' = map ($ const $ return ()) updates++commaAfterComment :: ComInfoLocation -> Printer State ()+commaAfterComment loc = case loc of+  Before -> write ", "+  After -> return ()+ rhss :: Extend Rhs rhss (UnGuardedRhs rhsLoc exp) = do-  write " "-  rhsSeparator-  if onNextLine exp-    then indented indentSpaces $ do-      newline-      pretty exp-    else do-      space-      pretty exp+  letBind <- userGets gibianskyLetBind+  let exp'+        | lineBreakAfterRhs rhsLoc exp =+            indented indentSpaces $ do+              newline+              pretty exp+        | letBind =+            depend space (pretty exp)+        | otherwise = space >> pretty exp+  if letBind+    then depend (space >> rhsSeparator) exp'+    else space >> rhsSeparator >> exp'+rhss (GuardedRhss _ rs) =+  flip onSeparateLines' rs $ \a@(GuardedRhs rhsLoc stmts exp) -> do+    let manyStmts = length stmts > 1+        remainder = do+          if manyStmts then newline else space+          rhsSeparator+          if not manyStmts && lineBreakAfterRhs rhsLoc exp+            then newline >> indented indentSpaces (pretty exp)+            else space >> pretty exp+        writeStmts = +          case stmts of+            x:xs -> do+              pretty x+              forM_ xs $ \x -> write "," >> newline >> pretty x+            [] -> return () +    printComments Before a+    if manyStmts+      then do +        depend (write "| ") writeStmts+        remainder+      else+        depend (write "| ") $ writeStmts >> remainder++lineBreakAfterRhs :: NodeInfo -> Exp NodeInfo -> Bool+lineBreakAfterRhs rhsLoc exp = onNextLine exp   where     -- Cannot use lineDelta because we need to look at rhs start line, not end line     prevLine = srcSpanStartLine . srcInfoSpan . nodeInfoSpan $ rhsLoc@@ -562,64 +833,95 @@     onNextLine Let{} = True     onNextLine Case{} = True     onNextLine _ = emptyLines > 0-rhss (GuardedRhss _ rs) =-  lined $ flip map rs $ \a@(GuardedRhs _ stmts exp) -> do-    printComments Before a-    depend (write "| ") $ do-      inter (write ", ") $ map pretty stmts-      rhsRest exp  guardedRhs :: Extend GuardedRhs guardedRhs (GuardedRhs _ stmts exp) = do   indented 1 $ prefixedLined "," (map (\p -> space >> pretty p) stmts)+  space   rhsRest exp  rhsRest :: Pretty ast => ast NodeInfo -> Printer State () rhsRest exp = do-  write " "   rhsSeparator-  write " "+  space   pretty exp +stmts :: Extend Stmt+stmts (LetStmt _ binds) = depend (write "let ") (writeWhereBinds binds)+stmts stmt = prettyNoExt stmt+ decls :: Extend Decl decls (DataDecl _ dataOrNew Nothing declHead constructors mayDeriving) = do-  pretty dataOrNew-  write " "-  pretty declHead-  case constructors of-    [] -> return ()-    [x] -> do-      write " = "-      pretty x-    (x:xs) ->-      depend (write " ") $ do-        write "= "+  depend (pretty dataOrNew >> space) $ do+    pretty declHead+    case constructors of+      [] -> return ()+      [x] -> do+        write " ="         pretty x-        forM_ xs $ \constructor -> do-          newline-          write "| "-          pretty constructor+      (x:xs) ->+        depend space $ do+          write "="+          pretty x+          forM_ xs $ \constructor -> do+            newline+            write "|"+            pretty constructor    forM_ mayDeriving $ \deriv -> do     newline     indented indentSpaces $ pretty deriv decls (PatBind _ pat rhs mbinds) = funBody [pat] rhs mbinds decls (FunBind _ matches) =-  lined $ flip map matches $ \match -> do-    (name, pat, rhs, mbinds) <- case match of-                                  Match _ name pat rhs mbinds -> return (name, pat, rhs, mbinds)+  flip onSeparateLines' matches $ \match -> do+    printComments Before match+    (writeName, pat, rhs, mbinds) <- case match of+                                  Match _ name pat rhs mbinds -> return (pretty name, pat, rhs, mbinds)                                   InfixMatch _ left name pat rhs mbinds -> do                                     pretty left-                                    write " "-                                    return (name, pat, rhs, mbinds)--    case name of-      Symbol _ name' -> string name'-      name' -> pretty name'-    write " "+                                    space+                                    let writeName = case name of+                                          Symbol _ name' -> string name'+                                          Ident _ name' -> do+                                            write "`"+                                            string name'+                                            write "`"+                                    return (writeName, pat, rhs, mbinds)+    writeName+    space     funBody pat rhs mbinds+decls (ClassDecl _ ctx dhead fundeps mayDecls) = do+  let decls = fromMaybe [] mayDecls+      noDecls = null decls++  -- Header+  depend (write "class ") $+    depend (maybeCtx ctx) $+      depend (pretty dhead >> space) $+        depend (unless (null fundeps) (write " | " >> commas (map pretty fundeps))) $+          unless noDecls (write "where")++  -- Class method declarations+  unless noDecls $ do+    newline+    indentSpaces <- getIndentSpaces+    indented indentSpaces (onSeparateLines decls) decls decl = prettyNoExt decl +qualConDecl :: Extend QualConDecl+qualConDecl (QualConDecl _ tyvars ctx d) =+  depend (unless (null (fromMaybe [] tyvars))+                  (do write " forall "+                      spaced (map pretty (fromMaybe [] tyvars))+                      write ". "))+          (depend (maybeCtx' ctx)+                  (pretty d))+  where+    maybeCtx' = maybe (return ())+                      (\p ->+                        pretty p >>+                        write " =>")+ funBody :: [Pat NodeInfo] -> Rhs NodeInfo -> Maybe (Binds NodeInfo) -> Printer State () funBody pat rhs mbinds = do   spaced $ map pretty pat@@ -649,13 +951,43 @@  -- Print all the ASTs on separate lines, respecting user spacing. onSeparateLines :: (Pretty ast, Annotated ast) => [ast NodeInfo] -> Printer State ()-onSeparateLines vals@(first:rest) = do-  pretty first-  forM_ (zip vals rest) $ \(prev, cur) -> do+onSeparateLines = onSeparateLines' pretty++onSeparateLines' :: Annotated ast => (ast NodeInfo -> Printer State ()) -> [ast NodeInfo] -> Printer State ()+onSeparateLines' _ [] = return ()+onSeparateLines' pretty' vals = do+  let vals' = map (amap fixSpans) vals+      (first:rest) = vals'++  +  pretty' first+  forM_ (zip vals' rest) $ \(prev, cur) -> do     replicateM_ (max 1 $ lineDelta cur prev) newline-    pretty cur-onSeparateLines [] = return ()+    pretty' cur +fixSpans :: NodeInfo -> NodeInfo+fixSpans info =+  let infoSpan = nodeInfoSpan info+      srcSpan = srcInfoSpan infoSpan++      points = srcInfoPoints infoSpan+      lastPt = last points++      prevLastPt = last (init points)+      prevPtEnd = (srcSpanEndLine prevLastPt, srcSpanEndColumn prevLastPt)++      lastPtEndLoc = (srcSpanEndLine lastPt, srcSpanEndColumn lastPt)+      invalidLastPt = srcSpanStartLine lastPt == srcSpanEndLine lastPt &&+                      srcSpanStartColumn lastPt > srcSpanEndColumn lastPt++      infoEndLoc = (srcSpanEndLine srcSpan, srcSpanEndColumn srcSpan)+  in if length points > 1 && lastPtEndLoc == infoEndLoc && invalidLastPt+       then info { nodeInfoSpan = infoSpan { srcInfoSpan = setEnd srcSpan prevPtEnd } }+       else info+  where+    setEnd (SrcSpan fname startL startC _ _) (endL, endC) = SrcSpan fname startL startC endL endC++ astStartLine :: Annotated ast => ast NodeInfo -> Int astStartLine decl =   let info = ann decl@@ -672,27 +1004,44 @@  condecls :: Extend ConDecl condecls (ConDecl _ name bangty) =-  depend (pretty name) $+  depend (space >> pretty name) $     forM_ bangty $ \ty -> space >> pretty ty-condecls (RecDecl _ name fields) =-  depend (pretty name >> space) $ do-    write "{ "-    case fields of-      [] -> return ()-      [x] -> do-        pretty x-        eol <- gets psEolComment-        unless eol space-      first:rest -> do-        pretty first+condecls decl@(RecDecl _ name fields) = if hasComments decl+                                        then multiRec+                                        else attemptSingleLine singleRec multiRec+  where+    singleRec = space >> depend (pretty name >> space) recBody+    multiRec = do+      newline+      indented indentSpaces $ keepingColumn $ do+        pretty name         newline+        indented indentSpaces recBody++    recBody = do+      write "{ "+      writeFields fields+      write "}"++    writeFields [] = return ()+    writeFields [x] = do+      pretty x+      eol <- gets psEolComment+      unless eol space+    writeFields (first:rest) = do+        singleLine <- gets (gibianskyForceSingleLine . psUserState)++        pretty first+        unless singleLine newline         forM_ rest $ \field -> do-          comma-          space-          pretty field-          newline-    write "}"+          prettyCommentCallbacks field commaAfterComment+          unless singleLine newline++        when singleLine space condecls other = prettyNoExt other++hasComments :: Foldable ast => ast NodeInfo -> Bool+hasComments = any (not . null . nodeInfoComments)  alt :: Extend Alt alt (Alt _ p rhs mbinds) = do
src/HIndent/Styles/JohanTibell.hs view
@@ -44,6 +44,8 @@         ,styleInitialState = State         ,styleExtenders =            [Extender decl+           ,Extender context+           ,Extender typ            ,Extender conDecl            ,Extender exp            ,Extender guardedRhs@@ -53,7 +55,8 @@            ]         ,styleDefConfig =            defaultConfig {configMaxColumns = 80-                         ,configIndentSpaces = 4}}+                         ,configIndentSpaces = 4}+        ,styleCommentPreprocessor = return}  -------------------------------------------------------------------------------- -- Extenders@@ -221,11 +224,29 @@ exp (RecConstr _ qname updates) = recUpdateExpr (pretty qname) updates exp e = prettyNoExt e +-- | Format contexts with spaces and commas between class constraints.+context :: Context NodeInfo -> Printer s ()+context (CxTuple _ asserts) =+  parens $ inter (comma >> space) $ map pretty asserts+context ctx = prettyNoExt ctx++unboxParens :: MonadState (PrintState s) m => m a -> m a+unboxParens p =+  depend (write "(# ")+         (do v <- p+             write " #)"+             return v)++typ :: Type NodeInfo -> Printer s ()+typ (TyTuple _ Boxed types) = parens $ inter (write ", ") $ map pretty types+typ (TyTuple _ Unboxed types) = unboxParens $ inter (write ", ") $ map pretty types+typ ty = prettyNoExt ty+ -- | Specially format records. Indent where clauses only 2 spaces. decl :: Decl NodeInfo -> Printer s () -- | Pretty print type signatures like ----- foo :: (Show x,Read x)+-- foo :: (Show x, Read x) --     => (Foo -> Bar) --     -> Maybe Int --     -> (Char -> X -> Y)
src/HIndent/Types.hs view
@@ -3,6 +3,7 @@ {-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE FlexibleContexts #-}  -- | All types. @@ -50,10 +51,11 @@              ,psEolComment :: !Bool -- ^ An end of line comment has just been outputted.              ,psInsideCase :: !Bool -- ^ Whether we're in a case statement, used for Rhs printing.              ,psParseMode :: !ParseMode -- ^ Mode used to parse the original AST.+             ,psCommentPreprocessor :: forall m. MonadState (PrintState s) m => [Comment] -> m [Comment] -- ^ Preprocessor applied to comments on an AST before printing.              }  instance Eq (PrintState s) where-  PrintState ilevel out newline col line _ _ _ eolc inc _ == PrintState ilevel' out' newline' col' line' _ _ _ eolc' inc' _ =+  PrintState ilevel out newline col line _ _ _ eolc inc _pm _ == PrintState ilevel' out' newline' col' line' _ _ _ eolc' inc' _pm' _ =     (ilevel,out,newline,col,line,eolc, inc) == (ilevel',out',newline',col',line',eolc', inc')  -- | A printer extender. Takes as argument the user state that the@@ -71,6 +73,7 @@                   ,styleInitialState :: !s -- ^ User state, if needed.                   ,styleExtenders :: ![Extender s] -- ^ Extenders to the printer.                   ,styleDefConfig :: !Config -- ^ Default config to use for this style.+                  ,styleCommentPreprocessor :: forall s' m. MonadState (PrintState s') m => [Comment] -> m [Comment] -- ^ Preprocessor to use for comments.                   }  -- | Configurations shared among the different styles. Styles may pay
src/main/Main.hs view
@@ -1,6 +1,5 @@ {-# LANGUAGE PatternGuards #-} {-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE ViewPatterns #-} {-# LANGUAGE QuasiQuotes #-}  -- | Main entry point to hindent.
test/Spec.hs view
@@ -78,7 +78,7 @@         (nonNull, _:rest) -> (map fst nonNull, map fst rest)      pieceBreak :: (String, String) -> Bool-    pieceBreak ("", "") = error "Two consecutive line breaks!"+    pieceBreak ("", "") = error $ "Two consecutive line breaks in:\n" ++ str     pieceBreak (line, next) = null line && head next /= ' '      mkNewlines :: String -> String
test/gibiansky/expected/11.exp view
@@ -3,12 +3,10 @@        | D Float       -- ^ hi        | E Float Float -- ^ hi -data A = B             -- ^ hi-                       -- continuing the comment+data A = B             -- ^ hi continuing the comment        | C Int         -- ^ hi        | D Float       -- ^ hi-       | E Float Float -- ^ hi-                       -- continuing the comment+       | E Float Float -- ^ hi continuing the comment  a =   case x of@@ -42,11 +40,14 @@     Just something -> do       putStrLn "hello" -data X = X { a :: Int    -- ^ hi-           , b :: String -- ^ hi-           }+data X =+       X+         { a :: Int    -- ^ hi+         , b :: String -- ^ hi+         } -data X = X { a :: Int    -- ^ hi-           , b :: String -- ^ hi-                         -- continued-           }+data X =+       X+         { a :: Int    -- ^ hi+         , b :: String -- ^ hi continued+         }
test/gibiansky/expected/13.exp view
@@ -2,8 +2,7 @@   where     blah = blah -    -- hello-    -- bye+    -- hello bye     hello = hello  a = b
test/gibiansky/expected/18.exp view
@@ -2,14 +2,16 @@  a = b { c = "d", e = "f" } -longLines = longLines { longLines = "word word word word"-                      , wordWordWordWord = "long lines long long long"-                      }+longLines = longLines+  { longLines = "word word word word"+  , wordWordWordWord = "long lines long long long"+  }  a = B { c = "d" }  a = B { c = "d", e = "f" } -longLines = LongLines { longLines = "word word word word"-                      , wordWordWordWord = "long lines long long long"-                      }+longLines = LongLines+  { longLines = "word word word word"+  , wordWordWordWord = "long lines long long long"+  }
test/gibiansky/expected/20.exp view
@@ -1,3 +1,2 @@--- Comment 1--- Comment 2+-- Comment 1 Comment 2 f x = x
test/gibiansky/expected/21.exp view
@@ -1,4 +1,5 @@-a = A { reallyLongName = reallyLongName-      , reallyLongName = reallyLongName-      , aaaaaaaaaaaaaaaaaaaaa = aaaaaaaaaaaaaaaa-      }+a = A+  { reallyLongName = reallyLongName+  , reallyLongName = reallyLongName+  , aaaaaaaaaaaaaaaaaaaaa = aaaaaaaaaaaaaaaa+  }
+ test/gibiansky/expected/30.exp view
@@ -0,0 +1,22 @@+-- Hello+a = a++-- Hello Hello+a = a++-- Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello+-- Hello Hello Hello Hello Hello+a = a++{-+Hello+-}+a = a++type Maybe a = forall r. (a -> r) -> r -> r -- foo bar zot sdfs zot sdfs zot sdfs zot sdfs zot sdfs+                                            -- zot sdfs zot sdfs zot sdfs zot sdfs++type Maybe a = forall r. (a -> r)+                      -> r+                      -> r -- foo bar zot sdfs zot sdfs zot sdfs zot sdfs zot sdfs zot sdfs zot sdfs+                           -- zot sdfs zot sdfs
+ test/gibiansky/expected/31.exp view
@@ -0,0 +1,58 @@+instance A B+>+-- Hello+x = y++f x+  | pattern <- matched,+    condition+  = result++f x+  | pattern <- matched,+    condition+  = result++f x+  | pattern <- matched,+    condition+  = result++f x+  | pattern <- matched,+    pattern2 <- match2,+    pattern3 <- match3,+    condition+  = result++a =+  case x of+    LongLongRecordConstructor+      { longLongLongRecordName = val+      , longLongLongRecordName = val+      , longLongLongRecordName = val+      , longLongLongRecordName = val+      , longLongLongRecordName = val+      } -> val++-- This is a test+-- > Should not get rearranged+a = b++-- This is a test+-- > Should not get rearranged+-- > Should not get rearranged+a = b++-- This is a test+-- >>> Should not get rearranged+-- >>> Should not get rearranged+a = b++-- This is a test+-- @+--  f x = 3+--  f x = 3+-- @+--+a = b
+ test/gibiansky/expected/32.exp view
@@ -0,0 +1,39 @@+instance A B where+  x = y+>+a = b++instance A B where+  x = y+>+a = b++data ConvertSpec f =+       ConvertSpec+         { convertToIpynb :: f Bool+         , convertInput :: f FilePath+         , convertOutput :: f FilePath+         , convertLhsStyle :: f (LhsStyle T.Text)+         , convertOverwriteFiles :: Bool+         }++f b+  | b = 3++f b+  | b =+      3++a =+  case x of+    Record { x = x }+      | test -> ans++a =+  case x of+    Just x+      | test -> ans++{-# NOINLINE val #-}++{-# INLINE val #-}
+ test/gibiansky/expected/33.exp view
@@ -0,0 +1,46 @@+f x+  | a = b+  | a = b+  | a = b++f x+  | a = b+>+  | a = b+>+  | a = b++f x+  | a = b+>+  | a = b+>+>+  | a = b++f x+  -- branch+  | a = b+>+  -- branch+  | a = b+>+>+  -- branch+  | a = b++a = do+  let x = y+      z = 10+  3++a = do+  let x = y+>+>+      z = 10+  3++f x = 3+-- test+f x = 3
+ test/gibiansky/expected/34.exp view
@@ -0,0 +1,17 @@+   x = 3++#if+    x = 3+#else+    y = 3+#endif++f = z + moreThings+  where+    x = 3+#if MIN_VERSION_ghc(7, 10, 0)+    z = 10+#else+    z = 11+#endif+    moreThings = z + 1
+ test/gibiansky/expected/35.exp view
@@ -0,0 +1,3 @@+  > x = 3+  > +  > x = 3
+ test/gibiansky/expected/36.exp view
@@ -0,0 +1,60 @@+import           A.Long.Module.Name (With(many, many, many, many, many), imports, and, exports, that,+                                     don't, fit, on, one, line, at, all)++import           A.Long.Module.Name (With(many, many, many, many, many),+                                     With(many, many, many, many, many),+                                     With(many, many, many, many, many), imports, and, exports, that,+                                     don't, fit, on, one, line, at, all)++f (Zee x) =+  -- Comment!+  startswith "No instance for (Show" msg && True++x = do+  -- hi+  return+    output+      { longLongLong = 3+      , longLongLong = 3+      , longLongLong = 3+      , longLongLong = 3+      , longLongLong = 3+      , longLongLong = 3+      }++f x = f $ do+  -- hello+  f x++f x = f $+  -- hello+  f x++a =+  case x of+    z -> y -- what+    z -> y++class A be where+  x = y+  z = w++class A b where+  x = y+>+  z = w++data Widget = forall a. IHaskellWidget a => Widget a+  deriving Typeable++instance Monoid X where+  mempty = X+  X `mappend` X = X++a =+  let x = X+            { y = z+            -- FIXME+            , z = z+            }+  in Z
+ test/gibiansky/expected/37.exp view
@@ -0,0 +1,5 @@+instance A B where+  x =+    3+>+x = y
+ test/gibiansky/expected/38.exp view
@@ -0,0 +1,8 @@+type X = Y+>+-- Comment+instance A a => B a where+  x = y++{-# INLINE x #-}+x = 3
+ test/gibiansky/expected/39.exp view
@@ -0,0 +1,19 @@+a =+  if | x -> y+     | z -> z++a =+  if | x+      , x <- Just y -> y++a =+  f $ \x ->+    -- hello+    z++a =+  f $ \x -> do+    -- hello+    z++{-# OPTIONS_GHC -option #-}
test/gibiansky/expected/5.exp view
@@ -1,43 +1,30 @@ data A = B { field :: Int } -data A = B { field :: Int-           , field2 :: Char-           }+data A = B { field :: Int, field2 :: Char } -data A = B { field :: Int-           , field2 :: Char-           , field3 :: String-           }+data A = B { field :: Int, field2 :: Char, field3 :: String } -data A = B { field :: Int-           , field2 :: Char-           , field3 :: String-           }+data A = B { field :: Int, field2 :: Char, field3 :: String }   deriving Show -data A = B { field :: Int-           , field2 :: Char-           , field3 :: String-           }+data A = B { field :: Int, field2 :: Char, field3 :: String }   deriving Show -data A = B { field :: Int-           , field2 :: Char-           , field3 :: String-           }+data A = B { field :: Int, field2 :: Char, field3 :: String }   deriving (Show, Eq) -data A = B { field :: Int-           , field2 :: Char-           , field3 :: String-           }+data A = B { field :: Int, field2 :: Char, field3 :: String }   deriving (Show, Eq) -data A = B { field :: Int -- ^ Field 1-           }+data A =+       B+         { field :: Int -- ^ Field 1+         } -data A = B { field :: Int  -- ^ Field 1-           , field2 :: Char   -- ^ field 2-           , field3 :: String-           }+data A =+       B+         { field :: Int  -- ^ Field 1+         , field2 :: Char   -- ^ field 2+         , field3 :: String+         }   deriving Show
test/gibiansky/tests/11.test view
@@ -3,12 +3,10 @@        | D Float       -- ^ hi        | E Float Float -- ^ hi -data A = B             -- ^ hi-                       -- continuing the comment+data A = B             -- ^ hi continuing the comment        | C Int         -- ^ hi        | D Float       -- ^ hi-       | E Float Float -- ^ hi-                       -- continuing the comment+       | E Float Float -- ^ hi continuing the comment  a = case x of   Nothing -> 2@@ -41,6 +39,5 @@            }  data X = X { a :: Int    -- ^ hi-           , b :: String -- ^ hi-                         -- continued+           , b :: String -- ^ hi continued            }
test/gibiansky/tests/13.test view
@@ -2,8 +2,7 @@   where     blah = blah -    -- hello-    -- bye+    -- hello bye     hello = hello  a = b
test/gibiansky/tests/20.test view
@@ -1,3 +1,2 @@--- Comment 1--- Comment 2+-- Comment 1 Comment 2 f x = x
test/gibiansky/tests/21.test view
@@ -1,4 +1,5 @@-a = A { reallyLongName = reallyLongName-      , reallyLongName = reallyLongName-      , aaaaaaaaaaaaaaaaaaaaa = aaaaaaaaaaaaaaaa-      }+a = A+  { reallyLongName = reallyLongName+  , reallyLongName = reallyLongName+  , aaaaaaaaaaaaaaaaaaaaa = aaaaaaaaaaaaaaaa+  }
+ test/gibiansky/tests/30.test view
@@ -0,0 +1,25 @@+-- Hello+a = a++-- Hello+-- Hello+a = a++-- Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello Hello+a = a++{-+Hello+-}+a = a++type Maybe a = forall r. (a -> r) -> r -> r -- foo bar zot sdfs zot+                                            -- sdfs zot sdfs zot sdfs+                                            -- zot sdfs zot sdfs zot+                                            -- sdfs zot sdfs zot sdfs++type Maybe a = +  forall r. (a -> r) +            -> r +            -> r -- foo bar zot sdfs zot sdfs zot sdfs zot sdfs zot+                 -- sdfs zot sdfs zot sdfs zot sdfs zot sdfs
+ test/gibiansky/tests/31.test view
@@ -0,0 +1,48 @@+instance A B+>+-- Hello+x = y++f x+  | pattern <- matched,+    condition+  = result++f x+  | pattern <- matched, condition+  = result++f x+  | pattern <- matched, condition = result++f x+  | pattern <- matched,+    pattern2 <- match2,+    pattern3 <- match3,+    condition+  = result++a = case x of+  LongLongRecordConstructor { longLongLongRecordName = val, longLongLongRecordName = val, longLongLongRecordName = val, longLongLongRecordName = val, longLongLongRecordName = val }  -> val++-- This is a test+-- > Should not get rearranged+a = b++-- This is a test+-- > Should not get rearranged+-- > Should not get rearranged+a = b++-- This is a test+-- >>> Should not get rearranged+-- >>> Should not get rearranged+a = b++-- This is a test+-- @+--  f x = 3+--  f x = 3+-- @+--+a = b
+ test/gibiansky/tests/32.test view
@@ -0,0 +1,37 @@+instance A B where+  x = y+>+a = b++instance A B where+  x = y+>+a = b++data ConvertSpec f =+       ConvertSpec+         { convertToIpynb :: f Bool+         , convertInput :: f FilePath+         , convertOutput :: f FilePath+         , convertLhsStyle :: f (LhsStyle T.Text)+         , convertOverwriteFiles :: Bool+         }++f b+  | b = 3++f b+  | b =+      3++a =+  case x of+    Record { x = x }| test -> ans++a =+  case x of+    Just x | test -> ans++{-# NOINLINE val #-}++{-# INLINE val #-}
+ test/gibiansky/tests/33.test view
@@ -0,0 +1,46 @@+f x+  | a = b+  | a = b+  | a = b++f x+  | a = b+>+  | a = b+>+  | a = b++f x+  | a = b+>+  | a = b+>+>+  | a = b++f x+  -- branch+  | a = b+>+  -- branch+  | a = b+>+>+  -- branch+  | a = b++a = do+  let x = y+      z = 10+  3++a = do+  let x = y+>+>+      z = 10+  3++f x = 3+-- test+f x = 3
+ test/gibiansky/tests/34.test view
@@ -0,0 +1,17 @@+   x = 3++#if+    x = 3+#else+    y = 3+#endif++f = z + moreThings+  where+    x = 3+#if MIN_VERSION_ghc(7, 10, 0)+    z = 10+#else+    z = 11+#endif+    moreThings = z + 1
+ test/gibiansky/tests/35.test view
@@ -0,0 +1,2 @@+  > x = 3+  > x = 3
+ test/gibiansky/tests/36.test view
@@ -0,0 +1,46 @@+import A.Long.Module.Name (With(many, many, many,  many, many), imports, and, exports, that, don't, fit, on, one, line, at, all)++import A.Long.Module.Name (With(many, many, many,  many, many), With(many, many, many,  many, many), With(many, many, many,  many, many), imports, and, exports, that, don't, fit, on, one, line, at, all)++f (Zee x) =+  -- Comment!+  startswith "No instance for (Show" msg && True++x = do+  -- hi+  return output { longLongLong = 3,  longLongLong = 3, longLongLong = 3, longLongLong = 3, longLongLong = 3, longLongLong = 3}++f x = f $ do+  -- hello+  f x++f x = f $+  -- hello+  f x++a =+  case x of+    z -> y -- what+    z -> y++class A be where+  x = y+  z = w++class A b where+  x = y+>+  z = w++data Widget = forall a. IHaskellWidget a => Widget a+  deriving Typeable++instance Monoid X where+    mempty = X+    X `mappend` X = X++a =+  let x = X { y = z, +              -- FIXME+              z = z }+  in Z
+ test/gibiansky/tests/37.test view
@@ -0,0 +1,5 @@+instance A B where+  x =+    3+>+x = y
+ test/gibiansky/tests/38.test view
@@ -0,0 +1,9 @@+type X = Y+>+-- Comment+instance A a => B a where+  x = y+>++{-# INLINE x #-}+x = 3
+ test/gibiansky/tests/39.test view
@@ -0,0 +1,19 @@+a = +  if | x -> y+     | z -> z++a =+  if | x, x <- Just y -> y++a =+  f $ \x ->+    -- hello+    z++a =+  f $ \x -> do+    -- hello+    z++{-# OPTIONS_GHC -option #-}+>
+ test/johan-tibell/expected/5.exp view
@@ -0,0 +1,7 @@+fun :: (Class a, Class b)+    => a -> b -> c++fun :: (a, b, c) -> (a, b)++fun :: (Class a, Class b)+    => a -> (# d, e #) -> c
+ test/johan-tibell/tests/5.test view
@@ -0,0 +1,7 @@+fun :: (Class a,Class b)+    => a -> b -> c++fun :: (a,b,c) -> (a,b)++fun :: (Class a, Class b)+    => a ->(# d,e #)-> c