hcdu/app/Main.hs

126 lines
3.8 KiB
Haskell
Raw Normal View History

2023-10-16 09:07:50 +00:00
{-# LANGUAGE BlockArguments #-}
2023-10-12 13:01:36 +00:00
module Main where
2023-10-14 11:49:13 +00:00
import System.Posix.Directory ( getWorkingDirectory )
import System.Directory ( pathIsSymbolicLink
, doesFileExist
, getFileSize
, doesDirectoryExist )
import Data.Functor ( (<&>) )
import Control.Monad ( filterM )
import System.Directory.Extra ( listContents )
import Brick
2023-10-16 09:07:50 +00:00
import Brick.Widgets.Edit
2023-10-14 11:49:13 +00:00
import Graphics.Vty
import Data.List.Extra
import qualified Data.Ord
2023-10-16 09:07:50 +00:00
import Data.Maybe
2023-10-12 14:37:54 +00:00
2023-10-13 13:54:57 +00:00
listNonSymFiles :: FilePath -> IO [FilePath]
2023-10-16 09:07:50 +00:00
listNonSymFiles dir = filterM ((not <$>) . pathIsSymbolicLink) =<< filterM doesFileExist =<< listContents dir
2023-10-12 14:37:54 +00:00
2023-10-13 13:54:57 +00:00
listNonSymDirectories :: FilePath -> IO [FilePath]
2023-10-16 09:07:50 +00:00
listNonSymDirectories dir = filterM ((not <$>) . pathIsSymbolicLink) =<< filterM doesDirectoryExist =<< listContents dir
listSym :: FilePath -> IO [FilePath]
listSym dir = filterM pathIsSymbolicLink =<< listContents dir
2023-10-13 13:24:26 +00:00
2023-10-13 13:54:57 +00:00
getSizeSubpaths :: FilePath -> IO [(FilePath, Integer)]
getSizeSubpaths x = do
sub <- listNonSymDirectories x
subby <- mapM (\y -> (y,) . sum . map snd <$> getSizeSubpaths y) sub
2023-10-16 09:07:50 +00:00
syms <- listSym x
2023-10-13 13:54:57 +00:00
local <- listNonSymFiles x >>= (\y -> mapM getFileSize y <&> zip y)
2023-10-16 09:07:50 +00:00
pure $ sortOn (Data.Ord.Down . snd) $ local ++ subby ++ zip syms [0..0]
2023-10-14 11:35:22 +00:00
data AppS = AppS
{
_appCWD :: FilePath
, _appCursor :: Int
, _appFocus :: Maybe FilePath
, _appSubFiles :: [(FilePath, Integer)]
}
data ScrollDirection where
SUp :: ScrollDirection
SDown :: ScrollDirection
ui :: Widget ()
ui = viewport () Vertical $ str "Svamp är gott"
2023-10-16 09:07:50 +00:00
app :: App AppS e ()
2023-10-14 11:35:22 +00:00
app =
2023-10-16 09:07:50 +00:00
App { appDraw = pure . browse
2023-10-14 11:35:22 +00:00
, appHandleEvent = resizeOrQuit
, appStartEvent = pure ()
2023-10-16 09:07:50 +00:00
, appAttrMap = attributeMap
, appChooseCursor = showFirstCursor
2023-10-14 11:35:22 +00:00
}
2023-10-16 09:07:50 +00:00
attributeMap :: AppS -> AttrMap
attributeMap = const $ attrMap defAttr
[ (attrName "selected", withStyle defAttr reverseVideo)
, (editAttr, fg brightBlack)
]
select :: Widget () -> Widget ()
select = withAttr (attrName "selected")
browse :: AppS -> Widget ()
browse s =
str "Path" <+> padLeft Max (str "Size") <=>
viewport () Vertical (foldr (widgetCons s) emptyWidget (_appSubFiles s))
widgetCons :: AppS -> (FilePath, Integer) -> Widget () -> Widget ()
widgetCons s w@(f,_) ws = (<=> ws) if Just f == _appFocus s then
select . visible $ pathWidget w
else pathWidget w
pathWidget :: (FilePath, Integer) -> Widget ()
pathWidget (f, s) = str (show f) <+> padLeft Max (str (show s))
2023-10-14 11:35:22 +00:00
sizeDir :: AppS -> IO AppS
sizeDir s = do
subFiles <- getSizeSubpaths $ _appCWD s
pure $ s {_appSubFiles = subFiles}
2023-10-16 09:07:50 +00:00
changeDir :: AppS -> IO AppS
changeDir so
| isJust $ _appFocus so =
let s = so {
_appCWD = fromJust $ _appFocus so
, _appSubFiles = []
} in
sizeDir s
| otherwise = pure so
2023-10-14 11:35:22 +00:00
scroll :: ScrollDirection -> AppS -> AppS
scroll d s = s {
_appCursor = newCursor
, _appFocus = maybeNewPath
}
where cursor =
_appCursor s +
case d of
SUp -> (-1)
SDown -> 1
newCursor = max 0 (min ((-) 1 . length $ _appSubFiles s) cursor)
maybeNewPath = fst <$> _appSubFiles s !? newCursor
2023-10-16 09:07:50 +00:00
initialState :: FilePath -> AppS
initialState f = AppS {
_appCWD = f
, _appCursor = 0
, _appFocus = pure f
, _appSubFiles = []
}
2023-10-12 14:37:54 +00:00
2023-10-12 13:01:36 +00:00
main :: IO ()
2023-10-12 14:37:54 +00:00
main = do
2023-10-13 13:24:26 +00:00
a <- getWorkingDirectory
2023-10-16 09:07:50 +00:00
b <- changeDir $ initialState a
_ <- defaultMain app b
return ()