packages feed

noise-0.0.1: src-cli/Main.hs

{-# LANGUAGE TupleSections #-}

import           Control.Applicative
import qualified System.Environment as Env
import qualified System.Console.GetOpt as Opt
import qualified System.IO as IO
import qualified Text.Noise.Error as Error
import qualified Text.Noise.Parser as Parser
import qualified Text.Noise.Compiler as Compiler
import qualified Text.Noise.Renderer as Renderer
import qualified Text.Noise.SourceRange as SourceRange

main :: IO ()
main = do
  (flags, files, errors) <- getOptions
  runWithOptions flags files errors

runWithOptions :: [Flag] -> [String] -> [String] -> IO ()
runWithOptions [] files [] = do
  (sourceName, source) <- case files of
    [file] -> (file,) <$> readFile file
    []     -> ("-",)  <$> getContents
    _      -> ioError (userError "multiple input files")
  case Parser.parse sourceName source of
    Left err -> printErr err
    Right ast -> case Compiler.compile ast of
      Left err -> printErr err
      Right doc -> putStr (Renderer.render doc)
  where printErr err = IO.hPutStrLn IO.stderr (showError err)
runWithOptions _ _ _ = putStr helpText

showError :: (Error.Error a) => a -> String
showError err = sourceName ++ ":" ++ line ++ ":" ++ column ++ ": " ++ message
  where message = Error.message err
        range = SourceRange.rangeInSource err
        line = show (SourceRange.startLine range)
        column = show (SourceRange.startColumn range)
        sourceName = SourceRange.sourceName range

data Flag = Help

optionsSpec :: [Opt.OptDescr Flag]
optionsSpec =
  [ Opt.Option "h" ["help"] (Opt.NoArg Help) "Print this help text."
  ]

getOptions :: IO ([Flag], [String], [String])
getOptions = Opt.getOpt Opt.Permute optionsSpec <$> Env.getArgs

helpText :: String
helpText = Opt.usageInfo "Usage: noise [file]" optionsSpec