on 501c607 help sign in
elk/src/Elm/Utils.hs
121 lines 3.7 kB history raw
1{-# OPTIONS_GHC -Wall #-}
2{-# LANGUAGE FlexibleContexts #-}
3module Elm.Utils ((|>), (<|), getAsset, run, unwrappedRun, CommandError(..)) where
5import Control.Monad.Error (MonadError, MonadIO, liftIO, throwError)
6import System.Directory (doesFileExist)
7import System.Environment (getEnv)
8import System.Exit (ExitCode(ExitSuccess, ExitFailure))
9import System.FilePath ((</>))
10import System.IO.Error (tryIOError)
11import System.Process (readProcessWithExitCode)
13import qualified Elm.Compiler.Version as Version
16{-| Forward function application `x |> f == f x`. This function is useful
17for avoiding parenthesis and writing code in a more natural way.
18-}
19(|>) :: a -> (a -> b) -> b
20x |> f = f x
23{-| Backward function application `f <| x == f x`. This function is useful for
24avoiding parenthesis.
25-}
26(<|) :: (a -> b) -> a -> b
27f <| x = f x
30infixr 0 <|
31infixl 0 |>
34-- RUN EXECUTABLES
36data CommandError
37 = MissingExe String
38 | CommandFailed String String
41{-| Run a command, throw an error if the command is not found or if something
42goes wrong.
43-}
44run :: (MonadError String m, MonadIO m) => String -> [String] -> m String
45run command args =
46 do result <- liftIO (unwrappedRun command args)
47 case result of
48 Right out -> return out
49 Left err ->
50 throwError (context (message err))
51 where
52 context msg =
53 "failure when running:" ++ concatMap (' ':) (command:args) ++ "\n" ++ msg
55 message err =
56 case err of
57 CommandFailed stderr stdout ->
58 stdout ++ stderr
59 MissingExe msg ->
60 msg
63unwrappedRun :: String -> [String] -> IO (Either CommandError String)
64unwrappedRun command args =
65 do (exitCode, stdout, stderr) <- readProcessWithExitCode command args ""
66 return $
67 case exitCode of
68 ExitSuccess -> Right stdout
69 ExitFailure code
70 | code == 127 -> Left (missingExe command) -- UNIX
71 | code == 9009 -> Left (missingExe command) -- Windows
72 | otherwise -> Left (CommandFailed stdout stderr)
75missingExe :: String -> CommandError
76missingExe command =
77 MissingExe $
78 "Could not find command '" ++ command ++ "'. Do you have it installed?\n\
79 \ Can it be run from anywhere? Is it on your PATH?"
83-- GET STATIC ASSETS
85{-| Get the absolute path to a data file. If you install with cabal it will look
86-}
87getAsset :: String -> (FilePath -> IO FilePath) -> FilePath -> IO FilePath
88getAsset project getDataFileName name =
89 do path <- getDataFileName name
90 exists <- doesFileExist path
91 if exists
92 then return path
93 else do
94 environment <- tryIOError (getEnv "ELM_HOME")
95 case environment of
96 Right env ->
97 return (env </> project </> name)
99 Left _ ->
100 fail (errorNotFound name)
103errorNotFound :: FilePath -> String
104errorNotFound name =
105 unlines
106 [ "Unable to find the ELM_HOME environment variable when searching"
107 , "for the " ++ name ++ " file."
108 , ""
109 , "If you installed Elm Platform with the Mac or Windows installer, it looks like"
110 , "ELM_HOME was not set automatically. Look up how to set environment variables"
111 , "on your platform and set ELM_HOME to the directory that contains Elm's static"
112 , "files:"
113 , ""
114 , " * On Mac it is /usr/local/share/elm"
115 , " * On Windows it is one of the following:"
116 , " C:/Program Files/Elm Platform/" ++ Version.version ++ "/share"
117 , " C:/Program Files (x86)/Elm Platform/" ++ Version.version ++ "/share"
118 , ""
119 , "If it seems like a more complex issue, please report it here:"
120 , " <https://github.com/elm-lang/elm-platform/issues>"
121 ]