1
0
mirror of https://github.com/chylex/IntelliJ-IdeaVim.git synced 2025-03-02 16:22:31 +01:00

Extracted logic from MapHandler to KeyGroup

This commit is contained in:
Andrey Vlasovskikh 2014-04-04 16:02:55 +04:00
parent db6399f1c5
commit bb9d551dad
2 changed files with 152 additions and 145 deletions
src/com/maddyhome/idea/vim

View File

@ -18,23 +18,22 @@
package com.maddyhome.idea.vim.ex.handler;
import com.google.common.collect.ImmutableList;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.editor.Editor;
import com.maddyhome.idea.vim.VimPlugin;
import com.maddyhome.idea.vim.command.MappingMode;
import com.maddyhome.idea.vim.ex.*;
import com.maddyhome.idea.vim.key.KeyMapping;
import com.maddyhome.idea.vim.ex.CommandHandler;
import com.maddyhome.idea.vim.ex.CommandName;
import com.maddyhome.idea.vim.ex.ExCommand;
import com.maddyhome.idea.vim.ex.VimrcCommandHandler;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.event.KeyEvent;
import java.util.*;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static com.maddyhome.idea.vim.helper.StringHelper.*;
import static com.maddyhome.idea.vim.helper.StringHelper.parseKeys;
/**
* @author vlan
@ -56,32 +55,26 @@ public class MapHandler extends CommandHandler implements VimrcCommandHandler {
}
@Override
public boolean execute(@NotNull Editor editor, @NotNull DataContext context,
@NotNull ExCommand cmd) throws ExException {
public boolean execute(@NotNull Editor editor, @NotNull DataContext context, @NotNull ExCommand cmd) {
return executeCommand(cmd, editor);
}
@Override
public void execute(@NotNull ExCommand cmd) throws ExException {
public void execute(@NotNull ExCommand cmd) {
executeCommand(cmd, null);
}
private boolean executeCommand(@NotNull ExCommand cmd, @Nullable Editor editor) throws ExException {
private boolean executeCommand(@NotNull ExCommand cmd, @Nullable Editor editor) {
final Set<MappingMode> modes = getMappingModes(cmd.getCommand());
if (modes != null) {
final String argument = cmd.getArgument();
if (argument.isEmpty()) {
return editor != null && showMappings(modes, editor);
return editor != null && VimPlugin.getKey().showKeyMappings(modes, editor);
}
else {
final Matcher matcher = RE_MAP_ARGUMENTS.matcher(argument);
if (matcher.matches()) {
final List<KeyStroke> leftKeys = parseKeys(matcher.group(1));
final List<KeyStroke> rightKeys = parseKeys(matcher.group(2));
for (MappingMode mode : modes) {
final KeyMapping mapping = VimPlugin.getKey().getKeyMapping(mode);
mapping.put(leftKeys, rightKeys);
}
VimPlugin.getKey().putKeyMapping(modes, parseKeys(matcher.group(1)), parseKeys(matcher.group(2)));
return true;
}
}
@ -89,56 +82,6 @@ public class MapHandler extends CommandHandler implements VimrcCommandHandler {
return false;
}
private boolean showMappings(@NotNull Set<MappingMode> modes, @NotNull Editor editor) {
final List<MappingRow> rows = getKeyMappingRows(modes);
final StringBuilder builder = new StringBuilder();
for (MappingRow row : rows) {
builder.append(leftJustify(getModesStringCode(row.getModes()), 2, ' '));
builder.append(" ");
builder.append(leftJustify(toKeyNotation(row.getFromKeys()), 13, ' '));
builder.append(" ");
builder.append(toKeyNotation(row.getToKeys()));
builder.append("\n");
}
ExOutputModel.getInstance(editor).output(builder.toString());
return true;
}
private List<MappingRow> getKeyMappingRows(@NotNull Set<MappingMode> modes) {
final Map<ImmutableList<KeyStroke>, Set<MappingMode>> actualModes = new HashMap<ImmutableList<KeyStroke>, Set<MappingMode>>();
for (MappingMode mode : modes) {
final KeyMapping mapping = VimPlugin.getKey().getKeyMapping(mode);
for (List<KeyStroke> fromKeys : mapping) {
final ImmutableList<KeyStroke> key = ImmutableList.copyOf(fromKeys);
final Set<MappingMode> value = actualModes.get(key);
final Set<MappingMode> newValue;
if (value != null) {
newValue = new HashSet<MappingMode>(value);
newValue.add(mode);
}
else {
newValue = EnumSet.of(mode);
}
actualModes.put(key, newValue);
}
}
final List<MappingRow> rows = new ArrayList<MappingRow>();
for (Map.Entry<ImmutableList<KeyStroke>, Set<MappingMode>> entry : actualModes.entrySet()) {
final ArrayList<KeyStroke> fromKeys = new ArrayList<KeyStroke>(entry.getKey());
final Set<MappingMode> mappingModes = entry.getValue();
if (!mappingModes.isEmpty()) {
final MappingMode mode = mappingModes.iterator().next();
final KeyMapping mapping = VimPlugin.getKey().getKeyMapping(mode);
final List<KeyStroke> toKeys = mapping.get(fromKeys);
if (toKeys != null) {
rows.add(new MappingRow(mappingModes, fromKeys, toKeys));
}
}
}
Collections.sort(rows);
return rows;
}
@Nullable
private Set<MappingMode> getMappingModes(@NotNull String command) {
if (command.equals("map")) {
@ -164,81 +107,4 @@ public class MapHandler extends CommandHandler implements VimrcCommandHandler {
}
return null;
}
private String getModesStringCode(@NotNull Set<MappingMode> modes) {
if (modes.equals(MappingMode.NVO)) {
return "";
}
else if (modes.contains(MappingMode.INSERT)) {
return "i";
}
else if (modes.contains(MappingMode.NORMAL)) {
return "n";
}
// TODO: Add more codes
return "";
}
private static class MappingRow implements Comparable<MappingRow> {
@NotNull private final Set<MappingMode> myModes;
@NotNull private final List<KeyStroke> myFromKeys;
@NotNull private final List<KeyStroke> myToKeys;
public MappingRow(@NotNull Set<MappingMode> modes, @NotNull List<KeyStroke> fromKeys,
@NotNull List<KeyStroke> toKeys) {
myModes = modes;
myFromKeys = fromKeys;
myToKeys = toKeys;
}
@Override
public int compareTo(@NotNull MappingRow other) {
final int size = myFromKeys.size();
final int otherSize = other.myFromKeys.size();
final int n = Math.min(size, otherSize);
for (int i = 0; i < n; i++) {
final int diff = compareKeys(myFromKeys.get(i), other.myFromKeys.get(i));
if (diff != 0) {
return diff;
}
}
return size - otherSize;
}
private int compareKeys(@NotNull KeyStroke key1, @NotNull KeyStroke key2) {
final char c1 = key1.getKeyChar();
final char c2 = key2.getKeyChar();
if (c1 == KeyEvent.CHAR_UNDEFINED && c2 == KeyEvent.CHAR_UNDEFINED) {
final int keyCodeDiff = key1.getKeyCode() - key2.getKeyCode();
if (keyCodeDiff != 0) {
return keyCodeDiff;
}
return key1.getModifiers() - key2.getModifiers();
}
else if (c1 == KeyEvent.CHAR_UNDEFINED) {
return -1;
}
else if (c2 == KeyEvent.CHAR_UNDEFINED) {
return 1;
}
else {
return c1 - c2;
}
}
@NotNull
public Set<MappingMode> getModes() {
return myModes;
}
@NotNull
public List<KeyStroke> getFromKeys() {
return myFromKeys;
}
@NotNull
public List<KeyStroke> getToKeys() {
return myToKeys;
}
}
}

View File

@ -1,16 +1,20 @@
package com.maddyhome.idea.vim.group;
import com.google.common.collect.ImmutableList;
import com.intellij.openapi.actionSystem.ActionManager;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.KeyboardShortcut;
import com.intellij.openapi.actionSystem.ex.ActionManagerEx;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.keymap.Keymap;
import com.intellij.openapi.keymap.ex.KeymapManagerEx;
import com.maddyhome.idea.vim.VimPlugin;
import com.maddyhome.idea.vim.action.VimCommandAction;
import com.maddyhome.idea.vim.action.VimShortcutKeyAction;
import com.maddyhome.idea.vim.command.Argument;
import com.maddyhome.idea.vim.command.Command;
import com.maddyhome.idea.vim.command.MappingMode;
import com.maddyhome.idea.vim.ex.ExOutputModel;
import com.maddyhome.idea.vim.helper.StringHelper;
import com.maddyhome.idea.vim.key.*;
import org.jdom.Element;
@ -21,6 +25,8 @@ import javax.swing.*;
import java.awt.event.KeyEvent;
import java.util.*;
import static com.maddyhome.idea.vim.helper.StringHelper.*;
/**
* @author vlan
*/
@ -35,6 +41,29 @@ public class KeyGroup {
@NotNull private HashMap<MappingMode, RootNode> keyRoots = new HashMap<MappingMode, RootNode>();
@NotNull private Map<MappingMode, KeyMapping> keyMappings = new HashMap<MappingMode, KeyMapping>();
public boolean showKeyMappings(@NotNull Set<MappingMode> modes, @NotNull Editor editor) {
final List<MappingRow> rows = getKeyMappingRows(modes);
final StringBuilder builder = new StringBuilder();
for (MappingRow row : rows) {
builder.append(leftJustify(getModesStringCode(row.getModes()), 2, ' '));
builder.append(" ");
builder.append(leftJustify(toKeyNotation(row.getFromKeys()), 13, ' '));
builder.append(" ");
builder.append(toKeyNotation(row.getToKeys()));
builder.append("\n");
}
ExOutputModel.getInstance(editor).output(builder.toString());
return true;
}
public void putKeyMapping(@NotNull Set<MappingMode> modes, @NotNull List<KeyStroke> fromKeys,
@NotNull List<KeyStroke> toKeys) {
for (MappingMode mode : modes) {
final KeyMapping mapping = getKeyMapping(mode);
mapping.put(fromKeys, toKeys);
}
}
public void saveData(@NotNull Element element) {
final Element conflictsElement = new Element(SHORTCUT_CONFLICTS_ELEMENT);
for (Map.Entry<KeyStroke, ShortcutOwner> entry : shortcutConflicts.entrySet()) {
@ -295,4 +324,116 @@ public class KeyGroup {
return node;
}
private static List<MappingRow> getKeyMappingRows(@NotNull Set<MappingMode> modes) {
final Map<ImmutableList<KeyStroke>, Set<MappingMode>> actualModes = new HashMap<ImmutableList<KeyStroke>, Set<MappingMode>>();
for (MappingMode mode : modes) {
final KeyMapping mapping = VimPlugin.getKey().getKeyMapping(mode);
for (List<KeyStroke> fromKeys : mapping) {
final ImmutableList<KeyStroke> key = ImmutableList.copyOf(fromKeys);
final Set<MappingMode> value = actualModes.get(key);
final Set<MappingMode> newValue;
if (value != null) {
newValue = new HashSet<MappingMode>(value);
newValue.add(mode);
}
else {
newValue = EnumSet.of(mode);
}
actualModes.put(key, newValue);
}
}
final List<MappingRow> rows = new ArrayList<MappingRow>();
for (Map.Entry<ImmutableList<KeyStroke>, Set<MappingMode>> entry : actualModes.entrySet()) {
final ArrayList<KeyStroke> fromKeys = new ArrayList<KeyStroke>(entry.getKey());
final Set<MappingMode> mappingModes = entry.getValue();
if (!mappingModes.isEmpty()) {
final MappingMode mode = mappingModes.iterator().next();
final KeyMapping mapping = VimPlugin.getKey().getKeyMapping(mode);
final List<KeyStroke> toKeys = mapping.get(fromKeys);
if (toKeys != null) {
rows.add(new MappingRow(mappingModes, fromKeys, toKeys));
}
}
}
Collections.sort(rows);
return rows;
}
private static String getModesStringCode(@NotNull Set<MappingMode> modes) {
if (modes.equals(MappingMode.NVO)) {
return "";
}
else if (modes.contains(MappingMode.INSERT)) {
return "i";
}
else if (modes.contains(MappingMode.NORMAL)) {
return "n";
}
// TODO: Add more codes
return "";
}
private static class MappingRow implements Comparable<MappingRow> {
@NotNull private final Set<MappingMode> myModes;
@NotNull private final List<KeyStroke> myFromKeys;
@NotNull private final List<KeyStroke> myToKeys;
public MappingRow(@NotNull Set<MappingMode> modes, @NotNull List<KeyStroke> fromKeys,
@NotNull List<KeyStroke> toKeys) {
myModes = modes;
myFromKeys = fromKeys;
myToKeys = toKeys;
}
@Override
public int compareTo(@NotNull MappingRow other) {
final int size = myFromKeys.size();
final int otherSize = other.myFromKeys.size();
final int n = Math.min(size, otherSize);
for (int i = 0; i < n; i++) {
final int diff = compareKeys(myFromKeys.get(i), other.myFromKeys.get(i));
if (diff != 0) {
return diff;
}
}
return size - otherSize;
}
private int compareKeys(@NotNull KeyStroke key1, @NotNull KeyStroke key2) {
final char c1 = key1.getKeyChar();
final char c2 = key2.getKeyChar();
if (c1 == KeyEvent.CHAR_UNDEFINED && c2 == KeyEvent.CHAR_UNDEFINED) {
final int keyCodeDiff = key1.getKeyCode() - key2.getKeyCode();
if (keyCodeDiff != 0) {
return keyCodeDiff;
}
return key1.getModifiers() - key2.getModifiers();
}
else if (c1 == KeyEvent.CHAR_UNDEFINED) {
return -1;
}
else if (c2 == KeyEvent.CHAR_UNDEFINED) {
return 1;
}
else {
return c1 - c2;
}
}
@NotNull
public Set<MappingMode> getModes() {
return myModes;
}
@NotNull
public List<KeyStroke> getFromKeys() {
return myFromKeys;
}
@NotNull
public List<KeyStroke> getToKeys() {
return myToKeys;
}
}
}