Search in sources :

Example 1 with CommandState

use of com.maddyhome.idea.vim.command.CommandState in project ideavim by JetBrains.

the class EditorActionHandlerBase method execute.

public final void execute(@NotNull Editor editor, @NotNull DataContext context) {
    editor = InjectedLanguageUtil.getTopLevelEditor(editor);
    logger.debug("execute");
    if (!VimPlugin.isEnabled()) {
        return;
    }
    final CommandState state = CommandState.getInstance(editor);
    final Command cmd = state.getCommand();
    if (cmd == null || !execute(editor, context, cmd)) {
        VimPlugin.indicateError();
    }
}
Also used : Command(com.maddyhome.idea.vim.command.Command) CommandState(com.maddyhome.idea.vim.command.CommandState)

Example 2 with CommandState

use of com.maddyhome.idea.vim.command.CommandState in project ideavim by JetBrains.

the class KeyHandler method partialReset.

/**
   * Partially resets the state of this handler. Resets the command count, clears the key list, resets the key tree
   * node to the root for the current mode we are in.
   *
   * @param editor The editor to reset.
   */
private void partialReset(@Nullable Editor editor) {
    count = 0;
    keys = new ArrayList<KeyStroke>();
    CommandState editorState = CommandState.getInstance(editor);
    editorState.stopMappingTimer();
    editorState.getMappingKeys().clear();
    editorState.setCurrentNode(VimPlugin.getKey().getKeyRoot(editorState.getMappingMode()));
}
Also used : CommandState(com.maddyhome.idea.vim.command.CommandState)

Example 3 with CommandState

use of com.maddyhome.idea.vim.command.CommandState in project ideavim by JetBrains.

the class KeyHandler method handleKey.

public void handleKey(@NotNull Editor editor, @NotNull KeyStroke key, @NotNull DataContext context, boolean allowKeyMappings) {
    VimPlugin.clearError();
    // All the editor actions should be performed with top level editor!!!
    // Be careful: all the EditorActionHandler implementation should correctly process InjectedEditors
    editor = InjectedLanguageUtil.getTopLevelEditor(editor);
    final CommandState editorState = CommandState.getInstance(editor);
    // If this is a "regular" character keystroke, get the character
    char chKey = key.getKeyChar() == KeyEvent.CHAR_UNDEFINED ? 0 : key.getKeyChar();
    final boolean isRecording = editorState.isRecording();
    boolean shouldRecord = true;
    // Check for command count before key mappings - otherwise e.g. ':map 0 ^' breaks command counts that contain a zero
    if (isCommandCount(editorState, chKey)) {
        // Update the count
        count = count * 10 + (chKey - '0');
    } else if (allowKeyMappings && handleKeyMapping(editor, key, context)) {
        return;
    } else // Unlike the digits, this must be checked *after* checking for key mappings
    if (isDeleteCommandCount(key, editorState)) {
        // "Remove" the last digit sent to us
        count /= 10;
    } else if (isEditorReset(key, editorState)) {
        handleEditorReset(editor, key, context);
    } else // First let's check to see if we are at the point of expecting a single character argument to a command.
    if (currentArg == Argument.Type.CHARACTER) {
        handleCharArgument(key, chKey);
    } else // If we are this far, then the user must be entering a command or a non-single-character argument
    // to an entered command. Let's figure out which it is
    {
        // For debugging purposes we track the keys entered for this command
        keys.add(key);
        // Ask the key/action tree if this is an appropriate key at this point in the command and if so,
        // return the node matching this keystroke
        final Node node = editorState.getCurrentNode().getChild(key);
        if (handleDigraph(editor, key, context, node)) {
            return;
        }
        // If this is a branch node we have entered only part of a multi-key command
        if (node instanceof BranchNode) {
            handleBranchNode(editor, context, editorState, chKey, (BranchNode) node);
        } else // If this is a command node the user has entered a valid key sequence of a known command
        if (node instanceof CommandNode) {
            handleCommandNode(editor, context, (CommandNode) node);
        } else // be the first keystroke of the argument of the current command
        if (node instanceof ArgumentNode) {
            shouldRecord = handleArgumentNode(editor, key, context, editorState, (ArgumentNode) node);
        } else {
            if (lastWasBS && lastChar != 0 && Options.getInstance().isSet("digraph")) {
                char dig = VimPlugin.getDigraph().getDigraph(lastChar, key.getKeyChar());
                key = KeyStroke.getKeyStroke(dig);
            }
            // If we are in insert/replace mode send this key in for processing
            if (editorState.getMode() == CommandState.Mode.INSERT || editorState.getMode() == CommandState.Mode.REPLACE) {
                if (!VimPlugin.getChange().processKey(editor, context, key)) {
                    shouldRecord = false;
                }
            } else if (editorState.getMappingMode() == MappingMode.CMD_LINE) {
                if (!VimPlugin.getProcess().processExKey(editor, key)) {
                    shouldRecord = false;
                }
            } else // If we get here then the user has entered an unrecognized series of keystrokes
            {
                state = State.BAD_COMMAND;
            }
            lastChar = key.getKeyChar();
            partialReset(editor);
        }
    }
    // Do we have a fully entered command at this point? If so, lets execute it
    if (state == State.READY) {
        executeCommand(editor, key, context, editorState);
    } else if (state == State.BAD_COMMAND) {
        if (editorState.getMappingMode() == MappingMode.OP_PENDING) {
            editorState.popState();
        } else {
            VimPlugin.indicateError();
            reset(editor);
        }
    } else // We had some sort of error so reset the handler and let the user know (beep)
    if (state == State.ERROR) {
        VimPlugin.indicateError();
        fullReset(editor);
    } else if (isRecording && shouldRecord) {
        VimPlugin.getRegister().recordKeyStroke(key);
    }
}
Also used : CommandState(com.maddyhome.idea.vim.command.CommandState)

