{-# 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)
import           Control.Monad.Reader           (MonadReader (ask), asks,
                                                 unless, when)
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 (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 (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 (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 (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 (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 (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 (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 (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
    NonEmpty BufferRef
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 (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Get [BufferRef]
forall t. Binary t => Get t
get
    Map BufferRef FBuffer
bs <- Get (Map BufferRef FBuffer)
forall t. Binary t => Get t
get
    Int
supply <- Get Int
forall t. Binary t => Get t
get
    PointedList Tab
ts <- Get (PointedList Tab)
forall t. Binary t => Get t
get
    DynamicState
dv <- Get DynamicState
forall t. Binary t => Get t
get
    Int
msh <- Get Int
forall t. Binary t => Get t
get
    Killring
kr <- Get Killring
forall t. Binary t => Get t
get
    Maybe SearchExp
regex <- Get (Maybe SearchExp)
forall t. Binary t => Get t
get
    Editor -> Get Editor
forall (m :: * -> *) a. Monad m => a -> m a
return (Editor -> Get Editor) -> Editor -> Get Editor
forall a b. (a -> b) -> a -> b
$ Editor
emptyEditor { bufferStack :: NonEmpty BufferRef
bufferStack = NonEmpty BufferRef
bss
                         , buffers :: Map BufferRef FBuffer
buffers = Map BufferRef FBuffer
bs
                         , refSupply :: Int
refSupply = Int
supply
                         , tabs_ :: PointedList Tab
tabs_ = PointedList Tab
ts
                         , dynamic :: DynamicState
dynamic = DynamicState
dv
                         , maxStatusHeight :: Int
maxStatusHeight = Int
msh
                         , killring :: Killring
killring = Killring
kr
                         , currentRegex :: Maybe SearchExp
currentRegex = Maybe SearchExp
regex
                         }

-- | The initial state
emptyEditor :: Editor
emptyEditor :: Editor
emptyEditor = Editor :: NonEmpty BufferRef
-> Map BufferRef FBuffer
-> Int
-> PointedList Tab
-> DynamicState
-> Statuses
-> Int
-> Killring
-> Maybe SearchExp
-> Direction
-> [Event]
-> Map BufferRef (EditorM ())
-> Editor
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, ([Text], StyleName)) -> 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
wkey = Int -> WindowRef
WindowRef Int
1 , isMini :: Bool
isMini = Bool
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 :: (PointedList Window -> f (PointedList Window))
-> Editor -> f Editor
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 :: (PointedList Tab -> f (PointedList Tab)) -> Editor -> f Editor
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 :: (Tab -> f Tab) -> Editor -> f Editor
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 :: m b
askConfigVariableA = do Config
cfg <- m Config
forall (m :: * -> *). MonadEditor m => m Config
askCfg
                        b -> m b
forall (m :: * -> *) a. Monad m => a -> m a
return (b -> m b) -> b -> m b
forall a b. (a -> b) -> a -> b
$ Config
cfg Config -> Getting b Config b -> b
forall s a. s -> Getting a s a -> a
^. Getting b Config b
forall a. YiConfigVariable a => Lens Config Config a a
configVariable

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

newRef :: MonadEditor m => m Int
newRef :: m Int
newRef = EditorM Int -> m Int
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 (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 :: 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 :: BufferId -> YiString -> m BufferRef
stringToNewBuffer BufferId
nm YiString
cs = EditorM BufferRef -> m BufferRef
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
    BufferRef
u <- EditorM BufferRef
forall (m :: * -> *). MonadEditor m => m BufferRef
newBufRef
    RegionStyle
defRegStyle <- Config -> RegionStyle
configRegionStyle (Config -> RegionStyle) -> EditorM Config -> EditorM RegionStyle
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> EditorM Config
forall (m :: * -> *). MonadEditor m => m Config
askCfg
    FBuffer -> EditorM ()
forall (m :: * -> *). MonadEditor m => FBuffer -> m ()
insertBuffer (FBuffer -> EditorM ()) -> FBuffer -> EditorM ()
forall a b. (a -> b) -> a -> b
$ BufferRef -> BufferId -> YiString -> FBuffer
newB BufferRef
u BufferId
nm YiString
cs
    AnyMode
m <- (Config -> AnyMode) -> EditorM AnyMode
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
asks Config -> AnyMode
configFundamentalMode
    BufferRef -> BufferM () -> EditorM ()
forall (m :: * -> *) a.
MonadEditor m =>
BufferRef -> BufferM a -> m a
withGivenBuffer BufferRef
u (BufferM () -> EditorM ()) -> BufferM () -> EditorM ()
forall a b. (a -> b) -> a -> b
$ do
        RegionStyle -> BufferM ()
putRegionStyle RegionStyle
defRegStyle
        AnyMode -> BufferM ()
setAnyMode AnyMode
m
    BufferRef -> EditorM BufferRef
forall (m :: * -> *) a. Monad m => a -> m a
return BufferRef
u

insertBuffer :: MonadEditor m => FBuffer -> m ()
insertBuffer :: FBuffer -> m ()
insertBuffer FBuffer
b = EditorM () -> m ()
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 :: NonEmpty BufferRef
bufferStack = NonEmpty BufferRef -> NonEmpty BufferRef
forall a. Eq a => NonEmpty a -> NonEmpty a
nub (Editor -> NonEmpty BufferRef
bufferStack Editor
e NonEmpty BufferRef -> NonEmpty BufferRef -> NonEmpty BufferRef
forall a. Semigroup a => a -> a -> a
<> (FBuffer -> BufferRef
bkey FBuffer
b BufferRef -> [BufferRef] -> NonEmpty BufferRef
forall a. a -> [a] -> NonEmpty a
:| []))
      , buffers :: Map BufferRef FBuffer
buffers = BufferRef
-> FBuffer -> Map BufferRef FBuffer -> Map BufferRef FBuffer
forall k a. Ord k => k -> a -> Map k a -> Map k a
M.insert (FBuffer -> BufferRef
bkey FBuffer
b) FBuffer
b (Editor -> Map BufferRef FBuffer
buffers Editor
e)}


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

forceFoldTabs :: Foldable t => t Tab -> t Tab
forceFoldTabs :: t Tab -> t Tab
forceFoldTabs t Tab
x = (Tab -> t Tab -> t Tab) -> t Tab -> t Tab -> t Tab
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr (Tab -> t Tab -> t Tab
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 :: BufferRef -> m ()
deleteBuffer BufferRef
k = EditorM () -> m ()
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 (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
    BufferRef
_ :| [] -> () -> EditorM ()
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 (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 (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.
  NonEmpty BufferRef
bs <- (Editor -> NonEmpty BufferRef) -> EditorM (NonEmpty BufferRef)
forall s (m :: * -> *) a. MonadState s m => (s -> a) -> m a
gets Editor -> NonEmpty BufferRef
bufferStack
  PointedList Window
ws <- Getting (PointedList Window) Editor (PointedList Window)
-> EditorM (PointedList Window)
forall s (m :: * -> *) a. MonadState s m => Getting a s a -> m a
use Getting (PointedList Window) Editor (PointedList Window)
Lens' Editor (PointedList Window)
windowsA
  case NonEmpty BufferRef
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 :: BufferRef
bufkey = BufferRef
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 (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. [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. [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 (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 (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 (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 (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
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. [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 :: m (NonEmpty FBuffer)
getBufferStack = EditorM (NonEmpty FBuffer) -> m (NonEmpty FBuffer)
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
  Map BufferRef FBuffer
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
  (Editor -> NonEmpty FBuffer) -> EditorM (NonEmpty FBuffer)
forall s (m :: * -> *) a. MonadState s m => (s -> a) -> m a
gets ((Editor -> NonEmpty FBuffer) -> EditorM (NonEmpty FBuffer))
-> (Editor -> NonEmpty FBuffer) -> EditorM (NonEmpty FBuffer)
forall a b. (a -> b) -> a -> b
$ (BufferRef -> FBuffer) -> NonEmpty BufferRef -> NonEmpty FBuffer
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Map BufferRef FBuffer
bufMap Map BufferRef FBuffer -> BufferRef -> FBuffer
forall k a. Ord k => Map k a -> k -> a
M.!) (NonEmpty BufferRef -> NonEmpty FBuffer)
-> (Editor -> NonEmpty BufferRef) -> Editor -> NonEmpty FBuffer
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Editor -> NonEmpty BufferRef
bufferStack

findBuffer :: MonadEditor m => BufferRef -> m (Maybe FBuffer)
findBuffer :: BufferRef -> m (Maybe FBuffer)
findBuffer BufferRef
k = EditorM (Maybe FBuffer) -> m (Maybe FBuffer)
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 (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 :: Text -> m BufferRef
getBufferWithName Text
bufName = EditorM BufferRef -> m BufferRef
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
  [BufferRef]
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 [BufferRef]
bs of
    [] -> FilePath -> EditorM BufferRef
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 (m :: * -> *) a. Monad m => a -> m a
return BufferRef
b
    [BufferRef]
_ -> FilePath -> EditorM BufferRef
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 :: BufferRef -> BufferM a -> m a
withGivenBuffer BufferRef
k BufferM a
f = do
    FBuffer
b <- (Editor -> FBuffer) -> m FBuffer
forall s (m :: * -> *) a. MonadState s m => (s -> a) -> m a
gets (BufferRef -> Editor -> FBuffer
findBufferWith BufferRef
k)

    Window -> BufferRef -> BufferM a -> m a
forall (m :: * -> *) a.
MonadEditor m =>
Window -> BufferRef -> BufferM a -> m a
withGivenBufferAndWindow (FBuffer
b FBuffer -> Getting Window FBuffer Window -> Window
forall s a. s -> Getting a s a -> a
^. Getting Window FBuffer Window
forall c. HasAttributes c => Lens' c Window
lastActiveWindowA) BufferRef
k BufferM a
f

-- | Perform action with any given buffer
withGivenBufferAndWindow :: MonadEditor m
    => Window -> BufferRef -> BufferM a -> m a
withGivenBufferAndWindow :: Window -> BufferRef -> BufferM a -> m a
withGivenBufferAndWindow Window
w BufferRef
k BufferM a
f = 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
  Bool
accum <- (Config -> Bool) -> EditorM Bool
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
asks Config -> Bool
configKillringAccumulate
  let edit :: Editor -> (Editor, (Seq Update, a))
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 (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))
  (Seq Update
us, a
v) <- (Editor -> (Editor, (Seq Update, a))) -> EditorM (Seq Update, a)
forall s (m :: * -> *) a. MonadState s m => (s -> (s, a)) -> m a
getsAndModify Editor -> (Editor, (Seq Update, a))
edit

  Seq (Seq Update -> BufferM ())
updHandler <- Seq (Seq Update -> BufferM ())
-> EditorM (Seq (Seq Update -> BufferM ()))
forall (m :: * -> *) a. Monad m => a -> m a
return (Seq (Seq Update -> BufferM ())
 -> EditorM (Seq (Seq Update -> BufferM ())))
-> (Config -> Seq (Seq Update -> BufferM ()))
-> Config
-> EditorM (Seq (Seq Update -> BufferM ()))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Config -> Seq (Seq Update -> BufferM ())
bufferUpdateHandler (Config -> EditorM (Seq (Seq Update -> BufferM ())))
-> EditorM Config -> EditorM (Seq (Seq Update -> BufferM ()))
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< EditorM Config
forall r (m :: * -> *). MonadReader r m => m r
ask
  Bool -> EditorM () -> EditorM ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (Seq Update -> Bool
forall a. Seq a -> Bool
S.null Seq Update
us Bool -> Bool -> Bool
|| Seq (Seq Update -> BufferM ()) -> Bool
forall a. Seq a -> Bool
S.null Seq (Seq Update -> BufferM ())
updHandler) (EditorM () -> EditorM ()) -> EditorM () -> EditorM ()
forall a b. (a -> b) -> a -> b
$
    Seq (Seq Update -> BufferM ())
-> ((Seq Update -> BufferM ()) -> EditorM ()) -> EditorM ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ Seq (Seq Update -> BufferM ())
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))
  a -> EditorM a
forall (m :: * -> *) a. Monad m => a -> m a
return a
v

-- | Perform action with current window's buffer
withCurrentBuffer :: MonadEditor m => BufferM a -> m a
withCurrentBuffer :: BufferM a -> m a
withCurrentBuffer BufferM a
f = 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
  Window
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
  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) BufferM a
f

withEveryBuffer :: MonadEditor m => BufferM a -> m [a]
withEveryBuffer :: BufferM a -> m [a]
withEveryBuffer BufferM a
action =
    EditorM (NonEmpty BufferRef) -> m (NonEmpty BufferRef)
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 (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)
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 :: (Window -> f Window) -> Editor -> f Editor
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 :: Text -> m ()
printMsg Text
s = ([Text], StyleName) -> m ()
forall (m :: * -> *). MonadEditor m => ([Text], StyleName) -> m ()
printStatus ([Text
s], StyleName
defaultStyle)

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

printStatus :: MonadEditor m => Status -> m ()
printStatus :: ([Text], StyleName) -> m ()
printStatus = Int -> ([Text], StyleName) -> m ()
forall (m :: * -> *).
MonadEditor m =>
Int -> ([Text], StyleName) -> m ()
setTmpStatus Int
1

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

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

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

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

setTmpStatus :: MonadEditor m => Int -> Status -> m ()
setTmpStatus :: Int -> ([Text], StyleName) -> m ()
setTmpStatus Int
delay ([Text], StyleName)
s = EditorM () -> m ()
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, ([Text], StyleName)) -> Statuses -> Statuses
forall a. (Int, a) -> DelayList a -> DelayList a
DelayList.insert (Int
delay, ([Text], StyleName)
s)
  -- also show in the messages buffer, so we don't loose any message
  [FBuffer]
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
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)

  BufferRef
b <- case [FBuffer]
bs of
         (FBuffer
b':[FBuffer]
_) -> BufferRef -> EditorM BufferRef
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
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
<$> ([Text], StyleName) -> [Text]
forall a b. (a, b) -> a
fst ([Text], StyleName)
s
  BufferRef -> BufferM () -> EditorM ()
forall (m :: * -> *) a.
MonadEditor m =>
BufferRef -> BufferM a -> m a
withGivenBuffer BufferRef
b (BufferM () -> EditorM ()) -> BufferM () -> EditorM ()
forall a b. (a -> b) -> a -> b
$ BufferM ()
botB BufferM () -> BufferM () -> BufferM ()
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> YiString -> BufferM ()
insertN (YiString
m YiString -> Char -> YiString
`R.snoc` Char
'\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 restult 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 :: 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 :: 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
    BufferRef
b <- BufferId -> YiString -> EditorM BufferRef
forall (m :: * -> *).
MonadEditor m =>
BufferId -> YiString -> m BufferRef
stringToNewBuffer BufferId
f YiString
s
    BufferRef -> EditorM ()
switchToBufferE BufferRef
b
    BufferRef -> EditorM BufferRef
forall (m :: * -> *) a. Monad m => a -> m a
return BufferRef
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 :: Window -> [BufferRef]
bufAccessList = [BufferRef]
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 [BufferRef] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [BufferRef]
lst Bool -> Bool -> Bool
|| ([BufferRef] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [BufferRef]
lst Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
n
      then FilePath -> EditorM ()
forall (m :: * -> *) a. MonadFail m => FilePath -> m a
fail FilePath
"no alternate buffer"
      else BufferRef -> EditorM ()
switchToBufferE (BufferRef -> EditorM ()) -> BufferRef -> EditorM ()
forall a b. (a -> b) -> a -> b
$ [BufferRef]
lst[BufferRef] -> Int -> BufferRef
forall a. [a] -> Int -> a
!!Int
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 :: Text -> m BufferRef
getBufferWithNameOrCurrent Text
t = EditorM BufferRef -> m BufferRef
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.
  BufferRef
b <- (Editor -> BufferRef) -> EditorM BufferRef
forall s (m :: * -> *) a. MonadState s m => (s -> a) -> m a
gets Editor -> BufferRef
currentBuffer
  EditorM ()
tryCloseE
  BufferRef -> EditorM ()
forall (m :: * -> *). MonadEditor m => BufferRef -> m ()
deleteBuffer BufferRef
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_ :: (Editor -> f Editor) -> Editor -> f 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
`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 :: 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. [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
  PointedList Tab
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 :: Tab -> [Window]
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)
  [Window] -> EditorM [Window]
forall (m :: * -> *) a. Monad m => a -> m a
return ([Window] -> EditorM [Window]) -> [Window] -> EditorM [Window]
forall a b. (a -> b) -> a -> b
$ (Tab -> [Window]) -> PointedList Tab -> [Window]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap Tab -> [Window]
tabBufEq PointedList Tab
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
    PointedList Tab
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, a) -> Window -> (Bool, a)
check (Bool
False, a
i) Window
win = if Window -> WindowRef
wkey Window
win WindowRef -> WindowRef -> Bool
forall a. Eq a => a -> a -> Bool
== WindowRef
k
                                    then (Bool
True, a
i)
                                    else (Bool
False, a
i a -> a -> a
forall a. Num a => a -> a -> a
+ a
1)
        check r :: (Bool, a)
r@(Bool
True, a
_) Window
_win = (Bool, a)
r

        searchWindowSet :: (Bool, a, c) -> Tab -> (Bool, a, c)
searchWindowSet (Bool
False, a
tabIndex, c
_) Tab
ws =
            case ((Bool, c) -> Window -> (Bool, c))
-> (Bool, c) -> PointedList Window -> (Bool, c)
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl (Bool, c) -> Window -> (Bool, c)
forall a. Num a => (Bool, a) -> Window -> (Bool, a)
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, a
tabIndex, c
winIndex)
                (Bool
False, c
_)       -> (Bool
False, a
tabIndex a -> a -> a
forall a. Num a => a -> a -> a
+ a
1, c
0)
        searchWindowSet r :: (Bool, a, c)
r@(Bool
True, a
_, c
_) Tab
_ws = (Bool, a, c)
r

    case ((Bool, Int, Int) -> Tab -> (Bool, Int, Int))
-> (Bool, Int, Int) -> PointedList Tab -> (Bool, Int, Int)
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl (Bool, Int, Int) -> Tab -> (Bool, Int, Int)
forall c a. (Num c, Num a) => (Bool, a, c) -> Tab -> (Bool, a, c)
searchWindowSet  (Bool
False, Int
0, Int
0) PointedList Tab
ts of
        (Bool
False, Int
_, Int
_) -> FilePath -> EditorM ()
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
  Window
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 (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Bool -> BufferRef -> EditorM Window
newWindowE Bool
False
  (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 ()
%= Window -> PointedList Window -> PointedList Window
forall a. a -> PointedList a -> PointedList a
PL.insertRight Window
w

-- | Prints the description of the current layout manager in the status bar
layoutManagersPrintMsgE :: EditorM ()
layoutManagersPrintMsgE :: EditorM ()
layoutManagersPrintMsgE = do
  AnyLayoutManager
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
  Text -> EditorM ()
forall (m :: * -> *). MonadEditor m => Text -> m ()
printMsg (Text -> EditorM ())
-> (FilePath -> Text) -> FilePath -> EditorM ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> Text
T.pack (FilePath -> EditorM ()) -> FilePath -> EditorM ()
forall a b. (a -> b) -> a -> b
$ AnyLayoutManager -> FilePath
forall m. LayoutManager m => m -> FilePath
describeLayout AnyLayoutManager
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 (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 (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 (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. [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
    BufferRef
bk <- (Editor -> BufferRef) -> EditorM BufferRef
forall s (m :: * -> *) a. MonadState s m => (s -> a) -> m a
gets Editor -> BufferRef
currentBuffer
    Window
win <- Bool -> BufferRef -> EditorM Window
newWindowE Bool
False BufferRef
bk
    Int
ref <- EditorM Int
forall (m :: * -> *). MonadEditor m => m Int
newRef
    (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 ()
%= Tab -> PointedList Tab -> PointedList Tab
forall a. a -> PointedList a -> PointedList a
PL.insertRight (Int -> Window -> Tab
makeTab1 Int
ref Window
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
    Int
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
    (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 ()
%= Maybe (PointedList Tab) -> PointedList Tab
forall a. HasCallStack => Maybe a -> a
fromJust (Maybe (PointedList Tab) -> PointedList Tab)
-> (PointedList Tab -> Maybe (PointedList Tab))
-> PointedList Tab
-> PointedList Tab
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> PointedList Tab -> Maybe (PointedList Tab)
forall a. Int -> PointedList a -> Maybe (PointedList a)
PL.moveTo (Int -> Int
forall a. Enum a => a -> a
pred Int
count)
moveTabE (Just Int
n) = do
    Maybe (PointedList Tab)
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)
    Bool -> EditorM () -> EditorM ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Maybe (PointedList Tab) -> Bool
forall a. Maybe a -> Bool
isNothing Maybe (PointedList Tab)
newTabs) EditorM ()
forall a. EditorM a
failure
    ((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 (PointedList Tab -> EditorM ()) -> PointedList Tab -> EditorM ()
forall a b. (a -> b) -> a -> b
$ Maybe (PointedList Tab) -> PointedList Tab
forall a. HasCallStack => Maybe a -> a
fromJust Maybe (PointedList Tab)
newTabs
  where failure :: EditorM a
failure = 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
    Int
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
    Int
nwins <- 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
    Bool -> EditorM () -> EditorM ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (Int
ntabs Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
1 Bool -> Bool -> Bool
&& Int
nwins Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
1) (EditorM () -> EditorM ()) -> EditorM () -> EditorM ()
forall a b. (a -> b) -> a -> b
$ if Int
nwins Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
1
      -- Could the Maybe response from deleteLeft be used instead of the
      -- def 'if'?
      then (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 ()
%= Maybe (PointedList Tab) -> PointedList Tab
forall a. HasCallStack => Maybe a -> a
fromJust (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)
PL.deleteLeft
      else (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
. PointedList Window -> Maybe (PointedList Window)
forall a. PointedList a -> Maybe (PointedList a)
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 :: m ()
shiftOtherWindow = EditorM () -> m ()
forall (m :: * -> *) a. MonadEditor m => EditorM a -> m a
withEditor (EditorM () -> m ()) -> EditorM () -> m ()
forall a b. (a -> b) -> a -> b
$ do
  Int
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 Int
len Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
1
    then EditorM ()
splitE
    else EditorM ()
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 :: m a -> m a
withOtherWindow m a
f = do
  m ()
forall (m :: * -> *). MonadEditor m => m ()
shiftOtherWindow
  a
x <- m a
f
  EditorM () -> m ()
forall (m :: * -> *) a. MonadEditor m => EditorM a -> m a
withEditor EditorM ()
prevWinE
  a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return a
x

acceptedInputs :: EditorM [T.Text]
acceptedInputs :: EditorM [Text]
acceptedInputs = do
  KeymapSet
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
  KeymapSet -> KeymapSet
keymap <- BufferM (KeymapSet -> KeymapSet)
-> EditorM (KeymapSet -> KeymapSet)
forall (m :: * -> *) a. MonadEditor m => BufferM a -> m a
withCurrentBuffer (BufferM (KeymapSet -> KeymapSet)
 -> EditorM (KeymapSet -> KeymapSet))
-> BufferM (KeymapSet -> KeymapSet)
-> EditorM (KeymapSet -> KeymapSet)
forall a b. (a -> b) -> a -> b
$ (FBuffer -> KeymapSet -> KeymapSet)
-> BufferM (KeymapSet -> KeymapSet)
forall s (m :: * -> *) a. MonadState s m => (s -> a) -> m a
gets ((forall syntax. Mode syntax -> KeymapSet -> KeymapSet)
-> FBuffer -> KeymapSet -> KeymapSet
forall a. (forall syntax. Mode syntax -> a) -> FBuffer -> a
withMode0 forall syntax. Mode syntax -> KeymapSet -> KeymapSet
modeKeymap)
  let l :: [[Text]]
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
  [Text] -> EditorM [Text]
forall (m :: * -> *) a. Monad m => a -> m a
return ([Text] -> EditorM [Text]) -> [Text] -> EditorM [Text]
forall a b. (a -> b) -> a -> b
$ ([Text] -> Text) -> [[Text]] -> [Text]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap [Text] -> Text
T.unwords [[Text]]
l

-- | Shows the current key bindings in a new window
acceptedInputsOtherWindow :: EditorM ()
acceptedInputsOtherWindow :: EditorM ()
acceptedInputsOtherWindow = do
  [Text]
ai <- EditorM [Text]
acceptedInputs
  BufferRef
b <- BufferId -> YiString -> EditorM BufferRef
forall (m :: * -> *).
MonadEditor m =>
BufferId -> YiString -> m BufferRef
stringToNewBuffer (Text -> BufferId
MemBuffer Text
"keybindings") (Text -> YiString
fromText (Text -> YiString) -> Text -> YiString
forall a b. (a -> b) -> a -> b
$ [Text] -> Text
T.unlines [Text]
ai)
  Window
w <- Bool -> BufferRef -> EditorM Window
newWindowE Bool
False BufferRef
b
  (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 ()
%= Window -> PointedList Window -> PointedList Window
forall a. a -> PointedList a -> PointedList a
PL.insertRight Window
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
  Window
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
  Bool
shouldAddJump <- case Window -> JumpList
jumpList Window
w of
    Just (PL.PointedList [Jump]
_ (Jump Mark
mark BufferRef
bf) [Jump]
_) -> do
      Maybe FBuffer
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 Maybe FBuffer
bfStillAlive of
        Maybe FBuffer
Nothing -> Bool -> EditorM Bool
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
False
        Maybe FBuffer
_ -> do
          Point
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 -> Lens' FBuffer Point
markPointA Mark
mark
          Bool -> EditorM Bool
forall (m :: * -> *) a. Monad m => a -> m a
return (Bool -> EditorM Bool) -> Bool -> EditorM Bool
forall a b. (a -> b) -> a -> b
$! (Point
p, BufferRef
bf) (Point, BufferRef) -> (Point, BufferRef) -> Bool
forall a. Eq a => a -> a -> Bool
/= (Point
point, Window -> BufferRef
bufkey Window
w)
    JumpList
_ -> Bool -> EditorM Bool
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
True
  Bool -> EditorM () -> EditorM ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
shouldAddJump (EditorM () -> EditorM ()) -> EditorM () -> EditorM ()
forall a b. (a -> b) -> a -> b
$ do
    Mark
m <- BufferM Mark -> EditorM Mark
forall (m :: * -> *) a. MonadEditor m => BufferM a -> m a
withCurrentBuffer BufferM Mark
setMarkHereB
    let bf :: BufferRef
bf = Window -> BufferRef
bufkey Window
w
        j :: Jump
j = Mark -> BufferRef -> Jump
Jump Mark
m BufferRef
bf
    ((Window -> Identity Window) -> Editor -> Identity Editor)
-> Window -> EditorM ()
forall s (m :: * -> *) a b.
MonadState s m =>
ASetter s s a b -> b -> m ()
assign (Window -> Identity Window) -> Editor -> Identity Editor
Lens' Editor Window
currentWindowA (Window -> EditorM ()) -> Window -> EditorM ()
forall a b. (a -> b) -> a -> b
$ Window
w Window -> (Window -> Window) -> Window
forall a b. a -> (a -> b) -> b
& (JumpList -> Identity JumpList) -> Window -> Identity Window
Lens' Window JumpList
jumpListA ((JumpList -> Identity JumpList) -> Window -> Identity Window)
-> (JumpList -> JumpList) -> Window -> Window
forall s t a b. ASetter s t a b -> (a -> b) -> s -> t
%~ Jump -> JumpList -> JumpList
addJump Jump
j
    () -> EditorM ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()

jumpBackE :: EditorM ()
jumpBackE :: EditorM ()
jumpBackE = EditorM ()
addJumpHereE EditorM () -> EditorM () -> EditorM ()
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
  Window
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 JumpList -> JumpList
f (JumpList -> JumpList) -> JumpList -> JumpList
forall a b. (a -> b) -> a -> b
$ Window
w Window -> Getting JumpList Window JumpList -> JumpList
forall s a. s -> Getting a s a -> a
^. Getting JumpList Window JumpList
Lens' Window JumpList
jumpListA of
    JumpList
Nothing -> () -> EditorM ()
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 -> Lens' FBuffer Point
markPointA Mark
mark) BufferM Point -> (Point -> BufferM ()) -> BufferM ()
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
  Editor
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 -> [Text] -> Text
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
next_tmp_name = Text -> [Text] -> Text
find_next Text
name [Text]
names
      (Text
name : [Text]
names) = ((Int -> Text) -> [Int] -> [Text]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((Text
"tmp-" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
Mon.<>) (Text -> Text) -> (Int -> Text) -> Int -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> Text
T.pack (FilePath -> Text) -> (Int -> FilePath) -> Int -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> FilePath
forall a. Show a => a -> FilePath
show) [Int
0 :: Int ..])

  BufferId -> EditorM BufferRef
newEmptyBufferE (Text -> BufferId
MemBuffer Text
next_tmp_name)