diff --git a/net.sourceforge.vrapper.core/src/net/sourceforge/vrapper/vim/commands/ReplaceCommand.java b/net.sourceforge.vrapper.core/src/net/sourceforge/vrapper/vim/commands/ReplaceCommand.java index 3ba000e68..d2865d617 100644 --- a/net.sourceforge.vrapper.core/src/net/sourceforge/vrapper/vim/commands/ReplaceCommand.java +++ b/net.sourceforge.vrapper.core/src/net/sourceforge/vrapper/vim/commands/ReplaceCommand.java @@ -7,9 +7,11 @@ import net.sourceforge.vrapper.utils.Function; import net.sourceforge.vrapper.utils.LineInformation; import net.sourceforge.vrapper.utils.StringUtils; +import net.sourceforge.vrapper.utils.TextRange; import net.sourceforge.vrapper.utils.VimUtils; import net.sourceforge.vrapper.vim.EditorAdaptor; import net.sourceforge.vrapper.vim.Options; +import net.sourceforge.vrapper.vim.modes.NormalMode; /** * Replaces the character at the current position with another one. @@ -38,6 +40,46 @@ protected int execute(TextContent c, int offset, int count) { } abstract int replace(TextContent c, int offset, int count, int targetOffset); + + public static class Visual extends ReplaceCommand { + private final char replaceChar; + private int selectionOffset; + private String selectionText; + + public Visual(char replacement) { + super(); + this.replaceChar = replacement; + } + + @Override + public void execute(EditorAdaptor editorAdaptor) + throws CommandExecutionException { + //grab current selection + TextRange selectionRange = editorAdaptor.getSelection().getRegion(editorAdaptor, 0); + selectionOffset = selectionRange.getLeftBound().getViewOffset(); + selectionText = editorAdaptor.getViewContent().getText(selectionRange); + replace(editorAdaptor.getModelContent(), selectionOffset, 1, selectionOffset); + editorAdaptor.changeMode(NormalMode.NAME); + } + + @Override + protected int replace(TextContent c, int offset, int count, int targetOffset) { + String s = ""; + for(int i=0; i < selectionText.length(); i++) { + //replace every character *except* newlines + s += VimUtils.isNewLine(""+selectionText.charAt(i)) ? selectionText.charAt(i) : replaceChar; + } + c.replace(selectionOffset, selectionText.length(), s); + return selectionOffset; + } + + public static final Function VISUAL_KEYSTROKE = new Function() { + public Command call(KeyStroke arg) { + return new Visual(arg.getCharacter()); + } + }; + + } private static class Character extends ReplaceCommand { diff --git a/net.sourceforge.vrapper.core/src/net/sourceforge/vrapper/vim/modes/AbstractVisualMode.java b/net.sourceforge.vrapper.core/src/net/sourceforge/vrapper/vim/modes/AbstractVisualMode.java index ac3c9d42a..3c149aeb3 100644 --- a/net.sourceforge.vrapper.core/src/net/sourceforge/vrapper/vim/modes/AbstractVisualMode.java +++ b/net.sourceforge.vrapper.core/src/net/sourceforge/vrapper/vim/modes/AbstractVisualMode.java @@ -1,6 +1,7 @@ package net.sourceforge.vrapper.vim.modes; import static net.sourceforge.vrapper.keymap.StateUtils.union; +import static net.sourceforge.vrapper.keymap.vim.ConstructorWrappers.changeCaret; import static net.sourceforge.vrapper.keymap.vim.ConstructorWrappers.convertKeyStroke; import static net.sourceforge.vrapper.keymap.vim.ConstructorWrappers.leafBind; import static net.sourceforge.vrapper.keymap.vim.ConstructorWrappers.leafCtrlBind; @@ -12,6 +13,7 @@ import net.sourceforge.vrapper.keymap.vim.RegisterState; import net.sourceforge.vrapper.keymap.vim.VisualMotionState; import net.sourceforge.vrapper.keymap.vim.VisualTextObjectState; +import net.sourceforge.vrapper.utils.CaretType; import net.sourceforge.vrapper.vim.EditorAdaptor; import net.sourceforge.vrapper.vim.VimConstants; import net.sourceforge.vrapper.vim.commands.CenterLineCommand; @@ -23,6 +25,7 @@ import net.sourceforge.vrapper.vim.commands.JoinVisualLinesCommand; import net.sourceforge.vrapper.vim.commands.LeaveVisualModeCommand; import net.sourceforge.vrapper.vim.commands.PasteOperation; +import net.sourceforge.vrapper.vim.commands.ReplaceCommand; import net.sourceforge.vrapper.vim.commands.Selection; import net.sourceforge.vrapper.vim.commands.SelectionBasedTextOperationCommand; import net.sourceforge.vrapper.vim.commands.SetMarkCommand; @@ -51,7 +54,8 @@ public AbstractVisualMode(EditorAdaptor editorAdaptor) { protected KeyMapResolver buildKeyMapResolver() { State state = union( state( - leafBind('z', KeyMapResolver.NO_KEYMAP)), + leafBind('z', KeyMapResolver.NO_KEYMAP), + leafBind('r', KeyMapResolver.NO_KEYMAP)), getKeyMapsForMotions(), editorAdaptor.getPlatformSpecificStateProvider().getKeyMaps(VisualMode.NAME)); final State countEater = new CountConsumingState(state); @@ -146,6 +150,10 @@ protected State buildInitialState() { leafBind('t', centerTopLine), leafBind(SpecialKey.RETURN, centerTopLine) ), + transitionBind('r', changeCaret(CaretType.UNDERLINE), + convertKeyStroke( + ReplaceCommand.Visual.VISUAL_KEYSTROKE, + VimConstants.PRINTABLE_KEYSTROKES_WITH_NL)), transitionBind('m', convertKeyStroke( SetMarkCommand.KEYSTROKE_CONVERTER,