packages feed

headroom-0.1.0.0: src/Headroom/Header/Utils.hs

{-|
Module      : Headroom.Header.Utils
Description : License header utilities
Copyright   : (c) 2019-2020 Vaclav Svejcar
License     : BSD-3
Maintainer  : vaclav.svejcar@gmail.com
Stability   : experimental
Portability : POSIX

Useful functions for searching specific text fragments in input text, used by
other modules to detect existing license headers in source code files.
-}
{-# LANGUAGE NoImplicitPrelude #-}
module Headroom.Header.Utils
  ( findLine
  , findLineStartingWith
  , linesCountByRegex
  , reML
  )
where

import           Language.Haskell.TH.Quote      ( QuasiQuoter )
import           RIO
import qualified RIO.List                      as L
import qualified RIO.Text                      as T
import           Text.Regex.PCRE.Heavy
import           Text.Regex.PCRE.Light

-- | Finds line in given text that matches given predicate and returns its line
-- number.
findLine :: (Text -> Bool) -- ^ predicate to find line
         -> Text           -- ^ input text
         -> Int            -- ^ number of line that matches given predicate
findLine predicate text =
  fromMaybe 0 $ L.findIndex (predicate . T.strip) (T.lines text)

-- | Finds line starting with one of given patterns and returns its line number
-- (specialized form of 'findLine').
findLineStartingWith :: [Text] -- ^ patterns to use
                     -> Text   -- ^ input text
                     -> Int    -- ^ number of line starting with one of patterns
findLineStartingWith patterns = findLine predicate
  where predicate line = or $ fmap (`T.isPrefixOf` line) patterns

-- | Count lines that matches the given (multiline) regex. Useful for example to
-- find how many lines are taken by multi-line comment in source code.
linesCountByRegex :: Regex -- ^ regular expression to use
                  -> Text  -- ^ input text
                  -> Int   -- ^ number of lines matching given regex
linesCountByRegex regex text = case L.headMaybe $ scan regex text of
  Just (comment, _) -> L.length . T.lines $ comment
  _                 -> 0

-- | Regex configuration for matching multi-line UTF strings.
reML :: QuasiQuoter
reML = mkRegexQQ [dotall, utf8]