1{-# LANGUAGE FlexibleInstances #-}
2{-# LANGUAGE RecordWildCards #-}
3module Stackage.BuildPlan
8import qualified Data.Map as Map
9import qualified Data.Set as Set
10import Distribution.Text (display, simpleParse)
13readBuildPlan :: FilePath -> IO BuildPlan
16 case fromString str of
17 Left s -> error $ "Could not read build plan: " ++ s
18 Right (x, "") -> return x
19 Right (_, _:_) -> error "Trailing content when reading build plan"
21writeBuildPlan :: FilePath -> BuildPlan -> IO ()
22writeBuildPlan fp bp = writeFile fp $ toString bp
25 toString :: a -> String
26 fromString :: String -> Either String (a, String)
28instance AsString BuildPlan where
29 toString BuildPlan {..} = concat
30 [ makeSection "tools" bpTools
31 , makeSection "packages" $ Map.toList bpPackages
32 , makeSection "core" $ Set.toList bpCore
33 , makeSection "optional-core" $ Map.toList bpOptionalCore
36 (tools, s2) <- getSection "tools" s1
37 (packages, s3) <- getSection "packages" s2
38 (core, s4) <- getSection "core" s3
39 (optionalCore, s5) <- getSection "optional-core" s4
42 , bpPackages = Map.fromList packages
43 , bpCore = Set.fromList core
44 , bpOptionalCore = Map.fromList optionalCore
48makeSection :: AsString a => String -> [a] -> String
49makeSection title contents = unlines
50 $ ("-- BEGIN " ++ title)
51 : map toString contents
52 ++ ["-- END " ++ title, ""]
54instance AsString String where
56 fromString s = Right (s, "")
58instance AsString PackageName where
59 toString (PackageName pn) = pn
60 fromString s = Right (PackageName s, "")
62instance AsString a => AsString (PackageName, a) where
63 toString (PackageName pn, s) = concat [pn, " ", toString s]
65 (pn, rest) <- takeWord s
66 (rest', s') <- fromString rest
67 return ((PackageName pn, rest'), s')
69takeWord :: AsString a => String -> Either String (a, String)
71 case break (== ' ') s of
73 (x', s') <- fromString x
76 else Left $ "Unconsumed input in takeWord call"
77 (_, []) -> Left "takeWord failed"
79instance AsString SelectedPackageInfo where
80 toString SelectedPackageInfo {..} = unwords
82 , toString spiHasTests
83 , maybe "@" ("@" ++) spiGithubUser
84 , unMaintainer spiMaintainer
87 (version, s2) <- takeWord s1
88 (hasTests, s3) <- takeWord s2
89 (gu, m) <- takeWord s3
90 Right (SelectedPackageInfo
91 { spiVersion = version
92 , spiHasTests = hasTests
94 , spiMaintainer = Maintainer m
97instance AsString (Maybe String) where
98 toString Nothing = "@"
99 toString (Just x) = "@" ++ x
100 fromString "@" = Right (Nothing, "")
101 fromString ('@':rest) = Right (Just rest, "")
102 fromString x = Left $ "Invalid Github user: " ++ x
104instance AsString Bool where
105 toString True = "test"
106 toString False = "notest"
107 fromString "test" = Right (True, "")
108 fromString "notest" = Right (False, "")
109 fromString x = Left $ "Invalid test value: " ++ x
111instance AsString Version where
114 case simpleParse s of
115 Nothing -> Left $ "Invalid version: " ++ s
116 Just v -> Right (v, "")
118getSection :: AsString a => String -> String -> Either String ([a], String)
119getSection title orig =
121 [] -> Left "Unexpected EOF when looking for a section"
124 case break (== end) ls1 of
125 (here, _:"":rest) -> do
126 here' <- mapM fromString' here
127 Right (here', unlines rest)
128 (_, _) -> Left $ "Could not find section end: " ++ title
129 | otherwise -> Left $ "Could not find section start: " ++ title
131 begin = "-- BEGIN " ++ title
132 end = "-- END " ++ title
135 (y, z) <- fromString x
138 else Left $ "Unconsumed input on line: " ++ x
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list