module Hob.Command.ReplaceText ( createMatcherForReplace, replaceCommandHandler, replaceNextCommandHandler, ) where import Data.Monoid (mconcat) import Graphics.UI.Gtk import Hob.Command.FindText import Hob.Context import Hob.Ui.Editor import Hob.Ui.Editor.Search createMatcherForReplace :: Char -> (String -> String -> CommandHandler) -> CommandMatcher createMatcherForReplace prefix handler = CommandMatcher (const Nothing) match where match [] = Nothing match (p:ps) | p == prefix = matchSearchAndReplaceFromStart ps | otherwise = Nothing matchSearchAndReplaceFromStart [] = Nothing matchSearchAndReplaceFromStart (separator:xs) = matchSearchAndReplaceFromSearch separator xs "" matchSearchAndReplaceFromSearch _ [] _ = Nothing matchSearchAndReplaceFromSearch separator (x:xs) accumSearch | '\\' == x = case xs of [] -> Nothing (s:xss) -> if s == separator then matchSearchAndReplaceFromSearch separator xss (accumSearch++[separator]) else matchSearchAndReplaceFromSearch separator xs (accumSearch++[x]) | separator == x = matchSearchAndReplaceFromReplace separator xs accumSearch "" | otherwise = matchSearchAndReplaceFromSearch separator xs (accumSearch++[x]) matchSearchAndReplaceFromReplace _ [] search accumReplace = Just $ handler search accumReplace matchSearchAndReplaceFromReplace separator (x:xs) search accumReplace | '\\' == x = case xs of [] -> Just $ handler search (accumReplace++[x]) (s:xss) -> if s == separator then matchSearchAndReplaceFromReplace separator xss search (accumReplace++[separator]) else matchSearchAndReplaceFromReplace separator xs search (accumReplace++[x]) | separator == x = Just $ handler search accumReplace | otherwise = matchSearchAndReplaceFromReplace separator xs search (accumReplace++[x]) replaceCommandHandler :: String -> String -> CommandHandler replaceCommandHandler searchText replaceText = CommandHandler (Just $ PreviewCommandHandler (searchPreview searchText) searchResetPreview) (replaceStart searchText replaceText) replaceNextCommandHandler :: CommandHandler replaceNextCommandHandler = CommandHandler Nothing invokeReplaceNext replaceStart :: String -> String -> App() replaceStart searchText replaceText = do enterMode replaceMode invokeOnActiveEditor $ \editor -> do startReplace editor searchText replaceText widgetGrabFocus editor invokeReplaceNext :: App() invokeReplaceNext = invokeOnActiveEditor replaceNext replaceReset :: App() replaceReset = invokeOnActiveEditor resetReplace replaceMode :: Mode replaceMode = Mode "replace" matcher replaceReset where matcher = mconcat [ commandMatcher searchMode , createMatcherForKeyBinding ([Shift, Control], "Down") replaceNextCommandHandler ]