Main.hs 2.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. {-# LANGUAGE OverloadedStrings #-}
  2. {-# LANGUAGE OverloadedLists #-}
  3. {-# LANGUAGE TypeFamilies #-}
  4. module Main where
  5. import qualified Control.Monad as M
  6. import qualified Data.IORef as IO
  7. import qualified Data.Map.Strict as Map
  8. import Data.Monoid ((<>))
  9. import qualified Data.Text as Text
  10. import qualified Data.Text.IO as Text
  11. import qualified System.Console.Readline as Readline
  12. import qualified System.Environment as Env
  13. import qualified System.Exit as Exit
  14. import qualified Parser
  15. import qualified Types
  16. readMap :: FilePath -> IO Types.TableMap
  17. readMap path = do
  18. cs <- Text.readFile path
  19. pure $ Map.fromList
  20. [ (Types.tableName t, t)
  21. | t <- Parser.parseTable cs
  22. ]
  23. main :: IO ()
  24. main = do
  25. args <- Env.getArgs
  26. let filename = case args of
  27. path:_ -> path
  28. _ -> "perilous-wilds.txt"
  29. tablesRef <- IO.newIORef =<< readMap filename
  30. Readline.setCompletionEntryFunction $ Just $ \ rs -> do
  31. tables <- IO.readIORef tablesRef
  32. pure [ Text.unpack k
  33. | k <- Map.keys tables
  34. , Text.pack rs `Text.isPrefixOf` k
  35. ]
  36. M.forever $ do
  37. input <- Readline.readline "\x1b[31m--> \x1b[39m"
  38. case input of
  39. Nothing -> do
  40. putStrLn "farewell"
  41. Exit.exitSuccess
  42. Just ":q" -> do
  43. putStrLn "farewell"
  44. Exit.exitSuccess
  45. Just "" -> pure ()
  46. Just ":l" -> do
  47. tables <- IO.readIORef tablesRef
  48. Text.putStrLn "Available tables: "
  49. Text.putStrLn (" " <> Text.unwords (Map.keys tables))
  50. Just ":r" ->
  51. IO.writeIORef tablesRef =<< readMap filename
  52. Just choice -> do
  53. tables <- IO.readIORef tablesRef
  54. let names = Text.unwords (Map.keys tables)
  55. Readline.addHistory choice
  56. case Map.lookup (Text.strip (Text.pack choice)) tables of
  57. Nothing -> do
  58. Text.putStrLn ("table not found: " <> Text.pack (show choice))
  59. Text.putStrLn (" valid tables include: " <> names)
  60. Just t -> do
  61. v <- Types.rollTable tables t
  62. showValueAndRolls v
  63. -- | simply show the value generated
  64. showValue :: Types.Value -> IO ()
  65. showValue value = Text.putStrLn (Types.valueMsg value)
  66. -- | pretty-print the value as well as each roll that was done on an
  67. -- intermediate table
  68. showValueAndRolls :: Types.Value -> IO ()
  69. showValueAndRolls value = go 0 value
  70. where
  71. go n v
  72. | Text.null (Text.strip (Types.valueMsg v)) = pure ()
  73. | otherwise = do
  74. Text.putStr "\x1b[36m"
  75. Text.putStr (Text.replicate (n+1) " ")
  76. putStr (show (Types.valueResult v))
  77. Text.putStr " on "
  78. Text.putStr (Types.valueFrom v)
  79. M.when (null (Types.valueSources v)) $ do
  80. Text.putStr ": \""
  81. Text.putStr (Text.strip (Types.valueMsg v))
  82. Text.putStr "\""
  83. Text.putStrLn "\x1b[39m"
  84. mapM_ (go (n+1)) (Types.valueSources v)
  85. M.when (n == 0) $
  86. Text.putStrLn (Types.valueMsg v)