Example 4 with CommandState

use of com.maddyhome.idea.vim.command.CommandState in project ideavim by JetBrains.

the class KeyHandler method handleKeyMapping.

private boolean handleKeyMapping(@NotNull final Editor editor, @NotNull final KeyStroke key, @NotNull final DataContext context) {
    final CommandState commandState = CommandState.getInstance(editor);
    commandState.stopMappingTimer();
    final List<KeyStroke> mappingKeys = commandState.getMappingKeys();
    final List<KeyStroke> fromKeys = new ArrayList<KeyStroke>(mappingKeys);
    fromKeys.add(key);
    final MappingMode mappingMode = commandState.getMappingMode();
    if (MappingMode.NVO.contains(mappingMode) && (state != State.NEW_COMMAND || currentArg != Argument.Type.NONE)) {
        return false;
    }
    final KeyMapping mapping = VimPlugin.getKey().getKeyMapping(mappingMode);
    final MappingInfo currentMappingInfo = mapping.get(fromKeys);
    final MappingInfo prevMappingInfo = mapping.get(mappingKeys);
    final MappingInfo mappingInfo = currentMappingInfo != null ? currentMappingInfo : prevMappingInfo;
    final Application application = ApplicationManager.getApplication();
    if (mapping.isPrefix(fromKeys)) {
        mappingKeys.add(key);
        if (!application.isUnitTestMode() && Options.getInstance().isSet(Options.TIMEOUT)) {
            commandState.startMappingTimer(new ActionListener() {

                @Override
                public void actionPerformed(ActionEvent actionEvent) {
                    mappingKeys.clear();
                    for (KeyStroke keyStroke : fromKeys) {
                        handleKey(editor, keyStroke, new EditorDataContext(editor), false);
                    }
                }
            });
        }
        return true;
    } else if (mappingInfo != null) {
        mappingKeys.clear();
        final Runnable handleMappedKeys = new Runnable() {

            @Override
            public void run() {
                if (editor.isDisposed()) {
                    return;
                }
                final List<KeyStroke> toKeys = mappingInfo.getToKeys();
                final VimExtensionHandler extensionHandler = mappingInfo.getExtensionHandler();
                final EditorDataContext currentContext = new EditorDataContext(editor);
                if (toKeys != null) {
                    final boolean fromIsPrefix = isPrefix(mappingInfo.getFromKeys(), toKeys);
                    boolean first = true;
                    for (KeyStroke keyStroke : toKeys) {
                        final boolean recursive = mappingInfo.isRecursive() && !(first && fromIsPrefix);
                        handleKey(editor, keyStroke, currentContext, recursive);
                        first = false;
                    }
                } else if (extensionHandler != null) {
                    RunnableHelper.runWriteCommand(editor.getProject(), new Runnable() {

                        @Override
                        public void run() {
                            extensionHandler.execute(editor, context);
                        }
                    }, "Vim " + extensionHandler.getClass().getSimpleName(), null);
                }
                if (prevMappingInfo != null) {
                    handleKey(editor, key, currentContext);
                }
            }
        };
        if (application.isUnitTestMode()) {
            handleMappedKeys.run();
        } else {
            application.invokeLater(handleMappedKeys);
        }
        return true;
    } else {
        final List<KeyStroke> unhandledKeys = new ArrayList<KeyStroke>(mappingKeys);
        mappingKeys.clear();
        for (KeyStroke keyStroke : unhandledKeys) {
            handleKey(editor, keyStroke, context, false);
        }
        return false;
    }
}
Also used : ActionEvent(java.awt.event.ActionEvent) AnActionEvent(com.intellij.openapi.actionSystem.AnActionEvent) VimExtensionHandler(com.maddyhome.idea.vim.extension.VimExtensionHandler) ArrayList(java.util.ArrayList) MappingMode(com.maddyhome.idea.vim.command.MappingMode) ActionListener(java.awt.event.ActionListener) CommandState(com.maddyhome.idea.vim.command.CommandState) ArrayList(java.util.ArrayList) List(java.util.List) Application(com.intellij.openapi.application.Application)

