tinyapp (empty) → 0.1.0.0
raw patch · 5 files changed
+120/−0 lines, 5 filesdep +basedep +tinyapp
Dependencies added: base, tinyapp
Files
- CHANGELOG.md +5/−0
- LICENSE +20/−0
- src/TinyApp/Repl.hs +48/−0
- test/Main.hs +4/−0
- tinyapp.cabal +43/−0
+ CHANGELOG.md view
@@ -0,0 +1,5 @@+# Revision history for tinyapp++## 0.1.0.0 -- 2024-07-18++* First version.
+ LICENSE view
@@ -0,0 +1,20 @@+Copyright (c) 2024 Brian J. Cardiff++Permission is hereby granted, free of charge, to any person obtaining+a copy of this software and associated documentation files (the+"Software"), to deal in the Software without restriction, including+without limitation the rights to use, copy, modify, merge, publish,+distribute, sublicense, and/or sell copies of the Software, and to+permit persons to whom the Software is furnished to do so, subject to+the following conditions:++The above copyright notice and this permission notice shall be included+in all copies or substantial portions of the Software.++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ src/TinyApp/Repl.hs view
@@ -0,0 +1,48 @@+-- | Build REPL apps+module TinyApp.Repl where++import Control.Exception+import Control.Monad+import System.IO++-- | Signals whether the REPL should continue asking input from the user or exit.+data ContinueExit = Continue | Exit+ deriving (Eq, Show)++-- | Defines a REPL application that is not allows to perform arbitrary IO while executing.+data Sandbox state = Sandbox+ { -- | Initial state+ initialize :: state,+ -- | The prompt to show. It can depend on the state+ prompt :: state -> String,+ -- | Process the user input given the current state+ -- Returns the next state, the output and whether to continue or not the program+ update :: String -> state -> (state, String, ContinueExit)+ }++-- | Executes the REPL application.+runRepl :: Sandbox s -> IO ()+runRepl = Control.Monad.void . runRepl'++-- | Executes the REPL application returning its final state.+runRepl' :: forall s. Sandbox s -> IO s+runRepl' config =+ let go :: s -> IO s+ go state = do+ System.IO.putStr (config.prompt state)+ -- Since the prompt does not finish in a newline we force a flush right after+ hFlush stdout+ -- When Control-D an exception is thrown+ input <- Control.Exception.catch @IOException (Just <$> System.IO.getLine) (\_ -> pure Nothing)+ case input of+ Nothing -> pure state+ Just input' -> do+ let (state', output, continue) = config.update input' state+ System.IO.putStrLn output+ case continue of+ Continue ->+ go state'+ Exit ->+ pure state'+ in do+ go config.initialize
+ test/Main.hs view
@@ -0,0 +1,4 @@+module Main (main) where++main :: IO ()+main = putStrLn "Test suite not yet implemented."
+ tinyapp.cabal view
@@ -0,0 +1,43 @@+cabal-version: 3.0+name: tinyapp+version: 0.1.0.0+synopsis: Library to build tiny apps in Haskell+description: Library to build tiny apps in Haskell such a REPLs+homepage: https://github.com/bcardiff/haskell-tinyapp+license: MIT+license-file: LICENSE+author: Brian J. Cardiff+maintainer: bcardiff@gmail.com+-- copyright:+build-type: Simple+extra-doc-files: CHANGELOG.md+-- extra-source-files:+category: REPL, Command Line++common warnings+ ghc-options: -Wall++library+ import: warnings+ exposed-modules:+ TinyApp.Repl+ -- other-modules:+ -- other-extensions:+ build-depends:+ base ^>=4.17.2.1+ hs-source-dirs: src+ default-language: GHC2021+ default-extensions:+ OverloadedRecordDot++test-suite tinyapp-test+ import: warnings+ default-language: GHC2021+ -- other-modules:+ -- other-extensions:+ type: exitcode-stdio-1.0+ hs-source-dirs: test+ main-is: Main.hs+ build-depends:+ base ^>=4.17.2.1,+ tinyapp