hsfm/src/HSFM/Settings/Bookmarks.hs

140 lines
3.6 KiB
Haskell

{--
HSFM, a filemanager written in Haskell.
Copyright (C) 2016 Julian Ospald
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
version 2 as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
--}
{-# LANGUAGE OverloadedStrings #-}
{-# OPTIONS_HADDOCK ignore-exports #-}
module HSFM.Settings.Bookmarks where
import Control.Monad
(
void
)
import Data.Attoparsec.ByteString
import qualified Data.ByteString as BS
import Data.ByteString
(
ByteString
)
import Data.Maybe
(
catMaybes
, fromJust
)
import Data.Word8
(
_nul
)
import qualified HPath as P
import HPath
(
Abs
, Fn
, Path
)
import HSFM.FileSystem.FileOperations
import HSFM.FileSystem.FileType
import Prelude hiding (readFile, writeFile)
import System.Posix.Env.ByteString
(
getEnv
)
-- |A bookmark. `bkName` is principally a description of the bookmark
-- but must satisfy the constraints of a filename.
data Bookmark = MkBookmark {
bkName :: Path Fn
, bkPath :: Path Abs
} deriving (Show)
-- |Parses bookmarks from a ByteString that has pairs of
-- name and path. Name and path are separated by one null character
-- and the pairs itself are separated by two null characters from
-- each other.
bkParser :: Parser [Bookmark]
bkParser =
fmap catMaybes $ many' (fmap toBm $ bookmark <* word8 _nul <* word8 _nul)
where
toBm :: (ByteString, ByteString) -> Maybe Bookmark
toBm (name, path) = MkBookmark <$> P.parseFn name
<*> P.parseAbs path
bookmark :: Parser (ByteString, ByteString)
bookmark =
(\x y -> (BS.pack x, BS.pack y))
<$> many1' char
<* (word8 _nul)
<*> many1' char
char = satisfy (`notElem` [_nul])
-- |Writes bookmarks to a given file.
writeBookmarks :: [Bookmark] -> IO ()
writeBookmarks [] = return ()
writeBookmarks bs = do
bf <- bookmarksFile
bfd <- bookmarksDir
mkdirP bfd
readFile getFileInfo bfd >>= (\x -> createFile x bookmarksFileName)
let str = foldr1 (\x y -> x `BS.append` BS.pack [_nul, _nul]
`BS.append`
y `BS.append` BS.pack [_nul, _nul])
(fmap toByteString bs)
file <- readFile getFileInfo bf
void $ writeFile file str
where
toByteString :: Bookmark -> ByteString
toByteString b = (P.fromRel $ bkName b)
`BS.append` BS.singleton _nul
`BS.append` (P.fromAbs $ bkPath b)
-- |Reads bookmarks from a given file.
readBookmarks :: IO [Bookmark]
readBookmarks = do
p <- bookmarksFile
file <- readFile getFileInfo p
c <- readFileContents file
case parseOnly bkParser c of
Left _ -> return []
Right x -> return x
bookmarksDir :: IO (Path Abs)
bookmarksDir = do
mhomedir <- getEnv "HOME"
case mhomedir of
Nothing -> ioError (userError "No valid homedir?!")
Just home -> do
phome <- P.parseAbs home
reldir <- P.parseRel ".config/hsfm"
return $ phome P.</> reldir
bookmarksFile :: IO (Path Abs)
bookmarksFile = do
path <- bookmarksDir
return $ path P.</> bookmarksFileName
bookmarksFileName :: Path Fn
bookmarksFileName = fromJust $ P.parseFn "bookmarks"