{-# LANGUAGE CPP #-}
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE Haskell2010 #-}
{-# LANGUAGE NoMonomorphismRestriction #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TemplateHaskell #-}
module Yi.PersistentState(loadPersistentState,
savePersistentState,
maxHistoryEntries,
persistentSearch)
where
import GHC.Generics (Generic)
import Control.Exc (ignoringException)
import Lens.Micro.Platform ((.=), 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
{ PersistentState -> Histories
histories :: !Histories
, PersistentState -> Killring
aKillring :: !Killring
, PersistentState -> Maybe SearchExp
aCurrentRegex :: Maybe SearchExp
} deriving ((forall x. PersistentState -> Rep PersistentState x)
-> (forall x. Rep PersistentState x -> PersistentState)
-> Generic PersistentState
forall x. Rep PersistentState x -> PersistentState
forall x. PersistentState -> Rep PersistentState x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. PersistentState -> Rep PersistentState x
from :: forall x. PersistentState -> Rep PersistentState x
$cto :: forall x. Rep PersistentState x -> PersistentState
to :: forall x. Rep PersistentState x -> PersistentState
Generic)
instance Binary PersistentState
newtype MaxHistoryEntries = MaxHistoryEntries { MaxHistoryEntries -> Int
_unMaxHistoryEntries :: Int }
deriving(Typeable, Get MaxHistoryEntries
[MaxHistoryEntries] -> Put
MaxHistoryEntries -> Put
(MaxHistoryEntries -> Put)
-> Get MaxHistoryEntries
-> ([MaxHistoryEntries] -> Put)
-> Binary MaxHistoryEntries
forall t. (t -> Put) -> Get t -> ([t] -> Put) -> Binary t
$cput :: MaxHistoryEntries -> Put
put :: MaxHistoryEntries -> Put
$cget :: Get MaxHistoryEntries
get :: Get MaxHistoryEntries
$cputList :: [MaxHistoryEntries] -> Put
putList :: [MaxHistoryEntries] -> Put
Binary)
instance Default MaxHistoryEntries where
def :: MaxHistoryEntries
def = Int -> MaxHistoryEntries
MaxHistoryEntries Int
1000
instance YiConfigVariable MaxHistoryEntries
makeLenses ''MaxHistoryEntries
maxHistoryEntries :: Field Int
maxHistoryEntries :: Field Int
maxHistoryEntries = (MaxHistoryEntries -> f MaxHistoryEntries) -> Config -> f Config
forall a. YiConfigVariable a => Field a
Field MaxHistoryEntries
customVariable ((MaxHistoryEntries -> f MaxHistoryEntries) -> Config -> f Config)
-> ((Int -> f Int) -> MaxHistoryEntries -> f MaxHistoryEntries)
-> (Int -> f Int)
-> Config
-> f Config
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int -> f Int) -> MaxHistoryEntries -> f MaxHistoryEntries
Lens' MaxHistoryEntries Int
unMaxHistoryEntries
newtype PersistentSearch = PersistentSearch { PersistentSearch -> Bool
_unPersistentSearch :: Bool }
deriving(Typeable, Get PersistentSearch
[PersistentSearch] -> Put
PersistentSearch -> Put
(PersistentSearch -> Put)
-> Get PersistentSearch
-> ([PersistentSearch] -> Put)
-> Binary PersistentSearch
forall t. (t -> Put) -> Get t -> ([t] -> Put) -> Binary t
$cput :: PersistentSearch -> Put
put :: PersistentSearch -> Put
$cget :: Get PersistentSearch
get :: Get PersistentSearch
$cputList :: [PersistentSearch] -> Put
putList :: [PersistentSearch] -> Put
Binary)
instance Default PersistentSearch where
def :: PersistentSearch
def = Bool -> PersistentSearch
PersistentSearch Bool
True
instance YiConfigVariable PersistentSearch
makeLenses ''PersistentSearch
persistentSearch :: Field Bool
persistentSearch :: Field Bool
persistentSearch = (PersistentSearch -> f PersistentSearch) -> Config -> f Config
forall a. YiConfigVariable a => Field a
Field PersistentSearch
customVariable ((PersistentSearch -> f PersistentSearch) -> Config -> f Config)
-> ((Bool -> f Bool) -> PersistentSearch -> f PersistentSearch)
-> (Bool -> f Bool)
-> Config
-> f Config
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Bool -> f Bool) -> PersistentSearch -> f PersistentSearch
Lens' PersistentSearch Bool
unPersistentSearch
trimHistories :: Int -> Histories -> Histories
trimHistories :: Int -> Histories -> Histories
trimHistories Int
maxHistory (Histories Map Text History
m) = Map Text History -> Histories
Histories (Map Text History -> Histories) -> Map Text History -> Histories
forall a b. (a -> b) -> a -> b
$ (History -> History) -> Map Text History -> Map Text History
forall a b k. (a -> b) -> Map k a -> Map k b
M.map History -> History
trimH Map Text History
m
where
trimH :: History -> History
trimH (History Int
cur [Text]
content Text
prefix) = Int -> [Text] -> Text -> History
History Int
cur ([Text] -> [Text]
forall {a}. [a] -> [a]
trim [Text]
content) Text
prefix
trim :: [a] -> [a]
trim [a]
content = Int -> [a] -> [a]
forall a. Int -> [a] -> [a]
drop (Int -> Int -> Int
forall a. Ord a => a -> a -> a
max Int
0 ([a] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [a]
content Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
maxHistory)) [a]
content
savePersistentState :: YiM ()
savePersistentState :: YiM ()
savePersistentState = do
MaxHistoryEntries histLimit <- EditorM MaxHistoryEntries -> YiM MaxHistoryEntries
forall a. EditorM a -> YiM a
forall (m :: * -> *) a. MonadEditor m => EditorM a -> m a
withEditor EditorM MaxHistoryEntries
forall b (m :: * -> *). (YiConfigVariable b, MonadEditor m) => m b
askConfigVariableA
pStateFilename <- getPersistentStateFilename
(hist :: Histories) <- withEditor getEditorDyn
kr <- withEditor $ use killringA
curRe <- withEditor getRegexE
let pState = PersistentState {
histories :: Histories
histories = Int -> Histories -> Histories
trimHistories Int
histLimit Histories
hist
, aKillring :: Killring
aKillring = Killring
kr
, aCurrentRegex :: Maybe SearchExp
aCurrentRegex = Maybe SearchExp
curRe
}
io $ encodeFile pStateFilename pState
readPersistentState :: YiM (Maybe PersistentState)
readPersistentState :: YiM (Maybe PersistentState)
readPersistentState = do pStateFilename <- YiM FilePath
forall (m :: * -> *). MonadBase IO m => m FilePath
getPersistentStateFilename
pStateExists <- io $ doesFileExist pStateFilename
if not pStateExists
then return Nothing
else io $ ignoringException $ strictDecoder pStateFilename
where
strictDecoder :: FilePath -> IO (Maybe PersistentState)
strictDecoder FilePath
filename = do (state :: PersistentState) <- FilePath -> IO PersistentState
forall a. Binary a => FilePath -> IO a
decodeFile FilePath
filename
state `seq` return (Just state)
loadPersistentState :: YiM ()
loadPersistentState :: YiM ()
loadPersistentState = do
maybePState <- YiM (Maybe PersistentState)
readPersistentState
case maybePState of
Maybe PersistentState
Nothing -> () -> YiM ()
forall a. a -> YiM a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
Just PersistentState
pState -> do Histories -> YiM ()
forall (m :: * -> *) a.
(MonadEditor m, YiVariable a, Functor m) =>
a -> m ()
putEditorDyn (Histories -> YiM ()) -> Histories -> YiM ()
forall a b. (a -> b) -> a -> b
$ PersistentState -> Histories
histories PersistentState
pState
ASetter Editor Editor Killring Killring -> Killring -> YiM ()
forall s (m :: * -> *) a b.
MonadState s m =>
ASetter s s a b -> b -> m ()
(.=) ASetter Editor Editor Killring Killring
Lens' Editor Killring
killringA (Killring -> YiM ()) -> Killring -> YiM ()
forall a b. (a -> b) -> a -> b
$ PersistentState -> Killring
aKillring PersistentState
pState
PersistentSearch keepSearch <- YiM PersistentSearch
forall b (m :: * -> *). (YiConfigVariable b, MonadEditor m) => m b
askConfigVariableA
when keepSearch . withEditor $
maybe (return ()) setRegexE $ aCurrentRegex pState