packages feed

elm-repl-0.2.1: src/Repl.hs

module Main where

import Control.Monad
import Control.Monad.Trans
import Data.Functor ((<$))
import System.Console.Haskeline hiding (handle)
import System.Directory
import System.Exit
import System.FilePath ((</>))

import qualified System.Console.CmdArgs as CmdArgs

import Monad

import qualified Action      as Act
import qualified Command     as Cmd
import qualified Completion
import qualified Evaluator   as Eval
import qualified Environment as Env
import qualified Flags
import qualified Parse

main :: IO ()
main = do
  flags <- CmdArgs.cmdArgs Flags.flags
  buildExisted <- doesDirectoryExist "build"
  cacheExisted <- doesDirectoryExist "cache"
  settings     <- mkSettings
  putStrLn welcomeMessage
  let mt = Env.empty (Flags.compiler flags)
  exitCode <- runReplM flags mt . runInputT settings . withInterrupt $ repl
  unless buildExisted (removeDirectoryRecursive "build")
  unless cacheExisted (removeDirectoryRecursive "cache")
  exitWith exitCode

repl :: InputT ReplM ExitCode
repl = do
  str' <- handleInterrupt (return . Just $ "") getInput
  case str' of
    Nothing -> return ExitSuccess
    Just str -> do
      let act = Parse.input str
      m <- lift $ handle act
      case m of
        Just exit -> return exit
        Nothing   -> repl

handle :: Act.Action -> ReplM (Maybe ExitCode)
handle (Act.Command cmd) = Cmd.run cmd
handle (Act.Code src)    = Nothing <$ Eval.evalPrint src
handle (Act.Skip)        = return Nothing

getInput :: (MonadException m) => InputT m (Maybe String)
getInput = go "> " ""
    where
      go str old = do
        input <- getInputLine str
        case input of
          Nothing  -> return Nothing
          Just new -> continueWith (old ++ new)

      continueWith str
        | null str || last str /= '\\' = return $ Just str
        | otherwise = go "| " (init str ++ "\n")

welcomeMessage :: String
welcomeMessage =
    "Elm REPL " ++ Flags.version ++
    " <https://github.com/elm-lang/elm-repl#elm-repl>\n\
    \Type :help for help, :exit to exit"

elmdir :: IO FilePath
elmdir = do
  dir <- (</> "repl") `fmap` getAppUserDataDirectory "elm"
  createDirectoryIfMissing True dir
  return dir

mkSettings :: IO (Settings ReplM)
mkSettings = do
  historyFile <- (</> "history") `fmap` elmdir
  return $ Settings { historyFile    = Just historyFile
                    , autoAddHistory = True
                    , complete       = Completion.complete
                    }