{-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE OverloadedStrings #-} -- | Helper functions for working with source templates module Language.Haskell.Tools.PrettyPrint.Prepare.SourceTemplateHelpers where import Control.Reference ((.=)) import Data.String (IsString(..), String) import Language.Haskell.Tools.AST import Language.Haskell.Tools.PrettyPrint.Prepare.SourceTemplate import SrcLoc (noSrcSpan, combineSrcSpans) type ASTElement node dom = Ann node dom SrcTemplateStage type ASTOptional node dom = AnnMaybeG node dom SrcTemplateStage type ASTMulti node dom = AnnListG node dom SrcTemplateStage instance IsString (SpanInfo SrcTemplateStage) where fromString s = SourceTemplateNode noSrcSpan [TextElem [NormalText s] noSrcSpan] 0 Nothing -- * Basic elements child :: SpanInfo SrcTemplateStage child = SourceTemplateNode noSrcSpan [ChildElem] 0 Nothing opt :: OptionalInfo SrcTemplateStage opt = SourceTemplateOpt noSrcSpan "" "" 0 Nothing list :: ListInfo SrcTemplateStage list = SourceTemplateList noSrcSpan "" "" "" Nothing [] 0 Nothing -- * Modifiers class AfterBefore i where -- | Put the given string before the element if it is not empty after :: String -> i -> i -- | The given string should follow the element if it is not empty followedBy :: String -> i -> i instance AfterBefore (ListInfo SrcTemplateStage) where after str = srcTmpListBefore .= str followedBy str = srcTmpListAfter .= str instance AfterBefore (OptionalInfo SrcTemplateStage) where after str = srcTmpOptBefore .= str followedBy str = srcTmpOptAfter .= str class RelativeIndent i where -- | The element should be indented relatively to its parent relativeIndented :: Int -> i -> i instance RelativeIndent (SpanInfo SrcTemplateStage) where relativeIndented i = srcTmpRelPos .= Just i instance RelativeIndent (ListInfo SrcTemplateStage) where relativeIndented i = srcTmpListRelPos .= Just i instance RelativeIndent (OptionalInfo SrcTemplateStage) where relativeIndented i = srcTmpOptRelPos .= Just i class MinimumIndent i where -- | The elements should be indented at least to the given number of spaces minimumIndented :: Int -> i -> i instance MinimumIndent (SpanInfo SrcTemplateStage) where minimumIndented i = sourceTemplateMinimalIndent .= i instance MinimumIndent (ListInfo SrcTemplateStage) where minimumIndented i = srcTmpListMinimalIndent .= i instance MinimumIndent (OptionalInfo SrcTemplateStage) where minimumIndented i = srcTmpOptMinimalIndent .= i -- | The elements of the list should be separated by the given string by default (might be overridden) separatedBy :: String -> ListInfo SrcTemplateStage -> ListInfo SrcTemplateStage separatedBy sep = srcTmpDefaultSeparator .= sep -- | The elements of the list should be indented on the same column indented :: ListInfo SrcTemplateStage -> ListInfo SrcTemplateStage indented = (srcTmpIndented .= Just []) . (srcTmpDefaultSeparator .= "\n") -- Concatenates two source templates to produce a new template with all child elements. instance Semigroup (SpanInfo SrcTemplateStage) where SourceTemplateNode sp1 el1 _ _ <> SourceTemplateNode sp2 el2 _ _ = SourceTemplateNode (combineSrcSpans sp1 sp2) (el1 ++ el2) 0 Nothing