1{-# LANGUAGE OverloadedStrings, DeriveDataTypeable #-}
4import System.Console.CmdArgs
10import Control.Applicative ((<$>))
11import Control.Arrow (second)
12import qualified Data.Aeson.Encode.Pretty as Json
13import qualified Data.ByteString.Lazy.Char8 as BS
14import qualified Data.Map as Map
15import qualified Data.Maybe as Maybe
16import qualified Data.Set as Set
18import qualified AST.Declaration as Decl
19import qualified AST.Expression.Source as Source
20import qualified AST.Variable as Var
22import Text.Parsec hiding (newline, spaces)
23import qualified Parse.Declaration as Parse (typeDecl, infixDecl)
24import qualified Parse.Expression as Parse (typeAnnotation)
25import qualified Parse.Helpers as Parse
26import qualified Parse.Module as Parse (header)
27import qualified Elm.Compiler.Module as Module
28import qualified Elm.Compiler.Type.Extract as Type
29import qualified Elm.Docs as Docs
36 , output :: Maybe FilePath
38 deriving (Data,Typeable,Show,Eq)
43 { input = def &= args &= typ "FILE"
45 , output = Nothing &= typFile
46 &= help "file name for generated JSON documentation"
48 } &= help "Generate documentation for Elm"
49 &= summary "Generate documentation for Elm, (c) Evan Czaplicki"
52-- GENERATE DOCUMENTATION
56 do flags <- cmdArgs defaultFlags
57 source <- readFile (input flags)
58 case Parse.iParse documentation source of
60 let json = Json.encodePretty' config docs in
62 Nothing -> BS.putStrLn json
64 do createDirectoryIfMissing True (dropFileName docPath)
65 BS.writeFile docPath json
68 do hPutStrLn stderr (show err)
76 , Json.confCompare = Json.keyOrder keys
80 [ "tag", "name", "comment", "aliases", "types"
81 , "values", "func", "args", "type", "cases"
87documentation :: Parse.IParser Docs.Documentation
89 do optional Parse.freshLine
90 (names, exports) <- Parse.header
92 manyTill (string " " <|> Parse.newline <?> "more whitespace")
93 (lookAhead (string "{-|") <?> "module documentation comment")
95 overview <- docComment
97 decls <- allDeclarations
99 let (aliases, unions, values) = categorizeDeclarations decls
105 (filterAliases exports aliases)
106 (filterUnions exports unions)
107 (filterValues exports values)
110docComment :: Parse.IParser String
112 do try (string "{-|")
113 contents <- Parse.closeComment
116 dropWhile (`elem` " \n\r") . drop 2 $ reverse contents
118 return $ dropWhile (==' ') (reverse reversed)
121allDeclarations :: Parse.IParser [(String, Decl.SourceDecl)]
123 Parse.onFreshLines (:) [] declaration
126declaration :: Parse.IParser (String, Decl.SourceDecl)
128 uncommentable <|> commented <|> uncommented ""
131 (,) "" <$> Parse.infixDecl
134 do comment <- docComment
138 uncommented comment =
140 <$> choice [ Parse.typeDecl, Decl.Definition <$> Parse.typeAnnotation ]
143-- CATEGORIZE DECLARATIONS
145data CategoryInfo = CategoryInfo
146 { aliases :: [Docs.Alias]
147 , unions :: [Docs.Union]
148 , values :: Map.Map String Docs.Value
149 , infixes :: Map.Map String (String, Int)
153emptyInfo :: CategoryInfo
155 CategoryInfo [] [] Map.empty Map.empty
158categorizeDeclarations :: [(String, Decl.SourceDecl)] -> ([Docs.Alias], [Docs.Union], [Docs.Value])
159categorizeDeclarations decls =
160 (aliases, unions, Map.elems values)
162 (CategoryInfo aliases unions rawValues infixes) =
163 foldr collectInfo emptyInfo decls
167 (Map.intersectionWith addInfixInfo rawValues infixes)
171addInfixInfo :: Docs.Value -> (String, Int) -> Docs.Value
172addInfixInfo value infixInfo =
173 value { Docs.valueAssocPrec = Just infixInfo }
176collectInfo :: (String, Decl.SourceDecl) -> CategoryInfo -> CategoryInfo
177collectInfo (comment, decl) info =
179 Decl.Definition def ->
181 Source.Definition _ _ -> error errorMessage
182 Source.TypeAnnotation name tipe ->
183 let value = Docs.Value name comment (Type.fromInternalType tipe) Nothing
185 info { values = Map.insert name value (values info) }
187 Decl.Datatype name args cases ->
188 let cases' = map (second (map Type.fromInternalType)) cases
189 union = Docs.Union name comment args cases'
191 info { unions = union : unions info }
193 Decl.TypeAlias name args tipe ->
194 let alias = Docs.Alias name comment args (Type.fromInternalType tipe)
196 info { aliases = alias : aliases info }
198 Decl.Fixity assoc prec name ->
199 let infixInfo = (Decl.assocToString assoc, prec)
201 info { infixes = Map.insert name infixInfo (infixes info) }
207errorMessage :: String
209 "there appears to be a bug in this tool.\n" ++
210 "Please report it to <https://github.com/elm-lang/Elm/issues>"
213-- FILTER OUT UNEXPORTED VALUES, ALIASES, and UNIONS
215filterValues :: Var.Listing Var.Value -> [Docs.Value] -> [Docs.Value]
216filterValues (Var.Listing exports open) values =
221 Set.fromList (Var.getValues exports)
223 filter (\value -> Set.member (Docs.valueName value) names) values
226filterAliases :: Var.Listing Var.Value -> [Docs.Alias] -> [Docs.Alias]
227filterAliases (Var.Listing exports open) aliases =
232 Set.fromList (Var.getAliases exports)
234 filter (\value -> Set.member (Docs.aliasName value) names) aliases
237filterUnions :: Var.Listing Var.Value -> [Docs.Union] -> [Docs.Union]
238filterUnions (Var.Listing exports open) unions =
242 Maybe.mapMaybe (filterUnion exportedUnions) unions
245 Map.fromList (Var.getUnions exports)
248filterUnion :: Map.Map String (Var.Listing String) -> Docs.Union -> Maybe Docs.Union
249filterUnion exportedUnions union =
250 case Map.lookup (Docs.unionName union) exportedUnions of
254 Just (Var.Listing tags unionOpen)
259 filter (\(tag, _) -> tag `elem` tags) (Docs.unionCases union)
261 Just (union { Docs.unionCases = publicTags })
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