packages feed

fourmolu-0.4.0.0: src/Ormolu/Processing/Common.hs

{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE ViewPatterns #-}

-- | Common definitions for pre- and post- processing.
module Ormolu.Processing.Common
  ( removeIndentation,
    reindent,
    linesInRegion,
    regionInbetween,
    intSetToRegions,
  )
where

import Data.Char (isSpace)
import Data.IntSet (IntSet)
import qualified Data.IntSet as IntSet
import Data.Text (Text)
import qualified Data.Text as T
import Ormolu.Config

-- | Remove indentation from a given 'String'. Return the input with
-- indentation removed and the detected indentation level.
removeIndentation :: String -> (String, Int)
removeIndentation (lines -> xs) = (unlines (drop n <$> xs), n)
  where
    n = minimum (getIndent <$> xs)
    getIndent y =
      if all isSpace y
        then 0
        else length (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 -> String -> String
linesInRegion RegionDeltas {..} (lines -> ls) = unlines middle
  where
    (_, nonPrefix) = splitAt regionPrefixLength ls
    middle = take (length nonPrefix - regionSuffixLength) nonPrefix

-- | Get the region after the end of the first and till the end of
-- the second region.
regionInbetween ::
  -- | Total number of lines
  Int ->
  RegionDeltas ->
  RegionDeltas ->
  RegionDeltas
regionInbetween total r r' =
  RegionDeltas
    { regionPrefixLength = total - regionSuffixLength r,
      regionSuffixLength = total - regionPrefixLength r'
    }

-- | 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