headroom-0.3.0.0: src/Headroom/HeaderFn/UpdateCopyright.hs
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE TypeApplications #-}
{-|
Module : Headroom.HeaderFn.UpdateCopyright
Description : /License Header function/ for updating years in copyrights
Copyright : (c) 2019-2020 Vaclav Svejcar
License : BSD-3-Clause
Maintainer : vaclav.svejcar@gmail.com
Stability : experimental
Portability : POSIX
This module provides functionality for updating years in copyright statements
in already rendered /license headers/.
-}
module Headroom.HeaderFn.UpdateCopyright
( -- * Data Types
SelectedAuthors(..)
, UpdateCopyrightMode(..)
-- * Header Functions
, updateCopyright
-- * Helper Functions
, updateYears
)
where
import Headroom.Data.Has ( Has(..) )
import Headroom.Data.Regex ( re
, replace
)
import Headroom.Data.TextExtra ( mapLines
, read
)
import Headroom.HeaderFn.Types ( HeaderFn(..) )
import Headroom.Types ( CurrentYear(..) )
import RIO
import qualified RIO.NonEmpty as NE
import qualified RIO.Text as T
--------------------------------- DATA TYPES ---------------------------------
-- | Non-empty list of authors for which to update years in their copyrights.
newtype SelectedAuthors = SelectedAuthors (NonEmpty Text) deriving (Eq, Show)
-- | Mode that changes behaviour of the 'updateCopyright' function.
data UpdateCopyrightMode
= UpdateAllAuthors
-- ^ updates years in copyrights for all authors
| UpdateSelectedAuthors !SelectedAuthors
-- ^ updates years in copyrights only for selected authors
deriving (Eq, Show)
------------------------------ PUBLIC FUNCTIONS ------------------------------
-- | /License header function/ that updates years and year ranges in any
-- present copyright statements.
--
-- = Reader Environment Parameters
-- ['CurrentYear'] value of the current year
-- ['UpdateCopyrightMode'] mode specifying the behaviour of the updater
updateCopyright :: (Has CurrentYear env, Has UpdateCopyrightMode env)
=> HeaderFn env
updateCopyright = HeaderFn $ \input -> do
currentYear <- viewL
mode <- viewL
pure $ mapLines (update mode currentYear) input
where
update mode year line | shouldUpdate mode line = updateYears year line
| otherwise = line
shouldUpdate UpdateAllAuthors _ = True
shouldUpdate (UpdateSelectedAuthors (SelectedAuthors authors)) input =
any (`T.isInfixOf` input) (NE.toList authors)
-- | Updates years and years ranges in given text.
--
-- >>> updateYears (CurrentYear 2020) "Copyright (c) 2020"
-- "Copyright (c) 2020"
--
-- >>> updateYears (CurrentYear 2020) "Copyright (c) 2019"
-- "Copyright (c) 2019-2020"
--
-- >>> updateYears (CurrentYear 2020) "Copyright (c) 2018-2020"
-- "Copyright (c) 2018-2020"
--
-- >>> updateYears (CurrentYear 2020) "Copyright (c) 2018-2019"
-- "Copyright (c) 2018-2020"
updateYears :: CurrentYear
-- ^ current year
-> Text
-- ^ text to update
-> Text
-- ^ text with updated years
updateYears (CurrentYear year) = processYear . processRange
where
processYear = replace [re|(?!\d{4}-)(?<!-)(\d{4})|] processYear'
processRange = replace [re|(\d{4})-(\d{4})|] processRange'
replaceYear curr | read curr == Just year = tshow year
| otherwise = mconcat [curr, "-", tshow year]
replaceRange full fY tY | read tY == Just year = full
| otherwise = mconcat [fY, "-", tshow year]
processYear' _ (curr : _) = replaceYear curr
processYear' full _ = full
processRange' full (fromY : toY : _) = replaceRange full fromY toY
processRange' full _ = full