module Yi.Buffer.Region
(
module Yi.Region
, swapRegionsB
, deleteRegionB
, replaceRegionB
, readRegionB
, mapRegionB
, modifyRegionB
, winRegionB
, inclusiveRegionB
, blockifyRegion
, joinLinesB
, concatLinesB
)
where
import Control.Applicative
import Control.Monad
import Data.Char (isSpace)
import Data.Monoid (mconcat)
import Data.List (sort)
import Yi.Buffer.Misc
import Yi.Region
import Yi.Rope (YiString)
import qualified Yi.Rope as R
import Yi.String (overInit)
import Yi.Utils
import Yi.Window (winRegion)
winRegionB :: BufferM Region
winRegionB = askWindow winRegion
deleteRegionB :: Region -> BufferM ()
deleteRegionB r = deleteNAt (regionDirection r) (fromIntegral (regionEnd r ~- regionStart r)) (regionStart r)
readRegionB :: Region -> BufferM YiString
readRegionB r = nelemsB (fromIntegral (regionEnd r i)) i
where i = regionStart r
replaceRegionB :: Region -> YiString -> BufferM ()
replaceRegionB r s = do
deleteRegionB r
insertNAt s $ regionStart r
mapRegionB :: Region -> (Char -> Char) -> BufferM ()
mapRegionB r f = do
text <- readRegionB r
replaceRegionB r (R.map f text)
swapRegionsB :: Region -> Region -> BufferM ()
swapRegionsB r r'
| regionStart r > regionStart r' = swapRegionsB r' r
| otherwise = do w0 <- readRegionB r
w1 <- readRegionB r'
replaceRegionB r' w0
replaceRegionB r w1
modifyRegionB :: (R.YiString -> R.YiString)
-> Region
-> BufferM ()
modifyRegionB f region = f <$> readRegionB region >>= replaceRegionB region
inclusiveRegionB :: Region -> BufferM Region
inclusiveRegionB r =
if regionStart r <= regionEnd r
then mkRegion (regionStart r) <$> pointAfterCursorB (regionEnd r)
else mkRegion <$> pointAfterCursorB (regionStart r) <*> pure (regionEnd r)
blockifyRegion :: Region -> BufferM [Region]
blockifyRegion r = savingPointB $ do
[lowCol, highCol] <- sort <$> mapM colOf [regionStart r, regionEnd r]
startLine <- lineOf $ regionStart r
endLine <- lineOf $ regionEnd r
when (startLine > endLine) $ fail "blockifyRegion: impossible"
mapM (\line -> mkRegion <$> pointOfLineColB line lowCol
<*> pointOfLineColB line (1 + highCol))
[startLine..endLine]
joinLinesB :: Region -> BufferM ()
joinLinesB = savingPointB . modifyRegionB g'
where
g' = overInit $ mconcat . pad . R.lines
pad :: [R.YiString] -> [R.YiString]
pad [] = []
pad (x:xs) = x : fmap (skip (R.cons ' ' . R.dropWhile isSpace)) xs
skip g x = if R.null x then x else g x
concatLinesB :: Region -> BufferM ()
concatLinesB = savingPointB . modifyRegionB (overInit $ R.filter (/= '\n'))