Main.hs 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. {-# LANGUAGE OverloadedStrings #-}
  2. {-# LANGUAGE OverloadedLists #-}
  3. {-# LANGUAGE TypeFamilies #-}
  4. module Main (main) where
  5. import qualified Control.Exception as Exn
  6. import qualified Control.Monad as M
  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 Potrero.Opts as Opts
  15. import qualified Potrero.Parser as Parser
  16. import qualified Potrero.Types as Types
  17. readMap :: FilePath -> IO Types.TableMap
  18. readMap path = do
  19. cs <- Text.readFile path
  20. pure $ Map.fromList
  21. [ (Types.tableName t, t)
  22. | t <- Parser.parseTable cs
  23. ]
  24. main :: IO ()
  25. main = do
  26. args <- Env.getArgs
  27. case Opts.getConfig args of
  28. Left err -> do
  29. putStrLn err
  30. putStrLn Opts.usage
  31. Exit.exitFailure
  32. Right config
  33. | Opts.configMode config == Opts.ShowHelp ->
  34. putStrLn Opts.usage
  35. | Opts.configMode config == Opts.ShowVersion ->
  36. putStrLn Opts.version
  37. | otherwise -> do
  38. maps <- mapM readMap (Opts.configFiles config)
  39. runRepl (Map.unions maps) config
  40. setCompletion :: Types.TableMap -> IO ()
  41. setCompletion tables =
  42. Readline.setCompletionEntryFunction $ Just $ \rs ->
  43. pure [ Text.unpack k
  44. | k <- Map.keys tables
  45. , Text.pack rs `Text.isPrefixOf` k
  46. ]
  47. runRepl :: Types.TableMap -> Opts.Config -> IO ()
  48. runRepl tables config = do
  49. setCompletion tables
  50. let printFunc = case Opts.configShowRolls config of
  51. False -> showValue
  52. True -> showValueAndRolls
  53. input <- Readline.readline "\x1b[31m--> \x1b[39m"
  54. case input of
  55. Nothing -> do
  56. putStrLn "farewell"
  57. Exit.exitSuccess
  58. Just ":q" -> do
  59. putStrLn "farewell"
  60. Exit.exitSuccess
  61. Just "" -> runRepl tables config
  62. Just ":l" -> do
  63. Text.putStrLn "Available tables: "
  64. Text.putStrLn (" " <> Text.unwords (Map.keys tables))
  65. runRepl tables config
  66. Just ":r" -> do
  67. maps <- mapM readMap (Opts.configFiles config)
  68. putStrLn ("reloaded: " <> unwords (Opts.configFiles config))
  69. runRepl (Map.unions maps) config
  70. Just choice -> do
  71. let names = Text.unwords (Map.keys tables)
  72. Readline.addHistory choice
  73. case Map.lookup (Text.strip (Text.pack choice)) tables of
  74. Nothing -> do
  75. Text.putStrLn ("table not found: " <> Text.pack (show choice))
  76. Text.putStrLn (" valid tables include: " <> names)
  77. Just t ->
  78. (Types.rollTable tables t >>= printFunc)
  79. `Exn.catch` handleBadTable
  80. runRepl tables config
  81. handleBadTable :: Types.BadTable -> IO ()
  82. handleBadTable bt = do
  83. let msg = Text.intercalate "\n" (Types.potreroMessage bt)
  84. Text.putStr "\x1b[91m"
  85. Text.putStr msg
  86. Text.putStrLn "\x1b[39m"
  87. -- | simply show the value generated
  88. showValue :: Types.Value -> IO ()
  89. showValue value = Text.putStrLn (Types.valueMsg value)
  90. -- | pretty-print the value as well as each roll that was done on an
  91. -- intermediate table
  92. showValueAndRolls :: Types.Value -> IO ()
  93. showValueAndRolls value = go 0 value
  94. where
  95. go n v
  96. | Text.null (Text.strip (Types.valueMsg v)) = pure ()
  97. | otherwise = do
  98. Text.putStr "\x1b[36m"
  99. Text.putStr (Text.replicate (n+1) " ")
  100. putStr (show (Types.valueResult v))
  101. Text.putStr " on "
  102. Text.putStr (Types.valueFrom v)
  103. M.when (null (Types.valueSources v)) $ do
  104. Text.putStr ": \""
  105. Text.putStr (Text.strip (Types.valueMsg v))
  106. Text.putStr "\""
  107. Text.putStrLn "\x1b[39m"
  108. mapM_ (go (n+1)) (Types.valueSources v)
  109. M.when (n == 0) $
  110. Text.putStrLn (Types.valueMsg v)