content: {-# LANGUAGE OverloadedStrings #-}
  {-# LANGUAGE RecordWildCards #-}
  {-# LANGUAGE ViewPatterns #-}
  
  -- | Common definitions for pre- and post- processing.
  module Ormolu.Processing.Common
    ( removeIndentation,
      reindent,
      linesInRegion,
      intSetToRegions,
    )
  where
  
  import Data.Char (isSpace)
  import Data.IntSet (IntSet)
  import Data.IntSet qualified as IntSet
  import Data.Text (Text)
  import Data.Text qualified as T
  import Ormolu.Config
  
  -- | Remove indentation from a given 'Text'. Return the input with indentation
  -- removed and the detected indentation level.
  removeIndentation :: Text -> (Text, Int)
  removeIndentation (T.lines -> xs) = (T.unlines (T.drop n <$> xs), n)
    where
      n = minimum (getIndent <$> xs)
      getIndent y =
        if T.all isSpace y
          then 0
          else T.length (T.takeWhile isSpace y)
  
  -- | Add indentation to a 'Text'.
  reindent :: Int -> Text -> Text
  reindent i = T.unlines . fmap (T.replicate i " " <>) . T.lines
  
  -- | All lines in the region specified by 'RegionDeltas'.
  linesInRegion :: RegionDeltas -> Text -> Text
  linesInRegion RegionDeltas {..} (T.lines -> ls) = T.unlines middle
    where
      (_, nonPrefix) = splitAt regionPrefixLength ls
      middle = take (length nonPrefix - regionSuffixLength) nonPrefix
  
  -- | Convert a set of line indices into disjoint 'RegionDelta's
  intSetToRegions ::
    -- | Total number of lines
    Int ->
    IntSet ->
    [RegionDeltas]
  intSetToRegions total (IntSet.toAscList -> indices) =
    regionIndicesToDeltas total <$> go Nothing indices
    where
      go Nothing [] = []
      go (Just (a, b)) [] = [RegionIndices (Just a) (Just b)]
      go Nothing (i : is) = go (Just (i, i)) is
      go (Just (a, b)) (i : is)
        | b + 1 == i = go (Just (a, i)) is
        | otherwise = RegionIndices (Just a) (Just b) : go (Just (i, i)) is
  