{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE OverloadedStrings #-}
{-# OPTIONS_HADDOCK show-extensions #-}
module Yi.Search (
setRegexE,
resetRegexE,
getRegexE,
SearchMatch,
SearchResult(..),
SearchOption(..),
doSearch,
searchInit,
continueSearch,
makeSimpleSearch,
searchReplaceRegionB,
searchReplaceSelectionB,
replaceString,
searchAndRepRegion,
searchAndRepRegion0,
searchAndRepUnit,
isearchInitE,
isearchIsEmpty,
isearchAddE,
isearchPrevE,
isearchNextE,
isearchWordE,
isearchHistory,
isearchDelE,
isearchCancelE,
isearchFinishE,
isearchCancelWithE,
isearchFinishWithE,
qrNext,
qrReplaceAll,
qrReplaceOne,
qrFinish
) where
import Lens.Micro.Platform ((.=))
import Control.Monad (void, when)
import Data.Binary (Binary, get, put)
import Data.Char (isAlpha, isUpper)
import Data.Default (Default, def)
import Data.Maybe (listToMaybe)
import Data.Monoid ((<>))
import qualified Data.Text as T (Text, any, break, empty, length, null, takeWhile, unpack)
import qualified Data.Text.Encoding as E (decodeUtf8, encodeUtf8)
import Data.Typeable (Typeable)
import Yi.Buffer
import Yi.Editor
import Yi.History (historyFinishGen, historyMoveGen, historyStartGen)
import Yi.Regex (SearchOption(..), makeSearchOptsM, emptyRegex, SearchExp(..))
import qualified Yi.Rope as R (YiString, null, toString, toText)
import Yi.Search.Internal (getRegexE, resetRegexE, setRegexE)
import Yi.String (showT)
import Yi.Types (YiVariable)
import Yi.Utils (fst3)
import Yi.Window (Window)
type SearchMatch = Region
data SearchResult = PatternFound
| PatternNotFound
| SearchWrapped
deriving SearchResult -> SearchResult -> Bool
(SearchResult -> SearchResult -> Bool)
-> (SearchResult -> SearchResult -> Bool) -> Eq SearchResult
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: SearchResult -> SearchResult -> Bool
$c/= :: SearchResult -> SearchResult -> Bool
== :: SearchResult -> SearchResult -> Bool
$c== :: SearchResult -> SearchResult -> Bool
Eq
doSearch :: Maybe String
-> [SearchOption]
-> Direction
-> EditorM SearchResult
doSearch :: Maybe String -> [SearchOption] -> Direction -> EditorM SearchResult
doSearch (Just String
re) [SearchOption]
fs Direction
d = String
-> Direction -> [SearchOption] -> EditorM (SearchExp, Direction)
searchInit String
re Direction
d [SearchOption]
fs EditorM (SearchExp, Direction)
-> ((SearchExp, Direction) -> EditorM SearchResult)
-> EditorM SearchResult
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= BufferM SearchResult -> EditorM SearchResult
forall (m :: * -> *) a. MonadEditor m => BufferM a -> m a
withCurrentBuffer (BufferM SearchResult -> EditorM SearchResult)
-> ((SearchExp, Direction) -> BufferM SearchResult)
-> (SearchExp, Direction)
-> EditorM SearchResult
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (SearchExp, Direction) -> BufferM SearchResult
continueSearch
doSearch Maybe String
Nothing [SearchOption]
_ Direction
d = do
Maybe SearchExp
mre <- EditorM (Maybe SearchExp)
getRegexE
case Maybe SearchExp
mre of
Maybe SearchExp
Nothing -> String -> EditorM SearchResult
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"No previous search pattern"
Just SearchExp
r -> BufferM SearchResult -> EditorM SearchResult
forall (m :: * -> *) a. MonadEditor m => BufferM a -> m a
withCurrentBuffer ((SearchExp, Direction) -> BufferM SearchResult
continueSearch (SearchExp
r,Direction
d))
searchInit :: String -> Direction -> [SearchOption] -> EditorM (SearchExp, Direction)
searchInit :: String
-> Direction -> [SearchOption] -> EditorM (SearchExp, Direction)
searchInit String
re Direction
d [SearchOption]
fs = do
let Right SearchExp
c_re = [SearchOption] -> String -> Either String SearchExp
makeSearchOptsM [SearchOption]
fs String
re
SearchExp -> EditorM ()
setRegexE SearchExp
c_re
(Direction -> Identity Direction) -> Editor -> Identity Editor
Lens' Editor Direction
searchDirectionA ((Direction -> Identity Direction) -> Editor -> Identity Editor)
-> Direction -> EditorM ()
forall s (m :: * -> *) a b.
MonadState s m =>
ASetter s s a b -> b -> m ()
.= Direction
d
(SearchExp, Direction) -> EditorM (SearchExp, Direction)
forall (m :: * -> *) a. Monad m => a -> m a
return (SearchExp
c_re,Direction
d)
continueSearch :: (SearchExp, Direction) -> BufferM SearchResult
continueSearch :: (SearchExp, Direction) -> BufferM SearchResult
continueSearch (SearchExp
c_re, Direction
dir) = do
Maybe (Either Region Region)
mp <- BufferM (Maybe (Either Region Region))
-> BufferM (Maybe (Either Region Region))
forall a. BufferM a -> BufferM a
savingPointB (BufferM (Maybe (Either Region Region))
-> BufferM (Maybe (Either Region Region)))
-> BufferM (Maybe (Either Region Region))
-> BufferM (Maybe (Either Region Region))
forall a b. (a -> b) -> a -> b
$ do
TextUnit -> Direction -> BufferM ()
moveB TextUnit
Character Direction
dir
[Region]
rs <- Direction -> SearchExp -> BufferM [Region]
regexB Direction
dir SearchExp
c_re
TextUnit -> Direction -> BufferM ()
moveB TextUnit
Document (Direction -> Direction
reverseDir Direction
dir)
[Region]
ls <- Direction -> SearchExp -> BufferM [Region]
regexB Direction
dir SearchExp
c_re
Maybe (Either Region Region)
-> BufferM (Maybe (Either Region Region))
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe (Either Region Region)
-> BufferM (Maybe (Either Region Region)))
-> Maybe (Either Region Region)
-> BufferM (Maybe (Either Region Region))
forall a b. (a -> b) -> a -> b
$ [Either Region Region] -> Maybe (Either Region Region)
forall a. [a] -> Maybe a
listToMaybe ([Either Region Region] -> Maybe (Either Region Region))
-> [Either Region Region] -> Maybe (Either Region Region)
forall a b. (a -> b) -> a -> b
$ (Region -> Either Region Region)
-> [Region] -> [Either Region Region]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Region -> Either Region Region
forall a b. b -> Either a b
Right [Region]
rs [Either Region Region]
-> [Either Region Region] -> [Either Region Region]
forall a. [a] -> [a] -> [a]
++ (Region -> Either Region Region)
-> [Region] -> [Either Region Region]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Region -> Either Region Region
forall a b. a -> Either a b
Left [Region]
ls
BufferM ()
-> (Either Region Region -> BufferM ())
-> Maybe (Either Region Region)
-> BufferM ()
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (() -> BufferM ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()) (Point -> BufferM ()
moveTo (Point -> BufferM ())
-> (Either Region Region -> Point)
-> Either Region Region
-> BufferM ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Region -> Point
regionStart (Region -> Point)
-> (Either Region Region -> Region)
-> Either Region Region
-> Point
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Region -> Region)
-> (Region -> Region) -> Either Region Region -> Region
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either Region -> Region
forall a. a -> a
id Region -> Region
forall a. a -> a
id) Maybe (Either Region Region)
mp
SearchResult -> BufferM SearchResult
forall (m :: * -> *) a. Monad m => a -> m a
return (SearchResult -> BufferM SearchResult)
-> SearchResult -> BufferM SearchResult
forall a b. (a -> b) -> a -> b
$ Maybe (Either Region Region) -> SearchResult
forall a b. Maybe (Either a b) -> SearchResult
f Maybe (Either Region Region)
mp
where
f :: Maybe (Either a b) -> SearchResult
f (Just (Right b
_)) = SearchResult
PatternFound
f (Just (Left a
_)) = SearchResult
SearchWrapped
f Maybe (Either a b)
Nothing = SearchResult
PatternNotFound
searchReplaceRegionB :: R.YiString
-> R.YiString
-> Region
-> BufferM Int
searchReplaceRegionB :: YiString -> YiString -> Region -> BufferM Int
searchReplaceRegionB YiString
from YiString
to =
SearchExp -> YiString -> Bool -> Region -> BufferM Int
searchAndRepRegion0 (YiString -> SearchExp
makeSimpleSearch YiString
from) YiString
to Bool
True
searchReplaceSelectionB :: R.YiString
-> R.YiString
-> BufferM Int
searchReplaceSelectionB :: YiString -> YiString -> BufferM Int
searchReplaceSelectionB YiString
from YiString
to =
BufferM Region
getSelectRegionB BufferM Region -> (Region -> BufferM Int) -> BufferM Int
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= YiString -> YiString -> Region -> BufferM Int
searchReplaceRegionB YiString
from YiString
to
replaceString :: R.YiString -> R.YiString -> BufferM Int
replaceString :: YiString -> YiString -> BufferM Int
replaceString YiString
a YiString
b = TextUnit -> BufferM Region
regionOfB TextUnit
Document BufferM Region -> (Region -> BufferM Int) -> BufferM Int
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= YiString -> YiString -> Region -> BufferM Int
searchReplaceRegionB YiString
a YiString
b
searchAndRepRegion0 :: SearchExp -> R.YiString -> Bool -> Region -> BufferM Int
searchAndRepRegion0 :: SearchExp -> YiString -> Bool -> Region -> BufferM Int
searchAndRepRegion0 SearchExp
c_re YiString
str Bool
globally Region
region = do
[Region]
mp <- (if Bool
globally then [Region] -> [Region]
forall a. a -> a
id else Int -> [Region] -> [Region]
forall a. Int -> [a] -> [a]
take Int
1) ([Region] -> [Region]) -> BufferM [Region] -> BufferM [Region]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> SearchExp -> Region -> BufferM [Region]
regexRegionB SearchExp
c_re Region
region
let mp' :: [Region]
mp' = Direction -> [Region] -> [Region]
forall a. Direction -> [a] -> [a]
mayReverse (Direction -> Direction
reverseDir (Direction -> Direction) -> Direction -> Direction
forall a b. (a -> b) -> a -> b
$ Region -> Direction
regionDirection Region
region) [Region]
mp
(Region -> BufferM ()) -> [Region] -> BufferM ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ (Region -> YiString -> BufferM ()
`replaceRegionB` YiString
str) [Region]
mp'
Int -> BufferM Int
forall (m :: * -> *) a. Monad m => a -> m a
return ([Region] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Region]
mp)
searchAndRepRegion :: R.YiString -> R.YiString -> Bool -> Region -> EditorM Bool
searchAndRepRegion :: YiString -> YiString -> Bool -> Region -> EditorM Bool
searchAndRepRegion YiString
s YiString
str Bool
globally Region
region = case YiString -> Bool
R.null YiString
s of
Bool
False -> Bool -> EditorM Bool
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
False
Bool
True -> do
let c_re :: SearchExp
c_re = YiString -> SearchExp
makeSimpleSearch YiString
s
SearchExp -> EditorM ()
setRegexE SearchExp
c_re
(Direction -> Identity Direction) -> Editor -> Identity Editor
Lens' Editor Direction
searchDirectionA ((Direction -> Identity Direction) -> Editor -> Identity Editor)
-> Direction -> EditorM ()
forall s (m :: * -> *) a b.
MonadState s m =>
ASetter s s a b -> b -> m ()
.= Direction
Forward
BufferM Bool -> EditorM Bool
forall (m :: * -> *) a. MonadEditor m => BufferM a -> m a
withCurrentBuffer (BufferM Bool -> EditorM Bool) -> BufferM Bool -> EditorM Bool
forall a b. (a -> b) -> a -> b
$ (Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= Int
0) (Int -> Bool) -> BufferM Int -> BufferM Bool
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> SearchExp -> YiString -> Bool -> Region -> BufferM Int
searchAndRepRegion0 SearchExp
c_re YiString
str Bool
globally Region
region
searchAndRepUnit :: R.YiString -> R.YiString -> Bool -> TextUnit -> EditorM Bool
searchAndRepUnit :: YiString -> YiString -> Bool -> TextUnit -> EditorM Bool
searchAndRepUnit YiString
re YiString
str Bool
g TextUnit
unit =
BufferM Region -> EditorM Region
forall (m :: * -> *) a. MonadEditor m => BufferM a -> m a
withCurrentBuffer (TextUnit -> BufferM Region
regionOfB TextUnit
unit) EditorM Region -> (Region -> EditorM Bool) -> EditorM Bool
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= YiString -> YiString -> Bool -> Region -> EditorM Bool
searchAndRepRegion YiString
re YiString
str Bool
g
newtype Isearch = Isearch [(T.Text, Region, Direction)]
deriving (Typeable, Int -> Isearch -> ShowS
[Isearch] -> ShowS
Isearch -> String
(Int -> Isearch -> ShowS)
-> (Isearch -> String) -> ([Isearch] -> ShowS) -> Show Isearch
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Isearch] -> ShowS
$cshowList :: [Isearch] -> ShowS
show :: Isearch -> String
$cshow :: Isearch -> String
showsPrec :: Int -> Isearch -> ShowS
$cshowsPrec :: Int -> Isearch -> ShowS
Show)
instance Binary Isearch where
put :: Isearch -> Put
put (Isearch [(Text, Region, Direction)]
ts) = [(ByteString, Region, Direction)] -> Put
forall t. Binary t => t -> Put
put ((Text -> ByteString)
-> [(Text, Region, Direction)] -> [(ByteString, Region, Direction)]
forall a d b c. (a -> d) -> [(a, b, c)] -> [(d, b, c)]
map3 Text -> ByteString
E.encodeUtf8 [(Text, Region, Direction)]
ts)
get :: Get Isearch
get = [(Text, Region, Direction)] -> Isearch
Isearch ([(Text, Region, Direction)] -> Isearch)
-> ([(ByteString, Region, Direction)]
-> [(Text, Region, Direction)])
-> [(ByteString, Region, Direction)]
-> Isearch
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (ByteString -> Text)
-> [(ByteString, Region, Direction)] -> [(Text, Region, Direction)]
forall a d b c. (a -> d) -> [(a, b, c)] -> [(d, b, c)]
map3 ByteString -> Text
E.decodeUtf8 ([(ByteString, Region, Direction)] -> Isearch)
-> Get [(ByteString, Region, Direction)] -> Get Isearch
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Get [(ByteString, Region, Direction)]
forall t. Binary t => Get t
get
map3 :: (a -> d) -> [(a, b, c)] -> [(d, b, c)]
map3 :: (a -> d) -> [(a, b, c)] -> [(d, b, c)]
map3 a -> d
_ [] = []
map3 a -> d
f ((a
a, b
b, c
c):[(a, b, c)]
xs) = (a -> d
f a
a, b
b, c
c) (d, b, c) -> [(d, b, c)] -> [(d, b, c)]
forall a. a -> [a] -> [a]
: (a -> d) -> [(a, b, c)] -> [(d, b, c)]
forall a d b c. (a -> d) -> [(a, b, c)] -> [(d, b, c)]
map3 a -> d
f [(a, b, c)]
xs
instance Default Isearch where
def :: Isearch
def = [(Text, Region, Direction)] -> Isearch
Isearch []
instance YiVariable Isearch
isearchInitE :: Direction -> EditorM ()
isearchInitE :: Direction -> EditorM ()
isearchInitE Direction
dir = do
Text -> EditorM ()
historyStartGen Text
iSearch
Point
p <- BufferM Point -> EditorM Point
forall (m :: * -> *) a. MonadEditor m => BufferM a -> m a
withCurrentBuffer BufferM Point
pointB
Isearch -> EditorM ()
forall (m :: * -> *) a.
(MonadEditor m, YiVariable a, Functor m) =>
a -> m ()
putEditorDyn ([(Text, Region, Direction)] -> Isearch
Isearch [(Text
T.empty ,Point -> Point -> Region
mkRegion Point
p Point
p, Direction
dir)])
Text -> EditorM ()
forall (m :: * -> *). MonadEditor m => Text -> m ()
printMsg Text
"I-search: "
isearchIsEmpty :: EditorM Bool
isearchIsEmpty :: EditorM Bool
isearchIsEmpty = do
Isearch [(Text, Region, Direction)]
s <- EditorM Isearch
forall (m :: * -> *) a.
(MonadEditor m, YiVariable a, Default a, Functor m) =>
m a
getEditorDyn
Bool -> EditorM Bool
forall (m :: * -> *) a. Monad m => a -> m a
return (Bool -> EditorM Bool)
-> ((Text, Region, Direction) -> Bool)
-> (Text, Region, Direction)
-> EditorM Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Bool -> Bool
not (Bool -> Bool)
-> ((Text, Region, Direction) -> Bool)
-> (Text, Region, Direction)
-> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Bool
T.null (Text -> Bool)
-> ((Text, Region, Direction) -> Text)
-> (Text, Region, Direction)
-> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Text, Region, Direction) -> Text
forall a b c. (a, b, c) -> a
fst3 ((Text, Region, Direction) -> EditorM Bool)
-> (Text, Region, Direction) -> EditorM Bool
forall a b. (a -> b) -> a -> b
$ [(Text, Region, Direction)] -> (Text, Region, Direction)
forall a. [a] -> a
head [(Text, Region, Direction)]
s
isearchAddE :: T.Text -> EditorM ()
isearchAddE :: Text -> EditorM ()
isearchAddE Text
inc = (Text -> Text) -> EditorM ()
isearchFunE (Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
inc)
makeSimpleSearch :: R.YiString -> SearchExp
makeSimpleSearch :: YiString -> SearchExp
makeSimpleSearch YiString
s = SearchExp
se
where Right SearchExp
se = [SearchOption] -> String -> Either String SearchExp
makeSearchOptsM [SearchOption
QuoteRegex] (YiString -> String
R.toString YiString
s)
makeISearch :: T.Text -> SearchExp
makeISearch :: Text -> SearchExp
makeISearch Text
s = case [SearchOption] -> String -> Either String SearchExp
makeSearchOptsM [SearchOption]
opts (Text -> String
T.unpack Text
s) of
Left String
_ -> String -> Regex -> Regex -> [SearchOption] -> SearchExp
SearchExp (Text -> String
T.unpack Text
s) Regex
emptyRegex Regex
emptyRegex []
Right SearchExp
search -> SearchExp
search
where opts :: [SearchOption]
opts = SearchOption
QuoteRegex SearchOption -> [SearchOption] -> [SearchOption]
forall a. a -> [a] -> [a]
: if (Char -> Bool) -> Text -> Bool
T.any Char -> Bool
isUpper Text
s then [] else [SearchOption
IgnoreCase]
isearchFunE :: (T.Text -> T.Text) -> EditorM ()
isearchFunE :: (Text -> Text) -> EditorM ()
isearchFunE Text -> Text
fun = do
Isearch [(Text, Region, Direction)]
s <- EditorM Isearch
forall (m :: * -> *) a.
(MonadEditor m, YiVariable a, Default a, Functor m) =>
m a
getEditorDyn
case [(Text, Region, Direction)]
s of
[(Text, Region, Direction)
_] -> EditorM ()
resetRegexE
[(Text, Region, Direction)]
_ -> () -> EditorM ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
let (Text
previous,Region
p0,Direction
direction) = [(Text, Region, Direction)] -> (Text, Region, Direction)
forall a. [a] -> a
head [(Text, Region, Direction)]
s
current :: Text
current = Text -> Text
fun Text
previous
srch :: SearchExp
srch = Text -> SearchExp
makeISearch Text
current
Text -> EditorM ()
forall (m :: * -> *). MonadEditor m => Text -> m ()
printMsg (Text -> EditorM ()) -> Text -> EditorM ()
forall a b. (a -> b) -> a -> b
$ Text
"I-search: " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
current
SearchExp -> EditorM ()
setRegexE SearchExp
srch
Point
prevPoint <- BufferM Point -> EditorM Point
forall (m :: * -> *) a. MonadEditor m => BufferM a -> m a
withCurrentBuffer BufferM Point
pointB
[Region]
matches <- BufferM [Region] -> EditorM [Region]
forall (m :: * -> *) a. MonadEditor m => BufferM a -> m a
withCurrentBuffer (BufferM [Region] -> EditorM [Region])
-> BufferM [Region] -> EditorM [Region]
forall a b. (a -> b) -> a -> b
$ do
Point -> BufferM ()
moveTo (Point -> BufferM ()) -> Point -> BufferM ()
forall a b. (a -> b) -> a -> b
$ Region -> Point
regionStart Region
p0
Bool -> BufferM () -> BufferM ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Direction
direction Direction -> Direction -> Bool
forall a. Eq a => a -> a -> Bool
== Direction
Backward) (BufferM () -> BufferM ()) -> BufferM () -> BufferM ()
forall a b. (a -> b) -> a -> b
$
Int -> BufferM ()
moveN (Int -> BufferM ()) -> Int -> BufferM ()
forall a b. (a -> b) -> a -> b
$ Text -> Int
T.length Text
current
Direction -> SearchExp -> BufferM [Region]
regexB Direction
direction SearchExp
srch
let onSuccess :: Region -> m ()
onSuccess Region
p = do BufferM () -> m ()
forall (m :: * -> *) a. MonadEditor m => BufferM a -> m a
withCurrentBuffer (BufferM () -> m ()) -> BufferM () -> m ()
forall a b. (a -> b) -> a -> b
$ Point -> BufferM ()
moveTo (Region -> Point
regionEnd Region
p)
Isearch -> m ()
forall (m :: * -> *) a.
(MonadEditor m, YiVariable a, Functor m) =>
a -> m ()
putEditorDyn (Isearch -> m ()) -> Isearch -> m ()
forall a b. (a -> b) -> a -> b
$ [(Text, Region, Direction)] -> Isearch
Isearch ((Text
current, Region
p, Direction
direction) (Text, Region, Direction)
-> [(Text, Region, Direction)] -> [(Text, Region, Direction)]
forall a. a -> [a] -> [a]
: [(Text, Region, Direction)]
s)
case [Region]
matches of
(Region
p:[Region]
_) -> Region -> EditorM ()
forall (m :: * -> *). MonadEditor m => Region -> m ()
onSuccess Region
p
[] -> do [Region]
matchesAfterWrap <- BufferM [Region] -> EditorM [Region]
forall (m :: * -> *) a. MonadEditor m => BufferM a -> m a
withCurrentBuffer (BufferM [Region] -> EditorM [Region])
-> BufferM [Region] -> EditorM [Region]
forall a b. (a -> b) -> a -> b
$ do
case Direction
direction of
Direction
Forward -> Point -> BufferM ()
moveTo Point
0
Direction
Backward -> do
Point
bufferLength <- BufferM Point
sizeB
Point -> BufferM ()
moveTo Point
bufferLength
Direction -> SearchExp -> BufferM [Region]
regexB Direction
direction SearchExp
srch
case [Region]
matchesAfterWrap of
(Region
p:[Region]
_) -> Region -> EditorM ()
forall (m :: * -> *). MonadEditor m => Region -> m ()
onSuccess Region
p
[] -> do BufferM () -> EditorM ()
forall (m :: * -> *) a. MonadEditor m => BufferM a -> m a
withCurrentBuffer (BufferM () -> EditorM ()) -> BufferM () -> EditorM ()
forall a b. (a -> b) -> a -> b
$ Point -> BufferM ()
moveTo Point
prevPoint
Isearch -> EditorM ()
forall (m :: * -> *) a.
(MonadEditor m, YiVariable a, Functor m) =>
a -> m ()
putEditorDyn (Isearch -> EditorM ()) -> Isearch -> EditorM ()
forall a b. (a -> b) -> a -> b
$ [(Text, Region, Direction)] -> Isearch
Isearch ((Text
current, Region
p0, Direction
direction) (Text, Region, Direction)
-> [(Text, Region, Direction)] -> [(Text, Region, Direction)]
forall a. a -> [a] -> [a]
: [(Text, Region, Direction)]
s)
Text -> EditorM ()
forall (m :: * -> *). MonadEditor m => Text -> m ()
printMsg (Text -> EditorM ()) -> Text -> EditorM ()
forall a b. (a -> b) -> a -> b
$ Text
"Failing I-search: " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
current
isearchDelE :: EditorM ()
isearchDelE :: EditorM ()
isearchDelE = do
Isearch [(Text, Region, Direction)]
s <- EditorM Isearch
forall (m :: * -> *) a.
(MonadEditor m, YiVariable a, Default a, Functor m) =>
m a
getEditorDyn
case [(Text, Region, Direction)]
s of
((Text, Region, Direction)
_:(Text
text,Region
p,Direction
dir):[(Text, Region, Direction)]
rest) -> do
BufferM () -> EditorM ()
forall (m :: * -> *) a. MonadEditor m => BufferM a -> m a
withCurrentBuffer (BufferM () -> EditorM ()) -> BufferM () -> EditorM ()
forall a b. (a -> b) -> a -> b
$
Point -> BufferM ()
moveTo (Point -> BufferM ()) -> Point -> BufferM ()
forall a b. (a -> b) -> a -> b
$ Region -> Point
regionEnd Region
p
Isearch -> EditorM ()
forall (m :: * -> *) a.
(MonadEditor m, YiVariable a, Functor m) =>
a -> m ()
putEditorDyn (Isearch -> EditorM ()) -> Isearch -> EditorM ()
forall a b. (a -> b) -> a -> b
$ [(Text, Region, Direction)] -> Isearch
Isearch ((Text
text,Region
p,Direction
dir)(Text, Region, Direction)
-> [(Text, Region, Direction)] -> [(Text, Region, Direction)]
forall a. a -> [a] -> [a]
:[(Text, Region, Direction)]
rest)
SearchExp -> EditorM ()
setRegexE (SearchExp -> EditorM ()) -> SearchExp -> EditorM ()
forall a b. (a -> b) -> a -> b
$ Text -> SearchExp
makeISearch Text
text
Text -> EditorM ()
forall (m :: * -> *). MonadEditor m => Text -> m ()
printMsg (Text -> EditorM ()) -> Text -> EditorM ()
forall a b. (a -> b) -> a -> b
$ Text
"I-search: " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
text
[(Text, Region, Direction)]
_ -> () -> EditorM ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
isearchHistory :: Int -> EditorM ()
isearchHistory :: Int -> EditorM ()
isearchHistory Int
delta = do
Isearch ((Text
current,Region
_p0,Direction
_dir):[(Text, Region, Direction)]
_) <- EditorM Isearch
forall (m :: * -> *) a.
(MonadEditor m, YiVariable a, Default a, Functor m) =>
m a
getEditorDyn
Text
h <- Text -> Int -> EditorM Text -> EditorM Text
historyMoveGen Text
iSearch Int
delta (Text -> EditorM Text
forall (m :: * -> *) a. Monad m => a -> m a
return Text
current)
(Text -> Text) -> EditorM ()
isearchFunE (Text -> Text -> Text
forall a b. a -> b -> a
const Text
h)
isearchPrevE :: EditorM ()
isearchPrevE :: EditorM ()
isearchPrevE = Direction -> EditorM ()
isearchNext0 Direction
Backward
isearchNextE :: EditorM ()
isearchNextE :: EditorM ()
isearchNextE = Direction -> EditorM ()
isearchNext0 Direction
Forward
isearchNext0 :: Direction -> EditorM ()
isearchNext0 :: Direction -> EditorM ()
isearchNext0 Direction
newDir = do
Isearch ((Text
current,Region
_p0,Direction
_dir):[(Text, Region, Direction)]
_rest) <- EditorM Isearch
forall (m :: * -> *) a.
(MonadEditor m, YiVariable a, Default a, Functor m) =>
m a
getEditorDyn
if Text -> Bool
T.null Text
current
then Int -> EditorM ()
isearchHistory Int
1
else Direction -> EditorM ()
isearchNext Direction
newDir
isearchNext :: Direction -> EditorM ()
isearchNext :: Direction -> EditorM ()
isearchNext Direction
direction = do
Isearch ((Text
current, Region
p0, Direction
_dir) : [(Text, Region, Direction)]
rest) <- EditorM Isearch
forall (m :: * -> *) a.
(MonadEditor m, YiVariable a, Default a, Functor m) =>
m a
getEditorDyn
BufferM () -> EditorM ()
forall (m :: * -> *) a. MonadEditor m => BufferM a -> m a
withCurrentBuffer (BufferM () -> EditorM ()) -> BufferM () -> EditorM ()
forall a b. (a -> b) -> a -> b
$ Point -> BufferM ()
moveTo (Region -> Point
regionStart Region
p0 Point -> Point -> Point
forall a. Num a => a -> a -> a
+ Point
startOfs)
[Region]
mp <- BufferM [Region] -> EditorM [Region]
forall (m :: * -> *) a. MonadEditor m => BufferM a -> m a
withCurrentBuffer (BufferM [Region] -> EditorM [Region])
-> BufferM [Region] -> EditorM [Region]
forall a b. (a -> b) -> a -> b
$
Direction -> SearchExp -> BufferM [Region]
regexB Direction
direction (Text -> SearchExp
makeISearch Text
current)
case [Region]
mp of
[] -> do
Point
endPoint <- BufferM Point -> EditorM Point
forall (m :: * -> *) a. MonadEditor m => BufferM a -> m a
withCurrentBuffer (BufferM Point -> EditorM Point) -> BufferM Point -> EditorM Point
forall a b. (a -> b) -> a -> b
$ do
Point -> BufferM ()
moveTo (Region -> Point
regionEnd Region
p0)
BufferM Point
sizeB
Text -> EditorM ()
forall (m :: * -> *). MonadEditor m => Text -> m ()
printMsg Text
"isearch: end of document reached"
let wrappedOfs :: Region
wrappedOfs = case Direction
direction of
Direction
Forward -> Point -> Point -> Region
mkRegion Point
0 Point
0
Direction
Backward -> Point -> Point -> Region
mkRegion Point
endPoint Point
endPoint
Isearch -> EditorM ()
forall (m :: * -> *) a.
(MonadEditor m, YiVariable a, Functor m) =>
a -> m ()
putEditorDyn (Isearch -> EditorM ()) -> Isearch -> EditorM ()
forall a b. (a -> b) -> a -> b
$ [(Text, Region, Direction)] -> Isearch
Isearch ((Text
current,Region
wrappedOfs,Direction
direction)(Text, Region, Direction)
-> [(Text, Region, Direction)] -> [(Text, Region, Direction)]
forall a. a -> [a] -> [a]
:[(Text, Region, Direction)]
rest)
(Region
p:[Region]
_) -> do
BufferM () -> EditorM ()
forall (m :: * -> *) a. MonadEditor m => BufferM a -> m a
withCurrentBuffer (BufferM () -> EditorM ()) -> BufferM () -> EditorM ()
forall a b. (a -> b) -> a -> b
$
Point -> BufferM ()
moveTo (Region -> Point
regionEnd Region
p)
Text -> EditorM ()
forall (m :: * -> *). MonadEditor m => Text -> m ()
printMsg (Text -> EditorM ()) -> Text -> EditorM ()
forall a b. (a -> b) -> a -> b
$ Text
"I-search: " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
current
Isearch -> EditorM ()
forall (m :: * -> *) a.
(MonadEditor m, YiVariable a, Functor m) =>
a -> m ()
putEditorDyn (Isearch -> EditorM ()) -> Isearch -> EditorM ()
forall a b. (a -> b) -> a -> b
$ [(Text, Region, Direction)] -> Isearch
Isearch ((Text
current,Region
p,Direction
direction)(Text, Region, Direction)
-> [(Text, Region, Direction)] -> [(Text, Region, Direction)]
forall a. a -> [a] -> [a]
:[(Text, Region, Direction)]
rest)
where startOfs :: Point
startOfs = case Direction
direction of
Direction
Forward -> Point
1
Direction
Backward -> -Point
1
isearchWordE :: EditorM ()
isearchWordE :: EditorM ()
isearchWordE = do
Text
text <- YiString -> Text
R.toText (YiString -> Text) -> EditorM YiString -> EditorM Text
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> BufferM YiString -> EditorM YiString
forall (m :: * -> *) a. MonadEditor m => BufferM a -> m a
withCurrentBuffer (BufferM Point
pointB BufferM Point -> (Point -> BufferM YiString) -> BufferM YiString
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Int -> Point -> BufferM YiString
nelemsB Int
32)
let (Text
prefix, Text
rest) = (Char -> Bool) -> Text -> (Text, Text)
T.break Char -> Bool
isAlpha Text
text
word :: Text
word = (Char -> Bool) -> Text -> Text
T.takeWhile Char -> Bool
isAlpha Text
rest
Text -> EditorM ()
isearchAddE (Text -> EditorM ()) -> Text -> EditorM ()
forall a b. (a -> b) -> a -> b
$ Text
prefix Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
word
isearchFinishE :: EditorM ()
isearchFinishE :: EditorM ()
isearchFinishE = Bool -> EditorM ()
isearchEnd Bool
True
isearchCancelE :: EditorM ()
isearchCancelE :: EditorM ()
isearchCancelE = Bool -> EditorM ()
isearchEnd Bool
False
isearchFinishWithE :: EditorM a -> EditorM ()
isearchFinishWithE :: EditorM a -> EditorM ()
isearchFinishWithE EditorM a
act = EditorM a -> Bool -> EditorM ()
forall a. EditorM a -> Bool -> EditorM ()
isearchEndWith EditorM a
act Bool
True
isearchCancelWithE :: EditorM a -> EditorM ()
isearchCancelWithE :: EditorM a -> EditorM ()
isearchCancelWithE EditorM a
act = EditorM a -> Bool -> EditorM ()
forall a. EditorM a -> Bool -> EditorM ()
isearchEndWith EditorM a
act Bool
False
iSearch :: T.Text
iSearch :: Text
iSearch = Text
"isearch"
isearchEndWith :: EditorM a -> Bool -> EditorM ()
isearchEndWith :: EditorM a -> Bool -> EditorM ()
isearchEndWith EditorM a
act Bool
accept = EditorM Isearch
forall (m :: * -> *) a.
(MonadEditor m, YiVariable a, Default a, Functor m) =>
m a
getEditorDyn EditorM Isearch -> (Isearch -> EditorM ()) -> EditorM ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
Isearch [] -> () -> EditorM ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
Isearch s :: [(Text, Region, Direction)]
s@((Text
lastSearched, Region
_, Direction
dir):[(Text, Region, Direction)]
_) -> do
let (Text
_,Region
p0,Direction
_) = [(Text, Region, Direction)] -> (Text, Region, Direction)
forall a. [a] -> a
last [(Text, Region, Direction)]
s
Text -> EditorM Text -> EditorM ()
historyFinishGen Text
iSearch (Text -> EditorM Text
forall (m :: * -> *) a. Monad m => a -> m a
return Text
lastSearched)
(Direction -> Identity Direction) -> Editor -> Identity Editor
Lens' Editor Direction
searchDirectionA ((Direction -> Identity Direction) -> Editor -> Identity Editor)
-> Direction -> EditorM ()
forall s (m :: * -> *) a b.
MonadState s m =>
ASetter s s a b -> b -> m ()
.= Direction
dir
if Bool
accept
then do EditorM a -> EditorM ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void EditorM a
act
Text -> EditorM ()
forall (m :: * -> *). MonadEditor m => Text -> m ()
printMsg Text
"Quit"
else do EditorM ()
resetRegexE
BufferM () -> EditorM ()
forall (m :: * -> *) a. MonadEditor m => BufferM a -> m a
withCurrentBuffer (BufferM () -> EditorM ()) -> BufferM () -> EditorM ()
forall a b. (a -> b) -> a -> b
$ Point -> BufferM ()
moveTo (Point -> BufferM ()) -> Point -> BufferM ()
forall a b. (a -> b) -> a -> b
$ Region -> Point
regionStart Region
p0
isearchEnd :: Bool -> EditorM ()
isearchEnd :: Bool -> EditorM ()
isearchEnd = EditorM () -> Bool -> EditorM ()
forall a. EditorM a -> Bool -> EditorM ()
isearchEndWith (() -> EditorM ()
forall (m :: * -> *) a. Monad m => a -> m a
return ())
qrNext :: Window -> BufferRef -> SearchExp -> EditorM ()
qrNext :: Window -> BufferRef -> SearchExp -> EditorM ()
qrNext Window
win BufferRef
b SearchExp
what = do
[Region]
mp <- Window -> BufferRef -> BufferM [Region] -> EditorM [Region]
forall (m :: * -> *) a.
MonadEditor m =>
Window -> BufferRef -> BufferM a -> m a
withGivenBufferAndWindow Window
win BufferRef
b (BufferM [Region] -> EditorM [Region])
-> BufferM [Region] -> EditorM [Region]
forall a b. (a -> b) -> a -> b
$ Direction -> SearchExp -> BufferM [Region]
regexB Direction
Forward SearchExp
what
case [Region]
mp of
[] -> do
Text -> EditorM ()
forall (m :: * -> *). MonadEditor m => Text -> m ()
printMsg Text
"String to search not found"
EditorM ()
qrFinish
(Region
r:[Region]
_) -> Window -> BufferRef -> BufferM () -> EditorM ()
forall (m :: * -> *) a.
MonadEditor m =>
Window -> BufferRef -> BufferM a -> m a
withGivenBufferAndWindow Window
win BufferRef
b (BufferM () -> EditorM ()) -> BufferM () -> EditorM ()
forall a b. (a -> b) -> a -> b
$ Region -> BufferM ()
setSelectRegionB Region
r
qrReplaceAll :: Window -> BufferRef -> SearchExp -> R.YiString -> EditorM ()
qrReplaceAll :: Window -> BufferRef -> SearchExp -> YiString -> EditorM ()
qrReplaceAll Window
win BufferRef
b SearchExp
what YiString
replacement = do
Int
n <- Window -> BufferRef -> BufferM Int -> EditorM Int
forall (m :: * -> *) a.
MonadEditor m =>
Window -> BufferRef -> BufferM a -> m a
withGivenBufferAndWindow Window
win BufferRef
b (BufferM Int -> EditorM Int) -> BufferM Int -> EditorM Int
forall a b. (a -> b) -> a -> b
$ do
BufferM ()
exchangePointAndMarkB
SearchExp -> YiString -> Bool -> Region -> BufferM Int
searchAndRepRegion0 SearchExp
what YiString
replacement Bool
True (Region -> BufferM Int) -> BufferM Region -> BufferM Int
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< TextUnit -> Direction -> BufferM Region
regionOfPartB TextUnit
Document Direction
Forward
Text -> EditorM ()
forall (m :: * -> *). MonadEditor m => Text -> m ()
printMsg (Text -> EditorM ()) -> Text -> EditorM ()
forall a b. (a -> b) -> a -> b
$ Text
"Replaced " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Int -> Text
forall a. Show a => a -> Text
showT Int
n Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" occurrences"
EditorM ()
qrFinish
qrFinish :: EditorM ()
qrFinish :: EditorM ()
qrFinish = do
(Maybe SearchExp -> Identity (Maybe SearchExp))
-> Editor -> Identity Editor
Lens' Editor (Maybe SearchExp)
currentRegexA ((Maybe SearchExp -> Identity (Maybe SearchExp))
-> Editor -> Identity Editor)
-> Maybe SearchExp -> EditorM ()
forall s (m :: * -> *) a b.
MonadState s m =>
ASetter s s a b -> b -> m ()
.= Maybe SearchExp
forall a. Maybe a
Nothing
EditorM ()
closeBufferAndWindowE
qrReplaceOne :: Window -> BufferRef -> SearchExp -> R.YiString -> EditorM ()
qrReplaceOne :: Window -> BufferRef -> SearchExp -> YiString -> EditorM ()
qrReplaceOne Window
win BufferRef
b SearchExp
reg YiString
replacement = do
Window -> BufferRef -> YiString -> EditorM ()
qrReplaceCurrent Window
win BufferRef
b YiString
replacement
Window -> BufferRef -> SearchExp -> EditorM ()
qrNext Window
win BufferRef
b SearchExp
reg
qrReplaceCurrent :: Window -> BufferRef -> R.YiString -> EditorM ()
qrReplaceCurrent :: Window -> BufferRef -> YiString -> EditorM ()
qrReplaceCurrent Window
win BufferRef
b YiString
replacement =
Window -> BufferRef -> BufferM () -> EditorM ()
forall (m :: * -> *) a.
MonadEditor m =>
Window -> BufferRef -> BufferM a -> m a
withGivenBufferAndWindow Window
win BufferRef
b (BufferM () -> EditorM ()) -> BufferM () -> EditorM ()
forall a b. (a -> b) -> a -> b
$
(Region -> YiString -> BufferM ())
-> YiString -> Region -> BufferM ()
forall a b c. (a -> b -> c) -> b -> a -> c
flip Region -> YiString -> BufferM ()
replaceRegionB YiString
replacement (Region -> BufferM ()) -> BufferM Region -> BufferM ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< BufferM Region
getRawestSelectRegionB