Example 5 with CommandState

use of com.maddyhome.idea.vim.command.CommandState in project ideavim by JetBrains.

the class MacroActionTest method testRecordMacro.

// |q|
public void testRecordMacro() {
    final Editor editor = typeTextInFile(parseKeys("qa", "3l", "q"), "on<caret>e two three\n");
    final CommandState commandState = CommandState.getInstance(editor);
    assertFalse(commandState.isRecording());
    final RegisterGroup registerGroup = VimPlugin.getRegister();
    final Register register = registerGroup.getRegister('a');
    assertNotNull(register);
    assertEquals("3l", register.getText());
}
Also used : Register(com.maddyhome.idea.vim.common.Register) CommandState(com.maddyhome.idea.vim.command.CommandState) Editor(com.intellij.openapi.editor.Editor) RegisterGroup(com.maddyhome.idea.vim.group.RegisterGroup)

Aggregations

CommandState (com.maddyhome.idea.vim.command.CommandState)5 AnActionEvent (com.intellij.openapi.actionSystem.AnActionEvent)1 Application (com.intellij.openapi.application.Application)1 Editor (com.intellij.openapi.editor.Editor)1 Command (com.maddyhome.idea.vim.command.Command)1 MappingMode (com.maddyhome.idea.vim.command.MappingMode)1 Register (com.maddyhome.idea.vim.common.Register)1 VimExtensionHandler (com.maddyhome.idea.vim.extension.VimExtensionHandler)1 RegisterGroup (com.maddyhome.idea.vim.group.RegisterGroup)1 ActionEvent (java.awt.event.ActionEvent)1 ActionListener (java.awt.event.ActionListener)1 ArrayList (java.util.ArrayList)1 List (java.util.List)1