module System.Console.Haskeline.History(
History(),
emptyHistory,
addHistory,
addHistoryUnlessConsecutiveDupe,
addHistoryRemovingAllDupes,
historyLines,
readHistory,
writeHistory,
stifleHistory,
stifleAmount,
) where
import qualified Data.Sequence as Seq
import Data.Sequence ( Seq, (<|), ViewL(..), ViewR(..), viewl, viewr )
import Data.Foldable (toList)
import Control.Exception
import System.Directory(doesFileExist)
import qualified System.IO as IO
import System.Console.Haskeline.Recover
data History = History {histLines :: Seq String,
stifleAmt :: Maybe Int}
stifleAmount :: History -> Maybe Int
stifleAmount = stifleAmt
instance Show History where
show = show . histLines
emptyHistory :: History
emptyHistory = History Seq.empty Nothing
historyLines :: History -> [String]
historyLines = toList . histLines
readHistory :: FilePath -> IO History
readHistory file = handle (\(_::IOException) -> return emptyHistory) $ do
exists <- doesFileExist file
contents <- if exists
then readUTF8File file
else return ""
_ <- evaluate (length contents)
return History {histLines = Seq.fromList $ lines contents,
stifleAmt = Nothing}
writeHistory :: FilePath -> History -> IO ()
writeHistory file = handle (\(_::IOException) -> return ())
. writeUTF8File file
. unlines . historyLines
stifleHistory :: Maybe Int -> History -> History
stifleHistory Nothing hist = hist {stifleAmt = Nothing}
stifleHistory a@(Just n) hist = History {histLines = stifleFnc (histLines hist),
stifleAmt = a}
where
stifleFnc = if n > Seq.length (histLines hist)
then id
else Seq.fromList . take n . toList
addHistory :: String -> History -> History
addHistory s h = h {histLines = maybeDropLast (stifleAmt h) (s <| (histLines h))}
maybeDropLast :: Ord a => Maybe Int -> Seq a -> Seq a
maybeDropLast maxAmt hs
| rightSize = hs
| otherwise = case viewr hs of
EmptyR -> hs
hs' :> _ -> hs'
where
rightSize = maybe True (>= Seq.length hs) maxAmt
addHistoryUnlessConsecutiveDupe :: String -> History -> History
addHistoryUnlessConsecutiveDupe h hs = case viewl (histLines hs) of
h1 :< _ | h==h1 -> hs
_ -> addHistory h hs
addHistoryRemovingAllDupes :: String -> History -> History
addHistoryRemovingAllDupes h hs = addHistory h hs {histLines = filteredHS}
where
filteredHS = Seq.fromList $ filter (/= h) $ toList $ histLines hs
readUTF8File :: FilePath -> IO String
readUTF8File file = do
h <- IO.openFile file IO.ReadMode
IO.hSetEncoding h $ transliterateFailure IO.utf8
IO.hSetNewlineMode h IO.noNewlineTranslation
contents <- IO.hGetContents h
_ <- evaluate (length contents)
IO.hClose h
return contents
writeUTF8File :: FilePath -> String -> IO ()
writeUTF8File file contents = do
h <- IO.openFile file IO.WriteMode
IO.hSetEncoding h IO.utf8
IO.hSetNewlineMode h IO.noNewlineTranslation
IO.hPutStr h contents
IO.hClose h