yi-0.4.6: Yi/Rectangle.hs
-- Copyright (C) 2008 JP Bernardy
module Yi.Rectangle where
import Yi.Prelude
import Prelude (subtract)
import Data.List (splitAt, unzip)
import Control.Applicative
import Data.Char
import Data.List (sort)
import Yi.Buffer
import Yi.Buffer.HighLevel
import Yi.Buffer.Normal
import Yi.Buffer.Region
import Yi.Editor
import Yi.String
-- | Get the selected region as a rectangle.
-- Returns the region extended to lines, plus the start and end columns of the rectangle.
getRectangle :: BufferM (Region, Int, Int)
getRectangle = do
r <- getSelectRegionB
extR <- unitWiseRegion Line r
[lowCol,highCol] <- sort <$> mapM colOf [regionStart r, regionEnd r]
return (extR, lowCol, highCol)
multiSplit :: [Int] -> [a] -> [[a]]
multiSplit [] l = [l]
multiSplit (x:xs) l = left : multiSplit (fmap (subtract x) xs) right
where (left,right) = splitAt x l
onRectangle :: (Int -> Int -> String -> String) -> BufferM ()
onRectangle f = do
(reg, l, r) <- getRectangle
modifyRegionB (mapLines (f l r)) reg
openRectangle :: BufferM ()
openRectangle = onRectangle openLine
where openLine l r line = left ++ replicate (r-l) ' ' ++ right
where (left,right) = splitAt l line
stringRectangle :: String -> BufferM ()
stringRectangle inserted = onRectangle stringLine
where stringLine l r line = left ++ inserted ++ right
where [left,_,right] = multiSplit [l,r] line
killRectangle :: EditorM ()
killRectangle = do
cutted <- withBuffer0 $ do
(reg, l, r) <- getRectangle
text <- readRegionB reg
let (cutted, rest) = unzip $ fmap cut $ lines' text
cut line = let [left,mid,right] = multiSplit [l,r] line in (mid, left ++ right)
replaceRegionB reg (unlines' rest)
return cutted
setRegE (unlines' cutted)
yankRectangle :: EditorM ()
yankRectangle = do
text <- lines' <$> getRegE
withBuffer0 $ do
forM_ text $ \t -> do
savingPointB $ insertN t
lineDown