nix-lang-0.1.0.0: src/Nix/Lang/ExactPrint/Prepare/Reflow.hs
-- | Sequence reflow primitives used while rebuilding lists and binding groups.
module Nix.Lang.ExactPrint.Prepare.Reflow where
import Data.Text (Text)
import Nix.Lang.ExactPrint.Operations
import Nix.Lang.Span
import Nix.Lang.Utils
-- | Direction in which a rebuilt sequence should flow.
data Flow
= FlowInline
| FlowMultiline
-- | Reanchor and advance a sequence of items from left to right.
reflow :: Flow -> (a -> Text) -> (RenderCursor -> Located a -> Located a) -> RenderCursor -> [Located a] -> [Located a]
reflow flow renderItem moveItem startCursor = reverse . snd . foldl' step (startCursor, [])
where
step (!cursor, acc) item =
let moved = moveItem cursor item
next = advanceItem flow renderItem cursor moved
in (next, moved : acc)
-- | Advance the cursor past one rebuilt item according to the chosen flow.
advanceItem :: Flow -> (a -> Text) -> RenderCursor -> Located a -> RenderCursor
advanceItem flow renderItem startCursor item =
case flow of
FlowInline -> advanceCursor endCursor " "
FlowMultiline -> RenderCursor (rcLine endCursor + 1) (rcColumn startCursor)
where
endCursor = advanceCursor startCursor (renderItem (unLoc item))
-- | Compute where a closing delimiter should be placed after a rebuilt sequence.
closeAfter :: Flow -> (a -> Text) -> SrcSpan -> [Located a] -> RenderCursor
closeAfter flow renderItem oldClose items =
case reverse items of
[] -> cursorAtSpanStart oldClose
lastItem : _ ->
case flow of
FlowInline -> advanceCursor (cursorAtSpanStart (getLoc lastItem)) (renderItem (unLoc lastItem) <> " ")
FlowMultiline ->
let endCursor = advanceCursor (cursorAtSpanStart (getLoc lastItem)) (renderItem (unLoc lastItem))
in RenderCursor (rcLine endCursor + 1) (srcSpanStartColumn oldClose)