content: {-# language
       Rank2Types
    , TemplateHaskell
    , OverloadedStrings
    , ExistentialQuantification
    , ScopedTypeVariables
    , GeneralizedNewtypeDeriving
    , FlexibleInstances
    , StandaloneDeriving
    #-}
  
  module Rasa.Internal.Buffer
    ( Buffer
    , BufAction
    , HasBuffer(..)
    , BufRef(..)
    , text
    , mkBuffer
    , ref
  
    , buffers
    , nextBufId
    ) where
  
  
  import Eve
  
  import qualified Yi.Rope as Y
  import Control.Lens hiding (matching)
  import qualified Data.IntMap as IM
  import Data.Default
  
  -- | An opaque reference to a buffer.
  -- When operating over a BufRef Rasa checks if the 'Rasa.Internal.Buffer.Buffer' still
  -- exists and simply ignores any operations over non-existent buffers; typically returning 'Nothing'
  newtype BufRef =
    BufRef Int
    deriving (Show, Eq, Ord)
  
  newtype NextBufId = NextBufId
    { _nextBufId' :: Int 
    } deriving Show
  
  instance Default NextBufId where
    def = NextBufId 0
  
  makeLenses ''NextBufId
  nextBufId :: HasStates s => Lens' s Int
  nextBufId = stateLens.nextBufId'
  
  -- | A buffer, holds the text in the buffer and any extension states that are set on the buffer.
  data Buffer = Buffer
    { _text' :: Y.YiString
    , _bufStates' :: States
    , _ref :: BufRef
    }
  makeLenses ''Buffer
  
  instance HasStates Buffer where
    states = bufStates'
  
  instance HasEvents Buffer where
  
  -- | This allows creation of polymorphic lenses over any type which has access to a Buffer
  class HasBuffer a where
    buffer :: Lens' a Buffer
  
  instance HasBuffer Buffer where
    buffer = lens id (flip const)
  
  -- | This lens focuses the text of the in-scope buffer.
  text :: HasBuffer b => Lens' b Y.YiString
  text = buffer.text'
  
  instance Show Buffer where
    show b = "text:" ++ (Y.toString . Y.take 30 $ (b^.text)) ++ "...,\n"
  
  type BufAction a = Action Buffer a
  
  newtype Buffers = Buffers
    { _buffers' :: IM.IntMap Buffer
    } deriving Show
  makeLenses '' Buffers
  
  instance Default Buffers where
    def = Buffers mempty
  
  -- | A lens over the map of available buffers
  buffers :: HasStates s => Lens' s (IM.IntMap Buffer)
  buffers = stateLens.buffers'
  
  -- | Creates a new buffer from the given text.
  mkBuffer :: Y.YiString -> BufRef -> Buffer
  mkBuffer txt bRef =
    Buffer
      { _text' = txt
      , _bufStates' = mempty
      , _ref = bRef
      }
  