forked from JustusAdam/language-haskell
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathrefresh.hs
executable file
·79 lines (63 loc) · 2.68 KB
/
refresh.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
#!/usr/bin/env stack
-- stack script --resolver lts-15.12 --package aeson --package yaml --package filepath --package directory --package unordered-containers --package text
{-
This file is used to generate a database of scope keys used in
-}
{-# LANGUAGE LambdaCase, OverloadedStrings, GeneralizedNewtypeDeriving, RecordWildCards #-}
import Data.Yaml
import System.Environment
import System.FilePath
import System.Directory
import qualified Data.Text as T
import qualified Data.Text.IO as T
import qualified Data.HashMap.Strict as M
import qualified Data.HashSet as S
import Data.Foldable (toList)
import Data.Maybe
import Data.List (sort)
newtype Names = Names { names :: S.HashSet T.Text }
deriving (Monoid, Semigroup)
add :: T.Text -> Names -> Names
add n = Names . S.insert n . names
instance FromJSON Names where
parseJSON = \case
Object o -> do
new <- o .:? "name"
recursed <- mconcat <$> mapM parseJSON (M.elems o)
pure $ maybe id add new recursed
Array vs -> mconcat . toList <$> traverse parseJSON vs
_ -> pure mempty
data Info = Info { iname :: T.Text, idesc :: Maybe T.Text, iexample :: Maybe T.Text, ihide :: Bool }
instance FromJSON Info where
parseJSON = withObject "Info must be an object" $ \o ->
Info <$> o .: "scope" <*> o.:? "description" <*> o .:? "example" <*> o .:? "hide" .!= False
instance ToJSON Info where
toJSON Info{..} = object $
"description" .?= idesc $ "example" .?= iexample $ "hide" .?= (if ihide then Just ihide else Nothing) $ ["scope" .= iname]
where
_ .?= Nothing = id
a .?= Just b = (a .= b : )
toInfo :: Names -> [Info]
toInfo = map (\name -> Info name Nothing Nothing False) . sort . toList . names
toNames :: [Info] -> Names
toNames = Names . S.fromList . map iname
mergeInfo :: [Info] -> Names -> [Info]
mergeInfo ext (Names n) = ext <> toInfo (Names $ n `S.difference` names (toNames ext))
toMarkdown :: [Info] -> T.Text
toMarkdown info = T.unlines $
"| Scope Name | Description | Example |"
: "|-|-|-|"
: map (\Info{..} -> "| " <> iname <> " | " <> fromMaybe "" idesc <> " | " <> fromMaybe "" iexample <> " |") ( filter (not . ihide) info)
main =
getArgs >>= \case
["db",target, out] -> refreshDb target out
["md", target, out] -> makeMarkdown target out
where
refreshDb syntax outFile = do
fromGrammar <- decodeFileThrow syntax
old <-
doesFileExist outFile >>= \case
True -> Just <$> decodeFileThrow outFile
_ -> pure Nothing
encodeFile outFile $ maybe toInfo mergeInfo old fromGrammar
makeMarkdown db md = decodeFileThrow db >>= T.writeFile md . toMarkdown