Skip to content

Commit a031eb3

Browse files
committed
Add raw-project stanza
1 parent 7302183 commit a031eb3

File tree

6 files changed

+165
-1
lines changed

6 files changed

+165
-1
lines changed

.travis.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,9 @@ install:
100100
- "printf 'write-ghc-environment-files: always\\n' >> cabal.project"
101101
- echo 'package haskell-ci' >> cabal.project
102102
- "echo ' ghc-options: -Werror' >> cabal.project"
103+
- "echo 'keep-going: False' >> cabal.project"
104+
- echo 'package bytestring' >> cabal.project
105+
- "echo ' tests: False' >> cabal.project"
103106
- touch cabal.project.local
104107
- "for pkg in $($HCPKG list --simple-output); do echo $pkg | sed 's/-[^-]*$//' | grep -vE -- '^(Cabal|haskell-ci)$' | sed 's/^/constraints: /' | sed 's/$/ installed/' >> cabal.project.local; done"
105108
- cat cabal.project || true
@@ -128,6 +131,9 @@ script:
128131
- "printf 'write-ghc-environment-files: always\\n' >> cabal.project"
129132
- echo 'package haskell-ci' >> cabal.project
130133
- "echo ' ghc-options: -Werror' >> cabal.project"
134+
- "echo 'keep-going: False' >> cabal.project"
135+
- echo 'package bytestring' >> cabal.project
136+
- "echo ' tests: False' >> cabal.project"
131137
- touch cabal.project.local
132138
- "for pkg in $($HCPKG list --simple-output); do echo $pkg | sed 's/-[^-]*$//' | grep -vE -- '^(Cabal|haskell-ci)$' | sed 's/^/constraints: /' | sed 's/$/ installed/' >> cabal.project.local; done"
133139
- cat cabal.project || true

cabal.haskell-ci

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,3 +57,9 @@ doctest-options: --fast
5757
constraint-set deepseq-1.4
5858
ghc: (>= 7.8 && <7.10) || == 8.2.2
5959
constraints: deepseq ==1.4.*
60+
61+
-- Include these fields "as is" in generated cabal.project
62+
raw-project
63+
keep-going: False
64+
package bytestring
65+
tests: False

haskell-ci.cabal

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,10 @@ library
8484
HaskellCI.Project
8585
HaskellCI.TestedWith
8686

87+
-- vendored from Cabal development version
88+
other-modules:
89+
Distribution.Fields.Pretty
90+
8791
ghc-options:
8892
-Wall -Wcompat -Wnoncanonical-monad-instances
8993
-Wnoncanonical-monadfail-instances

