diff --git a/XSVim.Tests/ExModeTests.fs b/XSVim.Tests/ExModeTests.fs index 989f306..b8b9f7e 100644 --- a/XSVim.Tests/ExModeTests.fs +++ b/XSVim.Tests/ExModeTests.fs @@ -87,3 +87,8 @@ module ``Ex mode tests`` = """11111 5$5555""" + + [] + let ``Switching to substitute command mode with a selection``() = + let _, state, _ = test "a$bc" "v:" + state.statusMessage |> should equal (Some ":'<,'>") diff --git a/XSVim/ExMode.fs b/XSVim/ExMode.fs index a8ba1de..d8a650e 100644 --- a/XSVim/ExMode.fs +++ b/XSVim/ExMode.fs @@ -1,6 +1,8 @@ namespace XSVim open System open System.Text.RegularExpressions +open MonoDevelop.Core +open MonoDevelop.Core.ProgressMonitoring open MonoDevelop.Ide open MonoDevelop.Ide.Commands open MonoDevelop.Ide.Editor.Extension @@ -34,6 +36,18 @@ module exMode = else None + let (|Substitute|_|) input = + let matches = Regex.Matches(input, "(.*)s/(.*)/(.*)", RegexOptions.Compiled) + if matches.Count = 1 then + let m = matches.[0] + match m.Groups.[1].Value with + | "%" -> Some { find = m.Groups.[2].Value; replace = m.Groups.[3].Value; scope = Document } + | "'<,'>" -> Some { find = m.Groups.[2].Value; replace = m.Groups.[3].Value; scope = Selection } + | _ -> None + else + None + + let processKey (state:VimState) (key:KeyDescriptor) = let setMessage message = { state with statusMessage = message } let normalMode = { state with statusMessage = None; mode = NormalMode } @@ -132,6 +146,10 @@ module exMode = [ runOnce Move (Jump (StartOfLineNumber startLine)) runOnce DeleteWholeLines (Jump (StartOfLineNumber endLine)) ] normalMode, actions + | Substitute substition -> + match Substitute.substitute substition with + | true -> normalMode, resetKeys + | false -> state, resetKeys | _ -> { state with statusMessage = sprintf "Could not parse :%s" rest |> Some; mode = NormalMode; } , resetKeys diff --git a/XSVim/Properties/AssemblyInfo.fs b/XSVim/Properties/AssemblyInfo.fs index b479bc1..fca000a 100644 --- a/XSVim/Properties/AssemblyInfo.fs +++ b/XSVim/Properties/AssemblyInfo.fs @@ -5,7 +5,7 @@ open System.Runtime.CompilerServices [] module AddinVersion = [] - let version = "0.60.6" + let version = "0.61.0" [] // The assembly version has the format {Major}.{Minor}.{Build}.{Revision} diff --git a/XSVim/SubstituteCommand.fs b/XSVim/SubstituteCommand.fs new file mode 100644 index 0000000..fdfcf8a --- /dev/null +++ b/XSVim/SubstituteCommand.fs @@ -0,0 +1,43 @@ +namespace XSVim +open System +open MonoDevelop.Core +open MonoDevelop.Core.ProgressMonitoring +open MonoDevelop.Ide +open MonoDevelop.Ide.FindInFiles + +type SubstituteScope = Selection | Document + +type Substitution = { find: string; replace: string; scope: SubstituteScope } + +module Substitute = + let substitute substitution = + let find = FindInFiles.FindReplace() + let options = FindInFiles.FilterOptions() + options.RegexSearch <- true + if not(find.ValidatePattern(options, substitution.find)) then + MessageService.ShowError (GettextCatalog.GetString ("Search pattern is invalid")); + false + elif not(find.ValidatePattern(options, substitution.replace)) then + MessageService.ShowError (GettextCatalog.GetString ("Replace pattern is invalid")); + false + else + use monitor = + match IdeApp.Workbench with + | null -> new ConsoleProgressMonitor() :> ProgressMonitor + | workbench -> + let monitor = workbench.ProgressMonitors.GetSearchProgressMonitor (true) + monitor.PathMode <- PathMode.Hidden + monitor :> ProgressMonitor + let scope = + match substitution.scope with + | Document -> DocumentScope() :> Scope + | Selection -> SelectionScope() :> Scope + + find.FindAll(scope, monitor, substitution.find, substitution.replace, options, Threading.CancellationToken.None) + |> Seq.iter(fun res -> + match monitor with + | :? SearchProgressMonitor as mon -> + mon.ReportResult res + | _ -> printfn "%A" res) + + true \ No newline at end of file diff --git a/XSVim/Types.fs b/XSVim/Types.fs index 66f7c9f..e365df3 100644 --- a/XSVim/Types.fs +++ b/XSVim/Types.fs @@ -35,7 +35,7 @@ type VimMode = | VisualLineMode | InsertMode | ReplaceMode - | ExMode of char // initial char typed to get to command line + | ExMode of string // initial char typed to get to command line type MoveRightBehaviour = StopAtEndOfLine | MoveToNextLineAtEnd | IncludeDelimiter diff --git a/XSVim/XSVim.fs b/XSVim/XSVim.fs index 066a0f2..ad4daca 100755 --- a/XSVim/XSVim.fs +++ b/XSVim/XSVim.fs @@ -1522,9 +1522,10 @@ module Vim = | NotInsertMode, [ "*" ] -> [ run (Star After) Nothing ] | NotInsertMode, [ "#" ] -> [ run (Star Before) Nothing ] | NotInsertMode, [ "£" ] -> [ run (Star Before) Nothing ] - | NotInsertMode, [ SearchChar c ] -> [ switchMode (ExMode c); runOnce (SetSearchAction Move) Nothing ] - | NotInsertMode, [ ":" ] -> [ switchMode (ExMode ':') ] - | NotInsertMode, [ Action action; SearchChar c ] -> [ switchMode (ExMode c); runOnce (SetSearchAction action) Nothing ] + | NotInsertMode, [ SearchChar c ] -> [ switchMode (ExMode (string c)); runOnce (SetSearchAction Move) Nothing ] + | VisualModes, [ ":" ] -> [ switchMode (ExMode ":'<,'>") ] + | NotInsertMode, [ ":" ] -> [ switchMode (ExMode ":") ] + | NotInsertMode, [ Action action; SearchChar c ] -> [ switchMode (ExMode (string c)); runOnce (SetSearchAction action) Nothing ] | NormalMode, [ "z"; "z" ] -> [ dispatch ViewCommands.CenterAndFocusCurrentDocument ] | NormalMode, [ "z"; ] -> wait | NormalMode, [ "" ] -> [ dispatch TextEditorCommands.ScrollLineUp ] diff --git a/XSVim/XSVim.fsproj b/XSVim/XSVim.fsproj index 1804d1f..2ff162a 100644 --- a/XSVim/XSVim.fsproj +++ b/XSVim/XSVim.fsproj @@ -80,6 +80,7 @@ +