    {-# LANGUAGE OverloadedStrings #-}
    {-# OPTIONS_HADDOCK show-extensions #-}

    -- |
    -- Module      :  Yi.Keymap.Vim.Search
    -- License     :  GPL-2
    -- Maintainer  :  yi-devel@googlegroups.com
    -- Stability   :  experimental
    -- Portability :  portable

    module Yi.Keymap.Vim.Search (doVimSearch, continueVimSearch) where

    import Data.Maybe         (listToMaybe)
    import Data.Text          ()
    import Yi.Buffer
    import Yi.Editor          (EditorM, printMsg, withCurrentBuffer)
    import Yi.Search          (SearchOption, getRegexE, searchInit)

    doVimSearch :: Maybe String -> [SearchOption] -> Direction -> EditorM ()
    doVimSearch :: Maybe String -> [SearchOption] -> Direction -> EditorM ()
    doVimSearch Maybe String
    Nothing [SearchOption]
    _ Direction
    dir = do
        mbRegex <- EditorM (Maybe SearchExp)
    getRegexE
        case mbRegex of
            Just SearchExp
    regex -> BufferM () -> EditorM ()
    forall (m :: * -> *) a. MonadEditor m => BufferM a -> m a
    withCurrentBuffer (BufferM () -> EditorM ()) -> BufferM () -> EditorM ()
    forall a b. (a -> b) -> a -> b
    $ (SearchExp, Direction) -> BufferM ()
    continueVimSearch (SearchExp
    regex, Direction
    dir)
            Maybe SearchExp
    Nothing -> Text -> EditorM ()
    forall (m :: * -> *). MonadEditor m => Text -> m ()
    printMsg Text
    "No previous search pattern"
    doVimSearch (Just String
    needle) [SearchOption]
    opts Direction
    dir =
        String
    -> Direction -> [SearchOption] -> EditorM (SearchExp, Direction)
    searchInit String
    needle Direction
    dir [SearchOption]
    opts EditorM (SearchExp, Direction)
    -> ((SearchExp, Direction) -> EditorM ()) -> EditorM ()
    forall a b. EditorM a -> (a -> EditorM b) -> EditorM b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= BufferM () -> EditorM ()
    forall (m :: * -> *) a. MonadEditor m => BufferM a -> m a
    withCurrentBuffer (BufferM () -> EditorM ())
    -> ((SearchExp, Direction) -> BufferM ())
    -> (SearchExp, Direction)
    -> EditorM ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (SearchExp, Direction) -> BufferM ()
    continueVimSearch

    continueVimSearch :: (SearchExp, Direction) -> BufferM ()
    continueVimSearch :: (SearchExp, Direction) -> BufferM ()
    continueVimSearch (SearchExp
    searchExp, Direction
    dir) = do
        mp <- BufferM (Maybe Region) -> BufferM (Maybe Region)
    forall a. BufferM a -> BufferM a
    savingPointB (BufferM (Maybe Region) -> BufferM (Maybe Region))
    -> BufferM (Maybe Region) -> BufferM (Maybe Region)
    forall a b. (a -> b) -> a -> b
    $ do
            TextUnit -> Direction -> BufferM ()
    moveB TextUnit
    Character Direction
    dir  -- start immed. after cursor
            rs <- Direction -> SearchExp -> BufferM [Region]
    regexB Direction
    dir SearchExp
    searchExp
            moveB Document (reverseDir dir) -- wrap around
            ls <- regexB dir searchExp
            return $ listToMaybe $ rs ++ ls
        -- regionFirst doesn't work right here, because something inside
        -- Buffer.Implementation.regexRegionBI breaks Region invariant and
        -- may return Region (Forward, A, B) where A > B
        -- TODO: investigate
        maybe (return ()) (moveTo . regionFirst') mp

    regionFirst' :: Region -> Point
    regionFirst' :: Region -> Point
    regionFirst' Region
    r = Int -> Point
    Point (Int -> Point) -> Int -> Point
    forall a b. (a -> b) -> a -> b
    $ Int -> Int -> Int
    forall a. Ord a => a -> a -> a
    min Int
    a Int
    b
        where a :: Int
    a = Point -> Int
    fromPoint (Point -> Int) -> Point -> Int
    forall a b. (a -> b) -> a -> b
    $ Region -> Point
    regionStart Region
    r
              b :: Int
    b = Point -> Int
    fromPoint (Point -> Int) -> Point -> Int
    forall a b. (a -> b) -> a -> b
    $ Region -> Point
    regionEnd Region
    r