/src/Local.hs

http://github.com/Eelis/geordi · Haskell · 71 lines · 59 code · 11 blank · 1 comment · 7 complexity · 605df44cde7e605f181913df7d89cdd2 MD5 · raw file

  1. {-# LANGUAGE UnicodeSyntax, CPP #-}
  2. import qualified System.Environment
  3. import qualified RequestEval
  4. import qualified System.Console.Readline as RL
  5. import qualified Codec.Binary.UTF8.String as UTF8
  6. import qualified Cxx.Show
  7. import Request (Response(..), HistoryModification(..), Context(..), modify_history)
  8. import Control.Monad (forM_, when)
  9. import Control.Monad.Fix (fix)
  10. import System.IO (utf8, stdout, hSetEncoding)
  11. import System.Console.GetOpt (OptDescr(..), ArgDescr(..), ArgOrder(..), getOpt, usageInfo)
  12. import System.Locale.SetLocale (setLocale, Category(..))
  13. import Data.IORef (newIORef, readIORef, writeIORef)
  14. import Prelude hiding ((.), readFile)
  15. import Util
  16. data Opt = Help deriving Eq
  17. optsDesc :: [OptDescr Opt]
  18. optsDesc = [Option "h" ["help"] (NoArg Help) "Display this help and exit."]
  19. help :: String
  20. help = usageInfo "Usage: sudo geordi-local [option]... [request]...\nOptions:" optsDesc ++ "\nSee README.xhtml for more information."
  21. getArgs :: IO ([Opt], [String])
  22. getArgs = do
  23. args System.Environment.getArgs
  24. case getOpt RequireOrder optsDesc args of
  25. (_, _, err:_) fail $ init err
  26. (opts, rest, []) return (opts, rest)
  27. make_history_adder :: IO (String IO ())
  28. make_history_adder = do
  29. r newIORef Nothing
  30. return $ \s do
  31. prev readIORef r
  32. when (Just s prev) $ do
  33. RL.addHistory s
  34. writeIORef r (Just s)
  35. data Memory = Memory { context :: Context, last_outputs :: [String] }
  36. blankMemory :: Memory
  37. blankMemory = Memory (Context Cxx.Show.noHighlighting False []) []
  38. main :: IO ()
  39. main = do
  40. setLocale LC_ALL (Just "")
  41. hSetEncoding stdout utf8
  42. RL.initialize -- Reads stuff from files not present in the chroot.
  43. (opts, rest) getArgs
  44. if Help opts then putStrLn help else do
  45. eval RequestEval.evaluator
  46. forM_ rest $ \l do Request.Response _ output eval l (Context Cxx.Show.noHighlighting False []) []; putStrLn output
  47. addHistory make_history_adder
  48. when (rest == []) $ flip fix blankMemory $ \loop mem RL.readline "geordi: " >>= \line case line of
  49. Nothing putNewLn
  50. Just "" loop mem
  51. Just l do
  52. Response history_modification output eval l (context mem) []
  53. case history_modification of
  54. Just (AddLast e) addHistory $ UTF8.encodeString $ show $ fst e
  55. Just (ReplaceLast e) addHistory $ UTF8.encodeString $ show $ fst e
  56. _ return ()
  57. putStrLn $ describe_new_output (last_outputs mem) output
  58. loop Memory
  59. { context = maybe id modify_history history_modification $ context mem
  60. , last_outputs = output : last_outputs mem }