anchor.diff:  open MonoDevelop.Ide.Editor
   open MonoDevelop.Ide.Editor.Extension
   open Mono.TextEditor
  +open MonoDevelop.Core
  +
  +
  +type VimMode =
  +    | NormalMode
  +    | VisualMode
  +    | InsertMode
   
   type CommandType =
       | Move
       | Visual
       | Delete
       | Change
  -    //| FindForwards
  -    //| FindBackwards
  +    | SwitchMode of VimMode
       | DoNothing
   
   type TextObject =
  
positive.code: 
      let (|Movement|_|) character =
          match character with
          | 'h' -> Some Left
          | 'j' -> Some Down
          | 'k' -> Some Up
          | 'l' -> Some Right
          | '$' -> Some EndOfLine
          | '^' -> Some StartOfLine
          | '0' -> Some StartOfLine
          | '_' -> Some FirstNonWhitespace
          | _ -> None
  
      let (|FindChar|_|) character =
          match character with
          | 'f' -> Some ToCharInclusive
          | 'F' -> Some FindCharBackwards
          | 't' -> Some ToCharExclusive
          //| 'T' -> Some Right
          | _ -> None
  
      let (|Action|_|) character =
          match character with
          | 'd' -> Some Delete
          | 'c' -> Some Change
          | 'v' -> Some Visual
          //| 'v' -> Some FindForwards
          | _ -> None
  
      let keys = ResizeArray<_>()
      let mutable textEditorData = Unchecked.defaultof<TextEditorData>
      let getCommand (repeat: int option) commandType textObject =
          Some { repeat=(match repeat with | Some r -> r | None -> 1); commandType=commandType; textObject=textObject }
  
      let wait = getCommand (Some 1) DoNothing Nothing
  
      member x.RunCommand command =
          for i in [1..command.repeat] do
              let start, finish = VimHelpers.getRange textEditorData command.textObject
              match command.commandType with
              | Move -> x.Editor.CaretOffset <- finish
              | Delete -> 
                  x.Editor.SetSelection(start, finish)
                  ClipboardActions.Cut textEditorData
              | Visual ->
                  x.Editor.SetSelection(start, finish)
              | _ -> ()
  
      override x.Initialize() =
          textEditorData <- x.Editor.GetContent<ITextEditorDataProvider>().GetTextEditorData()
          textEditorData.Caret.Mode <- CaretMode.Block
  
      override x.KeyPress(descriptor:KeyDescriptor) =
          if descriptor.KeyChar = 'q' then
              // temp debug reset code
              keys.Clear()
              false
          else
          if descriptor.KeyChar <> '\000' then
              keys.Add descriptor.KeyChar
          let keyList = keys |> List.ofSeq
  
          let multiplier, keyList =
              match keyList with
              | OneToNine d1 :: Digit d2 :: Digit d3 :: Digit d4 :: t -> Some(d1 * 1000 + d2 * 100 + d3 * 10 + d4), t
  
negative.code: 
  type XSVim() =
      inherit TextEditorExtension()
      let runCommand vimState textEditorData command =
          for i in [1..command.repeat] do
              let start, finish = VimHelpers.getRange textEditorData command.textObject
              match command.commandType with
              | Move -> textEditorData.Caret.Offset <- finish
              | Delete ->
                  textEditorData.SetSelection(start, finish)
                  ClipboardActions.Cut textEditorData
              | Visual ->
                  textEditorData.SetSelection(start, finish)
              | _ -> ()
  
          match command.commandType with
          | SwitchMode mode ->
              match mode with
              | NormalMode -> textEditorData.Caret.Mode <- CaretMode.Block
              | VisualMode -> textEditorData.Caret.Mode <- CaretMode.Block
              | InsertMode -> textEditorData.Caret.Mode <- CaretMode.Insert
              { vimState with mode = mode }
          | _ -> vimState
  
      let (|Digit|_|) character =
          if character > "0" && character < "9" then
              Some (Convert.ToInt32 character)
          else
              None
  
      let (|OneToNine|_|) character =
          if character > "1" && character < "9" then
              Some (Convert.ToInt32 character)
          else
              None
  
      let (|BlockDelimiter|_|) character =
          let pairs =
              [ 
                  "[", ("[", "]")
                  "]", ("[", "]")
                  "(", ("(", ")")
                  ")", ("(", ")")
                  "{", ("{", "}")
                  "}", ("{", "}")
                  "<", ("<", ">")
                  ">", ("<", ">")
              ] |> dict
          if pairs.ContainsKey character then
              Some pairs.[character]
  