Skip to content

Support flushing command history #148

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion System/Console/Haskeline.hs
Original file line number Diff line number Diff line change
@@ -94,6 +94,7 @@ import System.Console.Haskeline.RunCommand
import Control.Monad.Catch (MonadMask, handle)
import Data.Char (isSpace, isPrint)
import Data.Maybe (isJust)
import Control.Monad (when)
import System.IO


@@ -188,13 +189,18 @@ maybeAddHistory :: forall m . MonadIO m => Maybe String -> InputT m ()
maybeAddHistory result = do
settings :: Settings m <- InputT ask
histDupes <- InputT $ asks historyDuplicates
doFlush <- InputT $ asks incAppendHistory
case result of
Just line | autoAddHistory settings && not (all isSpace line)
-> let adder = case histDupes of
AlwaysAdd -> addHistory
IgnoreConsecutive -> addHistoryUnlessConsecutiveDupe
IgnoreAll -> addHistoryRemovingAllDupes
in modifyHistory (adder line)
in do
modifyHistory (adder line)
when doFlush $ case historyFile settings of
Nothing -> pure ()
Just f -> liftIO $ appendFile f (line ++ "\n")
_ -> return ()

----------
17 changes: 12 additions & 5 deletions System/Console/Haskeline/Command/History.hs
Original file line number Diff line number Diff line change
@@ -9,6 +9,7 @@ import Data.List
import Data.Maybe(fromMaybe)
import System.Console.Haskeline.History
import Data.IORef
import Control.Monad (when)
import Control.Monad.Catch

data HistLog = HistLog {pastHistory, futureHistory :: [[Grapheme]]}
@@ -28,20 +29,26 @@ histLog :: History -> HistLog
histLog hist = HistLog {pastHistory = map stringToGraphemes $ historyLines hist,
futureHistory = []}

runHistoryFromFile :: (MonadIO m, MonadMask m) => Maybe FilePath -> Maybe Int
-> ReaderT (IORef History) m a -> m a
runHistoryFromFile Nothing _ f = do
runHistoryFromFile
:: (MonadIO m, MonadMask m)
=> Maybe FilePath
-> Maybe Int
-> Bool
-> ReaderT (IORef History) m a
-> m a
runHistoryFromFile Nothing _ _ f = do
historyRef <- liftIO $ newIORef emptyHistory
runReaderT f historyRef
runHistoryFromFile (Just file) stifleAmt f = do
runHistoryFromFile (Just file) stifleAmt writeHistoryOnExit f = do
oldHistory <- liftIO $ readHistory file
historyRef <- liftIO $ newIORef $ stifleHistory stifleAmt oldHistory
-- Run the action and then write the new history, even on an exception.
-- For example, if there's an unhandled ctrl-c, we don't want to lose
-- the user's previously-entered commands.
-- (Note that this requires using ReaderT (IORef History) instead of StateT.
x <- runReaderT f historyRef
`finally` (liftIO $ readIORef historyRef >>= writeHistory file)
`finally` when writeHistoryOnExit
(liftIO $ readIORef historyRef >>= writeHistory file)
return x

prevHistory, firstHistory :: Save s => s -> HistLog -> (s, HistLog)
4 changes: 2 additions & 2 deletions System/Console/Haskeline/History.hs
Original file line number Diff line number Diff line change
@@ -62,15 +62,15 @@ readHistory file = handle (\(_::IOException) -> return emptyHistory) $ do
then readUTF8File file
else return ""
_ <- evaluate (length contents) -- force file closed
return History {histLines = Seq.fromList $ lines contents,
return History {histLines = Seq.fromList $ reverse $ lines contents,
stifleAmt = Nothing}

-- | Writes the line history to the given file. If there is an
-- error when writing the file, it will be ignored.
writeHistory :: FilePath -> History -> IO ()
writeHistory file = handle (\(_::IOException) -> return ())
. writeUTF8File file
. unlines . historyLines
. unlines . reverse . historyLines

-- | Limit the number of lines stored in the history.
stifleHistory :: Maybe Int -> History -> History
1 change: 1 addition & 0 deletions System/Console/Haskeline/InputT.hs
Original file line number Diff line number Diff line change
@@ -181,6 +181,7 @@ execInputT prefs settings run (InputT f)
= runReaderT' settings $ runReaderT' prefs
$ runKillRing
$ runHistoryFromFile (historyFile settings) (maxHistorySize prefs)
(incAppendHistory prefs)
$ runReaderT f run

-- | Map a user interaction by modifying the base monad computation.
9 changes: 7 additions & 2 deletions System/Console/Haskeline/Prefs.hs
Original file line number Diff line number Diff line change
@@ -48,7 +48,10 @@ data Prefs = Prefs { bellStyle :: !BellStyle,
-- presses @TAB@ again.
customBindings :: Map.Map Key [Key],
-- (termName, keysequence, key)
customKeySequences :: [(Maybe String, String,Key)]
customKeySequences :: [(Maybe String, String,Key)],
incAppendHistory :: Bool
-- ^ If 'True' and @historyFile@ not 'Nothing'
-- flushes command history after every command
}
deriving Show

@@ -77,7 +80,8 @@ defaultPrefs = Prefs {bellStyle = AudibleBell,
listCompletionsImmediately = True,
historyDuplicates = AlwaysAdd,
customBindings = Map.empty,
customKeySequences = []
customKeySequences = [],
incAppendHistory = False
}

mkSettor :: Read a => (a -> Prefs -> Prefs) -> String -> Prefs -> Prefs
@@ -100,6 +104,7 @@ settors = [("bellstyle", mkSettor $ \x p -> p {bellStyle = x})
,("historyduplicates", mkSettor $ \x p -> p {historyDuplicates = x})
,("bind", addCustomBinding)
,("keyseq", addCustomKeySequence)
,("incappendhistory", mkSettor $ \x p -> p {incAppendHistory = x})
]

addCustomBinding :: String -> Prefs -> Prefs