on d87affe help sign in
elk/src/Elm/Utils.hs
119 lines 3.6 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)
14{-| Forward function application `x |> f == f x`. This function is useful
15for avoiding parenthesis and writing code in a more natural way.
16-}
17(|>) :: a -> (a -> b) -> b
18x |> f = f x
21{-| Backward function application `f <| x == f x`. This function is useful for
22avoiding parenthesis.
23-}
24(<|) :: (a -> b) -> a -> b
25f <| x = f x
28infixr 0 <|
29infixl 0 |>
32-- RUN EXECUTABLES
34data CommandError
35 = MissingExe String
36 | CommandFailed String String
39{-| Run a command, throw an error if the command is not found or if something
40goes wrong.
41-}
42run :: (MonadError String m, MonadIO m) => String -> [String] -> m String
43run command args =
44 do result <- liftIO (unwrappedRun command args)
45 case result of
46 Right out -> return out
47 Left err ->
48 throwError (context (message err))
49 where
50 context msg =
51 "failure when running:" ++ concatMap (' ':) (command:args) ++ "\n" ++ msg
53 message err =
54 case err of
55 CommandFailed stderr stdout ->
56 stdout ++ stderr
57 MissingExe msg ->
58 msg
61unwrappedRun :: String -> [String] -> IO (Either CommandError String)
62unwrappedRun command args =
63 do (exitCode, stdout, stderr) <- readProcessWithExitCode command args ""
64 return $
65 case exitCode of
66 ExitSuccess -> Right stdout
67 ExitFailure code
68 | code == 127 -> Left (missingExe command) -- UNIX
69 | code == 9009 -> Left (missingExe command) -- Windows
70 | otherwise -> Left (CommandFailed stdout stderr)
73missingExe :: String -> CommandError
74missingExe command =
75 MissingExe $
76 "Could not find command '" ++ command ++ "'. Do you have it installed?\n\
77 \ Can it be run from anywhere? Is it on your PATH?"
81-- GET STATIC ASSETS
83{-| Get the absolute path to a data file. If you install with cabal it will look
84-}
85getAsset :: String -> (FilePath -> IO FilePath) -> FilePath -> IO FilePath
86getAsset project getDataFileName name =
87 do path <- getDataFileName name
88 exists <- doesFileExist path
89 if exists
90 then return path
91 else do
92 environment <- tryIOError (getEnv "ELM_HOME")
93 case environment of
94 Right env ->
95 return (env </> project </> name)
97 Left _ ->
98 fail (errorNotFound name)
101errorNotFound :: FilePath -> String
102errorNotFound name =
103 unlines
104 [ "Unable to find the ELM_HOME environment variable when searching"
105 , "for the " ++ name ++ " file."
106 , ""
107 , "If you installed Elm Platform with the Mac or Windows installer, it looks like"
108 , "ELM_HOME was not set automatically. Look up how to set environment variables"
109 , "on your platform and set ELM_HOME to the directory that contains Elm's static"
110 , "files:"
111 , ""
112 , " * On Mac it is /usr/local/share/elm"
113 , " * On Windows it is one of the following:"
114 , " C:/Program Files/Elm Platform/0.13/share"
115 , " C:/Program Files (x86)/Elm Platform/0.13/share"
116 , ""
117 , "If it seems like a more complex issue, please report it here:"
118 , " <https://github.com/elm-lang/elm-platform/issues>"
119 ]