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.Map as Map
14import qualified Data.ByteString.Lazy.Char8 as BS
16import qualified AST.Declaration as Decl
17import qualified AST.Expression.Source as Source
19import Text.Parsec hiding (newline, spaces)
20import qualified Parse.Declaration as Parse (typeDecl, infixDecl)
21import qualified Parse.Expression as Parse (typeAnnotation)
22import qualified Parse.Helpers as Parse
23import qualified Parse.Module as Parse (header)
24import qualified Elm.Compiler.Module as Module
25import qualified Elm.Compiler.Type.Extract as Type
26import qualified Elm.Docs as Docs
33 , output :: Maybe FilePath
35 deriving (Data,Typeable,Show,Eq)
40 { input = def &= args &= typ "FILE"
42 , output = Nothing &= typFile
43 &= help "file name for generated JSON documentation"
45 } &= help "Generate documentation for Elm"
46 &= summary "Generate documentation for Elm, (c) Evan Czaplicki"
49-- GENERATE DOCUMENTATION
53 do flags <- cmdArgs defaultFlags
54 source <- readFile (input flags)
55 case Parse.iParse documentation source of
57 let json = Json.encodePretty' config docs in
59 Nothing -> BS.putStrLn json
61 do createDirectoryIfMissing True (dropFileName docPath)
62 BS.writeFile docPath json
65 do hPutStrLn stderr (show err)
73 , Json.confCompare = Json.keyOrder keys
77 [ "tag", "name", "comment", "aliases", "types"
78 , "values", "func", "args", "type", "cases"
84documentation :: Parse.IParser Docs.Documentation
86 do optional Parse.freshLine
87 (names, _exports) <- Parse.header
89 manyTill (string " " <|> Parse.newline <?> "more whitespace")
90 (lookAhead (string "{-|") <?> "module documentation comment")
92 overview <- docComment
94 decls <- allDeclarations
96 let (aliases, unions, values) = categorizeDeclarations decls
98 return (Docs.Documentation (Module.Name names) overview aliases unions values)
101docComment :: Parse.IParser String
103 do try (string "{-|")
104 contents <- Parse.closeComment
107 dropWhile (`elem` " \n\r") . drop 2 $ reverse contents
109 return $ dropWhile (==' ') (reverse reversed)
112allDeclarations :: Parse.IParser [(String, Decl.SourceDecl)]
114 Parse.onFreshLines (:) [] declaration
117declaration :: Parse.IParser (String, Decl.SourceDecl)
119 uncommentable <|> commented <|> uncommented ""
122 (,) "" <$> Parse.infixDecl
125 do comment <- docComment
129 uncommented comment =
131 <$> choice [ Parse.typeDecl, Decl.Definition <$> Parse.typeAnnotation ]
134-- CATEGORIZE DECLARATIONS
136data CategoryInfo = CategoryInfo
137 { aliases :: [Docs.Alias]
138 , unions :: [Docs.Union]
139 , values :: Map.Map String Docs.Value
140 , infixes :: Map.Map String (String, Int)
144emptyInfo :: CategoryInfo
146 CategoryInfo [] [] Map.empty Map.empty
149categorizeDeclarations :: [(String, Decl.SourceDecl)] -> ([Docs.Alias], [Docs.Union], [Docs.Value])
150categorizeDeclarations decls =
151 (aliases, unions, Map.elems values)
153 (CategoryInfo aliases unions rawValues infixes) =
154 foldr collectInfo emptyInfo decls
158 (Map.intersectionWith addInfixInfo rawValues infixes)
162addInfixInfo :: Docs.Value -> (String, Int) -> Docs.Value
163addInfixInfo value infixInfo =
164 value { Docs.valueAssocPrec = Just infixInfo }
167collectInfo :: (String, Decl.SourceDecl) -> CategoryInfo -> CategoryInfo
168collectInfo (comment, decl) info =
170 Decl.Definition def ->
172 Source.Definition _ _ -> error errorMessage
173 Source.TypeAnnotation name tipe ->
174 let value = Docs.Value name comment (Type.fromInternalType tipe) Nothing
176 info { values = Map.insert name value (values info) }
178 Decl.Datatype name args cases ->
179 let cases' = map (second (map Type.fromInternalType)) cases
180 union = Docs.Union name comment args cases'
182 info { unions = union : unions info }
184 Decl.TypeAlias name args tipe ->
185 let alias = Docs.Alias name comment args (Type.fromInternalType tipe)
187 info { aliases = alias : aliases info }
189 Decl.Fixity assoc prec name ->
190 let infixInfo = (Decl.assocToString assoc, prec)
192 info { infixes = Map.insert name infixInfo (infixes info) }
198errorMessage :: String
200 "there appears to be a bug in this tool.\n" ++
201 "Please report it to <https://github.com/elm-lang/Elm/issues>"
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