src/Distribution/Fields/Pretty.hs

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
{-# LANGUAGE BangPatterns #-}
2+
-- | Cabal-like file AST types: 'Field', 'Section' etc,
3+
--
4+
-- This (intermediate) data type is used for pretty-printing.
5+
--
6+
-- @since 3.0.0.0
7+
--
8+
module Distribution.Fields.Pretty (
9+
-- * Fields
10+
PrettyField (..),
11+
showFields,
12+
showFields',
13+
-- * Transformation from 'P.Field'
14+
fromParsecFields,
15+
genericFromParsecFields,
16+
prettyFieldLines,
17+
prettySectionArgs,
18+
) where
19+
20+
import Data.Functor.Identity (Identity (..))
21+
import Distribution.Pretty (showToken)
22+
23+
import Distribution.Parsec.Field (FieldName)
24+
import Distribution.Simple.Utils (fromUTF8BS)
25+
26+
import qualified Distribution.Parsec.Parser as P
27+
28+
import qualified Data.ByteString as BS
29+
import qualified Text.PrettyPrint as PP
30+
31+
data PrettyField
32+
= PrettyField FieldName PP.Doc
33+
| PrettySection FieldName [PP.Doc] [PrettyField]
34+
deriving Show
35+
36+
-- | Prettyprint a list of fields.
37+
showFields :: [PrettyField] -> String
38+
showFields = showFields' 4
39+
40+
-- | 'showFields' with user specified indentation.
41+
showFields' :: Int -> [PrettyField] -> String
42+
showFields' n = unlines . renderFields indent where
43+
-- few hardcoded, "unrolled" variants.
44+
indent | n == 4 = indent4
45+
| n == 2 = indent2
46+
| otherwise = (replicate (max n 1) ' ' ++)
47+
48+
indent4 :: String -> String
49+
indent4 [] = []
50+
indent4 xs = ' ' : ' ' : ' ' : ' ' : xs
51+
52+
indent2 :: String -> String
53+
indent2 [] = []
54+
indent2 xs = ' ' : ' ' : xs
55+
56+
renderFields :: (String -> String) -> [PrettyField] -> [String]
57+
renderFields indent fields = flattenBlocks $ map (renderField indent len) fields
58+
where
59+
len = maxNameLength 0 fields
60+
61+
maxNameLength !acc [] = acc
62+
maxNameLength !acc (PrettyField name _ : rest) = maxNameLength (max acc (BS.length name)) rest
63+
maxNameLength !acc (PrettySection {} : rest) = maxNameLength acc rest
64+
65+
-- | Block of lines,
66+
-- Boolean parameter tells whether block should be surrounded by empty lines
67+
data Block = Block Bool [String]
68+
69+
flattenBlocks :: [Block] -> [String]
70+
flattenBlocks = go0 where
71+
go0 [] = []
72+
go0 (Block surr strs : blocks) = strs ++ go surr blocks
73+
74+
go _surr' [] = []
75+
go surr' (Block surr strs : blocks) = ins $ strs ++ go surr blocks where
76+
ins | surr' || surr = ("" :)
77+
| otherwise = id
78+
79+
renderField :: (String -> String) -> Int -> PrettyField -> Block
80+
renderField indent fw (PrettyField name doc) = Block False $ case lines narrow of
81+
[] -> [ name' ++ ":" ]
82+
[singleLine] | length singleLine < 60
83+
-> [ name' ++ ": " ++ replicate (fw - length name') ' ' ++ narrow ]
84+
_ -> (name' ++ ":") : map indent (lines (PP.render doc))
85+
where
86+
name' = fromUTF8BS name
87+
narrow = PP.renderStyle narrowStyle doc
88+
89+
narrowStyle :: PP.Style
90+
narrowStyle = PP.style { PP.lineLength = PP.lineLength PP.style - fw }
91+
92+
renderField indent _ (PrettySection name args fields) = Block True $
93+
PP.render (PP.hsep $ PP.text (fromUTF8BS name) : args)
94+
:
95+
map indent (renderFields indent fields)
96+
97+
-------------------------------------------------------------------------------
98+
-- Transform from Parsec.Field
99+
-------------------------------------------------------------------------------
100+
101+
genericFromParsecFields
102+
:: Applicative f
103+
=> (FieldName -> [P.FieldLine ann] -> f PP.Doc) -- ^ transform field contents
104+
-> (FieldName -> [P.SectionArg ann] -> f [PP.Doc]) -- ^ transform section arguments
105+
-> [P.Field ann]
106+
-> f [PrettyField]
107+
genericFromParsecFields f g = goMany where
108+
goMany = traverse go
109+
110+
go (P.Field (P.Name _ann name) fls) = PrettyField name <$> f name fls
111+
go (P.Section (P.Name _ann name) secargs fs) = PrettySection name <$> g name secargs <*> goMany fs
112+
113+
-- | Used in 'fromParsecFields'.
114+
prettyFieldLines :: FieldName -> [P.FieldLine ann] -> PP.Doc
115+
prettyFieldLines _ fls = PP.vcat
116+
[ PP.text $ fromUTF8BS bs
117+
| P.FieldLine _ bs <- fls
118+
]
119+
120+
-- | Used in 'fromParsecFields'.
121+
prettySectionArgs :: FieldName -> [P.SectionArg ann] -> [PP.Doc]
122+
prettySectionArgs _ = map $ \sa -> case sa of
123+
P.SecArgName _ bs -> showToken $ fromUTF8BS bs
124+
P.SecArgStr _ bs -> showToken $ fromUTF8BS bs
125+
P.SecArgOther _ bs -> PP.text $ fromUTF8BS bs
126+
127+
-- | Simple variant of 'genericFromParsecField'
128+
fromParsecFields :: [P.Field ann] -> [PrettyField]
129+
fromParsecFields = runIdentity . genericFromParsecFields
130+
(Identity .: prettyFieldLines)
131+
(Identity .: prettySectionArgs)
132+
where
133+
(.:) :: (a -> b) -> (c -> d -> a) -> (c -> d -> b)
134+
(f .: g) x y = f (g x y)

src/HaskellCI.hs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ import Distribution.Verbosity (Verbosity)
7171
#endif
7272

7373
import qualified Distribution.FieldGrammar as C
74+
import qualified Distribution.Fields.Pretty as C
7475
import qualified Distribution.PackageDescription.FieldGrammar as C
7576
import qualified Distribution.Types.SourceRepo as C
7677
import qualified Text.PrettyPrint as PP
@@ -953,6 +954,12 @@ genTravisFromConfigs argv opts isCabalProject config prj@Project { prjPackages =
953954
tellStrLns [ sh $ "echo 'source-repository-package' >> cabal.project" ]
954955
tellStrLns [ sh $ "echo ' " ++ l ++ "' >> cabal.project" | l <- lines repo' ]
955956

957+
unless (null (cfgRawProject config)) $ tellStrLns
958+
[ sh $ "echo '" ++ l ++ "' >> cabal.project"
959+
| l <- lines $ C.showFields' 2 $ cfgRawProject config
960+
, not (null l)
961+
]
962+
956963
-- also write cabal.project.local file with
957964
-- @
958965
-- constraints: base installed

src/HaskellCI/Config.hs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import qualified Distribution.Parsec.Common as C
2525
import qualified Distribution.Parsec.Newtypes as C
2626
import qualified Distribution.Parsec.Parser as C
2727
import qualified Distribution.Parsec.ParseResult as C
28+
import qualified Distribution.Fields.Pretty as C
2829
import qualified Distribution.Pretty as C
2930
import qualified Distribution.Types.Version as C
3031
import qualified Text.PrettyPrint as PP
@@ -67,6 +68,7 @@ data Config = Config
6768
, cfgDoctest :: !DoctestConfig
6869
, cfgHLint :: !HLintConfig
6970
, cfgConstraintSets :: [ConstraintSet]
71+
, cfgRawProject :: [C.PrettyField]
7072
}
7173
deriving (Show, Generic)
7274

@@ -110,6 +112,7 @@ emptyConfig = Config
110112
, cfgLastInSeries = False
111113
, cfgOsx = S.empty
112114
, cfgApt = S.empty
115+
, cfgRawProject = []
113116
}
114117

115118
-------------------------------------------------------------------------------
@@ -166,7 +169,8 @@ configGrammar = Config
166169
^^^ metahelp "PKG" "Additional apt packages to install"
167170
<*> C.blurFieldGrammar #cfgDoctest doctestConfigGrammar
168171
<*> C.blurFieldGrammar #cfgHLint hlintConfigGrammar
169-
<*> pure []
172+
<*> pure [] -- constraint sets
173+
<*> pure [] -- raw project fields
170174

171175
-------------------------------------------------------------------------------
172176
-- Reading
@@ -190,6 +194,9 @@ parseConfigFile fields0 = do
190194
let (fs, _sections) = C.partitionFields cfields
191195
cs <- C.parseFieldGrammar C.cabalSpecLatest fs (constraintSetGrammar name')
192196
return $ over #cfgConstraintSets (++ [cs])
197+
| name == "raw-project" = do
198+
let fs = C.fromParsecFields cfields
199+
return $ over #cfgRawProject (++ fs)
193200
| otherwise = do
194201
C.parseWarning pos C.PWTUnknownSection $ "Unknown section " ++ fromUTF8BS name
195202
return id

0 commit comments

Comments
 (0)