10import Control.Monad.Catch
11import Prelude hiding (readFile, writeFile)
12import qualified Control.Exception as E
13import qualified Data.Map.Strict as M
14import qualified System.IO as IO
19-- | Effect for reading and writing files.
20data FileSystem = forall fs. FileSystem
22 , _readFile :: forall es. Error FsError :> es => fs -> FilePath -> Eff es String
23 , _writeFile :: forall es. Error FsError :> es => fs -> FilePath -> String -> Eff es fs
26-- | File system error.
27newtype FsError = FsError String
29instance Exception FsError
31----------------------------------------
34-- | Read contents of a file.
35readFile :: (FileSystem :> es, Error FsError :> es) => FilePath -> Eff es String
36readFile path = readerEffectM $ \FileSystem{..} -> _readFile _fs path
38-- | Write contents to a file.
39writeFile :: (FileSystem :> es, Error FsError :> es) => FilePath -> String -> Eff es ()
40writeFile path contents = stateEffectM $ \FileSystem{..} -> do
41 fs <- _writeFile _fs path contents
42 pure ((), FileSystem { _fs = fs, .. })
44----------------------------------------
47runFileSystemIO :: Eff (FileSystem : es) a -> Eff es a
48runFileSystemIO = evalEffect $ FileSystem
50 , _readFile = \() path -> wrap $ IO.readFile path
51 , _writeFile = \() path contents -> wrap $ IO.writeFile path contents
54 wrap m = impureEff_ m `catch` \(e::E.IOException) -> throwError . FsError $ show e
56runFileSystemPure :: M.Map FilePath String -> Eff (FileSystem : es) a -> Eff es a
57runFileSystemPure fs0 = evalEffect $ FileSystem
59 , _readFile = \fs path -> case path `M.lookup` fs of
60 Just contents -> pure contents
61 Nothing -> throwError . FsError $ "File not found: " ++ show path
62 , _writeFile = \fs path contents -> pure $ M.insert path contents fs
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list