module Yi.Keymap.Vim.Common
( VimMode(..)
, VimBinding(..)
, GotoCharCommand(..)
, VimState(..)
, Register(..)
, RepeatToken(..)
, RepeatableAction(..)
, MatchResult(..)
, EventString(..), unEv
, OperatorName(..), unOp
, RegisterName
, module Yi.Keymap.Vim.MatchResult
, lookupBestMatch, matchesString
) where
import Control.Applicative
import Control.Lens
import Data.Binary
#if __GLASGOW_HASKELL__ < 708
import Data.DeriveTH
#else
import GHC.Generics (Generic)
#endif
import Data.Default
import qualified Data.HashMap.Strict as HM
import Data.Monoid
import Data.String (IsString(..))
import qualified Data.Text as T
import qualified Data.Text.Encoding as E
import Data.Typeable
import Yi.Buffer.Adjusted hiding (Insert)
import Yi.Editor
import Yi.Keymap
import Yi.Keymap.Vim.MatchResult
import Yi.Rope (YiString)
import Yi.Types (YiVariable)
newtype EventString = Ev { _unEv :: T.Text } deriving (Show, Eq, Ord)
instance IsString EventString where
fromString = Ev . T.pack
newtype OperatorName = Op { _unOp :: T.Text } deriving (Show, Eq)
instance IsString OperatorName where
fromString = Op . T.pack
instance Monoid EventString where
mempty = Ev mempty
Ev t `mappend` Ev t' = Ev $ t <> t'
instance Monoid OperatorName where
mempty = Op mempty
Op t `mappend` Op t' = Op $ t <> t'
instance Binary EventString where
get = Ev . E.decodeUtf8 <$> get
put (Ev t) = put $ E.encodeUtf8 t
instance Binary OperatorName where
get = Op . E.decodeUtf8 <$> get
put (Op t) = put $ E.encodeUtf8 t
makeLenses ''EventString
makeLenses ''OperatorName
lookupBestMatch :: EventString -> [(EventString, a)] -> MatchResult a
lookupBestMatch key = foldl go NoMatch
where go m (k, x) = m <|> fmap (const x) (key `matchesString` k)
matchesString :: EventString -> EventString -> MatchResult ()
matchesString (Ev got) (Ev expected)
| expected == got = WholeMatch ()
| got `T.isPrefixOf` expected = PartialMatch
| otherwise = NoMatch
type RegisterName = Char
type MacroName = Char
data RepeatableAction = RepeatableAction {
raPreviousCount :: !Int
, raActionString :: !EventString
}
deriving (Typeable, Eq, Show)
data Register = Register {
regRegionStyle :: RegionStyle
, regContent :: YiString
}
data VimMode = Normal
| NormalOperatorPending OperatorName
| Insert Char
| Replace
| ReplaceSingleChar
| InsertNormal
| InsertVisual
| Visual RegionStyle
| Ex
| Search { previousMode :: VimMode, direction :: Direction }
deriving (Typeable, Eq, Show)
data GotoCharCommand = GotoCharCommand !Char !Direction !RegionStyle
data VimState = VimState {
vsMode :: !VimMode
, vsCount :: !(Maybe Int)
, vsAccumulator :: !EventString
, vsTextObjectAccumulator :: !EventString
, vsRegisterMap :: !(HM.HashMap RegisterName Register)
, vsActiveRegister :: !RegisterName
, vsRepeatableAction :: !(Maybe RepeatableAction)
, vsStringToEval :: !EventString
, vsStickyEol :: !Bool
, vsOngoingInsertEvents :: !EventString
, vsLastGotoCharCommand :: !(Maybe GotoCharCommand)
, vsBindingAccumulator :: !EventString
, vsSecondaryCursors :: ![Point]
, vsPaste :: !Bool
, vsCurrentMacroRecording :: !(Maybe (MacroName, EventString))
} deriving (Typeable)
#if __GLASGOW_HASKELL__ < 708
$(derive makeBinary ''RepeatableAction)
$(derive makeBinary ''Register)
$(derive makeBinary ''GotoCharCommand)
#else
deriving instance Generic RepeatableAction
deriving instance Generic Register
deriving instance Generic GotoCharCommand
instance Binary RepeatableAction
instance Binary Register
instance Binary GotoCharCommand
#endif
instance Default VimMode where
def = Normal
#if __GLASGOW_HASKELL__ < 708
$(derive makeBinary ''VimMode)
#else
deriving instance Generic VimMode
instance Binary VimMode
#endif
instance Default VimState where
def = VimState
Normal
Nothing
mempty
mempty
mempty
'\0'
Nothing
mempty
False
mempty
Nothing
mempty
mempty
False
Nothing
#if __GLASGOW_HASKELL__ < 708
$(derive makeBinary ''VimState)
#else
deriving instance Generic VimState
instance Binary VimState
#endif
instance YiVariable VimState
data RepeatToken = Finish
| Drop
| Continue
deriving Show
data VimBinding
= VimBindingY (EventString -> VimState -> MatchResult (YiM RepeatToken))
| VimBindingE (EventString -> VimState -> MatchResult (EditorM RepeatToken))