module Yi.PersistentState(loadPersistentState,
savePersistentState,
maxHistoryEntries,
persistentSearch)
where
import GHC.Generics (Generic)
import Control.Exc (ignoringException)
import Control.Lens (assign, makeLenses, use)
import Control.Monad (when)
import Data.Binary (Binary, decodeFile, encodeFile)
import Data.Default (Default, def)
import qualified Data.Map as M (map)
import Data.Typeable (Typeable)
import System.Directory (doesFileExist)
import Yi.Config.Simple.Types (Field, customVariable)
import Yi.Editor
import Yi.History (Histories (..), History (..))
import Yi.Keymap (YiM)
import Yi.KillRing (Killring (..))
import Yi.Paths (getPersistentStateFilename)
import Yi.Regex (SearchExp (..))
import Yi.Search.Internal (getRegexE, setRegexE)
import Yi.Types (YiConfigVariable)
import Yi.Utils (io)
data PersistentState = PersistentState
{ histories :: !Histories
, aKillring :: !Killring
, aCurrentRegex :: Maybe SearchExp
} deriving (Generic)
instance Binary PersistentState
newtype MaxHistoryEntries = MaxHistoryEntries { _unMaxHistoryEntries :: Int }
deriving(Typeable, Binary)
instance Default MaxHistoryEntries where
def = MaxHistoryEntries 1000
instance YiConfigVariable MaxHistoryEntries
makeLenses ''MaxHistoryEntries
maxHistoryEntries :: Field Int
maxHistoryEntries = customVariable . unMaxHistoryEntries
newtype PersistentSearch = PersistentSearch { _unPersistentSearch :: Bool }
deriving(Typeable, Binary)
instance Default PersistentSearch where
def = PersistentSearch True
instance YiConfigVariable PersistentSearch
makeLenses ''PersistentSearch
persistentSearch :: Field Bool
persistentSearch = customVariable . unPersistentSearch
trimHistories :: Int -> Histories -> Histories
trimHistories maxHistory (Histories m) = Histories $ M.map trimH m
where
trimH (History cur content prefix) = History cur (trim content) prefix
trim content = drop (max 0 (length content maxHistory)) content
savePersistentState :: YiM ()
savePersistentState = do
MaxHistoryEntries histLimit <- withEditor askConfigVariableA
pStateFilename <- getPersistentStateFilename
(hist :: Histories) <- withEditor getEditorDyn
kr <- withEditor $ use killringA
curRe <- withEditor getRegexE
let pState = PersistentState {
histories = trimHistories histLimit hist
, aKillring = kr
, aCurrentRegex = curRe
}
io $ encodeFile pStateFilename pState
readPersistentState :: YiM (Maybe PersistentState)
readPersistentState = do pStateFilename <- getPersistentStateFilename
pStateExists <- io $ doesFileExist pStateFilename
if not pStateExists
then return Nothing
else io $ ignoringException $ strictDecoder pStateFilename
where
strictDecoder filename = do (state :: PersistentState) <- decodeFile filename
state `seq` return (Just state)
loadPersistentState :: YiM ()
loadPersistentState = do
maybePState <- readPersistentState
case maybePState of
Nothing -> return ()
Just pState -> do putEditorDyn $ histories pState
assign killringA $ aKillring pState
PersistentSearch keepSearch <- askConfigVariableA
when keepSearch . withEditor $
maybe (return ()) setRegexE $ aCurrentRegex pState