module Yi.PersistentState(loadPersistentState,
savePersistentState,
maxHistoryEntries)
where
import Prelude hiding ((.))
import Data.Binary
import Data.DeriveTH
import Data.Accessor.Template(nameDeriveAccessors)
import System.Directory(doesFileExist)
import qualified Data.Map as M
import Control.Exc(ignoringException)
import Yi.Prelude
import Yi.Dynamic
import Yi.Config.Simple.Types(customVariable, Field)
import Yi.History
import Yi.Editor
import Yi.Keymap(YiM)
import Yi.Keymap.Vim.TagStack(VimTagStack(..), getTagStack, setTagStack)
import Yi.KillRing(Killring(..))
import Yi.Search(getRegexE, setRegexE)
import Yi.Regex(SearchExp(..))
import Yi.Paths(getPersistentStateFilename)
data PersistentState = PersistentState { histories :: !Histories
, vimTagStack :: !VimTagStack
, aKillring :: !Killring
, aCurrentRegex :: Maybe SearchExp
}
$(derive makeBinary ''PersistentState)
newtype MaxHistoryEntries = MaxHistoryEntries { unMaxHistoryEntries :: Int }
deriving(Typeable, Binary)
instance Initializable MaxHistoryEntries where
initial = MaxHistoryEntries 1000
instance YiConfigVariable MaxHistoryEntries
$(nameDeriveAccessors ''MaxHistoryEntries (\n -> Just (n ++ "A")))
maxHistoryEntries :: Field Int
maxHistoryEntries = unMaxHistoryEntriesA . customVariable
trimHistories :: Int -> Histories -> Histories
trimHistories maxHistory = M.map trimH
where
trimH (History cur content prefix) = History cur (trim content) prefix
trim content = drop (max 0 (length content maxHistory)) content
trimTagStack :: Int -> VimTagStack -> VimTagStack
trimTagStack maxHistory = VimTagStack . take maxHistory . tagsStack
savePersistentState :: YiM ()
savePersistentState = do MaxHistoryEntries histLimit <- withEditor $ askConfigVariableA
pStateFilename <- getPersistentStateFilename
(hist :: Histories) <- withEditor $ getA dynA
tagStack <- withEditor $ getTagStack
kr <- withEditor $ getA killringA
curRe <- withEditor $ getRegexE
let pState = PersistentState { histories = trimHistories histLimit hist
, vimTagStack = trimTagStack histLimit tagStack
, 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 withEditor $ putA dynA $ histories pState
withEditor $ setTagStack $ vimTagStack pState
withEditor $ putA killringA $ aKillring pState
withEditor $ maybe (return ()) setRegexE $ aCurrentRegex pState