    {-# LANGUAGE LambdaCase        #-}
    {-# LANGUAGE OverloadedStrings #-}
    {-# LANGUAGE TemplateHaskell   #-}
    {-# OPTIONS_GHC -fno-warn-orphans #-}
    {-# OPTIONS_HADDOCK show-extensions #-}

    -- |
    -- Module      :  Yi.Editor
    -- License     :  GPL-2
    -- Maintainer  :  yi-devel@googlegroups.com
    -- Stability   :  experimental
    -- Portability :  portable
    --
    -- The top level editor state, and operations on it. This is inside an
    -- internal module for easy re-export with Yi.Types bits.

    module Yi.Editor ( Editor(..), EditorM, MonadEditor(..)
                     , runEditor
                     , acceptedInputsOtherWindow
                     , addJumpAtE
                     , addJumpHereE
                     , alternateBufferE
                     , askConfigVariableA
                     , bufferSet
                     , buffersA
                     , closeBufferAndWindowE
                     , closeBufferE
                     , closeOtherE
                     , clrStatus
                     , commonNamePrefix
                     , currentBuffer
                     , currentRegexA
                     , currentWindowA
                     , deleteBuffer
                     , deleteTabE
                     , doesBufferNameExist
                     , emptyEditor
                     , findBuffer
                     , findBufferWith
                     , findBufferWithName
                     , findWindowWith
                     , focusWindowE
                     , getBufferStack
                     , getBufferWithName
                     , getBufferWithNameOrCurrent
                     , getEditorDyn
                     , getRegE
                     , jumpBackE
                     , jumpForwardE
                     , killringA
                     , layoutManagerNextVariantE
                     , layoutManagerPreviousVariantE
                     , layoutManagersNextE
                     , layoutManagersPreviousE
                     , layoutManagersPrintMsgE
                     , maxStatusHeightA
                     , moveTabE
                     , moveWinNextE
                     , moveWinPrevE
                     , newBufferE
                     , newEmptyBufferE
                     , newTabE
                     , newTempBufferE
                     , newWindowE
                     , nextTabE
                     , nextWinE
                     , onCloseActionsA
                     , pendingEventsA
                     , prevWinE
                     , previousTabE
                     , printMsg
                     , printMsgs
                     , printStatus
                     , pushWinToFirstE
                     , putEditorDyn
                     , searchDirectionA
                     , setDividerPosE
                     , setRegE
                     , setStatus
                     , shiftOtherWindow
                     , splitE
                     , statusLine
                     , statusLineInfo
                     , statusLinesA
                     , stringToNewBuffer
                     , swapWinWithFirstE
                     , switchToBufferE
                     , switchToBufferWithNameE
                     , tabsA
                     , tryCloseE
                     , windows
                     , windowsA
                     , windowsOnBufferE
                     , withCurrentBuffer
                     , withEveryBuffer
                     , withGivenBuffer
                     , withGivenBufferAndWindow
                     , withOtherWindow
                     , withWindowE
                     ) where

    import           Prelude                        hiding (all, concatMap, foldl, foldr)

    import           Lens.Micro.Platform            (Lens', lens, mapped,
                                                     use, view, (%=), (%~),
                                                     (&), (.~), (^.))
    import           Control.Monad                  (forM_, liftM, unless, when)
    import           Control.Monad.Reader           (MonadReader (ask), asks)
    import           Control.Monad.State            (gets, modify)
    import           Data.Binary                    (Binary, get, put)
    import           Data.Default                   (Default, def)
    import qualified Data.DelayList                 as DelayList (insert)
    import           Data.DynamicState.Serializable (getDyn, putDyn)
    import           Data.Foldable                  (Foldable (foldl, foldl', foldr), all, concatMap, toList)
    import           Data.List                      (delete, (\\))
    import           Data.List.NonEmpty             (NonEmpty (..), fromList, nub)
    import qualified Data.List.NonEmpty             as NE (filter, head, length, toList, (<|))
    import qualified Data.List.PointedList          as PL (atEnd, moveTo)
    import qualified Data.List.PointedList.Circular as PL (PointedList (..), delete,
                                                           deleteLeft, deleteOthers,
                                                           deleteRight, focus,
                                                           insertLeft, insertRight,
                                                           length, next, previous,
                                                           singleton, _focus)
    import qualified Data.Map                       as M (delete, elems, empty,
                                                          insert, lookup, singleton, (!))
    import           Data.Maybe                     (fromJust, fromMaybe, isNothing)
    import qualified Data.Monoid                    as Mon ((<>))
    import           Data.Semigroup                 ((<>))
    import qualified Data.Sequence                  as S
    import qualified Data.Text                      as T (Text, null, pack, unlines, unpack, unwords, isInfixOf)
    import           System.FilePath                (splitPath)
    import           Yi.Buffer
    import           Yi.Config
    import           Yi.Interact                    as I (accepted, mkAutomaton)
    import           Yi.JumpList                    (Jump (..), JumpList, addJump, jumpBack, jumpForward)
    import           Yi.KillRing                    (krEmpty, krGet, krPut, krSet)
    import           Yi.Layout
    import           Yi.Monad                       (assign, getsAndModify, uses)
    import           Yi.Rope                        (YiString, empty, fromText)
    import qualified Yi.Rope                        as R (YiString, fromText, snoc)
    import           Yi.String                      (listify)
    import           Yi.Style                       (defaultStyle)
    import           Yi.Tab
    import           Yi.Types
    import           Yi.Utils
    import           Yi.Window

    instance Binary Editor where
      put :: Editor -> Put
    put (Editor NonEmpty BufferRef
    bss Map BufferRef FBuffer
    bs Int
    supply PointedList Tab
    ts DynamicState
    dv Statuses
    _sl Int
    msh Killring
    kr Maybe SearchExp
    regex Direction
    _dir [Event]
    _ev Map BufferRef (EditorM ())
    _cwa ) =
        let putNE :: NonEmpty t -> Put
    putNE (t
    x :| [t]
    xs) = t -> Put
    forall t. Binary t => t -> Put
    put t
    x Put -> Put -> Put
    forall a b. PutM a -> PutM b -> PutM b
    forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
    >> [t] -> Put
    forall t. Binary t => t -> Put
    put [t]
    xs
        in NonEmpty BufferRef -> Put
    forall {t}. Binary t => NonEmpty t -> Put
    putNE NonEmpty BufferRef
    bss Put -> Put -> Put
    forall a b. PutM a -> PutM b -> PutM b
    forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
    >> Map BufferRef FBuffer -> Put
    forall t. Binary t => t -> Put
    put Map BufferRef FBuffer
    bs Put -> Put -> Put
    forall a b. PutM a -> PutM b -> PutM b
    forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
    >> Int -> Put
    forall t. Binary t => t -> Put
    put Int
    supply Put -> Put -> Put
    forall a b. PutM a -> PutM b -> PutM b
    forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
    >> PointedList Tab -> Put
    forall t. Binary t => t -> Put
    put PointedList Tab
    ts
           Put -> Put -> Put
    forall a b. PutM a -> PutM b -> PutM b
    forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
    >> DynamicState -> Put
    forall t. Binary t => t -> Put
    put DynamicState
    dv Put -> Put -> Put
    forall a b. PutM a -> PutM b -> PutM b
    forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
    >> Int -> Put
    forall t. Binary t => t -> Put
    put Int
    msh Put -> Put -> Put
    forall a b. PutM a -> PutM b -> PutM b
    forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
    >> Killring -> Put
    forall t. Binary t => t -> Put
    put Killring
    kr Put -> Put -> Put
    forall a b. PutM a -> PutM b -> PutM b
    forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
    >> Maybe SearchExp -> Put
    forall t. Binary t => t -> Put
    put Maybe SearchExp
    regex
      get :: Get Editor
    get = do
        bss <- BufferRef -> [BufferRef] -> NonEmpty BufferRef
    forall a. a -> [a] -> NonEmpty a
    (:|) (BufferRef -> [BufferRef] -> NonEmpty BufferRef)
    -> Get BufferRef -> Get ([BufferRef] -> NonEmpty BufferRef)
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Get BufferRef
    forall t. Binary t => Get t
    get Get ([BufferRef] -> NonEmpty BufferRef)
    -> Get [BufferRef] -> Get (NonEmpty BufferRef)
    forall a b. Get (a -> b) -> Get a -> Get b
    forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
    <*> Get [BufferRef]
    forall t. Binary t => Get t
    get
        bs <- get
        supply <- get
        ts <- get
        dv <- get
        msh <- get
        kr <- get
        regex <- get
        return $ emptyEditor { bufferStack = bss
                             , buffers = bs
                             , refSupply = supply
                             , tabs_ = ts
                             , dynamic = dv
                             , maxStatusHeight = msh
                             , killring = kr
                             , currentRegex = regex
                             }

    -- | The initial state
    emptyEditor :: Editor
    emptyEditor :: Editor
    emptyEditor = Editor
      { buffers :: Map BufferRef FBuffer
    buffers      = BufferRef -> FBuffer -> Map BufferRef FBuffer
    forall k a. k -> a -> Map k a
    M.singleton (FBuffer -> BufferRef
    bkey FBuffer
    buf) FBuffer
    buf
      , tabs_ :: PointedList Tab
    tabs_        = Tab -> PointedList Tab
    forall a. a -> PointedList a
    PL.singleton Tab
    tab
      , bufferStack :: NonEmpty BufferRef
    bufferStack  = FBuffer -> BufferRef
    bkey FBuffer
    buf BufferRef -> [BufferRef] -> NonEmpty BufferRef
    forall a. a -> [a] -> NonEmpty a
    :| []
      , refSupply :: Int
    refSupply    = Int
    3
      , currentRegex :: Maybe SearchExp
    currentRegex = Maybe SearchExp
    forall a. Maybe a
    Nothing
      , searchDirection :: Direction
    searchDirection = Direction
    Forward
      , dynamic :: DynamicState
    dynamic      = DynamicState
    forall a. Monoid a => a
    mempty
      , statusLines :: Statuses
    statusLines  = (Int, Status) -> Statuses -> Statuses
    forall a. (Int, a) -> DelayList a -> DelayList a
    DelayList.insert (Int
    forall a. Bounded a => a
    maxBound, ([Text
    ""], StyleName
    defaultStyle)) []
      , killring :: Killring
    killring     = Killring
    krEmpty
      , pendingEvents :: [Event]
    pendingEvents = []
      , maxStatusHeight :: Int
    maxStatusHeight = Int
    1
      , onCloseActions :: Map BufferRef (EditorM ())
    onCloseActions = Map BufferRef (EditorM ())
    forall k a. Map k a
    M.empty
      }
      where buf :: FBuffer
    buf = BufferRef -> BufferId -> YiString -> FBuffer
    newB BufferRef
    0 (Text -> BufferId
    MemBuffer Text
    "console") YiString
    forall a. Monoid a => a
    mempty
            win :: Window
    win = (BufferRef -> Window
    dummyWindow (FBuffer -> BufferRef
    bkey FBuffer
    buf)) { wkey = WindowRef 1 , isMini = False }
            tab :: Tab
    tab = Int -> Window -> Tab
    makeTab1 Int
    2 Window
    win

    -- ---------------------------------------------------------------------

    makeLensesWithSuffix "A" ''Editor

    windows :: Editor -> PL.PointedList Window
    windows :: Editor -> PointedList Window
    windows Editor
    e = Editor
    e Editor
    -> Getting (PointedList Window) Editor (PointedList Window)
    -> PointedList Window
    forall s a. s -> Getting a s a -> a
    ^. Getting (PointedList Window) Editor (PointedList Window)
    Lens' Editor (PointedList Window)
    windowsA

    windowsA :: Lens' Editor (PL.PointedList Window)
    windowsA :: Lens' Editor (PointedList Window)
    windowsA = (Tab -> f Tab) -> Editor -> f Editor
    Lens' Editor Tab
    currentTabA ((Tab -> f Tab) -> Editor -> f Editor)
    -> ((PointedList Window -> f (PointedList Window)) -> Tab -> f Tab)
    -> (PointedList Window -> f (PointedList Window))
    -> Editor
    -> f Editor
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (PointedList Window -> f (PointedList Window)) -> Tab -> f Tab
    forall (f :: * -> *).
    Functor f =>
    (PointedList Window -> f (PointedList Window)) -> Tab -> f Tab
    tabWindowsA

    tabsA :: Lens' Editor (PL.PointedList Tab)
    tabsA :: Lens' Editor (PointedList Tab)
    tabsA = (Editor -> f Editor) -> Editor -> f Editor
    Lens' Editor Editor
    fixCurrentBufferA_ ((Editor -> f Editor) -> Editor -> f Editor)
    -> ((PointedList Tab -> f (PointedList Tab)) -> Editor -> f Editor)
    -> (PointedList Tab -> f (PointedList Tab))
    -> Editor
    -> f Editor
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (PointedList Tab -> f (PointedList Tab)) -> Editor -> f Editor
    Lens' Editor (PointedList Tab)
    tabs_A

    currentTabA :: Lens' Editor Tab
    currentTabA :: Lens' Editor Tab
    currentTabA = (PointedList Tab -> f (PointedList Tab)) -> Editor -> f Editor
    Lens' Editor (PointedList Tab)
    tabsA ((PointedList Tab -> f (PointedList Tab)) -> Editor -> f Editor)
    -> ((Tab -> f Tab) -> PointedList Tab -> f (PointedList Tab))
    -> (Tab -> f Tab)
    -> Editor
    -> f Editor
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (Tab -> f Tab) -> PointedList Tab -> f (PointedList Tab)
    forall (f :: * -> *) a.
    Functor f =>
    (a -> f a) -> PointedList a -> f (PointedList a)
    PL.focus

    askConfigVariableA :: (YiConfigVariable b, MonadEditor m) => m b
    askConfigVariableA :: forall b (m :: * -> *). (YiConfigVariable b, MonadEditor m) => m b
    askConfigVariableA = do cfg <- m Config
    forall (m :: * -> *). MonadEditor m => m Config
    askCfg
                            return $ cfg ^. configVariable

    -- ---------------------------------------------------------------------
    -- Buffer operations

    newRef :: MonadEditor m => m Int
    newRef :: forall (m :: * -> *). MonadEditor m => m Int
    newRef = EditorM Int -> m Int
    forall a. EditorM a -> m a
    forall (m :: * -> *) a. MonadEditor m => EditorM a -> m a
    withEditor ((Int -> Identity Int) -> Editor -> Identity Editor
    Lens' Editor Int
    refSupplyA ((Int -> Identity Int) -> Editor -> Identity Editor)
    -> (Int -> Int) -> EditorM ()
    forall s (m :: * -> *) a b.
    MonadState s m =>
    ASetter s s a b -> (a -> b) -> m ()
    %= (Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    1) EditorM () -> EditorM Int -> EditorM Int
    forall a b. EditorM a -> EditorM b -> EditorM b
    forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
    >> Getting Int Editor Int -> EditorM Int
    forall s (m :: * -> *) a. MonadState s m => Getting a s a -> m a
    use Getting Int Editor Int
    Lens' Editor Int
    refSupplyA)

    newBufRef :: MonadEditor m => m BufferRef
    newBufRef :: forall (m :: * -> *). MonadEditor m => m BufferRef
    newBufRef = (Int -> BufferRef) -> m Int -> m BufferRef
    forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
    liftM Int -> BufferRef
    BufferRef m Int
    forall (m :: * -> *). MonadEditor m => m Int
    newRef

    -- | Create and fill a new buffer, using contents of string.
    -- | Does not focus the window, or make it the current window.
    -- | Call newWindowE or switchToBufferE to take care of that.
    stringToNewBuffer :: MonadEditor m
                      => BufferId -- ^ The buffer indentifier
                      -> YiString -- ^ The contents with which to populate
                                  -- the buffer
                      -> m BufferRef
    stringToNewBuffer :: forall (m :: * -> *).
    MonadEditor m =>
    BufferId -> YiString -> m BufferRef
    stringToNewBuffer BufferId
    nm YiString
    cs = EditorM BufferRef -> m BufferRef
    forall a. EditorM a -> m a
    forall (m :: * -> *) a. MonadEditor m => EditorM a -> m a
    withEditor (EditorM BufferRef -> m BufferRef)
    -> EditorM BufferRef -> m BufferRef
    forall a b. (a -> b) -> a -> b
    $ do
        u <- EditorM BufferRef
    forall (m :: * -> *). MonadEditor m => m BufferRef
    newBufRef
        defRegStyle <- configRegionStyle <$> askCfg
        insertBuffer $ newB u nm cs
        m <- asks configFundamentalMode
        withGivenBuffer u $ do
            putRegionStyle defRegStyle
            setAnyMode m
        return u

    insertBuffer :: MonadEditor m => FBuffer -> m ()
    insertBuffer :: forall (m :: * -> *). MonadEditor m => FBuffer -> m ()
    insertBuffer FBuffer
    b = EditorM () -> m ()
    forall a. EditorM a -> m a
    forall (m :: * -> *) a. MonadEditor m => EditorM a -> m a
    withEditor (EditorM () -> m ())
    -> ((Editor -> Editor) -> EditorM ()) -> (Editor -> Editor) -> m ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (Editor -> Editor) -> EditorM ()
    forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
    modify ((Editor -> Editor) -> m ()) -> (Editor -> Editor) -> m ()
    forall a b. (a -> b) -> a -> b
    $ \Editor
    e ->
        -- insert buffers at the end, so that
        -- "background" buffers do not interfere.
        Editor
    e { bufferStack = nub (bufferStack e <> (bkey b :| []))
          , buffers = M.insert (bkey b) b (buffers e)}

    -- Prevent possible space leaks in the editor structure
    forceFold1 :: Foldable t => t a -> t a
    forceFold1 :: forall (t :: * -> *) a. Foldable t => t a -> t a
    forceFold1 t a
    x = (a -> t a -> t a) -> t a -> t a -> t a
    forall a b. (a -> b -> b) -> b -> t a -> b
    forall (t :: * -> *) a b.
    Foldable t =>
    (a -> b -> b) -> b -> t a -> b
    foldr a -> t a -> t a
    forall a b. a -> b -> b
    seq t a
    x t a
    x

    forceFoldTabs :: Foldable t => t Tab -> t Tab
    forceFoldTabs :: forall (t :: * -> *). Foldable t => t Tab -> t Tab
    forceFoldTabs t Tab
    x = (Tab -> t Tab -> t Tab) -> t Tab -> t Tab -> t Tab
    forall a b. (a -> b -> b) -> b -> t a -> b
    forall (t :: * -> *) a b.
    Foldable t =>
    (a -> b -> b) -> b -> t a -> b
    foldr (Tab -> t Tab -> t Tab
    forall a b. a -> b -> b
    seq (Tab -> t Tab -> t Tab) -> (Tab -> Tab) -> Tab -> t Tab -> t Tab
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Tab -> Tab
    forceTab) t Tab
    x t Tab
    x

    -- | Delete a buffer (and release resources associated with it).
    deleteBuffer :: MonadEditor m => BufferRef -> m ()
    deleteBuffer :: forall (m :: * -> *). MonadEditor m => BufferRef -> m ()
    deleteBuffer BufferRef
    k = EditorM () -> m ()
    forall a. EditorM a -> m a
    forall (m :: * -> *) a. MonadEditor m => EditorM a -> m a
    withEditor (EditorM () -> m ()) -> EditorM () -> m ()
    forall a b. (a -> b) -> a -> b
    $ do
      -- If the buffer has an associated close action execute that now.
      -- Unless the buffer is the last buffer in the editor. In which case
      -- it cannot be closed and, I think, the close action should not be
      -- applied.
      --
      -- The close actions seem dangerous, but I know of no other simple
      -- way to resolve issues related to what buffer receives actions
      -- after the minibuffer closes.
      (Editor -> NonEmpty BufferRef) -> EditorM (NonEmpty BufferRef)
    forall s (m :: * -> *) a. MonadState s m => (s -> a) -> m a
    gets Editor -> NonEmpty BufferRef
    bufferStack EditorM (NonEmpty BufferRef)
    -> (NonEmpty BufferRef -> EditorM ()) -> EditorM ()
    forall a b. EditorM a -> (a -> EditorM b) -> EditorM b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= \case
        BufferRef
    _ :| [] -> () -> EditorM ()
    forall a. a -> EditorM a
    forall (m :: * -> *) a. Monad m => a -> m a
    return ()
        NonEmpty BufferRef
    _ -> BufferRef -> Map BufferRef (EditorM ()) -> Maybe (EditorM ())
    forall k a. Ord k => k -> Map k a -> Maybe a
    M.lookup BufferRef
    k (Map BufferRef (EditorM ()) -> Maybe (EditorM ()))
    -> EditorM (Map BufferRef (EditorM ()))
    -> EditorM (Maybe (EditorM ()))
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> (Editor -> Map BufferRef (EditorM ()))
    -> EditorM (Map BufferRef (EditorM ()))
    forall s (m :: * -> *) a. MonadState s m => (s -> a) -> m a
    gets Editor -> Map BufferRef (EditorM ())
    onCloseActions
             EditorM (Maybe (EditorM ()))
    -> (Maybe (EditorM ()) -> EditorM ()) -> EditorM ()
    forall a b. EditorM a -> (a -> EditorM b) -> EditorM b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= \Maybe (EditorM ())
    m_action -> EditorM () -> Maybe (EditorM ()) -> EditorM ()
    forall a. a -> Maybe a -> a
    fromMaybe (() -> EditorM ()
    forall a. a -> EditorM a
    forall (m :: * -> *) a. Monad m => a -> m a
    return ()) Maybe (EditorM ())
    m_action
      -- Now try deleting the buffer. Checking, once again, that it is not
      -- the last buffer.
      bs <- (Editor -> NonEmpty BufferRef) -> EditorM (NonEmpty BufferRef)
    forall s (m :: * -> *) a. MonadState s m => (s -> a) -> m a
    gets Editor -> NonEmpty BufferRef
    bufferStack
      ws <- use windowsA
      case bs of
        BufferRef
    b0 :| BufferRef
    nextB : [BufferRef]
    _ -> do
          let pickOther :: Window -> Window
    pickOther Window
    w = if Window -> BufferRef
    bufkey Window
    w BufferRef -> BufferRef -> Bool
    forall a. Eq a => a -> a -> Bool
    == BufferRef
    k then Window
    w {bufkey = other} else Window
    w
              visibleBuffers :: [BufferRef]
    visibleBuffers = Window -> BufferRef
    bufkey (Window -> BufferRef) -> [Window] -> [BufferRef]
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> PointedList Window -> [Window]
    forall a. PointedList a -> [a]
    forall (t :: * -> *) a. Foldable t => t a -> [a]
    toList PointedList Window
    ws

              -- This ‘head’ always works because we witness that length of
              -- bs ≥ 2 (through case) and ‘delete’ only deletes up to 1
              -- element so we at worst we end up with something like
              -- ‘head $ [] ++ [foo]’ when bs ≡ visibleBuffers
              bs' :: [BufferRef]
    bs' = NonEmpty BufferRef -> [BufferRef]
    forall a. NonEmpty a -> [a]
    NE.toList NonEmpty BufferRef
    bs
              other :: BufferRef
    other = [BufferRef] -> BufferRef
    forall a. HasCallStack => [a] -> a
    head ([BufferRef] -> BufferRef) -> [BufferRef] -> BufferRef
    forall a b. (a -> b) -> a -> b
    $ ([BufferRef]
    bs' [BufferRef] -> [BufferRef] -> [BufferRef]
    forall a. Eq a => [a] -> [a] -> [a]
    \\ [BufferRef]
    visibleBuffers) [BufferRef] -> [BufferRef] -> [BufferRef]
    forall a. [a] -> [a] -> [a]
    ++ BufferRef -> [BufferRef] -> [BufferRef]
    forall a. Eq a => a -> [a] -> [a]
    delete BufferRef
    k [BufferRef]
    bs'
          Bool -> EditorM () -> EditorM ()
    forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
    when (BufferRef
    b0 BufferRef -> BufferRef -> Bool
    forall a. Eq a => a -> a -> Bool
    == BufferRef
    k) (EditorM () -> EditorM ()) -> EditorM () -> EditorM ()
    forall a b. (a -> b) -> a -> b
    $
            -- we delete the currently selected buffer: the next buffer
            -- will become active in the main window, therefore it must be
            -- assigned a new window.
            BufferRef -> EditorM ()
    switchToBufferE BufferRef
    nextB

          -- NOTE: This *only* works if not all bufferStack buffers are
          -- equivalent to ‘k’. Assuring that there are no duplicates in
          -- the bufferStack is equivalent in this case because of its
          -- length.
          (Editor -> Editor) -> EditorM ()
    forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
    modify ((Editor -> Editor) -> EditorM ())
    -> (Editor -> Editor) -> EditorM ()
    forall a b. (a -> b) -> a -> b
    $ \Editor
    e ->
            Editor
    e Editor -> (Editor -> Editor) -> Editor
    forall a b. a -> (a -> b) -> b
    & (NonEmpty BufferRef -> Identity (NonEmpty BufferRef))
    -> Editor -> Identity Editor
    Lens' Editor (NonEmpty BufferRef)
    bufferStackA ((NonEmpty BufferRef -> Identity (NonEmpty BufferRef))
     -> Editor -> Identity Editor)
    -> (NonEmpty BufferRef -> NonEmpty BufferRef) -> Editor -> Editor
    forall s t a b. ASetter s t a b -> (a -> b) -> s -> t
    %~ [BufferRef] -> NonEmpty BufferRef
    forall a. HasCallStack => [a] -> NonEmpty a
    fromList ([BufferRef] -> NonEmpty BufferRef)
    -> (NonEmpty BufferRef -> [BufferRef])
    -> NonEmpty BufferRef
    -> NonEmpty BufferRef
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . [BufferRef] -> [BufferRef]
    forall (t :: * -> *) a. Foldable t => t a -> t a
    forceFold1 ([BufferRef] -> [BufferRef])
    -> (NonEmpty BufferRef -> [BufferRef])
    -> NonEmpty BufferRef
    -> [BufferRef]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (BufferRef -> Bool) -> NonEmpty BufferRef -> [BufferRef]
    forall a. (a -> Bool) -> NonEmpty a -> [a]
    NE.filter (BufferRef
    k BufferRef -> BufferRef -> Bool
    forall a. Eq a => a -> a -> Bool
    /=)
              Editor -> (Editor -> Editor) -> Editor
    forall a b. a -> (a -> b) -> b
    & (Map BufferRef FBuffer -> Identity (Map BufferRef FBuffer))
    -> Editor -> Identity Editor
    Lens' Editor (Map BufferRef FBuffer)
    buffersA ((Map BufferRef FBuffer -> Identity (Map BufferRef FBuffer))
     -> Editor -> Identity Editor)
    -> (Map BufferRef FBuffer -> Map BufferRef FBuffer)
    -> Editor
    -> Editor
    forall s t a b. ASetter s t a b -> (a -> b) -> s -> t
    %~ BufferRef -> Map BufferRef FBuffer -> Map BufferRef FBuffer
    forall k a. Ord k => k -> Map k a -> Map k a
    M.delete BufferRef
    k
              Editor -> (Editor -> Editor) -> Editor
    forall a b. a -> (a -> b) -> b
    & (PointedList Tab -> Identity (PointedList Tab))
    -> Editor -> Identity Editor
    Lens' Editor (PointedList Tab)
    tabs_A ((PointedList Tab -> Identity (PointedList Tab))
     -> Editor -> Identity Editor)
    -> (PointedList Tab -> PointedList Tab) -> Editor -> Editor
    forall s t a b. ASetter s t a b -> (a -> b) -> s -> t
    %~ PointedList Tab -> PointedList Tab
    forall (t :: * -> *). Foldable t => t Tab -> t Tab
    forceFoldTabs (PointedList Tab -> PointedList Tab)
    -> (PointedList Tab -> PointedList Tab)
    -> PointedList Tab
    -> PointedList Tab
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (Tab -> Tab) -> PointedList Tab -> PointedList Tab
    forall a b. (a -> b) -> PointedList a -> PointedList b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap ((Window -> Window) -> Tab -> Tab
    mapWindows Window -> Window
    pickOther)
              -- all windows open on that buffer must switch to another
              -- buffer.

          (PointedList Window -> Identity (PointedList Window))
    -> Editor -> Identity Editor
    Lens' Editor (PointedList Window)
    windowsA ((PointedList Window -> Identity (PointedList Window))
     -> Editor -> Identity Editor)
    -> (([BufferRef] -> Identity [BufferRef])
        -> PointedList Window -> Identity (PointedList Window))
    -> ([BufferRef] -> Identity [BufferRef])
    -> Editor
    -> Identity Editor
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ASetter (PointedList Window) (PointedList Window) Window Window
    forall (f :: * -> *) a b. Functor f => ASetter (f a) (f b) a b
    mapped ASetter (PointedList Window) (PointedList Window) Window Window
    -> (([BufferRef] -> Identity [BufferRef])
        -> Window -> Identity Window)
    -> ([BufferRef] -> Identity [BufferRef])
    -> PointedList Window
    -> Identity (PointedList Window)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ([BufferRef] -> Identity [BufferRef]) -> Window -> Identity Window
    Lens' Window [BufferRef]
    bufAccessListA (([BufferRef] -> Identity [BufferRef])
     -> Editor -> Identity Editor)
    -> ([BufferRef] -> [BufferRef]) -> EditorM ()
    forall s (m :: * -> *) a b.
    MonadState s m =>
    ASetter s s a b -> (a -> b) -> m ()
    %= [BufferRef] -> [BufferRef]
    forall (t :: * -> *) a. Foldable t => t a -> t a
    forceFold1 ([BufferRef] -> [BufferRef])
    -> ([BufferRef] -> [BufferRef]) -> [BufferRef] -> [BufferRef]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (BufferRef -> Bool) -> [BufferRef] -> [BufferRef]
    forall a. (a -> Bool) -> [a] -> [a]
    filter (BufferRef
    k BufferRef -> BufferRef -> Bool
    forall a. Eq a => a -> a -> Bool
    /=)
        NonEmpty BufferRef
    _ -> () -> EditorM ()
    forall a. a -> EditorM a
    forall (m :: * -> *) a. Monad m => a -> m a
    return () -- Don't delete the last buffer.

    -- | Return the buffers we have, /in no particular order/
    bufferSet :: Editor -> [FBuffer]
    bufferSet :: Editor -> [FBuffer]
    bufferSet = Map BufferRef FBuffer -> [FBuffer]
    forall k a. Map k a -> [a]
    M.elems (Map BufferRef FBuffer -> [FBuffer])
    -> (Editor -> Map BufferRef FBuffer) -> Editor -> [FBuffer]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Editor -> Map BufferRef FBuffer
    buffers

    -- | Return a prefix that can be removed from all buffer paths while
    -- keeping them unique.
    commonNamePrefix :: Editor -> [FilePath]
    commonNamePrefix :: Editor -> [FilePath]
    commonNamePrefix = [[FilePath]] -> [FilePath]
    forall a. Eq a => [[a]] -> [a]
    commonPrefix ([[FilePath]] -> [FilePath])
    -> (Editor -> [[FilePath]]) -> Editor -> [FilePath]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (FilePath -> [FilePath]) -> [FilePath] -> [[FilePath]]
    forall a b. (a -> b) -> [a] -> [b]
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap ([FilePath] -> [FilePath]
    forall {a}. [a] -> [a]
    dropLast ([FilePath] -> [FilePath])
    -> (FilePath -> [FilePath]) -> FilePath -> [FilePath]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . FilePath -> [FilePath]
    splitPath)
                       ([FilePath] -> [[FilePath]])
    -> (Editor -> [FilePath]) -> Editor -> [[FilePath]]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . [BufferId] -> [FilePath]
    fbufs ([BufferId] -> [FilePath])
    -> (Editor -> [BufferId]) -> Editor -> [FilePath]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (FBuffer -> BufferId) -> [FBuffer] -> [BufferId]
    forall a b. (a -> b) -> [a] -> [b]
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap (FBuffer -> Getting BufferId FBuffer BufferId -> BufferId
    forall s a. s -> Getting a s a -> a
    ^. Getting BufferId FBuffer BufferId
    forall c. HasAttributes c => Lens' c BufferId
    Lens' FBuffer BufferId
    identA) ([FBuffer] -> [BufferId])
    -> (Editor -> [FBuffer]) -> Editor -> [BufferId]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Editor -> [FBuffer]
    bufferSet
      where dropLast :: [a] -> [a]
    dropLast [] = []
            dropLast [a]
    x = [a] -> [a]
    forall a. HasCallStack => [a] -> [a]
    init [a]
    x
            fbufs :: [BufferId] -> [FilePath]
    fbufs [BufferId]
    xs = [ FilePath
    x | FileBuffer FilePath
    x <- [BufferId]
    xs ]
              -- drop the last component, so that it is never hidden.

    getBufferStack :: MonadEditor m => m (NonEmpty FBuffer)
    getBufferStack :: forall (m :: * -> *). MonadEditor m => m (NonEmpty FBuffer)
    getBufferStack = EditorM (NonEmpty FBuffer) -> m (NonEmpty FBuffer)
    forall a. EditorM a -> m a
    forall (m :: * -> *) a. MonadEditor m => EditorM a -> m a
    withEditor (EditorM (NonEmpty FBuffer) -> m (NonEmpty FBuffer))
    -> EditorM (NonEmpty FBuffer) -> m (NonEmpty FBuffer)
    forall a b. (a -> b) -> a -> b
    $ do
      bufMap <- (Editor -> Map BufferRef FBuffer)
    -> EditorM (Map BufferRef FBuffer)
    forall s (m :: * -> *) a. MonadState s m => (s -> a) -> m a
    gets Editor -> Map BufferRef FBuffer
    buffers
      gets $ fmap (bufMap M.!) . bufferStack

    findBuffer :: MonadEditor m => BufferRef -> m (Maybe FBuffer)
    findBuffer :: forall (m :: * -> *).
    MonadEditor m =>
    BufferRef -> m (Maybe FBuffer)
    findBuffer BufferRef
    k = EditorM (Maybe FBuffer) -> m (Maybe FBuffer)
    forall a. EditorM a -> m a
    forall (m :: * -> *) a. MonadEditor m => EditorM a -> m a
    withEditor ((Editor -> Maybe FBuffer) -> EditorM (Maybe FBuffer)
    forall s (m :: * -> *) a. MonadState s m => (s -> a) -> m a
    gets (BufferRef -> Map BufferRef FBuffer -> Maybe FBuffer
    forall k a. Ord k => k -> Map k a -> Maybe a
    M.lookup BufferRef
    k (Map BufferRef FBuffer -> Maybe FBuffer)
    -> (Editor -> Map BufferRef FBuffer) -> Editor -> Maybe FBuffer
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Editor -> Map BufferRef FBuffer
    buffers))

    -- | Find buffer with this key
    findBufferWith :: BufferRef -> Editor -> FBuffer
    findBufferWith :: BufferRef -> Editor -> FBuffer
    findBufferWith BufferRef
    k Editor
    e = case BufferRef -> Map BufferRef FBuffer -> Maybe FBuffer
    forall k a. Ord k => k -> Map k a -> Maybe a
    M.lookup BufferRef
    k (Editor -> Map BufferRef FBuffer
    buffers Editor
    e) of
      Just FBuffer
    x -> FBuffer
    x
      Maybe FBuffer
    Nothing -> FilePath -> FBuffer
    forall a. HasCallStack => FilePath -> a
    error FilePath
    "Editor.findBufferWith: no buffer has this key"

    -- | Find buffers with this name
    findBufferWithName :: T.Text -> Editor -> [BufferRef]
    findBufferWithName :: Text -> Editor -> [BufferRef]
    findBufferWithName Text
    n Editor
    e =
      let bufs :: [FBuffer]
    bufs = Map BufferRef FBuffer -> [FBuffer]
    forall k a. Map k a -> [a]
    M.elems (Map BufferRef FBuffer -> [FBuffer])
    -> Map BufferRef FBuffer -> [FBuffer]
    forall a b. (a -> b) -> a -> b
    $ Editor -> Map BufferRef FBuffer
    buffers Editor
    e
          hasInfix :: FBuffer -> Bool
    hasInfix FBuffer
    b = Text
    n Text -> Text -> Bool
    `T.isInfixOf` FBuffer -> Text
    identString FBuffer
    b
      in (FBuffer -> BufferRef) -> [FBuffer] -> [BufferRef]
    forall a b. (a -> b) -> [a] -> [b]
    map FBuffer -> BufferRef
    bkey ([FBuffer] -> [BufferRef]) -> [FBuffer] -> [BufferRef]
    forall a b. (a -> b) -> a -> b
    $ (FBuffer -> Bool) -> [FBuffer] -> [FBuffer]
    forall a. (a -> Bool) -> [a] -> [a]
    filter FBuffer -> Bool
    hasInfix [FBuffer]
    bufs

    doesBufferNameExist :: T.Text -> Editor -> Bool
    doesBufferNameExist :: Text -> Editor -> Bool
    doesBufferNameExist Text
    n Editor
    e =
      Bool -> Bool
    not (Bool -> Bool) -> Bool -> Bool
    forall a b. (a -> b) -> a -> b
    $ [FBuffer] -> Bool
    forall a. [a] -> Bool
    forall (t :: * -> *) a. Foldable t => t a -> Bool
    null ([FBuffer] -> Bool) -> [FBuffer] -> Bool
    forall a b. (a -> b) -> a -> b
    $ (FBuffer -> Bool) -> [FBuffer] -> [FBuffer]
    forall a. (a -> Bool) -> [a] -> [a]
    filter ((Text -> Text -> Bool
    forall a. Eq a => a -> a -> Bool
    == Text
    n) (Text -> Bool) -> (FBuffer -> Text) -> FBuffer -> Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . FBuffer -> Text
    identString) ([FBuffer] -> [FBuffer]) -> [FBuffer] -> [FBuffer]
    forall a b. (a -> b) -> a -> b
    $ Map BufferRef FBuffer -> [FBuffer]
    forall k a. Map k a -> [a]
    M.elems (Map BufferRef FBuffer -> [FBuffer])
    -> Map BufferRef FBuffer -> [FBuffer]
    forall a b. (a -> b) -> a -> b
    $ Editor -> Map BufferRef FBuffer
    buffers Editor
    e

    -- | Find buffer with given name. Fail if not found.
    getBufferWithName :: MonadEditor m => T.Text -> m BufferRef
    getBufferWithName :: forall (m :: * -> *). MonadEditor m => Text -> m BufferRef
    getBufferWithName Text
    bufName = EditorM BufferRef -> m BufferRef
    forall a. EditorM a -> m a
    forall (m :: * -> *) a. MonadEditor m => EditorM a -> m a
    withEditor (EditorM BufferRef -> m BufferRef)
    -> EditorM BufferRef -> m BufferRef
    forall a b. (a -> b) -> a -> b
    $ do
      bs <- (Editor -> [BufferRef]) -> EditorM [BufferRef]
    forall s (m :: * -> *) a. MonadState s m => (s -> a) -> m a
    gets ((Editor -> [BufferRef]) -> EditorM [BufferRef])
    -> (Editor -> [BufferRef]) -> EditorM [BufferRef]
    forall a b. (a -> b) -> a -> b
    $ Text -> Editor -> [BufferRef]
    findBufferWithName Text
    bufName
      case bs of
        [] -> FilePath -> EditorM BufferRef
    forall a. FilePath -> EditorM a
    forall (m :: * -> *) a. MonadFail m => FilePath -> m a
    fail (FilePath
    "Buffer not found: " FilePath -> FilePath -> FilePath
    forall a. [a] -> [a] -> [a]
    ++ Text -> FilePath
    T.unpack Text
    bufName)
        [BufferRef
    b] -> BufferRef -> EditorM BufferRef
    forall a. a -> EditorM a
    forall (m :: * -> *) a. Monad m => a -> m a
    return BufferRef
    b
        [BufferRef]
    _ -> FilePath -> EditorM BufferRef
    forall a. FilePath -> EditorM a
    forall (m :: * -> *) a. MonadFail m => FilePath -> m a
    fail (FilePath
    "Ambiguous buffer name: " FilePath -> FilePath -> FilePath
    forall a. [a] -> [a] -> [a]
    ++ Text -> FilePath
    T.unpack Text
    bufName)

    ------------------------------------------------------------------------
    -- | Perform action with any given buffer, using the last window that
    -- was used for that buffer.
    withGivenBuffer :: MonadEditor m => BufferRef -> BufferM a -> m a
    withGivenBuffer :: forall (m :: * -> *) a.
    MonadEditor m =>
    BufferRef -> BufferM a -> m a
    withGivenBuffer BufferRef
    k BufferM a
    f = do
        b <- (Editor -> FBuffer) -> m FBuffer
    forall s (m :: * -> *) a. MonadState s m => (s -> a) -> m a
    gets (BufferRef -> Editor -> FBuffer
    findBufferWith BufferRef
    k)

        withGivenBufferAndWindow (b ^. lastActiveWindowA) k f

    -- | Perform action with any given buffer
    withGivenBufferAndWindow :: MonadEditor m
        => Window -> BufferRef -> BufferM a -> m a
    withGivenBufferAndWindow :: forall (m :: * -> *) a.
    MonadEditor m =>
    Window -> BufferRef -> BufferM a -> m a
    withGivenBufferAndWindow Window
    w BufferRef
    k BufferM a
    f = EditorM a -> m a
    forall a. EditorM a -> m a
    forall (m :: * -> *) a. MonadEditor m => EditorM a -> m a
    withEditor (EditorM a -> m a) -> EditorM a -> m a
    forall a b. (a -> b) -> a -> b
    $ do
      accum <- (Config -> Bool) -> EditorM Bool
    forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
    asks Config -> Bool
    configKillringAccumulate
      let edit Editor
    e = let b :: FBuffer
    b = BufferRef -> Editor -> FBuffer
    findBufferWith BufferRef
    k Editor
    e
                       (a
    v, Seq Update
    us, FBuffer
    b') = Window -> FBuffer -> BufferM a -> (a, Seq Update, FBuffer)
    forall a.
    Window -> FBuffer -> BufferM a -> (a, Seq Update, FBuffer)
    runBufferFull Window
    w FBuffer
    b BufferM a
    f
                   in (Editor
    e Editor -> (Editor -> Editor) -> Editor
    forall a b. a -> (a -> b) -> b
    & (Map BufferRef FBuffer -> Identity (Map BufferRef FBuffer))
    -> Editor -> Identity Editor
    Lens' Editor (Map BufferRef FBuffer)
    buffersA ((Map BufferRef FBuffer -> Identity (Map BufferRef FBuffer))
     -> Editor -> Identity Editor)
    -> Map BufferRef FBuffer -> Editor -> Editor
    forall s t a b. ASetter s t a b -> b -> s -> t
    .~ (FBuffer -> FBuffer)
    -> BufferRef -> Map BufferRef FBuffer -> Map BufferRef FBuffer
    forall k a. Ord k => (a -> a) -> k -> Map k a -> Map k a
    mapAdjust' (FBuffer -> FBuffer -> FBuffer
    forall a b. a -> b -> a
    const FBuffer
    b') BufferRef
    k (Editor -> Map BufferRef FBuffer
    buffers Editor
    e)
                         Editor -> (Editor -> Editor) -> Editor
    forall a b. a -> (a -> b) -> b
    & (Killring -> Identity Killring) -> Editor -> Identity Editor
    Lens' Editor Killring
    killringA ((Killring -> Identity Killring) -> Editor -> Identity Editor)
    -> (Killring -> Killring) -> Editor -> Editor
    forall s t a b. ASetter s t a b -> (a -> b) -> s -> t
    %~
                            (\Killring
    kr ->
                               if Bool
    accum Bool -> Bool -> Bool
    && (Update -> Bool) -> Seq Update -> Bool
    forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
    all Update -> Bool
    updateIsDelete Seq Update
    us
                               then let putDelKr :: Killring -> Update -> Killring
    putDelKr Killring
    kr' (Delete Point
    _ Direction
    dir YiString
    s) = Direction -> YiString -> Killring -> Killring
    krPut Direction
    dir YiString
    s Killring
    kr'
                                        putDelKr Killring
    kr' Update
    _ = Killring
    kr'
                                    in (Killring -> Update -> Killring)
    -> Killring -> Seq Update -> Killring
    forall b a. (b -> a -> b) -> b -> Seq a -> b
    forall (t :: * -> *) b a.
    Foldable t =>
    (b -> a -> b) -> b -> t a -> b
    foldl' Killring -> Update -> Killring
    putDelKr Killring
    kr (Seq Update -> Seq Update
    forall a. Seq a -> Seq a
    S.reverse Seq Update
    us)
                               else Killring
    kr)
                      , (Seq Update
    us, a
    v))
      (us, v) <- getsAndModify edit

      updHandler <- return . bufferUpdateHandler =<< ask
      unless (S.null us || S.null updHandler) $
        forM_ updHandler (\Seq Update -> BufferM ()
    h -> Window -> BufferRef -> BufferM () -> EditorM ()
    forall (m :: * -> *) a.
    MonadEditor m =>
    Window -> BufferRef -> BufferM a -> m a
    withGivenBufferAndWindow Window
    w BufferRef
    k (Seq Update -> BufferM ()
    h Seq Update
    us))
      return v

    -- | Perform action with current window's buffer
    withCurrentBuffer :: MonadEditor m => BufferM a -> m a
    withCurrentBuffer :: forall (m :: * -> *) a. MonadEditor m => BufferM a -> m a
    withCurrentBuffer BufferM a
    f = EditorM a -> m a
    forall a. EditorM a -> m a
    forall (m :: * -> *) a. MonadEditor m => EditorM a -> m a
    withEditor (EditorM a -> m a) -> EditorM a -> m a
    forall a b. (a -> b) -> a -> b
    $ do
      w <- Getting Window Editor Window -> EditorM Window
    forall s (m :: * -> *) a. MonadState s m => Getting a s a -> m a
    use Getting Window Editor Window
    Lens' Editor Window
    currentWindowA
      withGivenBufferAndWindow w (bufkey w) f

    withEveryBuffer :: MonadEditor m => BufferM a -> m [a]
    withEveryBuffer :: forall (m :: * -> *) a. MonadEditor m => BufferM a -> m [a]
    withEveryBuffer BufferM a
    action =
        EditorM (NonEmpty BufferRef) -> m (NonEmpty BufferRef)
    forall a. EditorM a -> m a
    forall (m :: * -> *) a. MonadEditor m => EditorM a -> m a
    withEditor ((Editor -> NonEmpty BufferRef) -> EditorM (NonEmpty BufferRef)
    forall s (m :: * -> *) a. MonadState s m => (s -> a) -> m a
    gets Editor -> NonEmpty BufferRef
    bufferStack) m (NonEmpty BufferRef) -> (NonEmpty BufferRef -> m [a]) -> m [a]
    forall a b. m a -> (a -> m b) -> m b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= (BufferRef -> m a) -> [BufferRef] -> m [a]
    forall (t :: * -> *) (m :: * -> *) a b.
    (Traversable t, Monad m) =>
    (a -> m b) -> t a -> m (t b)
    forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
    mapM (BufferRef -> BufferM a -> m a
    forall (m :: * -> *) a.
    MonadEditor m =>
    BufferRef -> BufferM a -> m a
    `withGivenBuffer` BufferM a
    action) ([BufferRef] -> m [a])
    -> (NonEmpty BufferRef -> [BufferRef])
    -> NonEmpty BufferRef
    -> m [a]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . NonEmpty BufferRef -> [BufferRef]
    forall a. NonEmpty a -> [a]
    NE.toList

    currentWindowA :: Lens' Editor Window
    currentWindowA :: Lens' Editor Window
    currentWindowA = (PointedList Window -> f (PointedList Window))
    -> Editor -> f Editor
    Lens' Editor (PointedList Window)
    windowsA ((PointedList Window -> f (PointedList Window))
     -> Editor -> f Editor)
    -> ((Window -> f Window)
        -> PointedList Window -> f (PointedList Window))
    -> (Window -> f Window)
    -> Editor
    -> f Editor
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (Window -> f Window)
    -> PointedList Window -> f (PointedList Window)
    forall (f :: * -> *) a.
    Functor f =>
    (a -> f a) -> PointedList a -> f (PointedList a)
    PL.focus

    -- | Return the current buffer
    currentBuffer :: Editor -> BufferRef
    currentBuffer :: Editor -> BufferRef
    currentBuffer = NonEmpty BufferRef -> BufferRef
    forall a. NonEmpty a -> a
    NE.head (NonEmpty BufferRef -> BufferRef)
    -> (Editor -> NonEmpty BufferRef) -> Editor -> BufferRef
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Editor -> NonEmpty BufferRef
    bufferStack

    -----------------------
    -- Handling of status

    -- | Prints a message with 'defaultStyle'.
    printMsg :: MonadEditor m => T.Text -> m ()
    printMsg :: forall (m :: * -> *). MonadEditor m => Text -> m ()
    printMsg Text
    s = Status -> m ()
    forall (m :: * -> *). MonadEditor m => Status -> m ()
    printStatus ([Text
    s], StyleName
    defaultStyle)

    -- | Prints a all given messages with 'defaultStyle'.
    printMsgs :: MonadEditor m => [T.Text] -> m ()
    printMsgs :: forall (m :: * -> *). MonadEditor m => [Text] -> m ()
    printMsgs [Text]
    s = Status -> m ()
    forall (m :: * -> *). MonadEditor m => Status -> m ()
    printStatus ([Text]
    s, StyleName
    defaultStyle)

    printStatus :: MonadEditor m => Status -> m ()
    printStatus :: forall (m :: * -> *). MonadEditor m => Status -> m ()
    printStatus = Int -> Status -> m ()
    forall (m :: * -> *). MonadEditor m => Int -> Status -> m ()
    setTmpStatus Int
    1

    -- | Set the "background" status line
    setStatus :: MonadEditor m => Status -> m ()
    setStatus :: forall (m :: * -> *). MonadEditor m => Status -> m ()
    setStatus = Int -> Status -> m ()
    forall (m :: * -> *). MonadEditor m => Int -> Status -> m ()
    setTmpStatus Int
    forall a. Bounded a => a
    maxBound

    -- | Clear the status line
    clrStatus :: EditorM ()
    clrStatus :: EditorM ()
    clrStatus = Status -> EditorM ()
    forall (m :: * -> *). MonadEditor m => Status -> m ()
    setStatus ([Text
    ""], StyleName
    defaultStyle)

    statusLine :: Editor -> [T.Text]
    statusLine :: Editor -> [Text]
    statusLine = Status -> [Text]
    forall a b. (a, b) -> a
    fst (Status -> [Text]) -> (Editor -> Status) -> Editor -> [Text]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Editor -> Status
    statusLineInfo

    statusLineInfo :: Editor -> Status
    statusLineInfo :: Editor -> Status
    statusLineInfo = (Int, Status) -> Status
    forall a b. (a, b) -> b
    snd ((Int, Status) -> Status)
    -> (Editor -> (Int, Status)) -> Editor -> Status
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Statuses -> (Int, Status)
    forall a. HasCallStack => [a] -> a
    head (Statuses -> (Int, Status))
    -> (Editor -> Statuses) -> Editor -> (Int, Status)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Editor -> Statuses
    statusLines

    setTmpStatus :: MonadEditor m => Int -> Status -> m ()
    setTmpStatus :: forall (m :: * -> *). MonadEditor m => Int -> Status -> m ()
    setTmpStatus Int
    delay Status
    s = EditorM () -> m ()
    forall a. EditorM a -> m a
    forall (m :: * -> *) a. MonadEditor m => EditorM a -> m a
    withEditor (EditorM () -> m ()) -> EditorM () -> m ()
    forall a b. (a -> b) -> a -> b
    $ do
      (Statuses -> Identity Statuses) -> Editor -> Identity Editor
    Lens' Editor Statuses
    statusLinesA ((Statuses -> Identity Statuses) -> Editor -> Identity Editor)
    -> (Statuses -> Statuses) -> EditorM ()
    forall s (m :: * -> *) a b.
    MonadState s m =>
    ASetter s s a b -> (a -> b) -> m ()
    %= (Int, Status) -> Statuses -> Statuses
    forall a. (Int, a) -> DelayList a -> DelayList a
    DelayList.insert (Int
    delay, Status
    s)
      -- also show in the messages buffer, so we don't loose any message
      bs <- (Editor -> [FBuffer]) -> EditorM [FBuffer]
    forall s (m :: * -> *) a. MonadState s m => (s -> a) -> m a
    gets ((FBuffer -> Bool) -> [FBuffer] -> [FBuffer]
    forall a. (a -> Bool) -> [a] -> [a]
    filter ((BufferId -> BufferId -> Bool
    forall a. Eq a => a -> a -> Bool
    == Text -> BufferId
    MemBuffer Text
    "messages") (BufferId -> Bool) -> (FBuffer -> BufferId) -> FBuffer -> Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Getting BufferId FBuffer BufferId -> FBuffer -> BufferId
    forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
    view Getting BufferId FBuffer BufferId
    forall c. HasAttributes c => Lens' c BufferId
    Lens' FBuffer BufferId
    identA) ([FBuffer] -> [FBuffer])
    -> (Editor -> [FBuffer]) -> Editor -> [FBuffer]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Map BufferRef FBuffer -> [FBuffer]
    forall k a. Map k a -> [a]
    M.elems (Map BufferRef FBuffer -> [FBuffer])
    -> (Editor -> Map BufferRef FBuffer) -> Editor -> [FBuffer]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Editor -> Map BufferRef FBuffer
    buffers)

      b <- case bs of
             (FBuffer
    b':[FBuffer]
    _) -> BufferRef -> EditorM BufferRef
    forall a. a -> EditorM a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (BufferRef -> EditorM BufferRef) -> BufferRef -> EditorM BufferRef
    forall a b. (a -> b) -> a -> b
    $ FBuffer -> BufferRef
    bkey FBuffer
    b'
             [] -> BufferId -> YiString -> EditorM BufferRef
    forall (m :: * -> *).
    MonadEditor m =>
    BufferId -> YiString -> m BufferRef
    stringToNewBuffer (Text -> BufferId
    MemBuffer Text
    "messages") YiString
    forall a. Monoid a => a
    mempty
      let m = [YiString] -> YiString
    listify ([YiString] -> YiString) -> [YiString] -> YiString
    forall a b. (a -> b) -> a -> b
    $ Text -> YiString
    R.fromText (Text -> YiString) -> [Text] -> [YiString]
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Status -> [Text]
    forall a b. (a, b) -> a
    fst Status
    s
      withGivenBuffer b $ botB >> insertN (m `R.snoc` '\n')

    -- ---------------------------------------------------------------------
    -- kill-register (vim-style) interface to killring.
    --
    -- Note that our vim keymap currently has its own registers
    -- and doesn't use killring.

    -- | Put string into yank register
    setRegE :: R.YiString -> EditorM ()
    setRegE :: YiString -> EditorM ()
    setRegE YiString
    s = (Killring -> Identity Killring) -> Editor -> Identity Editor
    Lens' Editor Killring
    killringA ((Killring -> Identity Killring) -> Editor -> Identity Editor)
    -> (Killring -> Killring) -> EditorM ()
    forall s (m :: * -> *) a b.
    MonadState s m =>
    ASetter s s a b -> (a -> b) -> m ()
    %= YiString -> Killring -> Killring
    krSet YiString
    s

    -- | Return the contents of the yank register
    getRegE :: EditorM R.YiString
    getRegE :: EditorM YiString
    getRegE = Getting Killring Editor Killring
    -> (Killring -> YiString) -> EditorM YiString
    forall s (m :: * -> *) a b.
    MonadState s m =>
    Getting a s a -> (a -> b) -> m b
    uses Getting Killring Editor Killring
    Lens' Editor Killring
    killringA Killring -> YiString
    krGet

    -- ---------------------------------------------------------------------
    -- | Dynamically-extensible state components.
    --
    -- These hooks are used by keymaps to store values that result from
    -- Actions (i.e. that result from IO), as opposed to the pure values
    -- they generate themselves, and can be stored internally.
    --
    -- The `dynamic' field is a type-indexed map.
    --

    -- | Retrieve a value from the extensible state
    getEditorDyn :: (MonadEditor m, YiVariable a, Default a, Functor m) => m a
    getEditorDyn :: forall (m :: * -> *) a.
    (MonadEditor m, YiVariable a, Default a, Functor m) =>
    m a
    getEditorDyn = a -> Maybe a -> a
    forall a. a -> Maybe a -> a
    fromMaybe a
    forall a. Default a => a
    def (Maybe a -> a) -> m (Maybe a) -> m a
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> m DynamicState -> (DynamicState -> m ()) -> m (Maybe a)
    forall (m :: * -> *) a.
    (Typeable a, Binary a, Monad m) =>
    m DynamicState -> (DynamicState -> m ()) -> m (Maybe a)
    getDyn (Getting DynamicState Editor DynamicState -> m DynamicState
    forall s (m :: * -> *) a. MonadState s m => Getting a s a -> m a
    use Getting DynamicState Editor DynamicState
    Lens' Editor DynamicState
    dynamicA) (ASetter Editor Editor DynamicState DynamicState
    -> DynamicState -> m ()
    forall s (m :: * -> *) a b.
    MonadState s m =>
    ASetter s s a b -> b -> m ()
    assign ASetter Editor Editor DynamicState DynamicState
    Lens' Editor DynamicState
    dynamicA)

    -- | Insert a value into the extensible state, keyed by its type
    putEditorDyn :: (MonadEditor m, YiVariable a, Functor m) => a -> m ()
    putEditorDyn :: forall (m :: * -> *) a.
    (MonadEditor m, YiVariable a, Functor m) =>
    a -> m ()
    putEditorDyn = m DynamicState -> (DynamicState -> m ()) -> a -> m ()
    forall (m :: * -> *) a.
    (Typeable a, Binary a, Monad m) =>
    m DynamicState -> (DynamicState -> m ()) -> a -> m ()
    putDyn (Getting DynamicState Editor DynamicState -> m DynamicState
    forall s (m :: * -> *) a. MonadState s m => Getting a s a -> m a
    use Getting DynamicState Editor DynamicState
    Lens' Editor DynamicState
    dynamicA) (ASetter Editor Editor DynamicState DynamicState
    -> DynamicState -> m ()
    forall s (m :: * -> *) a b.
    MonadState s m =>
    ASetter s s a b -> b -> m ()
    assign ASetter Editor Editor DynamicState DynamicState
    Lens' Editor DynamicState
    dynamicA)

    -- | Like fnewE, create a new buffer filled with the String @s@,
    -- Switch the current window to this buffer. Doesn't associate any
    -- file with the buffer (unlike fnewE) and so is good for popup
    -- internal buffers (like scratch)
    newBufferE :: BufferId   -- ^ buffer name
               -> YiString -- ^ buffer contents
               -> EditorM BufferRef
    newBufferE :: BufferId -> YiString -> EditorM BufferRef
    newBufferE BufferId
    f YiString
    s = do
        b <- BufferId -> YiString -> EditorM BufferRef
    forall (m :: * -> *).
    MonadEditor m =>
    BufferId -> YiString -> m BufferRef
    stringToNewBuffer BufferId
    f YiString
    s
        switchToBufferE b
        return b

    -- | Like 'newBufferE' but defaults to empty contents.
    newEmptyBufferE :: BufferId -> EditorM BufferRef
    newEmptyBufferE :: BufferId -> EditorM BufferRef
    newEmptyBufferE BufferId
    f = BufferId -> YiString -> EditorM BufferRef
    newBufferE BufferId
    f YiString
    Yi.Rope.empty

    alternateBufferE :: Int -> EditorM ()
    alternateBufferE :: Int -> EditorM ()
    alternateBufferE Int
    n = do
        Window { bufAccessList = lst } <- Getting Window Editor Window -> EditorM Window
    forall s (m :: * -> *) a. MonadState s m => Getting a s a -> m a
    use Getting Window Editor Window
    Lens' Editor Window
    currentWindowA
        if null lst || (length lst - 1) < n
          then fail "no alternate buffer"
          else switchToBufferE $ lst!!n

    -- | Create a new zero size window on a given buffer
    newZeroSizeWindow :: Bool -> BufferRef -> WindowRef -> Window
    newZeroSizeWindow :: Bool -> BufferRef -> WindowRef -> Window
    newZeroSizeWindow Bool
    mini BufferRef
    bk WindowRef
    ref = Bool
    -> BufferRef
    -> [BufferRef]
    -> Int
    -> Int
    -> Region
    -> WindowRef
    -> Int
    -> JumpList
    -> Window
    Window Bool
    mini BufferRef
    bk [] Int
    0 Int
    0 Region
    emptyRegion WindowRef
    ref Int
    0 JumpList
    forall a. Maybe a
    Nothing

    -- | Create a new window onto the given buffer.
    newWindowE :: Bool -> BufferRef -> EditorM Window
    newWindowE :: Bool -> BufferRef -> EditorM Window
    newWindowE Bool
    mini BufferRef
    bk = Bool -> BufferRef -> WindowRef -> Window
    newZeroSizeWindow Bool
    mini BufferRef
    bk (WindowRef -> Window) -> (Int -> WindowRef) -> Int -> Window
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Int -> WindowRef
    WindowRef (Int -> Window) -> EditorM Int -> EditorM Window
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> EditorM Int
    forall (m :: * -> *). MonadEditor m => m Int
    newRef

    -- | Attach the specified buffer to the current window
    switchToBufferE :: BufferRef -> EditorM ()
    switchToBufferE :: BufferRef -> EditorM ()
    switchToBufferE BufferRef
    bk = (PointedList Window -> Identity (PointedList Window))
    -> Editor -> Identity Editor
    Lens' Editor (PointedList Window)
    windowsA ((PointedList Window -> Identity (PointedList Window))
     -> Editor -> Identity Editor)
    -> ASetter (PointedList Window) (PointedList Window) Window Window
    -> (Window -> Identity Window)
    -> Editor
    -> Identity Editor
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ASetter (PointedList Window) (PointedList Window) Window Window
    forall (f :: * -> *) a.
    Functor f =>
    (a -> f a) -> PointedList a -> f (PointedList a)
    PL.focus ((Window -> Identity Window) -> Editor -> Identity Editor)
    -> (Window -> Window) -> EditorM ()
    forall s (m :: * -> *) a b.
    MonadState s m =>
    ASetter s s a b -> (a -> b) -> m ()
    %= \Window
    w ->
      Window
    w Window -> (Window -> Window) -> Window
    forall a b. a -> (a -> b) -> b
    & (BufferRef -> Identity BufferRef) -> Window -> Identity Window
    Lens' Window BufferRef
    bufkeyA ((BufferRef -> Identity BufferRef) -> Window -> Identity Window)
    -> BufferRef -> Window -> Window
    forall s t a b. ASetter s t a b -> b -> s -> t
    .~ BufferRef
    bk
        Window -> (Window -> Window) -> Window
    forall a b. a -> (a -> b) -> b
    & ([BufferRef] -> Identity [BufferRef]) -> Window -> Identity Window
    Lens' Window [BufferRef]
    bufAccessListA (([BufferRef] -> Identity [BufferRef])
     -> Window -> Identity Window)
    -> ([BufferRef] -> [BufferRef]) -> Window -> Window
    forall s t a b. ASetter s t a b -> (a -> b) -> s -> t
    %~ [BufferRef] -> [BufferRef]
    forall (t :: * -> *) a. Foldable t => t a -> t a
    forceFold1 ([BufferRef] -> [BufferRef])
    -> ([BufferRef] -> [BufferRef]) -> [BufferRef] -> [BufferRef]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (Window -> BufferRef
    bufkey Window
    wBufferRef -> [BufferRef] -> [BufferRef]
    forall a. a -> [a] -> [a]
    :) ([BufferRef] -> [BufferRef])
    -> ([BufferRef] -> [BufferRef]) -> [BufferRef] -> [BufferRef]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (BufferRef -> Bool) -> [BufferRef] -> [BufferRef]
    forall a. (a -> Bool) -> [a] -> [a]
    filter (BufferRef
    bk BufferRef -> BufferRef -> Bool
    forall a. Eq a => a -> a -> Bool
    /=)

    -- | Switch to the buffer specified as parameter. If the buffer name
    -- is empty, switch to the next buffer.
    switchToBufferWithNameE :: T.Text -> EditorM ()
    switchToBufferWithNameE :: Text -> EditorM ()
    switchToBufferWithNameE Text
    "" = Int -> EditorM ()
    alternateBufferE Int
    0
    switchToBufferWithNameE Text
    bufName = BufferRef -> EditorM ()
    switchToBufferE (BufferRef -> EditorM ()) -> EditorM BufferRef -> EditorM ()
    forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
    =<< Text -> EditorM BufferRef
    forall (m :: * -> *). MonadEditor m => Text -> m BufferRef
    getBufferWithName Text
    bufName

    -- | Close a buffer.
    -- Note: close the current buffer if the empty string is given
    closeBufferE :: T.Text -> EditorM ()
    closeBufferE :: Text -> EditorM ()
    closeBufferE Text
    nm = BufferRef -> EditorM ()
    forall (m :: * -> *). MonadEditor m => BufferRef -> m ()
    deleteBuffer (BufferRef -> EditorM ()) -> EditorM BufferRef -> EditorM ()
    forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
    =<< Text -> EditorM BufferRef
    forall (m :: * -> *). MonadEditor m => Text -> m BufferRef
    getBufferWithNameOrCurrent Text
    nm

    getBufferWithNameOrCurrent :: MonadEditor m => T.Text -> m BufferRef
    getBufferWithNameOrCurrent :: forall (m :: * -> *). MonadEditor m => Text -> m BufferRef
    getBufferWithNameOrCurrent Text
    t = EditorM BufferRef -> m BufferRef
    forall a. EditorM a -> m a
    forall (m :: * -> *) a. MonadEditor m => EditorM a -> m a
    withEditor (EditorM BufferRef -> m BufferRef)
    -> EditorM BufferRef -> m BufferRef
    forall a b. (a -> b) -> a -> b
    $
        case Text -> Bool
    T.null Text
    t of
            Bool
    True -> (Editor -> BufferRef) -> EditorM BufferRef
    forall s (m :: * -> *) a. MonadState s m => (s -> a) -> m a
    gets Editor -> BufferRef
    currentBuffer
            Bool
    False -> Text -> EditorM BufferRef
    forall (m :: * -> *). MonadEditor m => Text -> m BufferRef
    getBufferWithName Text
    t

    ------------------------------------------------------------------------

    -- | Close current buffer and window, unless it's the last one.
    closeBufferAndWindowE :: EditorM ()
    closeBufferAndWindowE :: EditorM ()
    closeBufferAndWindowE = do
      -- Fetch the current buffer *before* closing the window.
      -- The tryCloseE, since it uses tabsA, will have the
      -- current buffer "fixed" to the buffer of the window that is
      -- brought into focus. If the current buffer is accessed after the
      -- tryCloseE then the current buffer may not be the same as the
      -- buffer before tryCloseE. This would be bad.
      b <- (Editor -> BufferRef) -> EditorM BufferRef
    forall s (m :: * -> *) a. MonadState s m => (s -> a) -> m a
    gets Editor -> BufferRef
    currentBuffer
      tryCloseE
      deleteBuffer b

    -- | Rotate focus to the next window
    nextWinE :: EditorM ()
    nextWinE :: EditorM ()
    nextWinE = (PointedList Window -> Identity (PointedList Window))
    -> Editor -> Identity Editor
    Lens' Editor (PointedList Window)
    windowsA ((PointedList Window -> Identity (PointedList Window))
     -> Editor -> Identity Editor)
    -> (PointedList Window -> PointedList Window) -> EditorM ()
    forall s (m :: * -> *) a b.
    MonadState s m =>
    ASetter s s a b -> (a -> b) -> m ()
    %= PointedList Window -> PointedList Window
    forall a. PointedList a -> PointedList a
    PL.next

    -- | Rotate focus to the previous window
    prevWinE :: EditorM ()
    prevWinE :: EditorM ()
    prevWinE = (PointedList Window -> Identity (PointedList Window))
    -> Editor -> Identity Editor
    Lens' Editor (PointedList Window)
    windowsA ((PointedList Window -> Identity (PointedList Window))
     -> Editor -> Identity Editor)
    -> (PointedList Window -> PointedList Window) -> EditorM ()
    forall s (m :: * -> *) a b.
    MonadState s m =>
    ASetter s s a b -> (a -> b) -> m ()
    %= PointedList Window -> PointedList Window
    forall a. PointedList a -> PointedList a
    PL.previous

    -- | Swaps the focused window with the first window. Useful for
    -- layouts such as 'HPairOneStack', for which the first window is the
    -- largest.
    swapWinWithFirstE :: EditorM ()
    swapWinWithFirstE :: EditorM ()
    swapWinWithFirstE = (PointedList Window -> Identity (PointedList Window))
    -> Editor -> Identity Editor
    Lens' Editor (PointedList Window)
    windowsA ((PointedList Window -> Identity (PointedList Window))
     -> Editor -> Identity Editor)
    -> (PointedList Window -> PointedList Window) -> EditorM ()
    forall s (m :: * -> *) a b.
    MonadState s m =>
    ASetter s s a b -> (a -> b) -> m ()
    %= (PointedList Window -> PointedList Window)
    -> PointedList Window -> PointedList Window
    forall a.
    (PointedList a -> PointedList a) -> PointedList a -> PointedList a
    swapFocus (Maybe (PointedList Window) -> PointedList Window
    forall a. HasCallStack => Maybe a -> a
    fromJust (Maybe (PointedList Window) -> PointedList Window)
    -> (PointedList Window -> Maybe (PointedList Window))
    -> PointedList Window
    -> PointedList Window
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Int -> PointedList Window -> Maybe (PointedList Window)
    forall a. Int -> PointedList a -> Maybe (PointedList a)
    PL.moveTo Int
    0)

    -- | Moves the focused window to the first window, and moves all other
    -- windows down the stack.
    pushWinToFirstE :: EditorM ()
    pushWinToFirstE :: EditorM ()
    pushWinToFirstE = (PointedList Window -> Identity (PointedList Window))
    -> Editor -> Identity Editor
    Lens' Editor (PointedList Window)
    windowsA ((PointedList Window -> Identity (PointedList Window))
     -> Editor -> Identity Editor)
    -> (PointedList Window -> PointedList Window) -> EditorM ()
    forall s (m :: * -> *) a b.
    MonadState s m =>
    ASetter s s a b -> (a -> b) -> m ()
    %= PointedList Window -> PointedList Window
    forall a. PointedList a -> PointedList a
    pushToFirst
      where
          pushToFirst :: PointedList a -> PointedList a
    pushToFirst PointedList a
    ws = case PointedList a -> Maybe (PointedList a)
    forall a. PointedList a -> Maybe (PointedList a)
    PL.delete PointedList a
    ws of
              Maybe (PointedList a)
    Nothing -> PointedList a
    ws
              Just PointedList a
    ws' -> a -> PointedList a -> PointedList a
    forall a. a -> PointedList a -> PointedList a
    PL.insertLeft (PointedList a
    ws PointedList a -> Getting a (PointedList a) a -> a
    forall s a. s -> Getting a s a -> a
    ^. Getting a (PointedList a) a
    forall (f :: * -> *) a.
    Functor f =>
    (a -> f a) -> PointedList a -> f (PointedList a)
    PL.focus) (Maybe (PointedList a) -> PointedList a
    forall a. HasCallStack => Maybe a -> a
    fromJust (Maybe (PointedList a) -> PointedList a)
    -> Maybe (PointedList a) -> PointedList a
    forall a b. (a -> b) -> a -> b
    $ Int -> PointedList a -> Maybe (PointedList a)
    forall a. Int -> PointedList a -> Maybe (PointedList a)
    PL.moveTo Int
    0 PointedList a
    ws')

    -- | Swap focused window with the next one
    moveWinNextE :: EditorM ()
    moveWinNextE :: EditorM ()
    moveWinNextE = (PointedList Window -> Identity (PointedList Window))
    -> Editor -> Identity Editor
    Lens' Editor (PointedList Window)
    windowsA ((PointedList Window -> Identity (PointedList Window))
     -> Editor -> Identity Editor)
    -> (PointedList Window -> PointedList Window) -> EditorM ()
    forall s (m :: * -> *) a b.
    MonadState s m =>
    ASetter s s a b -> (a -> b) -> m ()
    %= (PointedList Window -> PointedList Window)
    -> PointedList Window -> PointedList Window
    forall a.
    (PointedList a -> PointedList a) -> PointedList a -> PointedList a
    swapFocus PointedList Window -> PointedList Window
    forall a. PointedList a -> PointedList a
    PL.next

    -- | Swap focused window with the previous one
    moveWinPrevE :: EditorM ()
    moveWinPrevE :: EditorM ()
    moveWinPrevE = (PointedList Window -> Identity (PointedList Window))
    -> Editor -> Identity Editor
    Lens' Editor (PointedList Window)
    windowsA ((PointedList Window -> Identity (PointedList Window))
     -> Editor -> Identity Editor)
    -> (PointedList Window -> PointedList Window) -> EditorM ()
    forall s (m :: * -> *) a b.
    MonadState s m =>
    ASetter s s a b -> (a -> b) -> m ()
    %= (PointedList Window -> PointedList Window)
    -> PointedList Window -> PointedList Window
    forall a.
    (PointedList a -> PointedList a) -> PointedList a -> PointedList a
    swapFocus PointedList Window -> PointedList Window
    forall a. PointedList a -> PointedList a
    PL.previous

    -- | A "fake" accessor that fixes the current buffer after a change of
    -- the current window.
    --
    -- Enforces invariant that top of buffer stack is the buffer of the
    -- current window.
    fixCurrentBufferA_ :: Lens' Editor Editor
    fixCurrentBufferA_ :: Lens' Editor Editor
    fixCurrentBufferA_ = (Editor -> Editor)
    -> (Editor -> Editor -> Editor) -> Lens' Editor Editor
    forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
    lens Editor -> Editor
    forall a. a -> a
    id (\Editor
    _old Editor
    new -> let
      ws :: PointedList Window
    ws = Editor -> PointedList Window
    windows Editor
    new
      b :: FBuffer
    b = BufferRef -> Editor -> FBuffer
    findBufferWith (Window -> BufferRef
    bufkey (Window -> BufferRef) -> Window -> BufferRef
    forall a b. (a -> b) -> a -> b
    $ PointedList Window -> Window
    forall a. PointedList a -> a
    PL._focus PointedList Window
    ws) Editor
    new
      newBufferStack :: NonEmpty BufferRef
    newBufferStack = NonEmpty BufferRef -> NonEmpty BufferRef
    forall a. Eq a => NonEmpty a -> NonEmpty a
    nub (FBuffer -> BufferRef
    bkey FBuffer
    b BufferRef -> NonEmpty BufferRef -> NonEmpty BufferRef
    forall a. a -> NonEmpty a -> NonEmpty a
    NE.<| Editor -> NonEmpty BufferRef
    bufferStack Editor
    new)
      -- make sure we do not hold to old versions by seqing the length.
      in NonEmpty BufferRef -> Int
    forall a. NonEmpty a -> Int
    NE.length NonEmpty BufferRef
    newBufferStack Int -> Editor -> Editor
    forall a b. a -> b -> b
    `seq` Editor
    new Editor -> (Editor -> Editor) -> Editor
    forall a b. a -> (a -> b) -> b
    & (NonEmpty BufferRef -> Identity (NonEmpty BufferRef))
    -> Editor -> Identity Editor
    Lens' Editor (NonEmpty BufferRef)
    bufferStackA ((NonEmpty BufferRef -> Identity (NonEmpty BufferRef))
     -> Editor -> Identity Editor)
    -> NonEmpty BufferRef -> Editor -> Editor
    forall s t a b. ASetter s t a b -> b -> s -> t
    .~ NonEmpty BufferRef
    newBufferStack)

    withWindowE :: Window -> BufferM a -> EditorM a
    withWindowE :: forall a. Window -> BufferM a -> EditorM a
    withWindowE Window
    w = Window -> BufferRef -> BufferM a -> EditorM a
    forall (m :: * -> *) a.
    MonadEditor m =>
    Window -> BufferRef -> BufferM a -> m a
    withGivenBufferAndWindow Window
    w (Window -> BufferRef
    bufkey Window
    w)

    findWindowWith :: WindowRef -> Editor -> Window
    findWindowWith :: WindowRef -> Editor -> Window
    findWindowWith WindowRef
    k Editor
    e =
        [Window] -> Window
    forall a. HasCallStack => [a] -> a
    head ([Window] -> Window) -> [Window] -> Window
    forall a b. (a -> b) -> a -> b
    $ (Window -> [Window]) -> PointedList Window -> [Window]
    forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
    concatMap (\Window
    win -> [Window
    win | Window -> WindowRef
    wkey Window
    win WindowRef -> WindowRef -> Bool
    forall a. Eq a => a -> a -> Bool
    == WindowRef
    k]) (PointedList Window -> [Window]) -> PointedList Window -> [Window]
    forall a b. (a -> b) -> a -> b
    $ Editor -> PointedList Window
    windows Editor
    e

    -- | Return the windows that are currently open on the buffer whose
    -- key is given
    windowsOnBufferE :: BufferRef -> EditorM [Window]
    windowsOnBufferE :: BufferRef -> EditorM [Window]
    windowsOnBufferE BufferRef
    k = do
      ts <- Getting (PointedList Tab) Editor (PointedList Tab)
    -> EditorM (PointedList Tab)
    forall s (m :: * -> *) a. MonadState s m => Getting a s a -> m a
    use Getting (PointedList Tab) Editor (PointedList Tab)
    Lens' Editor (PointedList Tab)
    tabsA
      let tabBufEq = (Window -> [Window]) -> PointedList Window -> [Window]
    forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
    concatMap (\Window
    win -> [Window
    win | Window -> BufferRef
    bufkey Window
    win BufferRef -> BufferRef -> Bool
    forall a. Eq a => a -> a -> Bool
    == BufferRef
    k]) (PointedList Window -> [Window])
    -> (Tab -> PointedList Window) -> Tab -> [Window]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (Tab
    -> Getting (PointedList Window) Tab (PointedList Window)
    -> PointedList Window
    forall s a. s -> Getting a s a -> a
    ^. Getting (PointedList Window) Tab (PointedList Window)
    forall (f :: * -> *).
    Functor f =>
    (PointedList Window -> f (PointedList Window)) -> Tab -> f Tab
    tabWindowsA)
      return $ concatMap tabBufEq ts

    -- | bring the editor focus the window with the given key.
    --
    -- Fails if no window with the given key is found.
    focusWindowE :: WindowRef -> EditorM ()
    focusWindowE :: WindowRef -> EditorM ()
    focusWindowE WindowRef
    k = do
        -- Find the tab index and window index
        ts <- Getting (PointedList Tab) Editor (PointedList Tab)
    -> EditorM (PointedList Tab)
    forall s (m :: * -> *) a. MonadState s m => Getting a s a -> m a
    use Getting (PointedList Tab) Editor (PointedList Tab)
    Lens' Editor (PointedList Tab)
    tabsA
        let check (Bool
    False, b
    i) Window
    win = if Window -> WindowRef
    wkey Window
    win WindowRef -> WindowRef -> Bool
    forall a. Eq a => a -> a -> Bool
    == WindowRef
    k
                                        then (Bool
    True, b
    i)
                                        else (Bool
    False, b
    i b -> b -> b
    forall a. Num a => a -> a -> a
    + b
    1)
            check r :: (Bool, b)
    r@(Bool
    True, b
    _) Window
    _win = (Bool, b)
    r

            searchWindowSet (Bool
    False, b
    tabIndex, c
    _) Tab
    ws =
                case ((Bool, c) -> Window -> (Bool, c))
    -> (Bool, c) -> PointedList Window -> (Bool, c)
    forall b a. (b -> a -> b) -> b -> PointedList a -> b
    forall (t :: * -> *) b a.
    Foldable t =>
    (b -> a -> b) -> b -> t a -> b
    foldl (Bool, c) -> Window -> (Bool, c)
    forall {b}. Num b => (Bool, b) -> Window -> (Bool, b)
    check (Bool
    False, c
    0) (Tab
    ws Tab
    -> Getting (PointedList Window) Tab (PointedList Window)
    -> PointedList Window
    forall s a. s -> Getting a s a -> a
    ^. Getting (PointedList Window) Tab (PointedList Window)
    forall (f :: * -> *).
    Functor f =>
    (PointedList Window -> f (PointedList Window)) -> Tab -> f Tab
    tabWindowsA) of
                    (Bool
    True, c
    winIndex) -> (Bool
    True, b
    tabIndex, c
    winIndex)
                    (Bool
    False, c
    _)       -> (Bool
    False, b
    tabIndex b -> b -> b
    forall a. Num a => a -> a -> a
    + b
    1, c
    0)
            searchWindowSet r :: (Bool, b, c)
    r@(Bool
    True, b
    _, c
    _) Tab
    _ws = (Bool, b, c)
    r

        case foldl searchWindowSet  (False, 0, 0) ts of
            (Bool
    False, Int
    _, Int
    _) -> FilePath -> EditorM ()
    forall a. FilePath -> EditorM a
    forall (m :: * -> *) a. MonadFail m => FilePath -> m a
    fail (FilePath -> EditorM ()) -> FilePath -> EditorM ()
    forall a b. (a -> b) -> a -> b
    $ FilePath
    "No window with key " FilePath -> FilePath -> FilePath
    forall a. [a] -> [a] -> [a]
    ++ WindowRef -> FilePath
    forall a. Show a => a -> FilePath
    show WindowRef
    k FilePath -> FilePath -> FilePath
    forall a. [a] -> [a] -> [a]
    ++ FilePath
    "found. (focusWindowE)"
            (Bool
    True, Int
    tabIndex, Int
    winIndex) -> do
                ((PointedList Tab -> Identity (PointedList Tab))
     -> Editor -> Identity Editor)
    -> PointedList Tab -> EditorM ()
    forall s (m :: * -> *) a b.
    MonadState s m =>
    ASetter s s a b -> b -> m ()
    assign (PointedList Tab -> Identity (PointedList Tab))
    -> Editor -> Identity Editor
    Lens' Editor (PointedList Tab)
    tabsA (Maybe (PointedList Tab) -> PointedList Tab
    forall a. HasCallStack => Maybe a -> a
    fromJust (Maybe (PointedList Tab) -> PointedList Tab)
    -> Maybe (PointedList Tab) -> PointedList Tab
    forall a b. (a -> b) -> a -> b
    $ Int -> PointedList Tab -> Maybe (PointedList Tab)
    forall a. Int -> PointedList a -> Maybe (PointedList a)
    PL.moveTo Int
    tabIndex PointedList Tab
    ts)
                (PointedList Window -> Identity (PointedList Window))
    -> Editor -> Identity Editor
    Lens' Editor (PointedList Window)
    windowsA ((PointedList Window -> Identity (PointedList Window))
     -> Editor -> Identity Editor)
    -> (PointedList Window -> PointedList Window) -> EditorM ()
    forall s (m :: * -> *) a b.
    MonadState s m =>
    ASetter s s a b -> (a -> b) -> m ()
    %= Maybe (PointedList Window) -> PointedList Window
    forall a. HasCallStack => Maybe a -> a
    fromJust (Maybe (PointedList Window) -> PointedList Window)
    -> (PointedList Window -> Maybe (PointedList Window))
    -> PointedList Window
    -> PointedList Window
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Int -> PointedList Window -> Maybe (PointedList Window)
    forall a. Int -> PointedList a -> Maybe (PointedList a)
    PL.moveTo Int
    winIndex

    -- | Split the current window, opening a second window onto current buffer.
    -- TODO: unfold newWindowE here?
    splitE :: EditorM ()
    splitE :: EditorM ()
    splitE = do
      w <- (Editor -> BufferRef) -> EditorM BufferRef
    forall s (m :: * -> *) a. MonadState s m => (s -> a) -> m a
    gets Editor -> BufferRef
    currentBuffer EditorM BufferRef
    -> (BufferRef -> EditorM Window) -> EditorM Window
    forall a b. EditorM a -> (a -> EditorM b) -> EditorM b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= Bool -> BufferRef -> EditorM Window
    newWindowE Bool
    False
      windowsA %= PL.insertRight w

    -- | Prints the description of the current layout manager in the status bar
    layoutManagersPrintMsgE :: EditorM ()
    layoutManagersPrintMsgE :: EditorM ()
    layoutManagersPrintMsgE = do
      lm <- Getting AnyLayoutManager Editor AnyLayoutManager
    -> EditorM AnyLayoutManager
    forall s (m :: * -> *) a. MonadState s m => Getting a s a -> m a
    use (Getting AnyLayoutManager Editor AnyLayoutManager
     -> EditorM AnyLayoutManager)
    -> Getting AnyLayoutManager Editor AnyLayoutManager
    -> EditorM AnyLayoutManager
    forall a b. (a -> b) -> a -> b
    $ (Tab -> Const AnyLayoutManager Tab)
    -> Editor -> Const AnyLayoutManager Editor
    Lens' Editor Tab
    currentTabA ((Tab -> Const AnyLayoutManager Tab)
     -> Editor -> Const AnyLayoutManager Editor)
    -> ((AnyLayoutManager -> Const AnyLayoutManager AnyLayoutManager)
        -> Tab -> Const AnyLayoutManager Tab)
    -> Getting AnyLayoutManager Editor AnyLayoutManager
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (AnyLayoutManager -> Const AnyLayoutManager AnyLayoutManager)
    -> Tab -> Const AnyLayoutManager Tab
    forall (f :: * -> *).
    Functor f =>
    (AnyLayoutManager -> f AnyLayoutManager) -> Tab -> f Tab
    tabLayoutManagerA
      printMsg . T.pack $ describeLayout lm

    -- | Cycle to the next layout manager, or the first one if the current
    -- one is nonstandard.
    layoutManagersNextE :: EditorM ()
    layoutManagersNextE :: EditorM ()
    layoutManagersNextE = (PointedList AnyLayoutManager -> PointedList AnyLayoutManager)
    -> EditorM ()
    withLMStackE PointedList AnyLayoutManager -> PointedList AnyLayoutManager
    forall a. PointedList a -> PointedList a
    PL.next EditorM () -> EditorM () -> EditorM ()
    forall a b. EditorM a -> EditorM b -> EditorM b
    forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
    >> EditorM ()
    layoutManagersPrintMsgE

    -- | Cycle to the previous layout manager, or the first one if the
    -- current one is nonstandard.
    layoutManagersPreviousE :: EditorM ()
    layoutManagersPreviousE :: EditorM ()
    layoutManagersPreviousE = (PointedList AnyLayoutManager -> PointedList AnyLayoutManager)
    -> EditorM ()
    withLMStackE PointedList AnyLayoutManager -> PointedList AnyLayoutManager
    forall a. PointedList a -> PointedList a
    PL.previous EditorM () -> EditorM () -> EditorM ()
    forall a b. EditorM a -> EditorM b -> EditorM b
    forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
    >> EditorM ()
    layoutManagersPrintMsgE

    -- | Helper function for 'layoutManagersNext' and 'layoutManagersPrevious'
    withLMStackE :: (PL.PointedList AnyLayoutManager
                    -> PL.PointedList AnyLayoutManager)
                -> EditorM ()
    withLMStackE :: (PointedList AnyLayoutManager -> PointedList AnyLayoutManager)
    -> EditorM ()
    withLMStackE PointedList AnyLayoutManager -> PointedList AnyLayoutManager
    f = EditorM Config
    forall (m :: * -> *). MonadEditor m => m Config
    askCfg EditorM Config -> (Config -> EditorM ()) -> EditorM ()
    forall a b. EditorM a -> (a -> EditorM b) -> EditorM b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= \Config
    cfg ->
      (Tab -> Identity Tab) -> Editor -> Identity Editor
    Lens' Editor Tab
    currentTabA ((Tab -> Identity Tab) -> Editor -> Identity Editor)
    -> ((AnyLayoutManager -> Identity AnyLayoutManager)
        -> Tab -> Identity Tab)
    -> (AnyLayoutManager -> Identity AnyLayoutManager)
    -> Editor
    -> Identity Editor
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (AnyLayoutManager -> Identity AnyLayoutManager)
    -> Tab -> Identity Tab
    forall (f :: * -> *).
    Functor f =>
    (AnyLayoutManager -> f AnyLayoutManager) -> Tab -> f Tab
    tabLayoutManagerA ((AnyLayoutManager -> Identity AnyLayoutManager)
     -> Editor -> Identity Editor)
    -> (AnyLayoutManager -> AnyLayoutManager) -> EditorM ()
    forall s (m :: * -> *) a b.
    MonadState s m =>
    ASetter s s a b -> (a -> b) -> m ()
    %= [AnyLayoutManager] -> AnyLayoutManager -> AnyLayoutManager
    go (Config -> [AnyLayoutManager]
    layoutManagers Config
    cfg)
      where
       go :: [AnyLayoutManager] -> AnyLayoutManager -> AnyLayoutManager
    go [] AnyLayoutManager
    lm = AnyLayoutManager
    lm
       go [AnyLayoutManager]
    lms AnyLayoutManager
    lm =
         case (AnyLayoutManager -> Bool)
    -> [AnyLayoutManager] -> Maybe (PointedList AnyLayoutManager)
    forall a. (a -> Bool) -> [a] -> Maybe (PointedList a)
    findPL (AnyLayoutManager -> AnyLayoutManager -> Bool
    layoutManagerSameType AnyLayoutManager
    lm) [AnyLayoutManager]
    lms of
           Maybe (PointedList AnyLayoutManager)
    Nothing -> [AnyLayoutManager] -> AnyLayoutManager
    forall a. HasCallStack => [a] -> a
    head [AnyLayoutManager]
    lms
           Just PointedList AnyLayoutManager
    lmsPL -> PointedList AnyLayoutManager -> PointedList AnyLayoutManager
    f PointedList AnyLayoutManager
    lmsPL PointedList AnyLayoutManager
    -> Getting
         AnyLayoutManager (PointedList AnyLayoutManager) AnyLayoutManager
    -> AnyLayoutManager
    forall s a. s -> Getting a s a -> a
    ^. Getting
      AnyLayoutManager (PointedList AnyLayoutManager) AnyLayoutManager
    forall (f :: * -> *) a.
    Functor f =>
    (a -> f a) -> PointedList a -> f (PointedList a)
    PL.focus

    -- | Next variant of the current layout manager, as given by 'nextVariant'
    layoutManagerNextVariantE :: EditorM ()
    layoutManagerNextVariantE :: EditorM ()
    layoutManagerNextVariantE = do
      (Tab -> Identity Tab) -> Editor -> Identity Editor
    Lens' Editor Tab
    currentTabA ((Tab -> Identity Tab) -> Editor -> Identity Editor)
    -> ((AnyLayoutManager -> Identity AnyLayoutManager)
        -> Tab -> Identity Tab)
    -> (AnyLayoutManager -> Identity AnyLayoutManager)
    -> Editor
    -> Identity Editor
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (AnyLayoutManager -> Identity AnyLayoutManager)
    -> Tab -> Identity Tab
    forall (f :: * -> *).
    Functor f =>
    (AnyLayoutManager -> f AnyLayoutManager) -> Tab -> f Tab
    tabLayoutManagerA ((AnyLayoutManager -> Identity AnyLayoutManager)
     -> Editor -> Identity Editor)
    -> (AnyLayoutManager -> AnyLayoutManager) -> EditorM ()
    forall s (m :: * -> *) a b.
    MonadState s m =>
    ASetter s s a b -> (a -> b) -> m ()
    %= AnyLayoutManager -> AnyLayoutManager
    forall m. LayoutManager m => m -> m
    nextVariant
      EditorM ()
    layoutManagersPrintMsgE

    -- | Previous variant of the current layout manager, as given by
    -- 'previousVariant'
    layoutManagerPreviousVariantE :: EditorM ()
    layoutManagerPreviousVariantE :: EditorM ()
    layoutManagerPreviousVariantE = do
      (Tab -> Identity Tab) -> Editor -> Identity Editor
    Lens' Editor Tab
    currentTabA ((Tab -> Identity Tab) -> Editor -> Identity Editor)
    -> ((AnyLayoutManager -> Identity AnyLayoutManager)
        -> Tab -> Identity Tab)
    -> (AnyLayoutManager -> Identity AnyLayoutManager)
    -> Editor
    -> Identity Editor
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (AnyLayoutManager -> Identity AnyLayoutManager)
    -> Tab -> Identity Tab
    forall (f :: * -> *).
    Functor f =>
    (AnyLayoutManager -> f AnyLayoutManager) -> Tab -> f Tab
    tabLayoutManagerA ((AnyLayoutManager -> Identity AnyLayoutManager)
     -> Editor -> Identity Editor)
    -> (AnyLayoutManager -> AnyLayoutManager) -> EditorM ()
    forall s (m :: * -> *) a b.
    MonadState s m =>
    ASetter s s a b -> (a -> b) -> m ()
    %= AnyLayoutManager -> AnyLayoutManager
    forall m. LayoutManager m => m -> m
    previousVariant
      EditorM ()
    layoutManagersPrintMsgE

    -- | Sets the given divider position on the current tab
    setDividerPosE :: DividerRef -> DividerPosition -> EditorM ()
    setDividerPosE :: Int -> DividerPosition -> EditorM ()
    setDividerPosE Int
    ref = ASetter Editor Editor DividerPosition DividerPosition
    -> DividerPosition -> EditorM ()
    forall s (m :: * -> *) a b.
    MonadState s m =>
    ASetter s s a b -> b -> m ()
    assign ((Tab -> Identity Tab) -> Editor -> Identity Editor
    Lens' Editor Tab
    currentTabA ((Tab -> Identity Tab) -> Editor -> Identity Editor)
    -> ((DividerPosition -> Identity DividerPosition)
        -> Tab -> Identity Tab)
    -> ASetter Editor Editor DividerPosition DividerPosition
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Int -> Lens' Tab DividerPosition
    tabDividerPositionA Int
    ref)

    -- | Creates a new tab containing a window that views the current buffer.
    newTabE :: EditorM ()
    newTabE :: EditorM ()
    newTabE = do
        bk <- (Editor -> BufferRef) -> EditorM BufferRef
    forall s (m :: * -> *) a. MonadState s m => (s -> a) -> m a
    gets Editor -> BufferRef
    currentBuffer
        win <- newWindowE False bk
        ref <- newRef
        tabsA %= PL.insertRight (makeTab1 ref win)

    -- | Moves to the next tab in the round robin set of tabs
    nextTabE :: EditorM ()
    nextTabE :: EditorM ()
    nextTabE = (PointedList Tab -> Identity (PointedList Tab))
    -> Editor -> Identity Editor
    Lens' Editor (PointedList Tab)
    tabsA ((PointedList Tab -> Identity (PointedList Tab))
     -> Editor -> Identity Editor)
    -> (PointedList Tab -> PointedList Tab) -> EditorM ()
    forall s (m :: * -> *) a b.
    MonadState s m =>
    ASetter s s a b -> (a -> b) -> m ()
    %= PointedList Tab -> PointedList Tab
    forall a. PointedList a -> PointedList a
    PL.next

    -- | Moves to the previous tab in the round robin set of tabs
    previousTabE :: EditorM ()
    previousTabE :: EditorM ()
    previousTabE = (PointedList Tab -> Identity (PointedList Tab))
    -> Editor -> Identity Editor
    Lens' Editor (PointedList Tab)
    tabsA ((PointedList Tab -> Identity (PointedList Tab))
     -> Editor -> Identity Editor)
    -> (PointedList Tab -> PointedList Tab) -> EditorM ()
    forall s (m :: * -> *) a b.
    MonadState s m =>
    ASetter s s a b -> (a -> b) -> m ()
    %= PointedList Tab -> PointedList Tab
    forall a. PointedList a -> PointedList a
    PL.previous

    -- | Moves the focused tab to the given index, or to the end if the
    -- index is not specified.
    moveTabE :: Maybe Int -> EditorM ()
    moveTabE :: Maybe Int -> EditorM ()
    moveTabE Maybe Int
    Nothing  = do
        count <- Getting (PointedList Tab) Editor (PointedList Tab)
    -> (PointedList Tab -> Int) -> EditorM Int
    forall s (m :: * -> *) a b.
    MonadState s m =>
    Getting a s a -> (a -> b) -> m b
    uses Getting (PointedList Tab) Editor (PointedList Tab)
    Lens' Editor (PointedList Tab)
    tabsA PointedList Tab -> Int
    forall a. PointedList a -> Int
    PL.length
        tabsA %= fromJust . PL.moveTo (pred count)
    moveTabE (Just Int
    n) = do
        newTabs <- Getting (PointedList Tab) Editor (PointedList Tab)
    -> (PointedList Tab -> Maybe (PointedList Tab))
    -> EditorM (Maybe (PointedList Tab))
    forall s (m :: * -> *) a b.
    MonadState s m =>
    Getting a s a -> (a -> b) -> m b
    uses Getting (PointedList Tab) Editor (PointedList Tab)
    Lens' Editor (PointedList Tab)
    tabsA (Int -> PointedList Tab -> Maybe (PointedList Tab)
    forall a. Int -> PointedList a -> Maybe (PointedList a)
    PL.moveTo Int
    n)
        when (isNothing newTabs) failure
        assign tabsA $ fromJust newTabs
      where failure :: EditorM a
    failure = FilePath -> EditorM a
    forall a. FilePath -> EditorM a
    forall (m :: * -> *) a. MonadFail m => FilePath -> m a
    fail (FilePath -> EditorM a) -> FilePath -> EditorM a
    forall a b. (a -> b) -> a -> b
    $ FilePath
    "moveTab " FilePath -> FilePath -> FilePath
    forall a. [a] -> [a] -> [a]
    ++ Int -> FilePath
    forall a. Show a => a -> FilePath
    show Int
    n FilePath -> FilePath -> FilePath
    forall a. [a] -> [a] -> [a]
    ++ FilePath
    ": no such tab"

    -- | Deletes the current tab. If there is only one tab open then error out.
    --   When the last tab is focused, move focus to the left, otherwise
    --   move focus to the right.
    deleteTabE :: EditorM ()
    deleteTabE :: EditorM ()
    deleteTabE = (PointedList Tab -> Identity (PointedList Tab))
    -> Editor -> Identity Editor
    Lens' Editor (PointedList Tab)
    tabsA ((PointedList Tab -> Identity (PointedList Tab))
     -> Editor -> Identity Editor)
    -> (PointedList Tab -> PointedList Tab) -> EditorM ()
    forall s (m :: * -> *) a b.
    MonadState s m =>
    ASetter s s a b -> (a -> b) -> m ()
    %= PointedList Tab -> Maybe (PointedList Tab) -> PointedList Tab
    forall a. a -> Maybe a -> a
    fromMaybe PointedList Tab
    forall {a}. a
    failure (Maybe (PointedList Tab) -> PointedList Tab)
    -> (PointedList Tab -> Maybe (PointedList Tab))
    -> PointedList Tab
    -> PointedList Tab
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . PointedList Tab -> Maybe (PointedList Tab)
    forall a. PointedList a -> Maybe (PointedList a)
    deleteTab
      where failure :: a
    failure = FilePath -> a
    forall a. HasCallStack => FilePath -> a
    error FilePath
    "deleteTab: cannot delete sole tab"
            deleteTab :: PointedList a -> Maybe (PointedList a)
    deleteTab PointedList a
    tabs = if PointedList a -> Bool
    forall a. PointedList a -> Bool
    PL.atEnd PointedList a
    tabs
                             then PointedList a -> Maybe (PointedList a)
    forall a. PointedList a -> Maybe (PointedList a)
    PL.deleteLeft PointedList a
    tabs
                             else PointedList a -> Maybe (PointedList a)
    forall a. PointedList a -> Maybe (PointedList a)
    PL.deleteRight PointedList a
    tabs

    -- | Close the current window. If there is only one tab open and the tab
    -- contains only one window then do nothing.
    tryCloseE :: EditorM ()
    tryCloseE :: EditorM ()
    tryCloseE = do
        ntabs <- Getting (PointedList Tab) Editor (PointedList Tab)
    -> (PointedList Tab -> Int) -> EditorM Int
    forall s (m :: * -> *) a b.
    MonadState s m =>
    Getting a s a -> (a -> b) -> m b
    uses Getting (PointedList Tab) Editor (PointedList Tab)
    Lens' Editor (PointedList Tab)
    tabsA PointedList Tab -> Int
    forall a. PointedList a -> Int
    PL.length
        nwins <- uses windowsA PL.length
        unless (ntabs == 1 && nwins == 1) $ if nwins == 1
          -- Could the Maybe response from deleteLeft be used instead of the
          -- def 'if'?
          then tabsA %= fromJust . PL.deleteLeft
          else windowsA %= fromJust . PL.deleteLeft

    -- | Make the current window the only window on the screen
    closeOtherE :: EditorM ()
    closeOtherE :: EditorM ()
    closeOtherE = (PointedList Window -> Identity (PointedList Window))
    -> Editor -> Identity Editor
    Lens' Editor (PointedList Window)
    windowsA ((PointedList Window -> Identity (PointedList Window))
     -> Editor -> Identity Editor)
    -> (PointedList Window -> PointedList Window) -> EditorM ()
    forall s (m :: * -> *) a b.
    MonadState s m =>
    ASetter s s a b -> (a -> b) -> m ()
    %= PointedList Window -> PointedList Window
    forall a. PointedList a -> PointedList a
    PL.deleteOthers

    -- | Switch focus to some other window. If none is available, create one.
    shiftOtherWindow :: MonadEditor m => m ()
    shiftOtherWindow :: forall (m :: * -> *). MonadEditor m => m ()
    shiftOtherWindow = EditorM () -> m ()
    forall a. EditorM a -> m a
    forall (m :: * -> *) a. MonadEditor m => EditorM a -> m a
    withEditor (EditorM () -> m ()) -> EditorM () -> m ()
    forall a b. (a -> b) -> a -> b
    $ do
      len <- Getting (PointedList Window) Editor (PointedList Window)
    -> (PointedList Window -> Int) -> EditorM Int
    forall s (m :: * -> *) a b.
    MonadState s m =>
    Getting a s a -> (a -> b) -> m b
    uses Getting (PointedList Window) Editor (PointedList Window)
    Lens' Editor (PointedList Window)
    windowsA PointedList Window -> Int
    forall a. PointedList a -> Int
    PL.length
      if len == 1
        then splitE
        else nextWinE

    -- | Execute the argument in the context of an other window. Create
    -- one if necessary. The current window is re-focused after the
    -- argument has completed.
    withOtherWindow :: MonadEditor m => m a -> m a
    withOtherWindow :: forall (m :: * -> *) a. MonadEditor m => m a -> m a
    withOtherWindow m a
    f = do
      m ()
    forall (m :: * -> *). MonadEditor m => m ()
    shiftOtherWindow
      x <- m a
    f
      withEditor prevWinE
      return x

    acceptedInputs :: EditorM [T.Text]
    acceptedInputs :: EditorM [Text]
    acceptedInputs = do
      km <- Config -> KeymapSet
    defaultKm (Config -> KeymapSet) -> EditorM Config -> EditorM KeymapSet
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> EditorM Config
    forall (m :: * -> *). MonadEditor m => m Config
    askCfg
      keymap <- withCurrentBuffer $ gets (withMode0 modeKeymap)
      let l = Int -> P Event Action -> [[Text]]
    forall ev w. Show ev => Int -> P ev w -> [[Text]]
    I.accepted Int
    3 (P Event Action -> [[Text]])
    -> (KeymapSet -> P Event Action) -> KeymapSet -> [[Text]]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . I Event Action () -> P Event Action
    forall w ev a. Eq w => I ev w a -> P ev w
    I.mkAutomaton (I Event Action () -> P Event Action)
    -> (KeymapSet -> I Event Action ()) -> KeymapSet -> P Event Action
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . KeymapSet -> I Event Action ()
    extractTopKeymap (KeymapSet -> I Event Action ())
    -> (KeymapSet -> KeymapSet) -> KeymapSet -> I Event Action ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . KeymapSet -> KeymapSet
    keymap (KeymapSet -> [[Text]]) -> KeymapSet -> [[Text]]
    forall a b. (a -> b) -> a -> b
    $ KeymapSet
    km
      return $ fmap T.unwords l

    -- | Shows the current key bindings in a new window
    acceptedInputsOtherWindow :: EditorM ()
    acceptedInputsOtherWindow :: EditorM ()
    acceptedInputsOtherWindow = do
      ai <- EditorM [Text]
    acceptedInputs
      b <- stringToNewBuffer (MemBuffer "keybindings") (fromText $ T.unlines ai)
      w <- newWindowE False b
      windowsA %= PL.insertRight w

    addJumpHereE :: EditorM ()
    addJumpHereE :: EditorM ()
    addJumpHereE = Point -> EditorM ()
    addJumpAtE (Point -> EditorM ()) -> EditorM Point -> EditorM ()
    forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
    =<< BufferM Point -> EditorM Point
    forall (m :: * -> *) a. MonadEditor m => BufferM a -> m a
    withCurrentBuffer BufferM Point
    pointB

    addJumpAtE :: Point -> EditorM ()
    addJumpAtE :: Point -> EditorM ()
    addJumpAtE Point
    point = do
      w <- Getting Window Editor Window -> EditorM Window
    forall s (m :: * -> *) a. MonadState s m => Getting a s a -> m a
    use Getting Window Editor Window
    Lens' Editor Window
    currentWindowA
      shouldAddJump <- case jumpList w of
        Just (PL.PointedList [Jump]
    _ (Jump Mark
    mark BufferRef
    bf) [Jump]
    _) -> do
          bfStillAlive <- (Editor -> Maybe FBuffer) -> EditorM (Maybe FBuffer)
    forall s (m :: * -> *) a. MonadState s m => (s -> a) -> m a
    gets (BufferRef -> Map BufferRef FBuffer -> Maybe FBuffer
    forall k a. Ord k => k -> Map k a -> Maybe a
    M.lookup BufferRef
    bf (Map BufferRef FBuffer -> Maybe FBuffer)
    -> (Editor -> Map BufferRef FBuffer) -> Editor -> Maybe FBuffer
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Editor -> Map BufferRef FBuffer
    buffers)
          case bfStillAlive of
            Maybe FBuffer
    Nothing -> Bool -> EditorM Bool
    forall a. a -> EditorM a
    forall (m :: * -> *) a. Monad m => a -> m a
    return Bool
    False
            Maybe FBuffer
    _ -> do
              p <- BufferRef -> BufferM Point -> EditorM Point
    forall (m :: * -> *) a.
    MonadEditor m =>
    BufferRef -> BufferM a -> m a
    withGivenBuffer BufferRef
    bf (BufferM Point -> EditorM Point)
    -> (Getting Point FBuffer Point -> BufferM Point)
    -> Getting Point FBuffer Point
    -> EditorM Point
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Getting Point FBuffer Point -> BufferM Point
    forall s (m :: * -> *) a. MonadState s m => Getting a s a -> m a
    use (Getting Point FBuffer Point -> EditorM Point)
    -> Getting Point FBuffer Point -> EditorM Point
    forall a b. (a -> b) -> a -> b
    $ Mark -> Getting Point FBuffer Point
    forall (f :: * -> *).
    Functor f =>
    Mark -> (Point -> f Point) -> FBuffer -> f FBuffer
    markPointA Mark
    mark
              return $! (p, bf) /= (point, bufkey w)
        JumpList
    _ -> Bool -> EditorM Bool
    forall a. a -> EditorM a
    forall (m :: * -> *) a. Monad m => a -> m a
    return Bool
    True
      when shouldAddJump $ do
        m <- withCurrentBuffer setMarkHereB
        let bf = Window -> BufferRef
    bufkey Window
    w
            j = Mark -> BufferRef -> Jump
    Jump Mark
    m BufferRef
    bf
        assign currentWindowA $ w & jumpListA %~ addJump j
        return ()

    jumpBackE :: EditorM ()
    jumpBackE :: EditorM ()
    jumpBackE = EditorM ()
    addJumpHereE EditorM () -> EditorM () -> EditorM ()
    forall a b. EditorM a -> EditorM b -> EditorM b
    forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
    >> (JumpList -> JumpList) -> EditorM ()
    modifyJumpListE JumpList -> JumpList
    jumpBack

    jumpForwardE :: EditorM ()
    jumpForwardE :: EditorM ()
    jumpForwardE = (JumpList -> JumpList) -> EditorM ()
    modifyJumpListE JumpList -> JumpList
    jumpForward

    modifyJumpListE :: (JumpList -> JumpList) -> EditorM ()
    modifyJumpListE :: (JumpList -> JumpList) -> EditorM ()
    modifyJumpListE JumpList -> JumpList
    f = do
      w <- Getting Window Editor Window -> EditorM Window
    forall s (m :: * -> *) a. MonadState s m => Getting a s a -> m a
    use Getting Window Editor Window
    Lens' Editor Window
    currentWindowA
      case f $ w ^. jumpListA of
        JumpList
    Nothing -> () -> EditorM ()
    forall a. a -> EditorM a
    forall (m :: * -> *) a. Monad m => a -> m a
    return ()
        Just (PL.PointedList [Jump]
    _ (Jump Mark
    mark BufferRef
    bf) [Jump]
    _) -> do
          BufferRef -> EditorM ()
    switchToBufferE BufferRef
    bf
          BufferM () -> EditorM ()
    forall (m :: * -> *) a. MonadEditor m => BufferM a -> m a
    withCurrentBuffer (BufferM () -> EditorM ()) -> BufferM () -> EditorM ()
    forall a b. (a -> b) -> a -> b
    $ Getting Point FBuffer Point -> BufferM Point
    forall s (m :: * -> *) a. MonadState s m => Getting a s a -> m a
    use (Mark -> Getting Point FBuffer Point
    forall (f :: * -> *).
    Functor f =>
    Mark -> (Point -> f Point) -> FBuffer -> f FBuffer
    markPointA Mark
    mark) BufferM Point -> (Point -> BufferM ()) -> BufferM ()
    forall a b. BufferM a -> (a -> BufferM b) -> BufferM b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= Point -> BufferM ()
    moveTo
          (Window -> Identity Window) -> Editor -> Identity Editor
    Lens' Editor Window
    currentWindowA ((Window -> Identity Window) -> Editor -> Identity Editor)
    -> ((JumpList -> Identity JumpList) -> Window -> Identity Window)
    -> (JumpList -> Identity JumpList)
    -> Editor
    -> Identity Editor
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (JumpList -> Identity JumpList) -> Window -> Identity Window
    Lens' Window JumpList
    jumpListA ((JumpList -> Identity JumpList) -> Editor -> Identity Editor)
    -> (JumpList -> JumpList) -> EditorM ()
    forall s (m :: * -> *) a b.
    MonadState s m =>
    ASetter s s a b -> (a -> b) -> m ()
    %= JumpList -> JumpList
    f

    -- | Creates an in-memory buffer with a unique name.
    newTempBufferE :: EditorM BufferRef
    newTempBufferE :: EditorM BufferRef
    newTempBufferE = do
      e <- (Editor -> Editor) -> EditorM Editor
    forall s (m :: * -> *) a. MonadState s m => (s -> a) -> m a
    gets Editor -> Editor
    forall a. a -> a
    id
      -- increment the index of the hint until no buffer is found with that name
      let find_next Text
    currentName (Text
    nextName:[Text]
    otherNames) =
              if Text -> Editor -> Bool
    doesBufferNameExist Text
    currentName Editor
    e
                then Text -> [Text] -> Text
    find_next Text
    nextName [Text]
    otherNames
                else Text
    currentName
          find_next Text
    _ [] = FilePath -> Text
    forall a. HasCallStack => FilePath -> a
    error FilePath
    "Looks like nearly infinite list has just ended."
          next_tmp_name = Text -> [Text] -> Text
    find_next Text
    name [Text]
    names
          (name : names) = (fmap (("tmp-" Mon.<>) . T.pack . show) [0 :: Int ..])

      newEmptyBufferE (MemBuffer next_tmp_name)