From b6b3324f3816ef88c8282aa42da8b25d5d70c356 Mon Sep 17 00:00:00 2001 From: Chris Hackett Date: Sun, 20 Aug 2023 12:27:38 -0400 Subject: [PATCH 1/3] Updating to support building on Windows. --- brick.cabal | 3 +- src/Brick/Widgets/FileBrowser.hs | 66 ++++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+), 1 deletion(-) diff --git a/brick.cabal b/brick.cabal index c5bcf3a..c529d1a 100644 --- a/brick.cabal +++ b/brick.cabal @@ -114,9 +114,10 @@ library text-zipper >= 0.13, template-haskell, deepseq >= 1.3 && < 1.5, - unix, bytestring, word-wrap >= 0.2 + if !os(windows) + build-depends: unix executable brick-custom-keybinding-demo if !flag(demos) diff --git a/src/Brick/Widgets/FileBrowser.hs b/src/Brick/Widgets/FileBrowser.hs index 80358a3..c15c1ad 100644 --- a/src/Brick/Widgets/FileBrowser.hs +++ b/src/Brick/Widgets/FileBrowser.hs @@ -161,9 +161,14 @@ import Lens.Micro import Lens.Micro.Mtl ((%=)) import Lens.Micro.TH (lensRules, generateUpdateableOptics) import qualified Graphics.Vty as Vty + import qualified System.Directory as D + +#ifndef mingw32_HOST_OS import qualified System.Posix.Files as U import qualified System.Posix.Types as U +#endif + import qualified System.FilePath as FP import Text.Printf (printf) @@ -386,6 +391,51 @@ getFileInfo :: String -> IO FileInfo getFileInfo name = go [] where + +#ifdef mingw32_HOST_OS + go history fullPath = do + filePath <- D.makeAbsolute fullPath + + fileSize <- D.getFileSize fullPath + fileType <- fileTypeFromPath filePath + + let stat = FileStatus { fileStatusFileType = fileType + , fileStatusSize = fromInteger fileSize + } + + targetTy <- case fileType of + Just SymbolicLink -> do + targetPathResult <- E.try $ D.getSymbolicLinkTarget filePath + case targetPathResult of + Left (_::E.SomeException) -> return Nothing + Right targetPath -> + -- Watch out for recursive symlink chains: + -- if history starts repeating, abort the + -- symlink following process. + -- + -- Examples: + -- $ ln -s foo foo + -- + -- $ ln -s foo bar + -- $ ln -s bar foo + if targetPath `elem` history + then return Nothing + else do + targetInfo <- liftIO $ go (fullPath : history) targetPath + case fileInfoFileStatus targetInfo of + Right (FileStatus _ targetTy) -> return targetTy + _ -> return Nothing + _ -> return Nothing + + return FileInfo { fileInfoFilename = name + , fileInfoFilePath = filePath + , fileInfoSanitizedFilename = sanitizeFilename name + , fileInfoFileStatus = Right stat + , fileInfoLinkTargetType = targetTy + } + +#else + go history fullPath = do filePath <- D.makeAbsolute fullPath statusResult <- E.try $ U.getSymbolicLinkStatus filePath @@ -427,6 +477,7 @@ getFileInfo name = go [] , fileInfoFileStatus = stat , fileInfoLinkTargetType = targetTy } +#endif -- | Get the file type for this file info entry. If the file type could -- not be obtained due to an 'IOException', return 'Nothing'. @@ -552,6 +603,19 @@ entriesForDirectory rawPath = do return allEntries +#ifdef mingw32_HOST_OS + +fileTypeFromPath :: FilePath -> IO (Maybe FileType) +fileTypeFromPath filePath = do + isSymLink <- D.pathIsSymbolicLink filePath + isDir <- D.doesDirectoryExist filePath + + return $ if | isSymLink -> Just SymbolicLink + | isDir -> Just Directory + | otherwise -> Just RegularFile + +#else + fileTypeFromStatus :: U.FileStatus -> Maybe FileType fileTypeFromStatus s = if | U.isBlockDevice s -> Just BlockDevice @@ -563,6 +627,8 @@ fileTypeFromStatus s = | U.isSymbolicLink s -> Just SymbolicLink | otherwise -> Nothing +#endif + -- | Get the file information for the file under the cursor, if any. fileBrowserCursor :: FileBrowser n -> Maybe FileInfo fileBrowserCursor b = snd <$> listSelectedElement (b^.fileBrowserEntriesL) From 820b479136e4647bbf6e68be5f20d1d6867af7a9 Mon Sep 17 00:00:00 2001 From: Chris Hackett Date: Sun, 20 Aug 2023 13:41:10 -0400 Subject: [PATCH 2/3] Now using unix-compat. Removed ifdef conditionals. --- brick.cabal | 5 +-- src/Brick/Widgets/FileBrowser.hs | 69 ++------------------------------ 2 files changed, 5 insertions(+), 69 deletions(-) diff --git a/brick.cabal b/brick.cabal index c529d1a..844f63e 100644 --- a/brick.cabal +++ b/brick.cabal @@ -115,9 +115,8 @@ library template-haskell, deepseq >= 1.3 && < 1.5, bytestring, - word-wrap >= 0.2 - if !os(windows) - build-depends: unix + word-wrap >= 0.2, + unix-compat executable brick-custom-keybinding-demo if !flag(demos) diff --git a/src/Brick/Widgets/FileBrowser.hs b/src/Brick/Widgets/FileBrowser.hs index c15c1ad..6886bc9 100644 --- a/src/Brick/Widgets/FileBrowser.hs +++ b/src/Brick/Widgets/FileBrowser.hs @@ -164,10 +164,8 @@ import qualified Graphics.Vty as Vty import qualified System.Directory as D -#ifndef mingw32_HOST_OS -import qualified System.Posix.Files as U -import qualified System.Posix.Types as U -#endif +import qualified System.PosixCompat.Files as U +import System.Posix.Types (COff(..)) import qualified System.FilePath as FP import Text.Printf (printf) @@ -391,58 +389,13 @@ getFileInfo :: String -> IO FileInfo getFileInfo name = go [] where - -#ifdef mingw32_HOST_OS - go history fullPath = do - filePath <- D.makeAbsolute fullPath - - fileSize <- D.getFileSize fullPath - fileType <- fileTypeFromPath filePath - - let stat = FileStatus { fileStatusFileType = fileType - , fileStatusSize = fromInteger fileSize - } - - targetTy <- case fileType of - Just SymbolicLink -> do - targetPathResult <- E.try $ D.getSymbolicLinkTarget filePath - case targetPathResult of - Left (_::E.SomeException) -> return Nothing - Right targetPath -> - -- Watch out for recursive symlink chains: - -- if history starts repeating, abort the - -- symlink following process. - -- - -- Examples: - -- $ ln -s foo foo - -- - -- $ ln -s foo bar - -- $ ln -s bar foo - if targetPath `elem` history - then return Nothing - else do - targetInfo <- liftIO $ go (fullPath : history) targetPath - case fileInfoFileStatus targetInfo of - Right (FileStatus _ targetTy) -> return targetTy - _ -> return Nothing - _ -> return Nothing - - return FileInfo { fileInfoFilename = name - , fileInfoFilePath = filePath - , fileInfoSanitizedFilename = sanitizeFilename name - , fileInfoFileStatus = Right stat - , fileInfoLinkTargetType = targetTy - } - -#else - go history fullPath = do filePath <- D.makeAbsolute fullPath statusResult <- E.try $ U.getSymbolicLinkStatus filePath let stat = do status <- statusResult - let U.COff sz = U.fileSize status + let COff sz = U.fileSize status return FileStatus { fileStatusFileType = fileTypeFromStatus status , fileStatusSize = sz } @@ -477,7 +430,6 @@ getFileInfo name = go [] , fileInfoFileStatus = stat , fileInfoLinkTargetType = targetTy } -#endif -- | Get the file type for this file info entry. If the file type could -- not be obtained due to an 'IOException', return 'Nothing'. @@ -603,19 +555,6 @@ entriesForDirectory rawPath = do return allEntries -#ifdef mingw32_HOST_OS - -fileTypeFromPath :: FilePath -> IO (Maybe FileType) -fileTypeFromPath filePath = do - isSymLink <- D.pathIsSymbolicLink filePath - isDir <- D.doesDirectoryExist filePath - - return $ if | isSymLink -> Just SymbolicLink - | isDir -> Just Directory - | otherwise -> Just RegularFile - -#else - fileTypeFromStatus :: U.FileStatus -> Maybe FileType fileTypeFromStatus s = if | U.isBlockDevice s -> Just BlockDevice @@ -627,8 +566,6 @@ fileTypeFromStatus s = | U.isSymbolicLink s -> Just SymbolicLink | otherwise -> Nothing -#endif - -- | Get the file information for the file under the cursor, if any. fileBrowserCursor :: FileBrowser n -> Maybe FileInfo fileBrowserCursor b = snd <$> listSelectedElement (b^.fileBrowserEntriesL) From d01006e0f0d825b38140af9d1341760d02556cd4 Mon Sep 17 00:00:00 2001 From: Chris Hackett Date: Sun, 20 Aug 2023 13:46:38 -0400 Subject: [PATCH 3/3] Just a little cleanup. --- brick.cabal | 4 ++-- src/Brick/Widgets/FileBrowser.hs | 7 ++----- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/brick.cabal b/brick.cabal index 844f63e..befc64b 100644 --- a/brick.cabal +++ b/brick.cabal @@ -114,9 +114,9 @@ library text-zipper >= 0.13, template-haskell, deepseq >= 1.3 && < 1.5, + unix-compat, bytestring, - word-wrap >= 0.2, - unix-compat + word-wrap >= 0.2 executable brick-custom-keybinding-demo if !flag(demos) diff --git a/src/Brick/Widgets/FileBrowser.hs b/src/Brick/Widgets/FileBrowser.hs index 6886bc9..3373125 100644 --- a/src/Brick/Widgets/FileBrowser.hs +++ b/src/Brick/Widgets/FileBrowser.hs @@ -161,12 +161,9 @@ import Lens.Micro import Lens.Micro.Mtl ((%=)) import Lens.Micro.TH (lensRules, generateUpdateableOptics) import qualified Graphics.Vty as Vty - import qualified System.Directory as D - import qualified System.PosixCompat.Files as U -import System.Posix.Types (COff(..)) - +import qualified System.Posix.Types as U import qualified System.FilePath as FP import Text.Printf (printf) @@ -395,7 +392,7 @@ getFileInfo name = go [] let stat = do status <- statusResult - let COff sz = U.fileSize status + let U.COff sz = U.fileSize status return FileStatus { fileStatusFileType = fileTypeFromStatus status , fileStatusSize = sz }