Skip to content

Commit

Permalink
Merge pull request yi-editor#5 from reinerp/layout
Browse files Browse the repository at this point in the history
Layout support for yi.
  • Loading branch information
jeffwheeler committed May 19, 2011
2 parents 5e28d84 + 77d069a commit fa26b18
Show file tree
Hide file tree
Showing 18 changed files with 1,132 additions and 239 deletions.
8 changes: 8 additions & 0 deletions yi/src/library/Yi/Buffer/Basic.hs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ module Yi.Buffer.Basic where
import Prelude (reverse)
import Data.Binary
import Yi.Prelude
import Yi.Dynamic(Initializable(..))
import qualified Data.Rope as R
import Data.Typeable
import Data.DeriveTH
Expand Down Expand Up @@ -67,3 +68,10 @@ instance SemiNum Point Size where

fromString :: String -> Rope
fromString = R.fromString

-- | Window references
newtype WindowRef = WindowRef { unWindowRef :: Int }
deriving(Eq, Ord, Enum, Show, Typeable, Binary)

instance Initializable WindowRef where initial = WindowRef (-1)

4 changes: 2 additions & 2 deletions yi/src/library/Yi/Buffer/Implementation.hs
Original file line number Diff line number Diff line change
Expand Up @@ -377,8 +377,8 @@ getMarkDefaultPosBI name defaultPos fb@FBufferData {marks = mks, markNames = nms
in (fb {marks = mks', markNames = nms'}, newMark)


getAst :: Int -> BufferImpl syntax -> syntax
getAst :: WindowRef -> BufferImpl syntax -> syntax
getAst w FBufferData {hlCache = HLState (SynHL {hlGetTree = gt}) cache} = gt cache w

focusAst :: M.Map Int Region -> BufferImpl syntax -> BufferImpl syntax
focusAst :: M.Map WindowRef Region -> BufferImpl syntax -> BufferImpl syntax
focusAst r b@FBufferData {hlCache = HLState s@(SynHL {hlFocus = foc}) cache} = b {hlCache = HLState s (foc r cache)}
4 changes: 2 additions & 2 deletions yi/src/library/Yi/Buffer/Misc.hs
Original file line number Diff line number Diff line change
Expand Up @@ -343,7 +343,7 @@ rectangleSelectionA =
keymapProcessA :: Accessor FBuffer KeymapProcess
keymapProcessA = processAA . attrsA

winMarksA :: Accessor FBuffer (M.Map Int WinMarks)
winMarksA :: Accessor FBuffer (M.Map WindowRef WinMarks)
winMarksA = winMarksAA . attrsA

{- | Currently duplicates some of Vim's indent settings. Allowing a buffer to
Expand Down Expand Up @@ -499,7 +499,7 @@ runBufferFull w b f =
ms <- getMarks w
when (isNothing ms) $ do
-- this window has no marks for this buffer yet; have to create them.
newMarkValues <- if wkey (b ^. lastActiveWindowA) == dummyWindowKey
newMarkValues <- if wkey (b ^. lastActiveWindowA) == initial
then return
-- no previous window, create some marks from scratch.
MarkSet { insMark = MarkValue 0 Forward,
Expand Down
5 changes: 4 additions & 1 deletion yi/src/library/Yi/Config.hs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import qualified Data.Map as M
import Data.Prototype

import Yi.Buffer
import Yi.Layout
import Yi.Config.Misc
import {-# source #-} Yi.Keymap
import {-# source #-} Yi.Editor
Expand Down Expand Up @@ -57,7 +58,9 @@ data Config = Config {startFrontEnd :: UIBoot,
configKillringAccumulate :: Bool,
-- ^ Set to 'True' for an emacs-like behaviour, where
-- all deleted text is accumulated in a killring.
bufferUpdateHandler :: [([Update] -> BufferM ())]
bufferUpdateHandler :: [([Update] -> BufferM ())],
layoutManagers :: [AnyLayoutManager]
-- ^ List of layout managers for 'cycleLayoutManagersNext'
}

configFundamentalMode :: Config -> AnyMode
Expand Down
2 changes: 2 additions & 0 deletions yi/src/library/Yi/Config/Default.hs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import Yi.Core
import Yi.File
import Yi.IReader (saveAsNewArticle)
import Yi.Mode.IReader (ireaderMode, ireadMode)
import Yi.Layout
import Yi.Modes
#ifdef SCION
import Yi.Scion
Expand Down Expand Up @@ -177,6 +178,7 @@ defaultConfig =
, configRegionStyle = Exclusive
, configInputPreprocess = I.idAutomaton
, bufferUpdateHandler = []
, layoutManagers = [hPairNStack 1, vPairNStack 1, tall, wide]
}

defaultEmacsConfig, defaultVimConfig, defaultCuaConfig :: Config
Expand Down
72 changes: 63 additions & 9 deletions yi/src/library/Yi/Editor.hs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import Yi.Dynamic
import Yi.Event (Event)
import Yi.Interact as I
import Yi.KillRing
import Yi.Layout
import Yi.Prelude
import Yi.Style (StyleName, defaultStyle)
import Yi.Tab
Expand Down Expand Up @@ -117,8 +118,8 @@ emptyEditor = Editor {
,onCloseActions = M.empty
}
where buf = newB 0 (Left "console") (R.fromString "")
win = (dummyWindow (bkey buf)) {wkey = 1, isMini = False}
tab = Tab 2 (PL.singleton win)
win = (dummyWindow (bkey buf)) {wkey = WindowRef 1, isMini = False}
tab = makeTab1 2 win

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

Expand All @@ -128,16 +129,18 @@ runEditor cfg f e = let (a, e',()) = runRWS (fromEditorM f) cfg e in (e',a)
$(nameDeriveAccessors ''Editor (\n -> Just (n ++ "A")))


-- TODO: replace this by accessor
windows :: Editor -> PL.PointedList Window
windows editor = tabWindows . PL.focus $ tabs_ editor
windows e = e ^. windowsA

windowsA :: Accessor Editor (PL.PointedList Window)
windowsA = tabWindowsA . PL.focusA . tabsA
windowsA = tabWindowsA . currentTabA

tabsA :: Accessor Editor (PL.PointedList Tab)
tabsA = tabs_A . fixCurrentBufferA_

currentTabA :: Accessor Editor Tab
currentTabA = PL.focusA . tabsA

dynA :: Initializable a => Accessor Editor a
dynA = dynamicValueA . dynamicA

Expand Down Expand Up @@ -452,7 +455,7 @@ newZeroSizeWindow mini bk ref = Window mini bk [] 0 emptyRegion ref 0

-- | Create a new window onto the given buffer.
newWindowE :: Bool -> BufferRef -> EditorM Window
newWindowE mini bk = newZeroSizeWindow mini bk <$> newRef
newWindowE mini bk = newZeroSizeWindow mini bk . WindowRef <$> newRef

-- | Attach the specified buffer to the current window
switchToBufferE :: BufferRef -> EditorM ()
Expand Down Expand Up @@ -501,6 +504,26 @@ nextWinE = modA windowsA PL.next
prevWinE :: EditorM ()
prevWinE = modA windowsA 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 = modA windowsA (swapFocus (fromJust . PL.move 0))

-- | Moves the focused window to the first window, and moves all other windows down the stack.
pushWinToFirstE :: EditorM ()
pushWinToFirstE = modA windowsA pushToFirst
where
pushToFirst ws = case PL.delete ws of
Nothing -> ws
Just ws' -> PL.insertLeft (ws ^. PL.focusA) (fromJust $ PL.move 0 ws')

-- | Swap focused window with the next one
moveWinNextE :: EditorM ()
moveWinNextE = modA windowsA (swapFocus PL.next)

-- | Swap focused window with the previous one
moveWinPrevE :: EditorM ()
moveWinPrevE = modA windowsA (swapFocus 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.
Expand Down Expand Up @@ -531,7 +554,7 @@ findWindowWith k e =
windowsOnBufferE :: BufferRef -> EditorM [Window]
windowsOnBufferE k = do
ts <- getA tabsA
return $ concatMap (concatMap (\win -> if (bufkey win == k) then [win] else []) . tabWindows) ts
return $ concatMap (concatMap (\win -> if (bufkey win == k) then [win] else []) . (^. tabWindowsA)) ts

-- | bring the editor focus the window with the given key.
--
Expand All @@ -546,7 +569,7 @@ focusWindowE k = do
check r@(True, _) _win = r

searchWindowSet (False, tabIndex, _) ws =
case foldl check (False, 0) (tabWindows ws) of
case foldl check (False, 0) (ws ^. tabWindowsA) of
(True, winIndex) -> (True, tabIndex, winIndex)
(False, _) -> (False, tabIndex + 1, 0)
searchWindowSet r@(True, _, _) _ws = r
Expand All @@ -565,6 +588,33 @@ splitE = do
w <- newWindowE False b
modA windowsA (PL.insertRight w)

-- | Cycle to the next layout manager, or the first one if the current one is nonstandard.
layoutManagersNextE :: EditorM ()
layoutManagersNextE = withLMStack PL.next

-- | Cycle to the previous layout manager, or the first one if the current one is nonstandard.
layoutManagersPreviousE :: EditorM ()
layoutManagersPreviousE = withLMStack PL.previous

-- | Helper function for 'layoutManagersNext' and 'layoutManagersPrevious'
withLMStack :: (PL.PointedList AnyLayoutManager -> PL.PointedList AnyLayoutManager) -> EditorM ()
withLMStack f = askCfg >>= \cfg -> modA (tabLayoutManagerA . currentTabA) (go (layoutManagers cfg))
where
go [] lm = lm
go lms lm =
case findPL (layoutManagerSameType lm) lms of
Nothing -> head lms
Just lmsPL -> f lmsPL ^. PL.focusA

-- | Next variant of the current layout manager, as given by 'nextVariant'
layoutManagerNextVariantE :: EditorM ()
layoutManagerNextVariantE = modA (tabLayoutManagerA . currentTabA) nextVariant

-- | Previous variant of the current layout manager, as given by 'previousVariant'
layoutManagerPreviousVariantE :: EditorM ()
layoutManagerPreviousVariantE = modA (tabLayoutManagerA . currentTabA) previousVariant


-- | Enlarge the current window
enlargeWinE :: EditorM ()
enlargeWinE = error "enlargeWinE: not implemented"
Expand All @@ -573,13 +623,17 @@ enlargeWinE = error "enlargeWinE: not implemented"
shrinkWinE :: EditorM ()
shrinkWinE = error "shrinkWinE: not implemented"

-- | Sets the given divider position on the current tab
setDividerPosE :: DividerRef -> DividerPosition -> EditorM ()
setDividerPosE ref pos = putA (tabDividerPositionA ref . currentTabA) pos

-- | Creates a new tab containing a window that views the current buffer.
newTabE :: EditorM ()
newTabE = do
bk <- gets currentBuffer
win <- newWindowE False bk
ref <- newRef
modA tabsA (PL.insertRight (Tab ref (PL.singleton win)))
modA tabsA (PL.insertRight (makeTab1 ref win))

-- | Moves to the next tab in the round robin set of tabs
nextTabE :: EditorM ()
Expand Down
13 changes: 13 additions & 0 deletions yi/src/library/Yi/Keymap/Emacs.hs
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,19 @@ emacsKeys univArg =

-- All the keybindings of the form "C-M-c" where 'c' is some character
, ( ctrl $ metaCh 'w') ?>>! appendNextKillE
, ( ctrl $ metaCh ' ') ?>>! layoutManagersNextE
, ( ctrl $ metaCh ',') ?>>! layoutManagerNextVariantE
, ( ctrl $ metaCh '.') ?>>! layoutManagerPreviousVariantE
, ( ctrl $ metaCh 'j') ?>>! nextWinE
, ( ctrl $ metaCh 'k') ?>>! prevWinE
, ( ctrl $ meta $ spec KEnter) ?>>! swapWinWithFirstE


-- All the keybindings of the form "S-C-M-c" where 'c' is some key
, ( shift $ ctrl $ metaCh 'j') ?>>! moveWinNextE
, ( shift $ ctrl $ metaCh 'k') ?>>! moveWinPrevE
, ( shift $ ctrl $ meta $ spec KEnter) ?>>! pushWinToFirstE
, ( Event (KASCII ' ') [MShift,MCtrl,MMeta]) ?>>! layoutManagersPreviousE

-- All the key-bindings which are preceded by a 'C-x'
, ctrlCh 'x' ?>> ctrlX
Expand Down
Loading

0 comments on commit fa26b18

Please sign in to comment.