cabal-add-0.2: src/Distribution/Client/Common.hs
{-# LANGUAGE ImportQualifiedPost #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE OverloadedStrings #-}
-- |
-- Copyright: (c) 2023 Bodigrim
-- License: BSD-3-Clause
module Distribution.Client.Common (
CommonStanza (..),
isComponent,
splitAtPosition,
TargetField (..),
getTargetName,
) where
import Data.ByteString (ByteString)
import Data.ByteString.Char8 qualified as B
import Data.List qualified as L
import Distribution.Fields (
Field (..),
Name (..),
SectionArg (..),
)
import Distribution.PackageDescription (
ComponentName (..),
LibraryName (..),
componentNameStanza,
)
import Distribution.Parsec.Position (Position (..))
-- | Just a newtype wrapper, since @Cabal-syntax@ does not provide any.
newtype CommonStanza = CommonStanza {unCommonStanza :: ByteString}
deriving (Eq, Ord, Show)
isComponent :: Either CommonStanza ComponentName -> Field a -> Maybe [Field a]
isComponent (Right cmp) = \case
Section (Name _ "library") [] subFields
| cmp == CLibName LMainLibName ->
Just subFields
Section (Name _ sectionName) [SecArgName _pos sectionArg] subFields
| sectionName <> " " <> sectionArg == B.pack (componentNameStanza cmp) ->
Just subFields
Section (Name _ sectionName) [SecArgStr _pos sectionArg] subFields
| sectionName <> " " <> sectionArg == B.pack (componentNameStanza cmp) ->
Just subFields
_ -> Nothing
isComponent (Left (CommonStanza commonName)) = \case
Section (Name _ "common") [SecArgName _pos sectionArg] subFields
| sectionArg == commonName ->
Just subFields
Section (Name _ "common") [SecArgStr _pos sectionArg] subFields
| sectionArg == commonName ->
Just subFields
_ -> Nothing
-- Both lines and rows are 1-based.
splitAtPosition :: Position -> ByteString -> (ByteString, ByteString)
splitAtPosition (Position line row) bs
| line <= 1 = B.splitAt (row - 1) bs
| otherwise = case L.drop (line - 2) nls of
[] -> (bs, mempty)
nl : _ -> B.splitAt (nl + row) bs
where
nls = B.elemIndices '\n' bs
-- | A field in a cabal file, new content can be added to
data TargetField
= -- | Corresponds to @build-depends@ in the cabal file
BuildDepends
| -- | Corresponds to @exposed-modules@ in the cabal file
ExposedModules
| -- | Corresponds to @other-modules@ in the cabal file
OtherModules
deriving (Eq, Show, Ord)
getTargetName :: TargetField -> ByteString
getTargetName = \case
BuildDepends -> "build-depends"
ExposedModules -> "exposed-modules"
OtherModules -> "other-modules"