aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorAkshay Nair <phenax5@gmail.com>2025-10-03 21:57:20 +0530
committerAkshay Nair <phenax5@gmail.com>2025-10-03 21:57:20 +0530
commitb05be850349dbb813d2af6f3ee7a2fc3bf98b8ef (patch)
treedcfb1264b3305ef143f3cb642529b1bb81907197 /lib
parent931cf30e66238432fbf653adda7bd08f05a18e87 (diff)
downloaddaffm-b05be850349dbb813d2af6f3ee7a2fc3bf98b8ef.tar.gz
daffm-b05be850349dbb813d2af6f3ee7a2fc3bf98b8ef.zip
Refactor to Text
Diffstat (limited to 'lib')
-rw-r--r--lib/Daffm/Action/Cmdline.hs27
-rw-r--r--lib/Daffm/Action/Core.hs13
-rw-r--r--lib/Daffm/State.hs28
-rw-r--r--lib/Daffm/Types.hs17
-rw-r--r--lib/Daffm/View.hs62
5 files changed, 76 insertions, 71 deletions
diff --git a/lib/Daffm/Action/Cmdline.hs b/lib/Daffm/Action/Cmdline.hs
index e7376c3..12f7a9d 100644
--- a/lib/Daffm/Action/Cmdline.hs
+++ b/lib/Daffm/Action/Cmdline.hs
@@ -8,7 +8,6 @@ import Control.Monad.State (get, gets, modify)
import Daffm.Action.Core (reloadDir)
import Daffm.Types (AppEvent, AppState (..), FileInfo (..), FocusTarget (..))
import Data.Char (isSpace)
-import Data.List (dropWhileEnd)
import qualified Data.Set as Set
import qualified Data.Text as Text
import qualified Data.Text.Zipper as Z
@@ -21,9 +20,9 @@ leaveCmdline = clearCmdline >> modify (\st -> st {stateFocusTarget = FocusMain})
enterCmdline :: AppEvent ()
enterCmdline = modify (\st -> st {stateFocusTarget = FocusCmdline})
-setCmdlineText :: String -> AppEvent ()
+setCmdlineText :: Text.Text -> AppEvent ()
setCmdlineText text =
- applyCmdlineEdit (const $ Z.stringZipper [text] (Just 1))
+ applyCmdlineEdit (const $ Z.textZipper [text] (Just 1))
clearCmdline :: AppEvent ()
clearCmdline = applyCmdlineEdit Z.clearZipper
@@ -34,17 +33,17 @@ runCmdline = do
evaluateCommand cmd
leaveCmdline
where
- trimCmd = dropWhile isSpace . dropWhileEnd isSpace . unlines
+ trimCmd = Text.dropWhile isSpace . Text.dropWhileEnd isSpace . Text.unlines
-evaluateCommand :: String -> AppEvent ()
-evaluateCommand ('!' : '!' : cmd) = do
- cmd' <- Text.unpack <$> cmdSubstitutions (Text.pack cmd)
+evaluateCommand :: Text.Text -> AppEvent ()
+evaluateCommand (Text.splitAt 2 -> ("!!", cmd)) = do
+ cmd' <- Text.unpack <$> cmdSubstitutions cmd
suspendAndResume' $ do
callCommand cmd'
putStrLn "Press any key to continue" >> void getChar
reloadDir
-evaluateCommand ('!' : cmd) = do
- cmd' <- Text.unpack <$> cmdSubstitutions (Text.pack cmd)
+evaluateCommand (Text.splitAt 1 -> ("!", cmd)) = do
+ cmd' <- Text.unpack <$> cmdSubstitutions cmd
suspendAndResume' $ callCommand cmd'
reloadDir
evaluateCommand "delete" = do
@@ -54,7 +53,7 @@ evaluateCommand "delete" = do
then maybe [] ((: []) . filePath . snd) $ L.listSelectedElement stateFiles
else Set.elems stateFileSelections
unless (null files) $ do
- suspendAndResume' $ callProcess "rm" ("-rfi" : files)
+ suspendAndResume' $ callProcess "rm" ("-rfi" : map Text.unpack files)
reloadDir
evaluateCommand _cmd = pure ()
@@ -63,16 +62,16 @@ cmdSubstitutions cmd = do
(AppState {stateFiles, stateCwd, stateFileSelections}) <- get
let file = maybe "" (filePath . snd) . L.listSelectedElement $ stateFiles
let escape = (\s -> "'" <> s <> "'") . Text.replace "'" "\\'"
- let selections = map Text.pack $ Set.elems stateFileSelections
+ let selections = Set.elems stateFileSelections
-- TODO: Escaping %
let subst =
- Text.replace "%" (Text.pack file)
- . Text.replace "%d" (Text.pack stateCwd)
+ Text.replace "%" file
+ . Text.replace "%d" stateCwd
. Text.replace "%s" (Text.unwords $ map escape selections)
. Text.replace "%S" (Text.dropWhileEnd (== '\n') $ Text.unlines selections)
pure . subst $ cmd
-applyCmdlineEdit :: (Zipper.TextZipper String -> Zipper.TextZipper String) -> AppEvent ()
+applyCmdlineEdit :: (Zipper.TextZipper Text.Text -> Zipper.TextZipper Text.Text) -> AppEvent ()
applyCmdlineEdit zipper = do
editor <- gets stateCmdlineEditor
let editor' = Editor.applyEdit zipper editor
diff --git a/lib/Daffm/Action/Core.hs b/lib/Daffm/Action/Core.hs
index d18bda9..337801e 100644
--- a/lib/Daffm/Action/Core.hs
+++ b/lib/Daffm/Action/Core.hs
@@ -8,8 +8,9 @@ import Brick (suspendAndResume')
import qualified Brick.Widgets.List as L
import Control.Monad.State (MonadIO (liftIO), MonadState, get, gets, modify, put)
import Daffm.State
-import Daffm.Types (AppEvent, AppState (..), FileInfo (..), FileType (..))
+import Daffm.Types (AppEvent, AppState (..), FileInfo (..), FilePathText, FileType (..))
import qualified Data.Set as Set
+import qualified Data.Text as Text
import System.Directory (getHomeDirectory)
import System.FilePath (takeDirectory)
import System.Process (callProcess)
@@ -17,7 +18,7 @@ import System.Process (callProcess)
modifyM :: (MonadState s m) => (s -> m s) -> m ()
modifyM f = get >>= f >>= put
-loadDir :: FilePath -> FilePath -> AppEvent ()
+loadDir :: FilePathText -> FilePathText -> AppEvent ()
loadDir dir parentDir = do
modifyM (liftIO . (>>= filterInvalidSelections) . loadDirToState dir parentDir)
@@ -29,12 +30,12 @@ reloadDir = do
goBackToParentDir :: AppEvent ()
goBackToParentDir = do
dir <- gets stateParentDir
- loadDir dir (takeDirectory dir)
+ loadDir dir (Text.pack . takeDirectory $ Text.unpack dir)
goHome :: AppEvent ()
goHome = do
dir <- liftIO getHomeDirectory
- loadDir dir (takeDirectory dir)
+ loadDir (Text.pack dir) (Text.pack $ takeDirectory dir)
openSelectedFile :: AppEvent ()
openSelectedFile = do
@@ -47,8 +48,8 @@ openFile (FileInfo {filePath, fileType = Directory}) = do
gets stateCwd >>= loadDir filePath
openFile (FileInfo {filePath, fileType}) = do
suspendAndResume' $ do
- putStrLn $ "Opening " <> show fileType <> ": " <> filePath
- callProcess "nvim" [filePath]
+ putStrLn $ "Opening " <> show fileType <> ": " <> Text.unpack filePath
+ callProcess "nvim" [Text.unpack filePath]
currentFile :: AppEvent (Maybe FileInfo)
currentFile = do
diff --git a/lib/Daffm/State.hs b/lib/Daffm/State.hs
index d35dccf..beeb646 100644
--- a/lib/Daffm/State.hs
+++ b/lib/Daffm/State.hs
@@ -4,12 +4,12 @@ import qualified Brick.Widgets.Edit as Editor
import qualified Brick.Widgets.List as L
import Control.Applicative ((<|>))
import Control.Monad (filterM, forM)
-import Daffm.Types (AppState (..), FileInfo (..), FileType (..), FocusTarget (..))
-import Data.Char (toLower)
+import Daffm.Types (AppState (..), FileInfo (..), FilePathText, FileType (..), FocusTarget (..))
import Data.List (findIndex, sortBy)
import qualified Data.Map.Strict as Map
import Data.Maybe (fromMaybe)
import qualified Data.Set as Set
+import qualified Data.Text as Text
import qualified Data.Text.Zipper.Generic as Zipper
import qualified Data.Vector as Vec
import System.Directory (listDirectory, makeAbsolute, setCurrentDirectory)
@@ -35,12 +35,12 @@ toggleSetItem :: (Ord a) => a -> Set.Set a -> Set.Set a
toggleSetItem val set =
if val `Set.member` set then Set.delete val set else Set.insert val set
-toggleFileSelection :: FilePath -> AppState -> AppState
+toggleFileSelection :: FilePathText -> AppState -> AppState
toggleFileSelection path st = st {stateFileSelections = toggleSetItem path $ stateFileSelections st}
-loadDirToState :: FilePath -> FilePath -> AppState -> IO AppState
+loadDirToState :: FilePathText -> FilePathText -> AppState -> IO AppState
loadDirToState dir parentDir appState@(AppState {stateCwd, stateListPositionCache}) = do
- setCurrentDirectory dir
+ setCurrentDirectory $ Text.unpack dir
files <- listFilesInDir dir
let prevDirPosM = findIndex ((== stateCwd) . filePath) files
let cachedPosM = Map.lookup dir stateListPositionCache
@@ -65,13 +65,13 @@ fileTypeFromStatus s =
| Posix.isSymbolicLink s -> SymbolicLink
| otherwise -> UnknownFileType
-getFileInfo :: FilePath -> IO FileInfo
+getFileInfo :: FilePathText -> IO FileInfo
getFileInfo name = do
- path <- makeAbsolute name
+ path <- makeAbsolute $ Text.unpack name
stat <- Posix.getSymbolicLinkStatus path
pure $
FileInfo
- { filePath = path,
+ { filePath = Text.pack path,
fileName = name,
fileSize = Posix.fileSize stat,
fileMode = Posix.fileMode stat,
@@ -80,16 +80,16 @@ getFileInfo name = do
fileSorter :: FileInfo -> FileInfo -> Ordering
fileSorter (FileInfo {fileType = Directory, fileName = fa}) (FileInfo {fileType = Directory, fileName = fb}) =
- compare (toLower <$> fa) (toLower <$> fb)
+ compare (Text.toLower fa) (Text.toLower fb)
fileSorter (FileInfo {fileType = Directory}) _ = LT
fileSorter _ (FileInfo {fileType = Directory}) = GT
fileSorter (FileInfo {fileName = fa}) (FileInfo {fileName = fb}) =
- compare (toLower <$> fa) (toLower <$> fb)
+ compare (Text.toLower fa) (Text.toLower fb)
-listFilesInDir :: FilePath -> IO [FileInfo]
+listFilesInDir :: FilePathText -> IO [FileInfo]
listFilesInDir dir = do
- files <- listDirectory dir
- sortBy fileSorter <$> forM files getFileInfo
+ files <- listDirectory (Text.unpack dir)
+ sortBy fileSorter <$> forM files (getFileInfo . Text.pack)
cacheDirPosition :: AppState -> AppState
cacheDirPosition appState@(AppState {stateListPositionCache, stateCwd, stateFiles}) =
@@ -101,5 +101,5 @@ cacheDirPosition appState@(AppState {stateListPositionCache, stateCwd, stateFile
filterInvalidSelections :: AppState -> IO AppState
filterInvalidSelections st = do
- selections <- filterM fileExist . Set.elems $ stateFileSelections st
+ selections <- filterM (fileExist . Text.unpack) . Set.elems $ stateFileSelections st
pure $ st {stateFileSelections = Set.fromList selections}
diff --git a/lib/Daffm/Types.hs b/lib/Daffm/Types.hs
index 882a9de..ffff4d0 100644
--- a/lib/Daffm/Types.hs
+++ b/lib/Daffm/Types.hs
@@ -5,6 +5,7 @@ import qualified Brick.Widgets.Edit as Editor
import qualified Brick.Widgets.List as L
import qualified Data.Map as Map
import qualified Data.Set as Set
+import qualified Data.Text as Text
import System.Posix.Types (FileMode, FileOffset)
data FileType
@@ -18,9 +19,11 @@ data FileType
| UnknownFileType
deriving (Show)
+type FilePathText = Text.Text
+
data FileInfo = FileInfo
- { fileName :: String,
- filePath :: FilePath,
+ { fileName :: Text.Text,
+ filePath :: FilePathText,
fileSize :: FileOffset,
fileMode :: FileMode,
fileType :: FileType
@@ -32,14 +35,14 @@ data FocusTarget = FocusCmdline | FocusMain deriving (Show, Eq, Ord)
data AppState = AppState
{ stateFiles :: L.List FocusTarget FileInfo,
stateCmdlineEditor :: CmdlineEditor,
- stateFileSelections :: Set.Set FilePath,
+ stateFileSelections :: Set.Set FilePathText,
stateFocusTarget :: FocusTarget,
- stateCwd :: FilePath,
- stateListPositionCache :: Map.Map String Int,
- stateParentDir :: FilePath
+ stateCwd :: FilePathText,
+ stateListPositionCache :: Map.Map Text.Text Int,
+ stateParentDir :: FilePathText
}
deriving (Show)
type AppEvent = EventM FocusTarget AppState
-type CmdlineEditor = Editor.Editor String FocusTarget
+type CmdlineEditor = Editor.Editor Text.Text FocusTarget
diff --git a/lib/Daffm/View.hs b/lib/Daffm/View.hs
index 9e0294d..d3845ba 100644
--- a/lib/Daffm/View.hs
+++ b/lib/Daffm/View.hs
@@ -1,13 +1,14 @@
module Daffm.View where
import Brick.Types (Widget)
-import Brick.Widgets.Core (Padding (Max, Pad), hBox, hLimit, padLeft, padRight, str, vBox, vLimit, withAttr, (<+>))
+import Brick.Widgets.Core (Padding (Max, Pad), hBox, hLimit, padLeft, padRight, txt, vBox, vLimit, withAttr, (<+>))
import Brick.Widgets.Edit (renderEditor)
import qualified Brick.Widgets.List as L
import Daffm.Attrs (directoryAttr, directorySelectedAttr, fileAttr, fileSelectedAttr)
import Daffm.Types (AppState (..), FileInfo (..), FileType (..), FocusTarget (..))
import Data.Int (Int64)
import qualified Data.Set as Set
+import qualified Data.Text as Text
import qualified Data.Vector as Vec
import System.Posix.Types (FileMode)
import qualified System.PosixCompat as Posix
@@ -25,7 +26,7 @@ hFixed :: Int -> Widget n -> Widget n
hFixed w = hLimit w . padRight Max
headerView :: AppState -> Widget n
-headerView (AppState {stateCwd}) = str stateCwd
+headerView (AppState {stateCwd}) = txt stateCwd
fileItemView :: AppState -> Bool -> FileInfo -> Widget FocusTarget
fileItemView appState sel fileInfo@(FileInfo {filePath, fileSize, fileType, fileMode}) =
@@ -37,12 +38,12 @@ fileItemView appState sel fileInfo@(FileInfo {filePath, fileSize, fileType, file
fileNameView sel fileInfo
]
where
- fileSizeView = str . prettyFileSize . fromIntegral
- fileTypeView = str . showFileType
- fileModeView = str . showFileMode
- fileSelectionView = str $ if Set.member filePath $ stateFileSelections appState then ">" else " "
+ fileSizeView = txt . prettyFileSize . fromIntegral
+ fileTypeView = txt . showFileType
+ fileModeView = txt . showFileMode
+ fileSelectionView = txt $ if Set.member filePath $ stateFileSelections appState then ">" else " "
-showFileType :: FileType -> String
+showFileType :: FileType -> Text.Text
showFileType Directory = "dir"
showFileType SymbolicLink = "link"
showFileType UnixSocket = "sock"
@@ -52,48 +53,49 @@ showFileType BlockDevice = "bdev"
showFileType RegularFile = "file"
showFileType UnknownFileType = "?"
-showFileMode :: FileMode -> String
+showFileMode :: FileMode -> Text.Text
showFileMode mode = permchars
where
perm m c = if Posix.intersectFileModes mode m == m then c else '-'
permchars =
- [ perm Posix.ownerReadMode 'r',
- perm Posix.ownerWriteMode 'w',
- perm Posix.ownerExecuteMode 'x',
- perm Posix.groupReadMode 'r',
- perm Posix.groupWriteMode 'w',
- perm Posix.groupExecuteMode 'x',
- perm Posix.otherReadMode 'r',
- perm Posix.otherWriteMode 'w',
- perm Posix.otherExecuteMode 'x'
- ]
+ Text.pack
+ [ perm Posix.ownerReadMode 'r',
+ perm Posix.ownerWriteMode 'w',
+ perm Posix.ownerExecuteMode 'x',
+ perm Posix.groupReadMode 'r',
+ perm Posix.groupWriteMode 'w',
+ perm Posix.groupExecuteMode 'x',
+ perm Posix.otherReadMode 'r',
+ perm Posix.otherWriteMode 'w',
+ perm Posix.otherExecuteMode 'x'
+ ]
fileNameView :: Bool -> FileInfo -> Widget FocusTarget
-fileNameView True (FileInfo {fileName, fileType = Directory}) = withAttr directorySelectedAttr $ str $ fileName <> "/"
-fileNameView False (FileInfo {fileName, fileType = Directory}) = withAttr directoryAttr $ str $ fileName <> "/"
-fileNameView True (FileInfo {fileName}) = withAttr fileSelectedAttr $ str fileName
-fileNameView False (FileInfo {fileName}) = withAttr fileAttr $ str fileName
+fileNameView True (FileInfo {fileName, fileType = Directory}) = withAttr directorySelectedAttr $ txt $ fileName <> "/"
+fileNameView False (FileInfo {fileName, fileType = Directory}) = withAttr directoryAttr $ txt $ fileName <> "/"
+fileNameView True (FileInfo {fileName}) = withAttr fileSelectedAttr $ txt fileName
+fileNameView False (FileInfo {fileName}) = withAttr fileAttr $ txt fileName
cmdlineView :: AppState -> Widget FocusTarget
cmdlineView (AppState {stateFocusTarget = FocusCmdline, stateCmdlineEditor}) =
- str ":" <+> renderEditor (str . unlines) True stateCmdlineEditor
+ txt ":" <+> renderEditor (txt . Text.unlines) True stateCmdlineEditor
cmdlineView (AppState {stateFiles}) =
- hBox [str ":", padLeft Max $ padRight (Pad 1) posIndicator]
+ hBox [txt ":", padLeft Max $ padRight (Pad 1) posIndicator]
where
- posIndicator = str $ cur <> "/" <> total
+ posIndicator = txt $ cur <> "/" <> total
cur = case L.listSelected stateFiles of
Nothing -> "-"
- Just n -> show (n + 1)
- total = show $ Vec.length $ L.listElements stateFiles
+ Just n -> Text.pack $ show (n + 1)
+ total = Text.pack $ show $ Vec.length $ L.listElements stateFiles
-prettyFileSize :: Int64 -> String
+prettyFileSize :: Int64 -> Text.Text
prettyFileSize i
| i >= 2 ^ (40 :: Int64) = format (i `divBy` (2 ** 40)) <> "T"
| i >= 2 ^ (30 :: Int64) = format (i `divBy` (2 ** 30)) <> "G"
| i >= 2 ^ (20 :: Int64) = format (i `divBy` (2 ** 20)) <> "M"
| i >= 2 ^ (10 :: Int64) = format (i `divBy` (2 ** 10)) <> "K"
- | otherwise = show i
+ | otherwise = Text.pack $ show i
where
- format = printf "%0.1f"
+ format = Text.pack . printf "%0.1f"
divBy :: Int64 -> Double -> Double
divBy a b = (fromIntegral a :: Double) / b