1module Gdris23import Gopher4import Client5import Parser6import Menu78import System9import System.File1011import Data.Fin12import Data.Vect13import Data.Strings1415import Network.Socket.Data1617-- Valid REPL input commands.18data Command = Goto Integer | Menu | Exit | Unknown1920-- REPL execution context.21record Context where22 constructor MkCtx23 menu : (List Item)2425-- String used to prompt for input.26prompt : String27prompt = "> "2829newCtx : Context -> (List Item) -> Context30newCtx _ items = MkCtx items3132-- XXX: If this returns a Maybe Monad the totality checker doesn't terminate33lineToCmd : String -> Command34lineToCmd input = case words input of35 ["goto", x] => Goto $ cast x36 ["menu"] => Menu37 ["exit"] => Exit38 _ => Unknown3940readCommand : String -> IO Command41readCommand prompt42 = do eof <- fEOF stdin43 if eof44 then pure Exit45 else do putStr prompt46 fflush stdout47 x <- getLine48 pure $ lineToCmd x4950getItem : Context -> Integer -> Maybe Item51getItem ctx n = let idx = integerToFin n (length ctx.menu) in52 case idx of53 Just f => Just $ index f (fromList ctx.menu)54 Nothing => Nothing5556execTrans : Context -> Item -> IO (Context, String)57execTrans ctx (MkItem Document _ s addr) = do58 out <- makeReq addr s59 pure $ MkPair ctx $ case out of60 Right out => out61 Left err => "makeReq failed: " ++ show err62execTrans ctx (MkItem Directory _ s addr) = do63 out <- makeReq addr s64 case out of65 Right o => do i <- parseAll o66 pure $ case i of67 Right it => MkPair (newCtx ctx it) (showMenu it)68 Left err => MkPair ctx $ show err69 Left err => pure $ MkPair ctx $ "makeReq failed: " ++ show err70execTrans ctx _ = do71 pure $ MkPair ctx "item type not implemented yet"7273execGoto : Context -> Integer -> IO (Context, String)74execGoto ctx n =75 case item of76 Just i => do execTrans ctx i77 Nothing => do pure $ (MkPair ctx "unknown menu item")78 where79 item : Maybe Item80 item = getItem ctx n8182runREPL : Context -> IO ()83runREPL ctx = do84 cmd <- readCommand prompt85 case cmd of86 Goto x => do p <- execGoto ctx x87 putStrLn $ snd p88 runREPL $ fst p89 Menu => do putStrLn $ showMenu ctx.menu90 runREPL ctx91 Unknown => do putStrLn "unknown command"92 runREPL ctx93 Exit => pure ()9495 pure ()9697runClient : Address -> IO ()98runClient addr = do99 Right out <- makeReq addr ""100 | Left err => do putStrLn $ "makeReq failed: " ++ show err101 exitFailure102 Right items <- parseAll out103 | Left err => do putStrLn $ "Parsing failed: " ++ show err104 exitFailure105106 ctx <- pure $ MkCtx items107 putStrLn $ showMenu ctx.menu108109 runREPL ctx110111main : IO ()112main = do113 [prog, host, port] <- getArgs114 | _ => do putStrLn "USAGE: gdris HOST PORT"115 exitFailure116117 runClient (MkPair host (stringToNatOrZ port))