2Module : Idris.Package.Parser
3Description : `iPKG` file parser and package description information.
6Maintainer : The Idris Community.
8{-# LANGUAGE CPP, ConstraintKinds #-}
9#if !(MIN_VERSION_base(4,8,0))
10{-# LANGUAGE OverlappingInstances #-}
12module Idris.Package.Parser where
14import Idris.AbsSyntaxTree
15import Idris.CmdOptions
17import Idris.Package.Common
18import Idris.Parser.Helpers hiding (stringLiteral)
23import Control.Applicative
24import Control.Monad.State.Strict
25import Data.List (union)
26import Data.Maybe (fromJust, isNothing)
27import System.FilePath (isValid, takeFileName)
28import qualified Text.PrettyPrint.ANSI.Leijen as PP
29import Text.Trifecta hiding (char, charLiteral, natural, span, string, symbol,
32type PParser = StateT PkgDesc IdrisInnerParser
34instance HasLastTokenSpan PParser where
35 getLastTokenSpan = return Nothing
37#if MIN_VERSION_base(4,9,0)
38instance {-# OVERLAPPING #-} DeltaParsing PParser where
41 position = lift position
42 {-# INLINE position #-}
43 slicedWith f (StateT m) = StateT $ \s -> slicedWith (\(a,s') b -> (f a b, s')) $ m s
44 {-# INLINE slicedWith #-}
47 restOfLine = lift restOfLine
48 {-# INLINE restOfLine #-}
51#if MIN_VERSION_base(4,8,0)
52instance {-# OVERLAPPING #-} TokenParsing PParser where
54instance TokenParsing PParser where
56 someSpace = many (simpleWhiteSpace <|> singleLineComment <|> multiLineComment) *> pure ()
59parseDesc :: FilePath -> IO PkgDesc
62 case runparser pPkg defaultPkg fp p of
63 Failure (ErrInfo err _) -> fail (show $ PP.plain err)
66pPkg :: PParser PkgDesc
71 put (st { pkgname = p })
78-- | Parses a filename.
80-- | Treated for now as an identifier or a double-quoted string.
81filename :: (MonadicParsing m, HasLastTokenSpan m) => m String
84 -- Treat a double-quoted string as a filename to support spaces.
85 -- This also moves away from tying filenames to identifiers, so
86 -- it will also accept hyphens
87 -- (https://github.com/idris-lang/Idris-dev/issues/2721)
90 -- Through at least version 0.9.19.1, IPKG executable values were
91 -- possibly namespaced identifiers, like foo.bar.baz.
92 show <$> fst <$> iName []
93 case filenameErrorMessage filename of
94 Just errorMessage -> fail errorMessage
95 Nothing -> return filename)
98 -- TODO: Report failing span better! We could lookAhead,
99 -- or do something with DeltaParsing?
100 filenameErrorMessage :: FilePath -> Maybe String
101 filenameErrorMessage path = either Just (const Nothing) $ do
104 checkNoDirectoryComponent path
106 checkThat ok message =
107 if ok then Right () else Left message
110 checkThat (path /= "") "filename must not be empty"
113 checkThat (System.FilePath.isValid path)
114 "filename must contain only valid characters"
116 checkNoDirectoryComponent path =
117 checkThat (path == takeFileName path)
118 "filename must contain no directory component"
122pClause = do reserved "executable"; lchar '=';
125 put (st { execout = Just exec })
127 <|> do reserved "main"; lchar '=';
128 main <- fst <$> iName []
130 put (st { idris_main = Just main })
132 <|> do reserved "sourcedir"; lchar '=';
133 src <- fst <$> identifier
135 put (st { sourcedir = src })
137 <|> do reserved "opts"; lchar '=';
138 opts <- stringLiteral
140 let args = pureArgParser (words opts)
141 put (st { idris_opts = args ++ idris_opts st })
143 <|> do reserved "pkgs"; lchar '=';
144 ps <- sepBy1 (fst <$> identifier) (lchar ',')
146 let pkgs = pureArgParser $ concatMap (\x -> ["-p", x]) ps
148 put (st { pkgdeps = ps `union` (pkgdeps st)
149 , idris_opts = pkgs ++ idris_opts st})
151 <|> do reserved "modules"; lchar '=';
152 ms <- sepBy1 (fst <$> iName []) (lchar ',')
154 put (st { modules = modules st ++ ms })
156 <|> do reserved "libs"; lchar '=';
157 ls <- sepBy1 (fst <$> identifier) (lchar ',')
159 put (st { libdeps = libdeps st ++ ls })
161 <|> do reserved "objs"; lchar '=';
162 ls <- sepBy1 (fst <$> identifier) (lchar ',')
164 put (st { objs = objs st ++ ls })
166 <|> do reserved "makefile"; lchar '=';
167 mk <- fst <$> iName []
169 put (st { makefile = Just (show mk) })
171 <|> do reserved "tests"; lchar '=';
172 ts <- sepBy1 (fst <$> iName []) (lchar ',')
174 put st { idris_tests = idris_tests st ++ ts }
176 <|> do reserved "version"
178 vStr <- many (satisfy (not . isEol))
182 put st {pkgversion = Just vStr}
184 <|> do reserved "readme"
186 rme <- many (satisfy (not . isEol))
190 put (st { pkgreadme = Just rme })
192 <|> do reserved "license"
194 lStr <- many (satisfy (not . isEol))
197 put st {pkglicense = Just lStr}
199 <|> do reserved "homepage"
201 www <- many (satisfy (not . isEol))
205 put st {pkghomepage = Just www}
207 <|> do reserved "sourceloc"
209 srcpage <- many (satisfy (not . isEol))
213 put st {pkgsourceloc = Just srcpage}
215 <|> do reserved "bugtracker"
217 src <- many (satisfy (not . isEol))
221 put st {pkgbugtracker = Just src}
223 <|> do reserved "brief"
225 brief <- stringLiteral
228 put st {pkgbrief = Just brief}
230 <|> do reserved "author"; lchar '=';
231 author <- many (satisfy (not . isEol))
235 put st {pkgauthor = Just author}
237 <|> do reserved "maintainer"; lchar '=';
238 maintainer <- many (satisfy (not . isEol))
242 put st {pkgmaintainer = Just maintainer}
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