rasa-ext-cursors (empty) → 0.1.0.0
raw patch · 6 files changed
+251/−0 lines, 6 filesdep +basedep +data-defaultdep +lenssetup-changed
Dependencies added: base, data-default, lens, mtl, rasa, rasa-ext-style, text, text-lens, yi-rope
Files
- LICENSE +21/−0
- Setup.hs +2/−0
- rasa-ext-cursors.cabal +39/−0
- src/Rasa/Ext/Cursors.hs +31/−0
- src/Rasa/Ext/Cursors/Actions.hs +79/−0
- src/Rasa/Ext/Cursors/Base.hs +79/−0
+ LICENSE view
@@ -0,0 +1,21 @@+The MIT License++Copyright (c) 2016 Chris Penner++Permission is hereby granted, free of charge, to any person obtaining a copy+of this software and associated documentation files (the "Software"), to deal+in the Software without restriction, including without limitation the rights+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell+copies of the Software, and to permit persons to whom the Software is+furnished to do so, subject to the following conditions:++The above copyright notice and this permission notice shall be included in+all copies or substantial portions of the Software.++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN+THE SOFTWARE.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ rasa-ext-cursors.cabal view
@@ -0,0 +1,39 @@+name: rasa-ext-cursors+version: 0.1.0.0+synopsis: Rasa Ext adding cursor(s)+description: Rasa Ext adding cursor(s)+homepage: https://github.com/ChrisPenner/rasa/+license: MIT+license-file: LICENSE+author: Chris Penner+maintainer: christopher.penner@gmail.com+copyright: 2016 Chris Penner+category: Extension+build-type: Simple+-- extra-source-files:+cabal-version: >=1.10++library+ hs-source-dirs: src+ exposed-modules: Rasa.Ext.Cursors+ other-modules:+ Rasa.Ext.Cursors.Actions+ Rasa.Ext.Cursors.Base+ build-depends: base >= 4.7 && < 5+ , rasa+ , rasa-ext-style+ , text-lens+ , lens+ , mtl+ , text+ , yi-rope+ , data-default+ default-language: Haskell2010++ default-extensions:++ ghc-options: -Wall++source-repository head+ type: git+ location: https://github.com/ChrisPenner/rasa
+ src/Rasa/Ext/Cursors.hs view
@@ -0,0 +1,31 @@+module Rasa.Ext.Cursors+ (+ -- * Main+ cursors+ -- * Actions+ , delete+ , insertText+ , findNext+ , findNextFrom+ , findPrev+ , findPrevFrom++ -- * Working with Cursor Ranges+ , eachRange+ , addRange+ , ranges+ , rangeDo+ , rangeDo_+ , overRanges+ , moveRangesByN+ , moveRangesByC+ ) where++import Rasa.Ext.Cursors.Base+import Rasa.Ext.Cursors.Actions++import Rasa.Ext++-- | Registers hooks for the extension. The user should add this to their config.+cursors :: Scheduler ()+cursors = beforeRender $ bufDo displayRange
+ src/Rasa/Ext/Cursors/Actions.hs view
@@ -0,0 +1,79 @@+module Rasa.Ext.Cursors.Actions+ ( delete+ , insertText+ , findNext+ , findPrev+ , findNextFrom+ , findPrevFrom+ , moveRangesByN+ , moveRangesByC+ ) where++import qualified Data.Text as T++import Control.Lens+import Control.Lens.Text+import Rasa.Ext+import Rasa.Ext.Cursors.Base++-- | Moves all Ranges that are on the same END row as the given range by the coord's row and column+-- This is used to adjust cursors when things have been inserted/deleted before them in the row.+moveSameLineRangesBy :: Range -> Coord -> BufAction ()+moveSameLineRangesBy (Range _ (Coord endRow endCol)) amt = do+ let moveInLine r@(Range (Coord startRow startCol) _) = return $+ if endRow == startRow && startCol > endCol+ then moveRange amt r+ else r+ ranges <~ rangeDo moveInLine++-- | Delete the text of all ranges in a buffer+delete :: BufAction ()+delete = rangeDo_ $ \r -> do+ deleteRange r+ moveSameLineRangesBy r (negate $ sizeOfR r)++-- | Insert text at the beginning of all ranges in the buffer.+insertText :: T.Text -> BufAction ()+insertText txt = rangeDo_ $ \r@(Range s _) -> do+ insertAt s txt+ moveSameLineRangesBy r (Coord 0 (T.length txt))++-- | Move all ranges to the location of the next occurence of the given text.+findNext :: T.Text -> BufAction ()+findNext pat = do+ res <- rangeDo $ \(Range _ e) -> do+ off <- findNextFrom pat e+ let end = moveCursorByN 1 off+ return $ Range off end+ ranges .= res++-- | Get the 'Coord' of the next occurence of the given text after the given 'Coord'+findNextFrom :: T.Text -> Coord -> BufAction Coord+findNextFrom pat c = do+ distance <- use (rope . afterC c . asText . tillNext pat . from asText . to sizeOf)+ return (distance + c)++-- | Move all ranges to the location of the previous occurence of the given text.+findPrev :: T.Text -> BufAction ()+findPrev pat = do+ res <- rangeDo $ \(Range s _) -> do+ off <- findPrevFrom pat s+ let end = moveCursorByN 1 off+ return $ Range off end+ ranges .= res++-- | Get the 'Coord' of the previous occurence of the given text before the given 'Coord'+findPrevFrom :: T.Text -> Coord -> BufAction Coord+findPrevFrom pat c = do+ txt <- use rope+ let Offset o = c^.from (asCoord txt)+ distance <- use (text . before o . tillPrev pat . to T.length .to negate)+ return ((Offset $ distance + o)^.asCoord txt)++-- | Move all ranges by the given number of columns+moveRangesByN :: Int -> BufAction ()+moveRangesByN n = overRanges $ return . moveRangeByN n++-- | Move all ranges by the given number of rows and columns+moveRangesByC :: Coord -> BufAction ()+moveRangesByC c = overRanges $ return . moveRange c
+ src/Rasa/Ext/Cursors/Base.hs view
@@ -0,0 +1,79 @@+{-# LANGUAGE TemplateHaskell, OverloadedStrings, Rank2Types #-}++module Rasa.Ext.Cursors.Base+ ( rangeDo+ , rangeDo_+ , ranges+ , displayRange+ , eachRange+ , overRanges+ , addRange+ ) where+++import Rasa.Ext+import Rasa.Ext.Style++import Control.Monad.State+import Control.Lens+import Data.Typeable+import Data.List+import Data.Default+import qualified Yi.Rope as Y++-- | Stores the cursor ranges in each buffer.+data Cursors = Cursors+ { _cursors :: [Range]+ } deriving (Typeable, Show)++makeLenses ''Cursors++instance Default Cursors where+ def = Cursors {+ _cursors=[Range (Coord 0 0) (Coord 0 1)]+}++-- | Adjusts input ranges to contain at least one character.+ensureSize :: Range -> Range+ensureSize r@(Range s e)+ | s == e = Range s (moveCursorByN 1 e)+ | otherwise = r++-- | Sorts Ranges, removes duplicates, ensures they contain at least one character+-- and restricts them to fit within the given text.+cleanRanges :: Y.YiString -> [Range] -> [Range]+cleanRanges txt = fmap (ensureSize . clampRange txt) . reverse . nub . sort++-- | A lens over all the stored cursor ranges for a buffer+ranges :: Lens' Buffer [Range]+ranges = lens getter setter+ where getter buf = buf^.bufExt.cursors+ setter buf new = let txt = buf^.rope+ in buf & bufExt.cursors .~ cleanRanges txt new++-- | A Traversal over each Range for the given buffer.+eachRange :: Traversal' Buffer Range+eachRange = ranges.traverse++-- | Sequences actions over each range as a 'BufAction'+rangeDo :: (Range -> BufAction a) -> BufAction [a]+rangeDo f = use ranges >>= mapM f++-- | 'rangeDo' with void return.+rangeDo_ :: (Range -> BufAction a) -> BufAction ()+rangeDo_ = void . rangeDo++-- | Sequences actions over each range and replaces each range with its result.+overRanges :: (Range -> BufAction Range) -> BufAction ()+overRanges f = ranges <~ rangeDo f++-- | Adds a new range to the list of ranges.+addRange :: Range -> BufAction ()+addRange r = ranges <>= [r]++-- | Sets style attributes to show a given range.+displayRange :: BufAction ()+displayRange = rangeDo_ setStyle+ where+ setStyle :: Range -> BufAction ()+ setStyle r = addStyle r (flair ReverseVideo)