mirror of
https://github.com/chylex/IntelliJ-IdeaVim.git
synced 2025-08-10 15:40:37 +02:00
Improve handling of Delete and Backspace in ex entry
This commit is contained in:
parent
31d30a9115
commit
b157d07b6d
src/com/maddyhome/idea/vim/ui
test/org/jetbrains/plugins/ideavim/ex
@ -102,8 +102,6 @@ public class ExEditorKit extends DefaultEditorKit {
|
||||
static final String CancelEntry = "cancel-entry";
|
||||
static final String CompleteEntry = "complete-entry";
|
||||
static final String EscapeChar = "escape";
|
||||
static final String DeletePreviousChar = "delete-prev-char";
|
||||
static final String DeletePreviousWord = "delete-prev-word";
|
||||
static final String DeleteToCursor = "delete-to-cursor";
|
||||
static final String ToggleInsertReplace = "toggle-insert";
|
||||
static final String InsertRegister = "insert-register";
|
||||
@ -114,18 +112,19 @@ public class ExEditorKit extends DefaultEditorKit {
|
||||
static final String StartDigraph = "start-digraph";
|
||||
|
||||
@NotNull private final Action[] exActions = new Action[]{
|
||||
new ExEditorKit.CancelEntryAction(),
|
||||
new ExEditorKit.CompleteEntryAction(),
|
||||
new ExEditorKit.EscapeCharAction(),
|
||||
new ExEditorKit.DeletePreviousCharAction(),
|
||||
new ExEditorKit.DeletePreviousWordAction(),
|
||||
new ExEditorKit.DeleteToCursorAction(),
|
||||
new ExEditorKit.HistoryUpAction(),
|
||||
new ExEditorKit.HistoryDownAction(),
|
||||
new ExEditorKit.HistoryUpFilterAction(),
|
||||
new ExEditorKit.HistoryDownFilterAction(),
|
||||
new ExEditorKit.ToggleInsertReplaceAction(),
|
||||
new ExEditorKit.StartDigraphAction(),
|
||||
new CancelEntryAction(),
|
||||
new CompleteEntryAction(),
|
||||
new EscapeCharAction(),
|
||||
new DeleteNextCharAction(),
|
||||
new DeletePreviousCharAction(),
|
||||
new DeletePreviousWordAction(),
|
||||
new DeleteToCursorAction(),
|
||||
new HistoryUpAction(),
|
||||
new HistoryDownAction(),
|
||||
new HistoryUpFilterAction(),
|
||||
new HistoryDownFilterAction(),
|
||||
new ToggleInsertReplaceAction(),
|
||||
new StartDigraphAction(),
|
||||
new InsertRegisterAction(),
|
||||
};
|
||||
|
||||
@ -295,14 +294,95 @@ public class ExEditorKit extends DefaultEditorKit {
|
||||
}
|
||||
}
|
||||
|
||||
public static class DeletePreviousCharAction extends TextAction {
|
||||
DeletePreviousCharAction() {
|
||||
super(DeletePreviousChar);
|
||||
@SuppressWarnings("BooleanMethodIsAlwaysInverted")
|
||||
private static abstract class DeleteCharAction extends TextAction {
|
||||
|
||||
DeleteCharAction(String name) {
|
||||
super(name);
|
||||
}
|
||||
|
||||
boolean deleteSelection(Document doc, int dot, int mark) throws BadLocationException {
|
||||
if (dot != mark) {
|
||||
doc.remove(Math.min(dot, mark), Math.abs(dot - mark));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean deleteNextChar(Document doc, int dot) throws BadLocationException {
|
||||
if (dot < doc.getLength()) {
|
||||
int delChars = 1;
|
||||
|
||||
if (dot < doc.getLength() - 1) {
|
||||
final String dotChars = doc.getText(dot, 2);
|
||||
final char c0 = dotChars.charAt(0);
|
||||
final char c1 = dotChars.charAt(1);
|
||||
|
||||
if (c0 >= '\uD800' && c0 <= '\uDBFF' &&
|
||||
c1 >= '\uDC00' && c1 <= '\uDFFF') {
|
||||
delChars = 2;
|
||||
}
|
||||
}
|
||||
|
||||
doc.remove(dot, delChars);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean deletePrevChar(Document doc, int dot) throws BadLocationException {
|
||||
if (dot > 0) {
|
||||
int delChars = 1;
|
||||
|
||||
if (dot > 1) {
|
||||
final String dotChars = doc.getText(dot - 2, 2);
|
||||
final char c0 = dotChars.charAt(0);
|
||||
final char c1 = dotChars.charAt(1);
|
||||
|
||||
if (c0 >= '\uD800' && c0 <= '\uDBFF' &&
|
||||
c1 >= '\uDC00' && c1 <= '\uDFFF') {
|
||||
delChars = 2;
|
||||
}
|
||||
}
|
||||
|
||||
doc.remove(dot - delChars, delChars);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static class DeleteNextCharAction extends DeleteCharAction {
|
||||
DeleteNextCharAction() {
|
||||
super(deleteNextCharAction);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
final ExTextField target = (ExTextField)getTextComponent(e);
|
||||
target.saveLastEntry();
|
||||
|
||||
try {
|
||||
final Document doc = target.getDocument();
|
||||
final Caret caret = target.getCaret();
|
||||
final int dot = caret.getDot();
|
||||
final int mark = caret.getMark();
|
||||
if (!deleteSelection(doc, dot, mark) && !deleteNextChar(doc, dot) && !deletePrevChar(doc, dot)) {
|
||||
target.cancel();
|
||||
}
|
||||
} catch (BadLocationException ex) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class DeletePreviousCharAction extends DeleteCharAction {
|
||||
DeletePreviousCharAction() {
|
||||
super(deletePrevCharAction);
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoked when an action occurs.
|
||||
*/
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
ExTextField target = (ExTextField)getTextComponent(e);
|
||||
target.saveLastEntry();
|
||||
@ -312,27 +392,10 @@ public class ExEditorKit extends DefaultEditorKit {
|
||||
Caret caret = target.getCaret();
|
||||
int dot = caret.getDot();
|
||||
int mark = caret.getMark();
|
||||
if (dot != mark) {
|
||||
doc.remove(Math.min(dot, mark), Math.abs(dot - mark));
|
||||
}
|
||||
else if (dot > 0) {
|
||||
int delChars = 1;
|
||||
|
||||
if (dot > 1) {
|
||||
String dotChars = doc.getText(dot - 2, 2);
|
||||
char c0 = dotChars.charAt(0);
|
||||
char c1 = dotChars.charAt(1);
|
||||
|
||||
if (c0 >= '\uD800' && c0 <= '\uDBFF' &&
|
||||
c1 >= '\uDC00' && c1 <= '\uDFFF') {
|
||||
delChars = 2;
|
||||
}
|
||||
if (!deleteSelection(doc, dot, mark) && !deletePrevChar(doc, dot)) {
|
||||
if (dot == 0 && doc.getLength() == 0) {
|
||||
target.cancel();
|
||||
}
|
||||
|
||||
doc.remove(dot - delChars, delChars);
|
||||
}
|
||||
else if (dot == 0 && doc.getLength() == 0){
|
||||
target.cancel();
|
||||
}
|
||||
}
|
||||
catch (BadLocationException bl) {
|
||||
@ -343,7 +406,7 @@ public class ExEditorKit extends DefaultEditorKit {
|
||||
|
||||
public static class DeletePreviousWordAction extends TextAction {
|
||||
DeletePreviousWordAction() {
|
||||
super(DeletePreviousWord);
|
||||
super(deletePrevWordAction);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -52,13 +52,13 @@ public class ExKeyBindings {
|
||||
new KeyBinding(KeyStroke.getKeyStroke((char)0x05, KeyEvent.CTRL_MASK), ExEditorKit.endLineAction),
|
||||
new KeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_END, 0), ExEditorKit.endLineAction),
|
||||
|
||||
new KeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_BACK_SPACE, 0), ExEditorKit.DeletePreviousChar),
|
||||
new KeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_H, KeyEvent.CTRL_MASK), ExEditorKit.DeletePreviousChar),
|
||||
new KeyBinding(KeyStroke.getKeyStroke((char)0x08, KeyEvent.CTRL_MASK), ExEditorKit.DeletePreviousChar),
|
||||
new KeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_BACK_SPACE, 0), ExEditorKit.deletePrevCharAction),
|
||||
new KeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_H, KeyEvent.CTRL_MASK), ExEditorKit.deletePrevCharAction),
|
||||
new KeyBinding(KeyStroke.getKeyStroke((char)0x08, KeyEvent.CTRL_MASK), ExEditorKit.deletePrevCharAction),
|
||||
|
||||
new KeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0), ExEditorKit.deleteNextCharAction),
|
||||
|
||||
new KeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_W, KeyEvent.CTRL_MASK), ExEditorKit.DeletePreviousWord),
|
||||
new KeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_W, KeyEvent.CTRL_MASK), ExEditorKit.deletePrevWordAction),
|
||||
|
||||
new KeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_U, KeyEvent.CTRL_MASK), ExEditorKit.DeleteToCursor),
|
||||
|
||||
|
@ -133,6 +133,11 @@ public class ExTextField extends JTextField {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores the current text for use in filtering history. Required for scrolling through multiple history entries
|
||||
*
|
||||
* Called whenever the text is changed, either by typing, or by special characters altering the text (e.g. Delete)
|
||||
*/
|
||||
void saveLastEntry() {
|
||||
lastEntry = super.getText();
|
||||
}
|
||||
|
@ -112,7 +112,7 @@ class ExEntryTest: VimTestCase() {
|
||||
assertExOffset(13)
|
||||
}
|
||||
|
||||
fun `test delete character in front of caret`() {
|
||||
fun `test backspace deletes character in front of caret`() {
|
||||
typeExInput(":set incsearch<BS>")
|
||||
assertExText("set incsearc")
|
||||
|
||||
@ -120,7 +120,7 @@ class ExEntryTest: VimTestCase() {
|
||||
assertExText("set incsear")
|
||||
}
|
||||
|
||||
fun `test delete at start of text cancels entry`() {
|
||||
fun `test backspace at start of text cancels entry`() {
|
||||
typeExInput(":<BS>")
|
||||
assertIsDeactivated()
|
||||
|
||||
@ -143,12 +143,24 @@ class ExEntryTest: VimTestCase() {
|
||||
assertIsActive()
|
||||
}
|
||||
|
||||
fun `test delete character under caret`() {
|
||||
fun `test delete deletes character under caret`() {
|
||||
typeExInput(":set<Left>")
|
||||
typeText("<Del>")
|
||||
assertExText("se")
|
||||
}
|
||||
|
||||
fun `test delete at end of string deletes character to left of caret`() {
|
||||
typeExInput(":set")
|
||||
typeText("<Del>")
|
||||
assertExText("se")
|
||||
}
|
||||
|
||||
fun `test delete with no text cancels entry`() {
|
||||
typeExInput(":set")
|
||||
typeText("<Del><Del><Del><Del>")
|
||||
assertIsDeactivated()
|
||||
}
|
||||
|
||||
fun `test delete word before caret`() {
|
||||
typeExInput(":set incsearch<C-W>")
|
||||
assertExText("set ")
|
||||
|
Loading…
Reference in New Issue
Block a user