content: {-# LANGUAGE UnicodeSyntax, CPP #-}
  
  import qualified System.Environment
  import qualified RequestEval
  import qualified System.Console.Readline as RL
  import qualified Codec.Binary.UTF8.String as UTF8
  import qualified Cxx.Show
  
  import Request (Response(..), HistoryModification(..), Context(..), modify_history)
  import Control.Monad (forM_, when)
  import Control.Monad.Fix (fix)
  import System.IO (utf8, stdout, hSetEncoding)
  import System.Console.GetOpt (OptDescr(..), ArgDescr(..), ArgOrder(..), getOpt, usageInfo)
  import System.Locale.SetLocale (setLocale, Category(..))
  import Data.IORef (newIORef, readIORef, writeIORef)
  
  import Prelude hiding ((.), readFile)
  import Util
  
  data Opt = Help deriving Eq
  
  optsDesc :: [OptDescr Opt]
  optsDesc = [Option "h" ["help"] (NoArg Help) "Display this help and exit."]
  
  help :: String
  help = usageInfo "Usage: sudo geordi-local [option]... [request]...\nOptions:" optsDesc ++ "\nSee README.xhtml for more information."
  
  getArgs :: IO ([Opt], [String])
  getArgs = do
    args ← System.Environment.getArgs
    case getOpt RequireOrder optsDesc args of
      (_, _, err:_) → fail $ init err
      (opts, rest, []) → return (opts, rest)
  
  make_history_adder :: IO (String → IO ())
  make_history_adder = do
    r ← newIORef Nothing
    return $ \s → do
      prev ← readIORef r
      when (Just s ≠ prev) $ do
        RL.addHistory s
        writeIORef r (Just s)
  
  data Memory = Memory { context :: Context, last_outputs :: [String] }
  
  blankMemory :: Memory
  blankMemory = Memory (Context Cxx.Show.noHighlighting False []) []
  
  main :: IO ()
  main = do
   setLocale LC_ALL (Just "")
   hSetEncoding stdout utf8
   RL.initialize -- Reads stuff from files not present in the chroot.
   (opts, rest) ← getArgs
   if Help ∈ opts then putStrLn help else do
    eval ← RequestEval.evaluator
    forM_ rest $ \l → do Request.Response _ output ← eval l (Context Cxx.Show.noHighlighting False []) []; putStrLn output
    addHistory ← make_history_adder
    when (rest == []) $ flip fix blankMemory $ \loop mem → RL.readline "geordi: " >>= \line → case line of
      Nothing → putNewLn
      Just "" → loop mem
      Just l → do
        Response history_modification output ← eval l (context mem) []
        case history_modification of
          Just (AddLast e) → addHistory $ UTF8.encodeString $ show $ fst e
          Just (ReplaceLast e) → addHistory $ UTF8.encodeString $ show $ fst e
          _ → return ()
        putStrLn $ describe_new_output (last_outputs mem) output
        loop Memory
          { context = maybe id modify_history history_modification $ context mem
          , last_outputs = output : last_outputs mem }
  