packages feed

zwirn-0.2.3.1: app/zwirnmill/Editor/Cursor.hs

module Editor.Cursor where

import Data.Char (isSpace)
import Data.Text (Text)
import qualified Data.Text.Zipper as Z
import Editor.Core
import Editor.Util

moveCursorPos :: (Int, Int) -> EditorState -> EditorState
moveCursorPos p = withZipper (Z.moveCursorClosest p) . clearSelection

moveCursorUp :: EditorState -> EditorState
moveCursorUp = withZipper Z.moveUp . clearSelection

moveCursorDown :: EditorState -> EditorState
moveCursorDown = withZipper Z.moveDown . clearSelection

moveCursorLeft :: EditorState -> EditorState
moveCursorLeft = withZipper Z.moveLeft . clearSelection

moveCursorRight :: EditorState -> EditorState
moveCursorRight = withZipper Z.moveRight . clearSelection

moveCursorLineStart :: EditorState -> EditorState
moveCursorLineStart = withZipper Z.gotoBOL . clearSelection

moveCursorLineEnd :: EditorState -> EditorState
moveCursorLineEnd = withZipper Z.gotoEOL . clearSelection

moveCursorFileStart :: EditorState -> EditorState
moveCursorFileStart = withZipper Z.gotoBOF . clearSelection

moveCursorFileEnd :: EditorState -> EditorState
moveCursorFileEnd = withZipper Z.gotoEOF . clearSelection

moveCursorWordLeft :: EditorState -> EditorState
moveCursorWordLeft = withZipper moveWordStartLeft

moveCursorWordRight :: EditorState -> EditorState
moveCursorWordRight = withZipper moveWordStartRight

moveWordStartLeft :: Z.TextZipper Text -> Z.TextZipper Text
moveWordStartLeft tz = findWordStart (findWordLeft $ Z.moveLeft tz)
  where
    findWordLeft x = case Z.currentChar x of
      Nothing -> x
      Just c ->
        if isSpace c
          then
            let next = Z.moveLeft x
             in if Z.cursorPosition next == Z.cursorPosition x
                  then x
                  else findWordLeft next
          else x

    findWordStart x =
      let prev = Z.moveLeft x
       in if Z.cursorPosition prev == Z.cursorPosition x
            then x
            else case Z.currentChar prev of
              Nothing -> x
              Just c ->
                if not (isSpace c)
                  then findWordStart prev
                  else x

moveWordStartRight :: Z.TextZipper Text -> Z.TextZipper Text
moveWordStartRight tz = findWordStart (findWordRight $ Z.moveRight tz)
  where
    findWordRight x = case Z.currentChar x of
      Nothing ->
        let next = Z.moveRight x
         in if Z.cursorPosition next == Z.cursorPosition x
              then x
              else findWordRight next
      Just c ->
        if isSpace c
          then
            let next = Z.moveRight x
             in if Z.cursorPosition next == Z.cursorPosition x
                  then x
                  else findWordRight next
          else x

    findWordStart x =
      let prev = Z.moveRight x
       in if Z.cursorPosition prev == Z.cursorPosition x
            then x
            else case Z.currentChar prev of
              Nothing -> x
              Just c ->
                if not (isSpace c)
                  then findWordStart prev
                  else x