@@ -15,6 +15,7 @@ import Idris.CmdOptions
15import Control.Monad.State.Strict
15import Control.Monad.State.Strict
16import Control.Applicative
16import Control.Applicative
17import System.FilePath (takeFileName, isValid)
17import System.FilePath (takeFileName, isValid)
18+import Data.Maybe (isNothing, fromJust)
19import Util.System
20import Util.System
@@ -79,18 +80,33 @@ filename = (do
79 -- Through at least version 0.9.19.1, IPKG executable values were
80 -- Through at least version 0.9.19.1, IPKG executable values were
80 -- possibly namespaced identifiers, like foo.bar.baz.
81 -- possibly namespaced identifiers, like foo.bar.baz.
81 show <$> fst <$> iName []
82 show <$> fst <$> iName []
82− if isValidFilename filename
83+ let errorMessage = filenameErrorMessage filename
84+ if isNothing errorMessage
83 then return filename
85 then return filename
84− else fail "a filename must be non-empty and have no directory component")
86+ else fail $ fromJust errorMessage)
85 <?> "filename"
87 <?> "filename"
87− isValidFilename :: FilePath -> Bool
89+ -- TODO: Report failing span better! We could lookAhead,
88− isValidFilename path =
90+ -- or do something with DeltaParsing?
89− and [isNonEmpty, isValidPath, hasNoDirectoryComponent]
91+ filenameErrorMessage :: FilePath -> Maybe String
92+ filenameErrorMessage path = either Just (const Nothing) $ do
95+ checkNoDirectoryComponent path
91− isNonEmpty = path /= ""
97+ checkThat ok message =
98+ if ok then Right () else Left message
101+ checkThat (path /= "") "filename must not be empty"
92− isValidPath = System.FilePath.isValid path
104+ checkThat (System.FilePath.isValid path)
105+ "filename must contain only valid characters"
107+ checkNoDirectoryComponent path =
93− hasNoDirectoryComponent = path == takeFileName path
108+ checkThat (path == takeFileName path)
109+ "filename must contain no directory component"
96pClause :: PParser ()
112pClause :: PParser ()