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.Type as Type
17import qualified AST.Declaration as Decl
18import qualified AST.Expression.Source as Source
19import qualified AST.Variable as Var
21import Text.Parsec hiding (newline, spaces)
22import qualified Parse.Declaration as Parse (typeDecl, infixDecl)
23import qualified Parse.Expression as Parse (typeAnnotation)
24import qualified Parse.Helpers as Parse
25import qualified Parse.Module as Parse (header)
26import qualified Elm.Compiler.Module as Module
27import qualified Elm.Docs as Docs
34 , output :: Maybe FilePath
36 deriving (Data,Typeable,Show,Eq)
41 { input = def &= args &= typ "FILE"
43 , output = Nothing &= typFile
44 &= help "file name for generated JSON documentation"
46 } &= help "Generate documentation for Elm"
47 &= summary "Generate documentation for Elm, (c) Evan Czaplicki"
50-- GENERATE DOCUMENTATION
54 do flags <- cmdArgs defaultFlags
55 source <- readFile (input flags)
56 case Parse.iParse documentation source of
58 let json = Json.encodePretty' config docs in
60 Nothing -> BS.putStrLn json
62 do createDirectoryIfMissing True (dropFileName docPath)
63 BS.writeFile docPath json
66 do hPutStrLn stderr (show err)
74 , Json.confCompare = Json.keyOrder keys
78 [ "tag", "name", "comment", "aliases", "types"
79 , "values", "func", "args", "type", "cases"
85documentation :: Parse.IParser Docs.Documentation
87 do optional Parse.freshLine
88 (names, _exports) <- Parse.header
90 manyTill (string " " <|> Parse.newline <?> "more whitespace")
91 (lookAhead (string "{-|") <?> "module documentation comment")
93 overview <- docComment
95 decls <- allDeclarations
97 let (aliases, unions, values) = categorizeDeclarations decls
99 return (Docs.Documentation (Module.Name names) overview aliases unions values)
102docComment :: Parse.IParser String
104 do try (string "{-|")
105 contents <- Parse.closeComment
108 dropWhile (`elem` " \n\r") . drop 2 $ reverse contents
110 return $ dropWhile (==' ') (reverse reversed)
113allDeclarations :: Parse.IParser [(String, Decl.SourceDecl)]
115 Parse.onFreshLines (:) [] declaration
118declaration :: Parse.IParser (String, Decl.SourceDecl)
120 uncommentable <|> commented <|> uncommented ""
123 (,) "" <$> Parse.infixDecl
126 do comment <- docComment
130 uncommented comment =
132 <$> choice [ Parse.typeDecl, Decl.Definition <$> Parse.typeAnnotation ]
135-- CATEGORIZE DECLARATIONS
137data CategoryInfo = CategoryInfo
138 { aliases :: [Docs.Alias]
139 , unions :: [Docs.Union]
140 , values :: Map.Map String Docs.Value
141 , infixes :: Map.Map String (String, Int)
145emptyInfo :: CategoryInfo
147 CategoryInfo [] [] Map.empty Map.empty
150categorizeDeclarations :: [(String, Decl.SourceDecl)] -> ([Docs.Alias], [Docs.Union], [Docs.Value])
151categorizeDeclarations decls =
152 (aliases, unions, Map.elems values)
154 (CategoryInfo aliases unions rawValues infixes) =
155 foldr collectInfo emptyInfo decls
159 (Map.intersectionWith addInfixInfo rawValues infixes)
163addInfixInfo :: Docs.Value -> (String, Int) -> Docs.Value
164addInfixInfo value infixInfo =
165 value { Docs.valueAssocPrec = Just infixInfo }
168collectInfo :: (String, Decl.SourceDecl) -> CategoryInfo -> CategoryInfo
169collectInfo (comment, decl) info =
171 Decl.Definition def ->
173 Source.Definition _ _ -> error errorMessage
174 Source.TypeAnnotation name tipe ->
175 let value = Docs.Value name comment (toDocType tipe) Nothing
177 info { values = Map.insert name value (values info) }
179 Decl.Datatype name args cases ->
180 let cases' = map (second (map toDocType)) cases
181 union = Docs.Union name comment args cases'
183 info { unions = union : unions info }
185 Decl.TypeAlias name args tipe ->
186 let alias = Docs.Alias name comment args (toDocType tipe)
188 info { aliases = alias : aliases info }
190 Decl.Fixity assoc prec name ->
191 let infixInfo = (Decl.assocToString assoc, prec)
193 info { infixes = Map.insert name infixInfo (infixes info) }
199errorMessage :: String
201 "there appears to be a bug in this tool.\n" ++
202 "Please report it to <https://github.com/elm-lang/Elm/issues>"
205-- AST TYPE TO DOC TYPE
207toDocType :: Type.Type Var.Raw -> Docs.Type
211 Docs.Lambda (toDocType t1) (toDocType t2)
216 Type.Type (Var.Raw name) ->
220 Docs.App (toDocType t) (map toDocType ts)
222 Type.Record fields ext ->
223 Docs.Record (map (second toDocType) fields) (fmap toDocType ext)
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