mirror of https://github.com/voidlizard/hbs2
130 lines
3.3 KiB
Haskell
130 lines
3.3 KiB
Haskell
{-# Language MultiWayIf #-}
|
|
module Data.Config.Suckless.System where
|
|
|
|
import Data.Function
|
|
import System.FilePath
|
|
import System.Directory qualified as D
|
|
import System.IO.Temp qualified as Temp
|
|
import Data.ByteString.Lazy qualified as LBS
|
|
import UnliftIO
|
|
import Control.Exception qualified as E
|
|
import Control.Monad
|
|
|
|
import Streaming.Prelude qualified as S
|
|
|
|
data MkDirOpt = MkDirOptNone
|
|
|
|
class HasMkDirOptions a where
|
|
mkdirOpts :: a -> [MkDirOpt]
|
|
|
|
instance HasMkDirOptions FilePath where
|
|
mkdirOpts = mempty
|
|
|
|
class ToFilePath a where
|
|
toFilePath :: a -> FilePath
|
|
|
|
instance ToFilePath FilePath where
|
|
toFilePath = id
|
|
|
|
mkdir :: (MonadIO m, ToFilePath a) => a -> m ()
|
|
mkdir a = do
|
|
void $ liftIO $ E.try @SomeException (D.createDirectoryIfMissing True (toFilePath a))
|
|
|
|
data TouchOpt = TouchEasy | TouchHard
|
|
deriving stock (Eq,Ord,Show)
|
|
|
|
class ToFilePath a => HasTouchOpts a where
|
|
touchOpts :: a -> [TouchOpt]
|
|
|
|
instance HasTouchOpts FilePath where
|
|
touchOpts = const [TouchEasy]
|
|
|
|
touch :: (MonadIO m, HasTouchOpts a) => a -> m ()
|
|
touch what = do
|
|
here <- doesPathExist fn
|
|
dir <- doesDirectoryExist fn
|
|
|
|
when (not here || hard) do
|
|
mkdir (takeDirectory fn)
|
|
unless dir do
|
|
liftIO $ LBS.appendFile fn mempty
|
|
|
|
where
|
|
hard = TouchHard `elem` touchOpts what
|
|
fn = toFilePath what
|
|
|
|
pwd :: MonadIO m => m FilePath
|
|
pwd = liftIO D.getCurrentDirectory
|
|
|
|
|
|
doesPathExist :: MonadIO m => FilePath -> m Bool
|
|
doesPathExist = liftIO . D.doesPathExist
|
|
|
|
canonicalizePath :: MonadIO m => FilePath -> m FilePath
|
|
canonicalizePath = liftIO . D.canonicalizePath
|
|
|
|
expandPath :: MonadIO m => FilePath -> m FilePath
|
|
expandPath = liftIO . D.canonicalizePath
|
|
|
|
doesDirectoryExist :: MonadIO m => FilePath -> m Bool
|
|
doesDirectoryExist = liftIO . D.doesDirectoryExist
|
|
|
|
doesFileExist :: MonadIO m => FilePath -> m Bool
|
|
doesFileExist = liftIO . D.doesFileExist
|
|
|
|
|
|
fileSize :: MonadIO m => FilePath -> m Integer
|
|
fileSize = liftIO . D.getFileSize
|
|
|
|
mv :: MonadIO m => FilePath -> FilePath -> m ()
|
|
mv a b = liftIO $ D.renamePath a b
|
|
|
|
rm :: MonadIO m => FilePath -> m ()
|
|
rm fn = liftIO $ D.removePathForcibly fn
|
|
|
|
home :: MonadIO m => m FilePath
|
|
home = liftIO D.getHomeDirectory
|
|
|
|
cd :: MonadIO m => FilePath -> m()
|
|
cd = liftIO . D.setCurrentDirectory
|
|
|
|
data DirEntry =
|
|
EntryFile { dirEntryPath :: FilePath }
|
|
| EntryDir { dirEntryPath :: FilePath }
|
|
| EntryOther { dirEntryPath :: FilePath }
|
|
|
|
dirFiles :: MonadIO m => FilePath -> m [FilePath]
|
|
dirFiles d = S.toList_ $ do
|
|
dirEntries d $ \case
|
|
EntryFile f -> S.yield f >> pure True
|
|
_ -> pure True
|
|
|
|
dirEntries :: MonadIO m => FilePath -> ( DirEntry -> m Bool ) -> m ()
|
|
dirEntries dir what = do
|
|
es <- liftIO $ D.listDirectory dir
|
|
|
|
flip fix es $ \next -> \case
|
|
[] -> pure ()
|
|
(x:xs) -> do
|
|
let entry = dir </> x
|
|
isFile <- liftIO (D.doesFileExist entry)
|
|
isDir <- liftIO (D.doesDirectoryExist entry)
|
|
if | isFile -> continueThen (what (EntryFile entry)) (next xs)
|
|
| isDir -> continueThen (what (EntryDir entry)) (next xs)
|
|
| otherwise -> continueThen (what (EntryOther entry)) (next xs)
|
|
|
|
where
|
|
continueThen a b = do
|
|
r <- a
|
|
when r b
|
|
|
|
sysTempDir :: MonadIO m => m FilePath
|
|
sysTempDir = do
|
|
tmp1 <- liftIO D.getTemporaryDirectory
|
|
tmp2 <- liftIO $ Temp.getCanonicalTemporaryDirectory
|
|
pure $ if null tmp1 then tmp2 else tmp1
|
|
|
|
|
|
|
|
|