Skip to content

Commit

Permalink
Everything entered in insert mode can be undone atomically. Fixes #28
Browse files Browse the repository at this point in the history
  • Loading branch information
nosami committed May 9, 2017
1 parent 2eabbb2 commit f891052
Show file tree
Hide file tree
Showing 5 changed files with 19 additions and 12 deletions.
2 changes: 1 addition & 1 deletion XSVim.Tests/KeyParsing.fs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ open NUnit.Framework
module ``Key parsing tests`` =
let test keys =
let keys = [for c in keys -> c.ToString()]
let state = { keys=keys; mode=NormalMode; visualStartOffset=0; findCharCommand=None; lastAction=[]; desiredColumn=None}
let state = { keys=keys; mode=NormalMode; visualStartOffset=0; findCharCommand=None; lastAction=[]; desiredColumn=None; undoGroup=None }
let action, _state = Vim.parseKeys state
let first = action.Head
first.repeat, first.commandType, first.textObject
Expand Down
2 changes: 1 addition & 1 deletion XSVim.Tests/MiscTests.fs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ module ``Miscellaneous tests`` =

[<Test>]
let ``Undo insert mode``() =
assertText "abc$" "adef<esc>u" "abc$"
assertText "abc$" "adef ghi jkl<esc>u" "abc$"


[<Test>]
Expand Down
4 changes: 3 additions & 1 deletion XSVim.Tests/TestHelpers.fs
Original file line number Diff line number Diff line change
Expand Up @@ -107,12 +107,14 @@ module TestHelpers =
editor.CaretOffset <- caret-1

let plugin = new XSVim()
let state = { keys=[]; mode=NormalMode; visualStartOffset=0; findCharCommand=None; lastAction=[]; desiredColumn=None }
let state = { keys=[]; mode=NormalMode; visualStartOffset=0; findCharCommand=None; lastAction=[]; desiredColumn=None; undoGroup=None }
let keyDescriptors = parseKeys keys
let newState =
keyDescriptors
|> Array.fold(fun state c ->
let newState, handledKeyPress = Vim.handleKeyPress state c editor
if state.mode = InsertMode && c.SpecialKey <> SpecialKey.Escape then
editor.InsertAtCaret (c.KeyChar.ToString())
newState) state

let cursor = if newState.mode = InsertMode then "|" else "$"
Expand Down
2 changes: 1 addition & 1 deletion XSVim/Properties/AddinInfo.fs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ open MonoDevelop
[<assembly:Addin (
"XSVim",
Namespace = "XSVim",
Version = "0.16.7"
Version = "0.16.8"
)>]

[<assembly:AddinName ("Vim")>]
Expand Down
21 changes: 13 additions & 8 deletions XSVim/XSVim.fs
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ type VimState = {
findCharCommand: VimAction option // f,F,t or T command to be repeated with ;
lastAction: VimAction list // used by . command to repeat the last action
desiredColumn: int option
undoGroup: IDisposable option
}

[<AutoOpen>]
Expand Down Expand Up @@ -435,9 +436,10 @@ module Vim =
| InsertMode, Block -> EditActions.SwitchCaretMode editor
| _ -> ()

let switchToInsertMode state =
let switchToInsertMode (editor:TextEditor) state =
let group = editor.OpenUndoGroup()
setCaretMode Insert
{ state with mode = InsertMode; keys = [] }
{ state with mode = InsertMode; keys = []; undoGroup = Some group }

let rec processCommands count vimState =
let start, finish = VimHelpers.getRange vimState editor command.textObject
Expand Down Expand Up @@ -483,7 +485,7 @@ module Vim =
delete vimState start finish
else
vimState
switchToInsertMode state
switchToInsertMode editor state
| Yank ->
let finish =
match command.textObject with
Expand Down Expand Up @@ -556,13 +558,14 @@ module Vim =
editor.CaretColumn <- Math.Min(editor.CaretColumn, selectionStartLocation.Column)
editor.SetSelection(new DocumentLocation (topLine, selectionStartLocation.Column),new DocumentLocation (bottomLine, selectionStartLocation.Column))
if editor.SelectionMode = SelectionMode.Normal then dispatch TextEditorCommands.ToggleBlockSelectionMode
switchToInsertMode vimState
switchToInsertMode editor vimState
| SwitchMode mode ->
match mode with
| NormalMode ->
editor.ClearSelection()
setCaretMode Block
{ vimState with mode = mode }
vimState.undoGroup |> Option.iter(fun d -> d.Dispose())
{ vimState with mode = mode; undoGroup = None }
| VisualMode | VisualLineMode | VisualBlockMode ->
setCaretMode Block
let start, finish = VimHelpers.getRange vimState editor command.textObject
Expand All @@ -573,15 +576,17 @@ module Vim =
| _, SelectionMode.Block -> dispatch TextEditorCommands.ToggleBlockSelectionMode
| _ -> ()
newState
| InsertMode -> switchToInsertMode vimState
| InsertMode ->
switchToInsertMode editor vimState
| _ -> vimState
if count = 1 then newState else processCommands (count-1) newState
let count =
match command.repeat with
| Some r -> r
| None -> 1

use _group = editor.OpenUndoGroup()
use group = editor.OpenUndoGroup()

processCommands count vimState

let (|Digit|_|) character =
Expand Down Expand Up @@ -839,7 +844,7 @@ type XSVim() =

override x.Initialize() =
if not (editorStates.ContainsKey x.FileName) then
editorStates.Add(x.FileName, { keys=[]; mode=NormalMode; visualStartOffset=0; findCharCommand=None; lastAction=[]; desiredColumn=None })
editorStates.Add(x.FileName, { keys=[]; mode=NormalMode; visualStartOffset=0; findCharCommand=None; lastAction=[]; desiredColumn=None; undoGroup=None })
EditActions.SwitchCaretMode x.Editor
disposable <- Some (IdeApp.Workbench.DocumentClosed.Subscribe
(fun e -> let documentName = e.Document.Name
Expand Down

0 comments on commit f891052

Please sign in to comment.