{-# 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
$c== :: SearchResult -> SearchResult -> Bool
== :: SearchResult -> SearchResult -> Bool
$c/= :: SearchResult -> SearchResult -> Bool
/= :: 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 a b. EditorM a -> (a -> EditorM b) -> EditorM b
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
mre <- EditorM (Maybe SearchExp)
getRegexE
case mre of
Maybe SearchExp
Nothing -> String -> EditorM SearchResult
forall a. String -> EditorM a
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 a. a -> EditorM a
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
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
rs <- Direction -> SearchExp -> BufferM [Region]
regexB Direction
dir SearchExp
c_re
moveB Document (reverseDir dir)
ls <- regexB dir c_re
return $ listToMaybe $ fmap Right rs ++ fmap Left ls
maybe (return ()) (moveTo . regionStart . either id id) mp
return $ f 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 a b. BufferM a -> (a -> BufferM b) -> BufferM b
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 a b. BufferM a -> (a -> BufferM b) -> BufferM b
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
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' = 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
mapM_ (`replaceRegionB` str) mp'
return (length 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 a. a -> EditorM a
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 a b. EditorM a -> (a -> EditorM b) -> EditorM b
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
$cshowsPrec :: Int -> Isearch -> ShowS
showsPrec :: Int -> Isearch -> ShowS
$cshow :: Isearch -> String
show :: Isearch -> String
$cshowList :: [Isearch] -> ShowS
showList :: [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 :: forall a d b c. (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
p <- BufferM Point -> EditorM Point
forall (m :: * -> *) a. MonadEditor m => BufferM a -> m a
withCurrentBuffer BufferM Point
pointB
putEditorDyn (Isearch [(T.empty ,mkRegion p p, dir)])
printMsg "I-search: "
isearchIsEmpty :: EditorM Bool
isearchIsEmpty :: EditorM Bool
isearchIsEmpty = do
Isearch s <- EditorM Isearch
forall (m :: * -> *) a.
(MonadEditor m, YiVariable a, Default a, Functor m) =>
m a
getEditorDyn
return . not . T.null . fst3 $ head 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 s <- EditorM Isearch
forall (m :: * -> *) a.
(MonadEditor m, YiVariable a, Default a, Functor m) =>
m a
getEditorDyn
case s of
[(Text, Region, Direction)
_] -> EditorM ()
resetRegexE
[(Text, Region, Direction)]
_ -> () -> EditorM ()
forall a. a -> EditorM a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
let (previous,p0,direction) = head s
current = Text -> Text
fun Text
previous
srch = Text -> SearchExp
makeISearch Text
current
printMsg $ "I-search: " <> current
setRegexE srch
prevPoint <- withCurrentBuffer pointB
matches <- withCurrentBuffer $ do
moveTo $ regionStart p0
when (direction == Backward) $
moveN $ T.length current
regexB direction srch
let 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 matches of
(Region
p:[Region]
_) -> Region -> EditorM ()
forall {m :: * -> *}. MonadEditor m => Region -> m ()
onSuccess Region
p
[] -> do 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
bufferLength <- BufferM Point
sizeB
moveTo bufferLength
Direction -> SearchExp -> BufferM [Region]
regexB Direction
direction SearchExp
srch
case 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 s <- EditorM Isearch
forall (m :: * -> *) a.
(MonadEditor m, YiVariable a, Default a, Functor m) =>
m a
getEditorDyn
case 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 a. a -> EditorM a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
isearchHistory :: Int -> EditorM ()
isearchHistory :: Int -> EditorM ()
isearchHistory Int
delta = do
Isearch ((current,_p0,_dir):_) <- EditorM Isearch
forall (m :: * -> *) a.
(MonadEditor m, YiVariable a, Default a, Functor m) =>
m a
getEditorDyn
h <- historyMoveGen iSearch delta (return current)
isearchFunE (const 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 ((current,_p0,_dir):_rest) <- EditorM Isearch
forall (m :: * -> *) a.
(MonadEditor m, YiVariable a, Default a, Functor m) =>
m a
getEditorDyn
if T.null current
then isearchHistory 1
else isearchNext newDir
isearchNext :: Direction -> EditorM ()
isearchNext :: Direction -> EditorM ()
isearchNext Direction
direction = do
Isearch ((current, p0, _dir) : rest) <- EditorM Isearch
forall (m :: * -> *) a.
(MonadEditor m, YiVariable a, Default a, Functor m) =>
m a
getEditorDyn
withCurrentBuffer $ moveTo (regionStart p0 + startOfs)
mp <- withCurrentBuffer $
regexB direction (makeISearch current)
case mp of
[] -> do
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
printMsg "isearch: end of document reached"
let 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
putEditorDyn $ Isearch ((current,wrappedOfs,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 <- 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 a b. BufferM a -> (a -> BufferM b) -> BufferM b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Int -> Point -> BufferM YiString
nelemsB Int
32)
let (prefix, rest) = T.break isAlpha text
word = (Char -> Bool) -> Text -> Text
T.takeWhile Char -> Bool
isAlpha Text
rest
isearchAddE $ prefix <> 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 :: forall a. 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 :: forall a. 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 :: forall a. 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 a b. EditorM a -> (a -> EditorM b) -> EditorM b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
Isearch [] -> () -> EditorM ()
forall a. a -> EditorM a
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. HasCallStack => [a] -> a
last [(Text, Region, Direction)]
s
Text -> EditorM Text -> EditorM ()
historyFinishGen Text
iSearch (Text -> EditorM Text
forall a. a -> EditorM a
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 a. a -> EditorM a
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
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 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
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
printMsg $ "Replaced " <> showT n <> " occurrences"
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