mirror of
https://github.com/chylex/IntelliJ-IdeaVim.git
synced 2025-07-26 17:59:02 +02:00
Add prompt when inserting digraphs and registers
Also resets state correctly when cancelling inserts
This commit is contained in:
parent
906d2a4168
commit
8601730dd8
src/com/maddyhome/idea/vim
test/org/jetbrains/plugins/ideavim/ex
@ -49,7 +49,7 @@ public class DigraphSequence {
|
||||
if (key.getKeyCode() == KeyEvent.VK_K && (key.getModifiers() & KeyEvent.CTRL_MASK) != 0) {
|
||||
logger.debug("found Ctrl-K");
|
||||
digraphState = DIG_STATE_DIG_ONE;
|
||||
return DigraphResult.OK;
|
||||
return DigraphResult.OK_DIGRAPH;
|
||||
}
|
||||
else if ((key.getKeyCode() == KeyEvent.VK_V || key.getKeyCode() == KeyEvent.VK_Q) &&
|
||||
(key.getModifiers() & KeyEvent.CTRL_MASK) != 0) {
|
||||
@ -57,7 +57,7 @@ public class DigraphSequence {
|
||||
digraphState = DIG_STATE_CODE_START;
|
||||
codeChars = new char[8];
|
||||
codeCnt = 0;
|
||||
return DigraphResult.OK;
|
||||
return DigraphResult.OK_LITERAL;
|
||||
}
|
||||
else {
|
||||
return new DigraphResult(key);
|
||||
@ -68,7 +68,7 @@ public class DigraphSequence {
|
||||
digraphChar = key.getKeyChar();
|
||||
digraphState = DIG_STATE_DIG_TWO;
|
||||
|
||||
return DigraphResult.OK;
|
||||
return new DigraphResult(DigraphResult.RES_OK, digraphChar);
|
||||
}
|
||||
else {
|
||||
digraphState = DIG_STATE_START;
|
||||
@ -93,26 +93,26 @@ public class DigraphSequence {
|
||||
digraphState = DIG_STATE_CODE_CHAR;
|
||||
codeType = 8;
|
||||
logger.debug("Octal");
|
||||
return DigraphResult.OK;
|
||||
return DigraphResult.OK_LITERAL;
|
||||
case 'x':
|
||||
case 'X':
|
||||
codeMax = 2;
|
||||
digraphState = DIG_STATE_CODE_CHAR;
|
||||
codeType = 16;
|
||||
logger.debug("hex2");
|
||||
return DigraphResult.OK;
|
||||
return DigraphResult.OK_LITERAL;
|
||||
case 'u':
|
||||
codeMax = 4;
|
||||
digraphState = DIG_STATE_CODE_CHAR;
|
||||
codeType = 16;
|
||||
logger.debug("hex4");
|
||||
return DigraphResult.OK;
|
||||
return DigraphResult.OK_LITERAL;
|
||||
case 'U':
|
||||
codeMax = 8;
|
||||
digraphState = DIG_STATE_CODE_CHAR;
|
||||
codeType = 16;
|
||||
logger.debug("hex8");
|
||||
return DigraphResult.OK;
|
||||
return DigraphResult.OK_LITERAL;
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
@ -128,7 +128,7 @@ public class DigraphSequence {
|
||||
codeType = 10;
|
||||
codeChars[codeCnt++] = key.getKeyChar();
|
||||
logger.debug("decimal");
|
||||
return DigraphResult.OK;
|
||||
return DigraphResult.OK_LITERAL;
|
||||
default:
|
||||
switch (key.getKeyCode()) {
|
||||
case KeyEvent.VK_TAB:
|
||||
@ -177,7 +177,7 @@ public class DigraphSequence {
|
||||
return new DigraphResult(code);
|
||||
}
|
||||
else {
|
||||
return DigraphResult.OK;
|
||||
return DigraphResult.OK_LITERAL;
|
||||
}
|
||||
}
|
||||
else if (codeCnt > 0) {
|
||||
@ -204,14 +204,21 @@ public class DigraphSequence {
|
||||
public static final int RES_BAD = 1;
|
||||
public static final int RES_DONE = 2;
|
||||
|
||||
public static final DigraphResult OK = new DigraphResult(RES_OK);
|
||||
public static final DigraphResult BAD = new DigraphResult(RES_BAD);
|
||||
static final DigraphResult OK_DIGRAPH = new DigraphResult(RES_OK, '?');
|
||||
static final DigraphResult OK_LITERAL = new DigraphResult(RES_OK, '^');
|
||||
static final DigraphResult BAD = new DigraphResult(RES_BAD);
|
||||
|
||||
DigraphResult(int result) {
|
||||
this.result = result;
|
||||
stroke = null;
|
||||
}
|
||||
|
||||
DigraphResult(int result, char promptCharacter) {
|
||||
this.result = result;
|
||||
this.promptCharacter = promptCharacter;
|
||||
stroke = null;
|
||||
}
|
||||
|
||||
DigraphResult(@Nullable KeyStroke stroke) {
|
||||
result = RES_DONE;
|
||||
this.stroke = stroke;
|
||||
@ -226,8 +233,13 @@ public class DigraphSequence {
|
||||
return result;
|
||||
}
|
||||
|
||||
public char getPromptCharacter() {
|
||||
return promptCharacter;
|
||||
}
|
||||
|
||||
private final int result;
|
||||
@Nullable private final KeyStroke stroke;
|
||||
private char promptCharacter;
|
||||
}
|
||||
|
||||
private int digraphState = DIG_STATE_START;
|
||||
|
@ -157,6 +157,10 @@ public class ExEditorKit extends DefaultEditorKit {
|
||||
}
|
||||
}
|
||||
|
||||
public interface MultiStepAction extends Action {
|
||||
void reset();
|
||||
}
|
||||
|
||||
public static class HistoryUpAction extends TextAction {
|
||||
HistoryUpAction() {
|
||||
super(HistoryUp);
|
||||
@ -201,7 +205,7 @@ public class ExEditorKit extends DefaultEditorKit {
|
||||
}
|
||||
}
|
||||
|
||||
public static class InsertRegisterAction extends TextAction {
|
||||
public static class InsertRegisterAction extends TextAction implements MultiStepAction {
|
||||
private enum State {
|
||||
SKIP_CTRL_R,
|
||||
WAIT_REGISTER,
|
||||
@ -220,11 +224,11 @@ public class ExEditorKit extends DefaultEditorKit {
|
||||
switch (state) {
|
||||
case SKIP_CTRL_R:
|
||||
state = State.WAIT_REGISTER;
|
||||
target.setCurrentAction(this);
|
||||
target.setCurrentAction(this, '\"');
|
||||
break;
|
||||
case WAIT_REGISTER:
|
||||
state = State.SKIP_CTRL_R;
|
||||
target.setCurrentAction(null);
|
||||
target.clearCurrentAction();
|
||||
final char c = key.getKeyChar();
|
||||
if (c != KeyEvent.CHAR_UNDEFINED) {
|
||||
final Register register = VimPlugin.getRegister().getRegister(c);
|
||||
@ -244,6 +248,11 @@ public class ExEditorKit extends DefaultEditorKit {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
state = State.SKIP_CTRL_R;
|
||||
}
|
||||
}
|
||||
|
||||
public static class CompleteEntryAction extends TextAction {
|
||||
@ -268,9 +277,8 @@ public class ExEditorKit extends DefaultEditorKit {
|
||||
}
|
||||
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
VimPlugin.getProcess().cancelExEntry(
|
||||
ExEntryPanel.getInstance().getEntry().getEditor(),
|
||||
ExEntryPanel.getInstance().getEntry().getContext());
|
||||
ExTextField target = (ExTextField)getTextComponent(e);
|
||||
target.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
@ -322,9 +330,7 @@ public class ExEditorKit extends DefaultEditorKit {
|
||||
doc.remove(dot - delChars, delChars);
|
||||
}
|
||||
else {
|
||||
VimPlugin.getProcess().cancelExEntry(
|
||||
ExEntryPanel.getInstance().getEntry().getEditor(),
|
||||
ExEntryPanel.getInstance().getEntry().getContext());
|
||||
target.cancel();
|
||||
}
|
||||
}
|
||||
catch (BadLocationException bl) {
|
||||
@ -423,7 +429,7 @@ public class ExEditorKit extends DefaultEditorKit {
|
||||
}
|
||||
}
|
||||
|
||||
public static class StartDigraphAction extends TextAction {
|
||||
public static class StartDigraphAction extends TextAction implements MultiStepAction {
|
||||
@Nullable private DigraphSequence digraphSequence;
|
||||
|
||||
StartDigraphAction() {
|
||||
@ -436,14 +442,17 @@ public class ExEditorKit extends DefaultEditorKit {
|
||||
if (key != null && digraphSequence != null) {
|
||||
DigraphSequence.DigraphResult res = digraphSequence.processKey(key, target.getEditor());
|
||||
switch (res.getResult()) {
|
||||
case DigraphSequence.DigraphResult.RES_OK:
|
||||
target.setCurrentActionPromptCharacter(res.getPromptCharacter());
|
||||
break;
|
||||
case DigraphSequence.DigraphResult.RES_BAD:
|
||||
target.setCurrentAction(null);
|
||||
target.clearCurrentAction();
|
||||
target.handleKey(key);
|
||||
break;
|
||||
case DigraphSequence.DigraphResult.RES_DONE:
|
||||
final KeyStroke digraph = res.getStroke();
|
||||
digraphSequence = null;
|
||||
target.setCurrentAction(null);
|
||||
target.clearCurrentAction();
|
||||
if (digraph != null) {
|
||||
target.handleKey(digraph);
|
||||
}
|
||||
@ -451,11 +460,16 @@ public class ExEditorKit extends DefaultEditorKit {
|
||||
}
|
||||
}
|
||||
else if (key != null && DigraphSequence.isDigraphStart(key)) {
|
||||
target.setCurrentAction(this);
|
||||
digraphSequence = new DigraphSequence();
|
||||
digraphSequence.processKey(key, target.getEditor());
|
||||
DigraphSequence.DigraphResult res = digraphSequence.processKey(key, target.getEditor());
|
||||
target.setCurrentAction(this, res.getPromptCharacter());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
digraphSequence = null;
|
||||
}
|
||||
}
|
||||
|
||||
private static ExEditorKit instance;
|
||||
|
@ -111,10 +111,10 @@ public class ExEntryPanel extends JPanel implements LafManagerListener {
|
||||
this.label.setText(label);
|
||||
this.count = count;
|
||||
setFontForElements();
|
||||
entry.reset();
|
||||
entry.setEditor(editor, context);
|
||||
entry.setText(initText);
|
||||
entry.setType(label);
|
||||
entry.setInsertMode();
|
||||
parent = editor.getContentComponent();
|
||||
if (!ApplicationManager.getApplication().isUnitTestMode()) {
|
||||
JRootPane root = SwingUtilities.getRootPane(parent);
|
||||
@ -232,6 +232,8 @@ public class ExEntryPanel extends JPanel implements LafManagerListener {
|
||||
logger.info("deactivate");
|
||||
if (!active) return;
|
||||
active = false;
|
||||
entry.deactivate();
|
||||
|
||||
if (!ApplicationManager.getApplication().isUnitTestMode()) {
|
||||
if (refocusOwningEditor && parent != null) {
|
||||
UiHelper.requestFocus(parent);
|
||||
|
@ -33,8 +33,11 @@ public class ExKeyBindings {
|
||||
// TODO - add the following keys:
|
||||
// Ctrl-\ Ctrl-N - abort
|
||||
static final KeyBinding[] bindings = new KeyBinding[]{
|
||||
// Note that escape will cancel a pending insert digraph/register before cancelling
|
||||
new KeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), ExEditorKit.EscapeChar),
|
||||
new KeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_OPEN_BRACKET, KeyEvent.CTRL_MASK), ExEditorKit.EscapeChar),
|
||||
|
||||
// Cancel immediately cancels entry
|
||||
new KeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_C, KeyEvent.CTRL_MASK), ExEditorKit.CancelEntry),
|
||||
|
||||
new KeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), ExEditorKit.CompleteEntry),
|
||||
|
@ -26,6 +26,7 @@ import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.util.ui.JBUI;
|
||||
import com.maddyhome.idea.vim.VimPlugin;
|
||||
import com.maddyhome.idea.vim.group.HistoryGroup;
|
||||
import kotlin.text.StringsKt;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.annotations.TestOnly;
|
||||
@ -33,13 +34,12 @@ import org.jetbrains.annotations.TestOnly;
|
||||
import javax.swing.*;
|
||||
import javax.swing.text.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.FocusAdapter;
|
||||
import java.awt.event.FocusEvent;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.awt.event.*;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import static java.lang.Math.max;
|
||||
import static java.lang.Math.min;
|
||||
|
||||
/**
|
||||
* Provides a custom keymap for the text field. The keymap is the VIM Ex command keymapping
|
||||
@ -62,6 +62,15 @@ public class ExTextField extends JTextField {
|
||||
});
|
||||
}
|
||||
|
||||
void reset() {
|
||||
clearCurrentAction();
|
||||
setInsertMode();
|
||||
}
|
||||
|
||||
void deactivate() {
|
||||
clearCurrentAction();
|
||||
}
|
||||
|
||||
// Minimize margins and insets. These get added to the default margins in the UI class that we can't override.
|
||||
// (I.e. DarculaTextFieldUI#getDefaultMargins, MacIntelliJTextFieldUI#getDefaultMargin, WinIntelliJTextFieldUI#getDefaultMargin)
|
||||
// This is an attempt to mitigate the gap in ExEntryPanel between the label (':', '/', '?') and the text field.
|
||||
@ -231,17 +240,62 @@ public class ExTextField extends JTextField {
|
||||
return new ExDocument();
|
||||
}
|
||||
|
||||
public void escape() {
|
||||
/**
|
||||
* Cancels current action, if there is one. If not, cancels entry.
|
||||
*/
|
||||
void escape() {
|
||||
if (currentAction != null) {
|
||||
currentAction = null;
|
||||
clearCurrentAction();
|
||||
}
|
||||
else {
|
||||
VimPlugin.getProcess().cancelExEntry(editor, context);
|
||||
cancel();
|
||||
}
|
||||
}
|
||||
|
||||
void setCurrentAction(@Nullable Action action) {
|
||||
/**
|
||||
* Cancels entry, including any current action.
|
||||
*/
|
||||
void cancel() {
|
||||
clearCurrentAction();
|
||||
VimPlugin.getProcess().cancelExEntry(editor, context);
|
||||
}
|
||||
|
||||
void setCurrentAction(@NotNull ExEditorKit.MultiStepAction action, char pendingIndicator) {
|
||||
this.currentAction = action;
|
||||
setCurrentActionPromptCharacter(pendingIndicator);
|
||||
}
|
||||
|
||||
void clearCurrentAction() {
|
||||
if (currentAction != null) {
|
||||
currentAction.reset();
|
||||
}
|
||||
currentAction = null;
|
||||
clearCurrentActionPromptCharacter();
|
||||
}
|
||||
|
||||
void setCurrentActionPromptCharacter(char promptCharacter) {
|
||||
final String text = removePromptCharacter();
|
||||
this.currentActionPromptCharacter = promptCharacter;
|
||||
currentActionPromptCharacterOffset = currentActionPromptCharacterOffset == -1 ? getCaretPosition() : currentActionPromptCharacterOffset;
|
||||
StringBuilder sb = new StringBuilder(text);
|
||||
sb.insert(currentActionPromptCharacterOffset, currentActionPromptCharacter);
|
||||
updateText(sb.toString());
|
||||
setCaretPosition(currentActionPromptCharacterOffset);
|
||||
}
|
||||
|
||||
void clearCurrentActionPromptCharacter() {
|
||||
final int offset = getCaretPosition();
|
||||
final String text = removePromptCharacter();
|
||||
updateText(text);
|
||||
setCaretPosition(min(offset, text.length()));
|
||||
currentActionPromptCharacter = '\0';
|
||||
currentActionPromptCharacterOffset = -1;
|
||||
}
|
||||
|
||||
private String removePromptCharacter() {
|
||||
return currentActionPromptCharacterOffset == -1
|
||||
? getText()
|
||||
: StringsKt.removeRange(getText(), currentActionPromptCharacterOffset, currentActionPromptCharacterOffset + 1).toString();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@ -264,7 +318,7 @@ public class ExTextField extends JTextField {
|
||||
}
|
||||
|
||||
private void resetCaret() {
|
||||
if (getCaretPosition() == getText().length()) {
|
||||
if (getCaretPosition() == getText().length() || currentActionPromptCharacterOffset == getText().length() - 1) {
|
||||
setNormalModeCaret();
|
||||
}
|
||||
else {
|
||||
@ -315,7 +369,6 @@ public class ExTextField extends JTextField {
|
||||
}
|
||||
|
||||
void setMode(CaretMode mode, int blockPercentage) {
|
||||
|
||||
// Make sure damage gets updated for the old and new shape so the flashing works correctly
|
||||
updateDamage();
|
||||
this.mode = mode;
|
||||
@ -403,7 +456,9 @@ public class ExTextField extends JTextField {
|
||||
private String lastEntry;
|
||||
private List<HistoryGroup.HistoryEntry> history;
|
||||
private int histIndex = 0;
|
||||
@Nullable private Action currentAction;
|
||||
@Nullable private ExEditorKit.MultiStepAction currentAction;
|
||||
private char currentActionPromptCharacter;
|
||||
private int currentActionPromptCharacterOffset = -1;
|
||||
|
||||
private static final String vimExTextFieldDisposeKey = "vimExTextFieldDisposeKey";
|
||||
private static final Logger logger = Logger.getInstance(ExTextField.class.getName());
|
||||
|
@ -32,7 +32,6 @@ class ExEntryTest: VimTestCase() {
|
||||
|
||||
deactivateExEntry()
|
||||
|
||||
// TODO: This has a different implementation, which is correct? What are the side effects?
|
||||
assertFalse(options.isSet(Options.INCREMENTAL_SEARCH))
|
||||
typeExInput(":set incsearch<C-C>")
|
||||
assertFalse(options.isSet(Options.INCREMENTAL_SEARCH))
|
||||
@ -65,19 +64,25 @@ class ExEntryTest: VimTestCase() {
|
||||
}
|
||||
|
||||
fun `test caret shape`() {
|
||||
// Show block at end of input (normal)
|
||||
// Show vertical bar in insert mode
|
||||
// Show horizontal bar in replace mode
|
||||
typeExInput(":")
|
||||
assertEquals("BLOCK 100", exEntryPanel.entry.caretShape)
|
||||
|
||||
typeText("set")
|
||||
assertEquals("BLOCK 100", exEntryPanel.entry.caretShape)
|
||||
|
||||
typeText("<Home>")
|
||||
deactivateExEntry()
|
||||
typeExInput(":set<Home>")
|
||||
assertEquals("VER 25", exEntryPanel.entry.caretShape)
|
||||
|
||||
typeText("<Insert>")
|
||||
deactivateExEntry()
|
||||
typeExInput(":set<Home><Insert>")
|
||||
assertEquals("HOR 20", exEntryPanel.entry.caretShape)
|
||||
|
||||
typeText("<Insert>")
|
||||
deactivateExEntry()
|
||||
typeExInput(":set<Home><Insert><Insert>")
|
||||
assertEquals("VER 25", exEntryPanel.entry.caretShape)
|
||||
}
|
||||
|
||||
@ -349,24 +354,64 @@ class ExEntryTest: VimTestCase() {
|
||||
fun `test insert digraph`() {
|
||||
typeExInput(":<C-K>OK")
|
||||
assertExText("✓")
|
||||
assertExOffset(1)
|
||||
|
||||
deactivateExEntry()
|
||||
|
||||
typeExInput(":set<Home><C-K>OK")
|
||||
assertExText("✓set")
|
||||
assertExOffset(1)
|
||||
|
||||
deactivateExEntry()
|
||||
|
||||
typeExInput(":set<Home><Insert><C-K>OK")
|
||||
assertExText("✓et")
|
||||
assertExOffset(1)
|
||||
}
|
||||
|
||||
// TODO: Test caret feedback
|
||||
// Vim shows "?" as the char under the caret after <C-K>, then echoes the first char of the digraph
|
||||
fun `test prompt while inserting digraph`() {
|
||||
typeExInput(":<C-K>")
|
||||
assertExText("?")
|
||||
assertExOffset(0)
|
||||
|
||||
deactivateExEntry()
|
||||
|
||||
typeExInput(":<C-K>O")
|
||||
assertExText("O")
|
||||
assertExOffset(0)
|
||||
|
||||
deactivateExEntry()
|
||||
|
||||
typeExInput(":set<Home><C-K>")
|
||||
assertExText("?set")
|
||||
assertExOffset(0)
|
||||
|
||||
deactivateExEntry()
|
||||
|
||||
typeExInput(":set<Home><C-K>O")
|
||||
assertExText("Oset")
|
||||
assertExOffset(0)
|
||||
}
|
||||
|
||||
fun `test escape cancels digraph`() {
|
||||
typeExInput(":<C-K><Esc>OK")
|
||||
assertIsActive()
|
||||
assertExText("OK")
|
||||
|
||||
deactivateExEntry()
|
||||
|
||||
// Note that the docs state that hitting escape stops digraph entry and cancels command line mode. In practice,
|
||||
// this isn't true - digraph entry is stopped, but command line mode continues
|
||||
typeExInput(":<C-K>O<Esc>K")
|
||||
assertIsActive()
|
||||
assertEquals("K", exEntryPanel.text)
|
||||
|
||||
deactivateExEntry()
|
||||
}
|
||||
|
||||
// TODO: Test inserting control characters, if/when supported
|
||||
|
||||
fun `test enter literal character by code`() {
|
||||
fun `test insert literal character`() {
|
||||
typeExInput(":<C-V>123<C-V>080")
|
||||
assertExText("{P")
|
||||
|
||||
@ -394,21 +439,36 @@ class ExEntryTest: VimTestCase() {
|
||||
|
||||
typeExInput(":<C-Q>u00a9")
|
||||
assertExText("©")
|
||||
|
||||
deactivateExEntry()
|
||||
|
||||
typeExInput(":set<Home><C-V>u00A9")
|
||||
assertExText("©set")
|
||||
assertExOffset(1)
|
||||
}
|
||||
|
||||
fun `test escape cancels digraph`() {
|
||||
typeExInput(":<C-K><Esc>OK")
|
||||
assertIsActive()
|
||||
assertExText("OK")
|
||||
fun `test prompt while inserting literal character`() {
|
||||
typeExInput(":<C-V>")
|
||||
assertExText("^")
|
||||
assertExOffset(0)
|
||||
|
||||
// TODO: The Vim docs states Esc exits command line context, but Vim actually cancels digraph context
|
||||
// deactivateExEntry()
|
||||
//
|
||||
// typeExInput(":<C-K>O<Esc>K")
|
||||
// assertTrue(exEntryPanel.isActive)
|
||||
// assertEquals("K", exEntryPanel.text)
|
||||
//
|
||||
// deactivateExEntry()
|
||||
deactivateExEntry()
|
||||
|
||||
typeExInput(":<C-V>o")
|
||||
assertExText("^")
|
||||
assertExOffset(0)
|
||||
|
||||
typeText("1")
|
||||
assertExText("^")
|
||||
assertExOffset(0)
|
||||
|
||||
typeText("2")
|
||||
assertExText("^")
|
||||
assertExOffset(0)
|
||||
|
||||
typeText("3")
|
||||
assertExText("S")
|
||||
assertExOffset(1)
|
||||
}
|
||||
|
||||
fun `test insert register`() {
|
||||
@ -491,7 +551,7 @@ class ExEntryTest: VimTestCase() {
|
||||
private fun deactivateExEntry() {
|
||||
// We don't need to reset text, that's handled by #active
|
||||
if (exEntryPanel.isActive)
|
||||
typeText("<Esc>")
|
||||
typeText("<C-C>")
|
||||
}
|
||||
|
||||
private fun assertExText(expected: String) {
|
||||
|
Loading…
Reference in New Issue
Block a user