1
0
mirror of https://github.com/chylex/IntelliJ-IdeaVim.git synced 2025-08-17 16:31:45 +02:00

Compare commits

...

60 Commits
0.52 ... 0.53

Author SHA1 Message Date
Alex Plate
60caac5139 Update CHANGES.md 2019-08-07 14:14:01 +03:00
Alex Plate
307e438a1e [EA-128752] Fix NPE on isPrimaryEditor 2019-08-06 15:38:33 +03:00
Alex Plate
89489f7c7f [EA-144484] Fix NPE on panel activation 2019-08-06 15:15:31 +03:00
Alex Plate
923a4706a0 [EA-137898] Fix file is invalid exception 2019-08-06 14:23:03 +03:00
Alex Plate
2594c7179e [EA-138502] Control-flow exceptions (like ProcessCanceledException) should never be logged 2019-08-06 14:21:33 +03:00
Alex Plate
0e2289caa6 [EA-129083] Fix OOBE for # action 2019-08-05 20:39:07 +03:00
Alex Plate
be26968237 [EA-138309] Fix possible exception 2019-08-05 20:20:44 +03:00
Alex Plate
022f1ededc Fix caret shape after enabling of plugin 2019-08-05 19:50:32 +03:00
Alex Plate
70a19dd95d Fix positioning on the end line in insert mode 2019-08-05 19:19:46 +03:00
Alex Plate
00b3f5b9f5 Update CHANGES.md 2019-08-05 13:59:49 +03:00
Alex Plate
8b0bb413d8 Merge pull request #198 from citizenmatt/bug/ex-dead-keys
Fix exception with dead keys in ex entry
2019-08-05 13:14:14 +03:00
Matt Ellis
bd5e7d94fe Fix tests 2019-08-02 21:21:32 +01:00
Matt Ellis
d43b2364a0 Reset ex entry panel when emulation is disabled 2019-08-02 16:49:00 +01:00
Matt Ellis
610e73d9e3 Merge branch 'master' into bug/ex-dead-keys 2019-08-02 13:55:31 +01:00
Alex Plate
6f2a454d46 [EA-141098] Fix exception during surround 2019-08-02 15:30:45 +03:00
Alex Plate
4edce29d53 [EA-209287] Fix exception on file close 2019-08-02 15:25:40 +03:00
Alex Plate
ed2b8dd129 Fix ex search for japanese language 2019-08-02 14:03:30 +03:00
Alex Plate
42cdb36a51 Update CHANGES.md 2019-08-01 18:48:47 +03:00
Alex Plate
159c22ac21 [EA-117268 2352322] Fix OOBE for check in string function 2019-08-01 18:34:50 +03:00
Alex Plate
75b6833245 [EA-117268 2386601] Fix OOBE for sentence detection 2019-08-01 18:34:49 +03:00
Alex Plate
b567717c75 [EA-117268 2394021] Fix OOBE for isEmptyLine function 2019-08-01 18:34:49 +03:00
Alex Plate
b2af829e2e [EA-117268 5135780] Fix OOBE for display ascii info 2019-08-01 18:34:49 +03:00
Alex Plate
6e81714937 [EA-117268 5154892] Fix OOBE for motion outer word 2019-08-01 18:34:49 +03:00
Alex Plate
cb9474d8d0 [EA-117268 5159449] Fix exception for inser character around cursor 2019-08-01 18:34:49 +03:00
Alex Plate
be47e4c050 [EA-117268 5165327] Fix a' for last caret position 2019-08-01 18:34:45 +03:00
Alex Plate
c301898147 [EA-117268 5167045] Fix das for empty file 2019-08-01 17:35:51 +03:00
Alex Plate
8324561022 Remove code comments 2019-08-01 17:17:06 +03:00
Alex Plate
834d630ef7 [EA-117268] Fix exception with w action 2019-08-01 17:09:43 +03:00
Alex Plate
c6259adad1 [VIM-1743] Do not show ideaput notification during surround 2019-08-01 16:03:11 +03:00
Alex Plate
9d1be34958 [VIM-1648] Make S&R self synchronized 2019-08-01 13:20:00 +03:00
Alex Plate
ce4e64ec40 Create annotations to annotate whenever a function require write/read lock 2019-07-31 21:15:32 +03:00
Alex Plate
b017466270 Clean up searchAndReplace method 2019-07-31 20:35:10 +03:00
Alex Plate
568d2304ea Ex commands should define write/read access explicitly 2019-07-31 20:15:09 +03:00
Alex Plate
5dc1b245d0 Get rid of OTHER_READ_WRITE flag because technically it's right action 2019-07-31 16:56:57 +03:00
Alex Plate
978d95b351 Clean up ex command processing 2019-07-31 16:47:19 +03:00
Alex Plate
90079c9dfe Remove legacy DONT_REOPEN flag
It's not used since 18cd7547
2019-07-31 16:26:48 +03:00
Alex Plate
57dec7e211 Fix mouse click appearance 2019-07-30 19:32:54 +03:00
Alex Plate
fa75c853a7 Update mouse pressed caret rules 2019-07-30 18:53:03 +03:00
Alex Plate
0887a57e29 [VIM-1725] Enable selection adjustment with a small delay 2019-07-30 17:52:34 +03:00
Alex Plate
18901dcd44 [EA-104755] Fix "Editor is disposed" exception with CTRL-O command 2019-07-29 20:11:20 +03:00
Alex Plate
caecbe5b63 Reformat isEndAllowed method 2019-07-26 20:24:54 +03:00
Alex Plate
077cab656b [EA-209305] Fix SO exception on enabling disabled plugin 2019-07-26 19:57:09 +03:00
Alex Plate
95d7a7e860 Insert some inferred annotations 2019-07-26 16:10:30 +03:00
Alex Plate
77a77c34b8 Fix possible NPE 2019-07-26 16:09:25 +03:00
Alex Plate
fa78cc2a9f Add Naveen Kumar Molleti to contributors list 2019-07-26 16:03:00 +03:00
Alex Plate
03f18af66f Temporaly get back ideajoin-examples because of help link in release
Revert "Move ideajoin examples to wiki"

This reverts commit d06f2a2d
2019-07-26 16:01:12 +03:00
Alex Plate
4e21145808 Merge pull request #200 from NOLFXceptMe/master
Fix ideajoin examples URL
2019-07-26 15:59:39 +03:00
Alex Plate
258557ee5d [VIM-1713] Add possibility to get ExEntryPanel without shortcuts 2019-07-26 15:27:30 +03:00
Alex Plate
88ad420716 Update kotlin version 2019-07-26 12:04:08 +03:00
Naveen Kumar Molleti
4828e40f0d Fix ideajoin examples URL 2019-07-25 17:49:34 -07:00
Alex Plate
5be29f5a07 Convert ExKeyBindings to kotlin 2019-07-25 18:29:31 +03:00
Alex Plate
48ac99a29b WIP: Renaming file 'ExKeyBindings' with Kotlin extension 2019-07-25 17:20:59 +03:00
Alex Plate
2c4f2139dd Fix warnings 2019-07-25 13:52:07 +03:00
Alex Plate
47236c1e6c Convert VimSurroundExtenstionTest to kotlin 2019-07-25 13:28:00 +03:00
Alex Plate
5d8996dc38 WIP: Renaming file 'VimSurroundExtensionTest' with Kotlin extension 2019-07-25 13:24:00 +03:00
Alex Plate
9feff84125 [VIM-1710] Fix opening empty file with "relative number" enabled 2019-07-24 16:34:42 +03:00
Alex Plate
c0fc62a1d6 [VIM-1712] Fix Y command for visual mode 2019-07-24 15:56:19 +03:00
Alex Plate
6b06d58759 [VIM-1711] Search is not triggered during surround action 2019-07-24 15:10:48 +03:00
Alex Plate
d06f2a2d18 Move ideajoin examples to wiki 2019-07-24 12:20:23 +03:00
Matt Ellis
36c4596a08 Fix exception with dead keys in ex entry
Will also highlight composed text on Mac
2019-06-11 19:57:11 +01:00
121 changed files with 1353 additions and 1000 deletions

View File

@@ -73,6 +73,7 @@ Contributors:
* [Pierce Corcoran](mailto:pierce@plasticcow.com) * [Pierce Corcoran](mailto:pierce@plasticcow.com)
* [Jonatan Tierno](mailto:jonatantierno@gmail.com) * [Jonatan Tierno](mailto:jonatantierno@gmail.com)
* [Brendan Annable](mailto:brendan@annable.me) * [Brendan Annable](mailto:brendan@annable.me)
* [Naveen Kumar Molleti](mailto:nerd.naveen@gmail.com)
If you are a contributor and your name is not listed here, feel free to If you are a contributor and your name is not listed here, feel free to
contact the maintainer. contact the maintainer.

View File

@@ -16,10 +16,23 @@ It is important to distinguish EAP from traditional pre-release software.
Please note that the quality of EAP versions may at times be way below even Please note that the quality of EAP versions may at times be way below even
usual beta standards. usual beta standards.
0.53, 2019-08-07
--------------
* [VIM-1711](https://youtrack.jetbrains.com/issue/VIM-1711) Search is not triggered during surround action
* [VIM-1712](https://youtrack.jetbrains.com/issue/VIM-1712) Fix `Y` command for visual mode
* [VIM-1713](https://youtrack.jetbrains.com/issue/VIM-1713) Surround in visual mode put caret in correct position
* [VIM-1732](https://youtrack.jetbrains.com/issue/VIM-1732) Fix SO after enabling vim mode
* [VIM-1710](https://youtrack.jetbrains.com/issue/VIM-1710) Fix opening empty file with "relative number" enabled
* [VIM-1725](https://youtrack.jetbrains.com/issue/VIM-1725) Fix problems with Japanese language
* [VIM-1648](https://youtrack.jetbrains.com/issue/VIM-1648) Fix exception while substitute with conformation
* [VIM-1736](https://youtrack.jetbrains.com/issue/VIM-1736) Fix `` for ex panel
* [VIM-1739](https://youtrack.jetbrains.com/issue/VIM-1739) Fix full-width characters for ex panel
0.52, 2019-07-23 0.52, 2019-07-23
-------------- --------------
* Introduce [Select Mode](https://vimhelp.org/visual.txt.html#Select-mode). * Introduce [Select Mode](https://github.com/JetBrains/ideavim/wiki/Select-mode).
* Fixed `:only` command * Fixed `:only` command

View File

@@ -76,7 +76,7 @@ The following `:set` commands can appear in `~/.ideavimrc` or be set manually in
`ideajoin` `ideajoin` Boolean (default false) - IdeaVim ONLY `ideajoin` `ideajoin` Boolean (default false) - IdeaVim ONLY
If true, join command will be performed via IDE If true, join command will be performed via IDE
See ideajoin-examples.md See wiki/`ideajoin` examples
'sidescroll' 'ss' minimum number of columns to scroll horizontally 'sidescroll' 'ss' minimum number of columns to scroll horizontally
'sidescrolloff' 'siso' min. number of columns to left and right of cursor 'sidescrolloff' 'siso' min. number of columns to left and right of cursor
@@ -89,4 +89,4 @@ The following `:set` commands can appear in `~/.ideavimrc` or be set manually in
'wrapscan' 'ws' searches wrap around the end of file 'wrapscan' 'ws' searches wrap around the end of file
---------- ----------
[1] - cursor keys, <End>, <Home>, <PageUp> and <PageDown> [1] - cursor keys, <End>, <Home>, <PageUp> and <PageDown>

View File

@@ -3,7 +3,7 @@ downloadIdeaSources=true
instrumentPluginCode=true instrumentPluginCode=true
version=SNAPSHOT version=SNAPSHOT
javaVersion=1.8 javaVersion=1.8
kotlinVersion=1.3.40 kotlinVersion=1.3.41
publishUsername=username publishUsername=username
publishToken=token publishToken=token
publishChannels=eap publishChannels=eap

View File

@@ -68,12 +68,9 @@ public class EventFacade {
public void setupTypedActionHandler(@NotNull VimTypedActionHandler handler) { public void setupTypedActionHandler(@NotNull VimTypedActionHandler handler) {
final TypedAction typedAction = getTypedAction(); final TypedAction typedAction = getTypedAction();
final TypedActionHandler rawHandler = typedAction.getRawHandler(); myOriginalTypedActionHandler = typedAction.getRawHandler();
if (!(rawHandler instanceof VimTypedActionHandler)) {
// Actually this if should always be true, but just as protection typedAction.setupRawHandler(handler);
myOriginalTypedActionHandler = rawHandler;
typedAction.setupRawHandler(handler);
}
} }
public void restoreTypedActionHandler() { public void restoreTypedActionHandler() {

View File

@@ -54,6 +54,7 @@ import com.maddyhome.idea.vim.helper.DocumentManager;
import com.maddyhome.idea.vim.helper.MacKeyRepeat; import com.maddyhome.idea.vim.helper.MacKeyRepeat;
import com.maddyhome.idea.vim.listener.VimListenerManager; import com.maddyhome.idea.vim.listener.VimListenerManager;
import com.maddyhome.idea.vim.option.OptionsManager; import com.maddyhome.idea.vim.option.OptionsManager;
import com.maddyhome.idea.vim.ui.ExEntryPanel;
import com.maddyhome.idea.vim.ui.VimEmulationConfigurable; import com.maddyhome.idea.vim.ui.VimEmulationConfigurable;
import org.jdom.Element; import org.jdom.Element;
import org.jdom.JDOMException; import org.jdom.JDOMException;
@@ -342,7 +343,9 @@ public class VimPlugin implements BaseComponent, PersistentStateComponent<Elemen
ApplicationManager.getApplication().invokeLater(this::updateState); ApplicationManager.getApplication().invokeLater(this::updateState);
VimListenerManager.GlobalListeners.enable(); getEditor().turnOn();
getSearch().turnOn();
VimListenerManager.INSTANCE.turnOn();
// Register vim actions in command mode // Register vim actions in command mode
RegisterActions.registerActions(); RegisterActions.registerActions();
@@ -447,12 +450,15 @@ public class VimPlugin implements BaseComponent, PersistentStateComponent<Elemen
} }
private void turnOnPlugin() { private void turnOnPlugin() {
initializePlugin(); if (initialized) {
KeyHandler.getInstance().fullReset(null); KeyHandler.getInstance().fullReset(null);
getEditor().turnOn(); getEditor().turnOn();
getSearch().turnOn(); getSearch().turnOn();
VimListenerManager.INSTANCE.turnOn(); VimListenerManager.INSTANCE.turnOn();
} else {
initializePlugin();
}
} }
private void turnOffPlugin() { private void turnOffPlugin() {
@@ -461,6 +467,7 @@ public class VimPlugin implements BaseComponent, PersistentStateComponent<Elemen
getEditor().turnOff(); getEditor().turnOff();
getSearch().turnOff(); getSearch().turnOff();
VimListenerManager.INSTANCE.turnOff(); VimListenerManager.INSTANCE.turnOff();
ExEntryPanel.fullReset();
} }
private void updateState() { private void updateState() {

View File

@@ -1,26 +1,23 @@
package com.maddyhome.idea.vim package com.maddyhome.idea.vim
import org.jdom.Element import org.jdom.Element
import kotlin.properties.ReadWriteProperty
import kotlin.reflect.KProperty
/** /**
* @author Alex Plate * @author Alex Plate
*/ */
class VimState { class VimState {
var isIdeaJoinNotified = false var isIdeaJoinNotified by StateProperty("idea-join")
var isIdeaPutNotified = false var isIdeaPutNotified by StateProperty("idea-put")
var isTemplateInSelectModeNotified = false var isTemplateInSelectModeNotified by StateProperty("template-selectmode")
fun readData(element: Element) { fun readData(element: Element) {
val notifications: Element? = element.getChild("notifications") val notifications = element.getChild("notifications")
map.keys.forEach { name ->
notifications?.getChild("idea-join")?.getAttributeValue("enabled")?.let { notifications?.getChild(name)?.getAttributeValue("enabled")?.let {
isIdeaJoinNotified = it.toBoolean() map[name] = it.toBoolean()
} }
notifications?.getChild("idea-put")?.getAttributeValue("enabled")?.let {
isIdeaPutNotified = it.toBoolean()
}
notifications?.getChild("template-selectmode")?.getAttributeValue("enabled")?.let {
isIdeaPutNotified = it.toBoolean()
} }
} }
@@ -28,16 +25,25 @@ class VimState {
val notifications = Element("notifications") val notifications = Element("notifications")
element.addContent(notifications) element.addContent(notifications)
val ideaJoin = Element("idea-join") map.forEach { (name, value) ->
ideaJoin.setAttribute("enabled", isIdeaJoinNotified.toString()) val child = Element(name)
notifications.addContent(ideaJoin) child.setAttribute("enabled", value.toString())
notifications.addContent(child)
val ideaPut = Element("idea-put") }
ideaPut.setAttribute("enabled", isIdeaPutNotified.toString())
notifications.addContent(ideaPut)
val templateKeyModel = Element("template-selectmode")
templateKeyModel.setAttribute("enabled", isTemplateInSelectModeNotified.toString())
notifications.addContent(templateKeyModel)
} }
} }
val map by lazy { mutableMapOf<String, Boolean>() }
private class StateProperty(val xmlName: String) : ReadWriteProperty<VimState, Boolean> {
init {
map[xmlName] = false
}
override fun getValue(thisRef: VimState, property: KProperty<*>): Boolean = map.getOrPut(xmlName) { false }
override fun setValue(thisRef: VimState, property: KProperty<*>, value: Boolean) {
map[xmlName] = value
}
}

View File

@@ -47,7 +47,7 @@ public class ExEntryAction extends VimCommandAction {
@NotNull @NotNull
@Override @Override
public Command.Type getType() { public Command.Type getType() {
return Command.Type.OTHER_READ_WRITE; return Command.Type.OTHER_READONLY;
} }
@NotNull @NotNull

View File

@@ -25,6 +25,7 @@ import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.ex.util.EditorUtil; import com.intellij.openapi.editor.ex.util.EditorUtil;
import com.intellij.openapi.fileEditor.ex.FileEditorManagerEx; import com.intellij.openapi.fileEditor.ex.FileEditorManagerEx;
import com.intellij.openapi.progress.ProcessCanceledException;
import com.intellij.openapi.project.DumbAware; import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.project.Project; import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Key; import com.intellij.openapi.util.Key;
@@ -38,17 +39,13 @@ import com.maddyhome.idea.vim.helper.EditorHelper;
import com.maddyhome.idea.vim.key.ShortcutOwner; import com.maddyhome.idea.vim.key.ShortcutOwner;
import com.maddyhome.idea.vim.option.ListOption; import com.maddyhome.idea.vim.option.ListOption;
import com.maddyhome.idea.vim.option.OptionsManager; import com.maddyhome.idea.vim.option.OptionsManager;
import one.util.streamex.StreamEx;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import javax.swing.*; import javax.swing.*;
import java.awt.event.InputEvent; import java.awt.event.InputEvent;
import java.awt.event.KeyEvent; import java.awt.event.KeyEvent;
import java.util.ArrayList; import java.util.*;
import java.util.List;
import java.util.Map;
import java.util.Set;
import static java.awt.event.KeyEvent.*; import static java.awt.event.KeyEvent.*;
@@ -101,6 +98,10 @@ public class VimShortcutKeyAction extends AnAction implements DumbAware {
try { try {
KeyHandler.getInstance().handleKey(editor, keyStroke, new EditorDataContext(editor)); KeyHandler.getInstance().handleKey(editor, keyStroke, new EditorDataContext(editor));
} }
catch (ProcessCanceledException ignored) {
// Control-flow exceptions (like ProcessCanceledException) should never be logged
// See {@link com.intellij.openapi.diagnostic.Logger.checkException}
}
catch (Throwable throwable) { catch (Throwable throwable) {
ourLogger.error(throwable); ourLogger.error(throwable);
} }
@@ -195,7 +196,8 @@ public class VimShortcutKeyAction extends AnAction implements DumbAware {
final Project project = editor.getProject(); final Project project = editor.getProject();
if (project == null) return false; if (project == null) return false;
final FileEditorManagerEx fileEditorManager = FileEditorManagerEx.getInstanceEx(project); final FileEditorManagerEx fileEditorManager = FileEditorManagerEx.getInstanceEx(project);
return StreamEx.of(fileEditorManager.getAllEditors()) if (fileEditorManager == null) return false;
return Arrays.stream(fileEditorManager.getAllEditors())
.anyMatch(fileEditor -> editor.equals(EditorUtil.getEditorEx(fileEditor))); .anyMatch(fileEditor -> editor.equals(EditorUtil.getEditorEx(fileEditor)));
} }

View File

@@ -49,7 +49,7 @@ public class RepeatExCommandAction extends VimCommandAction {
@NotNull @NotNull
@Override @Override
public Command.Type getType() { public Command.Type getType() {
return Command.Type.OTHER_WRITABLE; return Command.Type.OTHER_SELF_SYNCHRONIZED;
} }
@NotNull @NotNull

View File

@@ -53,7 +53,7 @@ public class ChangeLastGlobalSearchReplaceAction extends VimCommandAction {
@NotNull @NotNull
@Override @Override
public Command.Type getType() { public Command.Type getType() {
return Command.Type.OTHER_WRITABLE; return Command.Type.OTHER_SELF_SYNCHRONIZED;
} }
@NotNull @NotNull

View File

@@ -53,7 +53,7 @@ public class ChangeLastSearchReplaceAction extends VimCommandAction {
@NotNull @NotNull
@Override @Override
public Command.Type getType() { public Command.Type getType() {
return Command.Type.OTHER_WRITABLE; return Command.Type.OTHER_SELF_SYNCHRONIZED;
} }
@NotNull @NotNull

View File

@@ -65,7 +65,7 @@ public class ProcessExEntryAction extends VimCommandAction {
@NotNull @NotNull
@Override @Override
public Command.Type getType() { public Command.Type getType() {
return Command.Type.OTHER_READ_WRITE; return Command.Type.OTHER_SELF_SYNCHRONIZED;
} }
@NotNull @NotNull

View File

@@ -87,7 +87,6 @@ data class Command(
SELECT_REGISTER, SELECT_REGISTER,
OTHER_READONLY, OTHER_READONLY,
OTHER_WRITABLE, OTHER_WRITABLE,
OTHER_READ_WRITE,
/** /**
* Represent commands that don't require an outer read or write action for synchronization. * Represent commands that don't require an outer read or write action for synchronization.
*/ */
@@ -96,14 +95,14 @@ data class Command(
val isRead: Boolean val isRead: Boolean
get() = when (this) { get() = when (this) {
MOTION, COPY, SELECT_REGISTER, OTHER_READONLY, OTHER_READ_WRITE, COMPLETION -> true MOTION, COPY, SELECT_REGISTER, OTHER_READONLY, COMPLETION -> true
else -> false else -> false
} }
val isWrite: Boolean val isWrite: Boolean
get() = when (this) { get() = when (this) {
INSERT, DELETE, CHANGE, PASTE, RESET, OTHER_WRITABLE, OTHER_READ_WRITE -> true INSERT, DELETE, CHANGE, PASTE, RESET, OTHER_WRITABLE -> true
else -> false else -> false
} }
} }
} }

View File

@@ -25,7 +25,11 @@ fun commands(vararg commands: String) = commands.map { command ->
?: throw RuntimeException("$command is invalid!") ?: throw RuntimeException("$command is invalid!")
}.toTypedArray() }.toTypedArray()
fun flags(rangeFlag: CommandHandler.RangeFlag, argumentFlag: CommandHandler.ArgumentFlag, vararg flags: CommandHandler.Flag) = fun flags(
CommandHandlerFlags(rangeFlag, argumentFlag, flags.toSet()) rangeFlag: CommandHandler.RangeFlag,
argumentFlag: CommandHandler.ArgumentFlag,
access: CommandHandler.Access,
vararg flags: CommandHandler.Flag
) = CommandHandlerFlags(rangeFlag, argumentFlag, access, flags.toSet())
private val commandPattern: Regex = "^([^\\[]+)(?:\\[([^]]+)])?\$".toRegex() private val commandPattern: Regex = "^([^\\[]+)(?:\\[([^]]+)])?\$".toRegex()

View File

@@ -87,9 +87,7 @@ sealed class CommandHandler {
ARGUMENT_FORBIDDEN ARGUMENT_FORBIDDEN
} }
enum class Flag { enum class Access {
DONT_REOPEN,
/** /**
* Indicates that this is a command that modifies the editor * Indicates that this is a command that modifies the editor
*/ */
@@ -98,6 +96,13 @@ sealed class CommandHandler {
* Indicates that this command does not modify the editor * Indicates that this command does not modify the editor
*/ */
READ_ONLY, READ_ONLY,
/**
* Indicates that this command handles writability by itself
*/
SELF_SYNCHRONIZED
}
enum class Flag {
DONT_SAVE_LAST, DONT_SAVE_LAST,
/** /**
@@ -182,4 +187,9 @@ sealed class CommandHandler {
} }
} }
data class CommandHandlerFlags(val rangeFlag: CommandHandler.RangeFlag, val argumentFlag: CommandHandler.ArgumentFlag, val flags: Set<CommandHandler.Flag>) data class CommandHandlerFlags(
val rangeFlag: CommandHandler.RangeFlag,
val argumentFlag: CommandHandler.ArgumentFlag,
val access: CommandHandler.Access,
val flags: Set<CommandHandler.Flag>
)

View File

@@ -18,8 +18,10 @@
package com.maddyhome.idea.vim.ex; package com.maddyhome.idea.vim.ex;
import com.intellij.openapi.actionSystem.DataContext; import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.util.ThrowableComputable;
import com.maddyhome.idea.vim.VimPlugin; import com.maddyhome.idea.vim.VimPlugin;
import com.maddyhome.idea.vim.command.SelectionType; import com.maddyhome.idea.vim.command.SelectionType;
import com.maddyhome.idea.vim.common.Register; import com.maddyhome.idea.vim.common.Register;
@@ -41,11 +43,7 @@ import java.util.regex.Pattern;
*/ */
public class CommandParser { public class CommandParser {
private static final int MAX_RECURSION = 100; private static final int MAX_RECURSION = 100;
public static final int RES_EMPTY = 1; private static final Pattern TRIM_WHITESPACE = Pattern.compile("[ \\t]*(.*)[ \\t\\n\\r]+", Pattern.DOTALL);
public static final int RES_ERROR = 1;
public static final int RES_READONLY = 1;
public static final int RES_DONT_REOPEN = 4;
public static final Pattern TRIM_WHITESPACE = Pattern.compile("[ \\t]*(.*)[ \\t\\n\\r]+", Pattern.DOTALL);
private final CommandHandler[] myHandlers = new CommandHandler[] { private final CommandHandler[] myHandlers = new CommandHandler[] {
new ActionListHandler(), new ActionListHandler(),
new AsciiHandler(), new AsciiHandler(),
@@ -169,31 +167,20 @@ public class CommandParser {
* @param context The data context * @param context The data context
* @param cmd The text entered by the user * @param cmd The text entered by the user
* @param count The count entered before the colon * @param count The count entered before the colon
* @return A bitwise collection of flags, if any, from the result of running the command.
* @throws ExException if any part of the command is invalid or unknown * @throws ExException if any part of the command is invalid or unknown
*/ */
public int processCommand(@NotNull Editor editor, @NotNull DataContext context, @NotNull String cmd, public void processCommand(@NotNull Editor editor, @NotNull DataContext context, @NotNull String cmd,
int count) throws ExException { int count) throws ExException {
return processCommand(editor, context, cmd, count, MAX_RECURSION); processCommand(editor, context, cmd, count, MAX_RECURSION);
} }
/** private void processCommand(@NotNull Editor editor, @NotNull DataContext context, @NotNull String cmd,
* Parse and execute an Ex command entered by the user
*
* @param editor The editor to run the command in
* @param context The data context
* @param cmd The text entered by the user
* @param count The count entered before the colon
* @param aliasCountdown A countdown for the depth of alias recursion that is allowed
* @return A bitwise collection of flags, if any, from the result of running the command.
* @throws ExException if any part of the command is invalid or unknown
*/
private int processCommand(@NotNull Editor editor, @NotNull DataContext context, @NotNull String cmd,
int count, int aliasCountdown) throws ExException { int count, int aliasCountdown) throws ExException {
// Nothing entered // Nothing entered
int result = 0; int result = 0;
if (cmd.length() == 0) { if (cmd.length() == 0) {
return result | RES_EMPTY; logger.warn("CMD is empty");
return;
} }
// Only save the command to the history if it is at the top of the stack. // Only save the command to the history if it is at the top of the stack.
@@ -210,14 +197,16 @@ public class CommandParser {
if (aliasCountdown > 0) { if (aliasCountdown > 0) {
String commandAlias = VimPlugin.getCommand().getAliasCommand(cmd, count); String commandAlias = VimPlugin.getCommand().getAliasCommand(cmd, count);
if (commandAlias.isEmpty()) { if (commandAlias.isEmpty()) {
return result |= RES_ERROR; logger.warn("Command alias is empty");
return;
} }
return processCommand(editor, context, commandAlias, count, aliasCountdown - 1); processCommand(editor, context, commandAlias, count, aliasCountdown - 1);
} else { } else {
VimPlugin.showMessage("Recursion detected, maximum alias depth reached."); VimPlugin.showMessage("Recursion detected, maximum alias depth reached.");
VimPlugin.indicateError(); VimPlugin.indicateError();
return result |= RES_ERROR; logger.warn("Recursion detected, maximum alias depth reached. ");
} }
return;
} }
// Parse the command // Parse the command
@@ -229,23 +218,33 @@ public class CommandParser {
throw new InvalidCommandException(message, cmd); throw new InvalidCommandException(message, cmd);
} }
if (handler.getArgFlags().getFlags().contains(CommandHandler.Flag.WRITABLE) && !editor.getDocument().isWritable()) { if (handler.getArgFlags().getAccess() == CommandHandler.Access.WRITABLE && !editor.getDocument().isWritable()) {
VimPlugin.indicateError(); VimPlugin.indicateError();
return result | RES_READONLY; logger.info("Trying to modify readonly document");
return;
} }
// Run the command // Run the command
boolean ok = handler.process(editor, context, command, count);
if (ok && !handler.getArgFlags().getFlags().contains(CommandHandler.Flag.DONT_SAVE_LAST)) {
VimPlugin.getRegister().storeTextInternal(editor, new TextRange(-1, -1), cmd,
SelectionType.CHARACTER_WISE, ':', false);
}
if (handler.getArgFlags().getFlags().contains(CommandHandler.Flag.DONT_REOPEN)) { ThrowableComputable<Object, ExException> runCommand = () -> {
result |= RES_DONT_REOPEN; boolean ok = handler.process(editor, context, command, count);
} if (ok && !handler.getArgFlags().getFlags().contains(CommandHandler.Flag.DONT_SAVE_LAST)) {
VimPlugin.getRegister().storeTextInternal(editor, new TextRange(-1, -1), cmd,
SelectionType.CHARACTER_WISE, ':', false);
}
return null;
};
return result; switch (handler.getArgFlags().getAccess()) {
case WRITABLE:
ApplicationManager.getApplication().runWriteAction(runCommand);
break;
case READ_ONLY:
ApplicationManager.getApplication().runReadAction(runCommand);
break;
case SELF_SYNCHRONIZED:
runCommand.compute();
}
} }
@Nullable @Nullable

View File

@@ -26,7 +26,6 @@ import com.intellij.openapi.editor.Editor
import com.maddyhome.idea.vim.KeyHandler import com.maddyhome.idea.vim.KeyHandler
import com.maddyhome.idea.vim.VimPlugin import com.maddyhome.idea.vim.VimPlugin
import com.maddyhome.idea.vim.ex.* import com.maddyhome.idea.vim.ex.*
import com.maddyhome.idea.vim.ex.CommandHandler.Flag.DONT_REOPEN
import com.maddyhome.idea.vim.ex.CommandHandler.Flag.SAVE_VISUAL import com.maddyhome.idea.vim.ex.CommandHandler.Flag.SAVE_VISUAL
import com.maddyhome.idea.vim.helper.runAfterGotFocus import com.maddyhome.idea.vim.helper.runAfterGotFocus
@@ -36,7 +35,7 @@ import com.maddyhome.idea.vim.helper.runAfterGotFocus
class ActionHandler : CommandHandler.SingleExecution() { class ActionHandler : CommandHandler.SingleExecution() {
override val names = commands("action") override val names = commands("action")
override val argFlags: CommandHandlerFlags = flags(RangeFlag.RANGE_OPTIONAL, ArgumentFlag.ARGUMENT_OPTIONAL, DONT_REOPEN, SAVE_VISUAL) override val argFlags: CommandHandlerFlags = flags(RangeFlag.RANGE_OPTIONAL, ArgumentFlag.ARGUMENT_OPTIONAL, Access.READ_ONLY, SAVE_VISUAL)
override fun execute(editor: Editor, context: DataContext, cmd: ExCommand): Boolean { override fun execute(editor: Editor, context: DataContext, cmd: ExCommand): Boolean {
val actionName = cmd.argument.trim() val actionName = cmd.argument.trim()

View File

@@ -22,14 +22,7 @@ import com.intellij.openapi.actionSystem.ActionManager
import com.intellij.openapi.actionSystem.DataContext import com.intellij.openapi.actionSystem.DataContext
import com.intellij.openapi.actionSystem.KeyboardShortcut import com.intellij.openapi.actionSystem.KeyboardShortcut
import com.intellij.openapi.editor.Editor import com.intellij.openapi.editor.Editor
import com.maddyhome.idea.vim.ex.CommandHandler import com.maddyhome.idea.vim.ex.*
import com.maddyhome.idea.vim.ex.CommandHandler.Flag.DONT_REOPEN
import com.maddyhome.idea.vim.ex.CommandHandlerFlags
import com.maddyhome.idea.vim.ex.CommandName
import com.maddyhome.idea.vim.ex.ExCommand
import com.maddyhome.idea.vim.ex.ExOutputModel
import com.maddyhome.idea.vim.ex.commands
import com.maddyhome.idea.vim.ex.flags
import com.maddyhome.idea.vim.helper.StringHelper import com.maddyhome.idea.vim.helper.StringHelper
/** /**
@@ -37,7 +30,7 @@ import com.maddyhome.idea.vim.helper.StringHelper
*/ */
class ActionListHandler : CommandHandler.SingleExecution() { class ActionListHandler : CommandHandler.SingleExecution() {
override val names: Array<CommandName> = commands("actionlist") override val names: Array<CommandName> = commands("actionlist")
override val argFlags: CommandHandlerFlags = flags(RangeFlag.RANGE_FORBIDDEN, ArgumentFlag.ARGUMENT_OPTIONAL, DONT_REOPEN) override val argFlags: CommandHandlerFlags = flags(RangeFlag.RANGE_FORBIDDEN, ArgumentFlag.ARGUMENT_OPTIONAL, Access.READ_ONLY)
override fun execute(editor: Editor, context: DataContext, cmd: ExCommand): Boolean { override fun execute(editor: Editor, context: DataContext, cmd: ExCommand): Boolean {
val lineSeparator = "\n" val lineSeparator = "\n"

View File

@@ -21,16 +21,11 @@ package com.maddyhome.idea.vim.ex.handler
import com.intellij.openapi.actionSystem.DataContext import com.intellij.openapi.actionSystem.DataContext
import com.intellij.openapi.editor.Editor import com.intellij.openapi.editor.Editor
import com.maddyhome.idea.vim.VimPlugin import com.maddyhome.idea.vim.VimPlugin
import com.maddyhome.idea.vim.ex.CommandHandler import com.maddyhome.idea.vim.ex.*
import com.maddyhome.idea.vim.ex.CommandHandlerFlags
import com.maddyhome.idea.vim.ex.CommandName
import com.maddyhome.idea.vim.ex.ExCommand
import com.maddyhome.idea.vim.ex.commands
import com.maddyhome.idea.vim.ex.flags
class AsciiHandler : CommandHandler.SingleExecution() { class AsciiHandler : CommandHandler.SingleExecution() {
override val names: Array<CommandName> = commands("as[cii]") override val names: Array<CommandName> = commands("as[cii]")
override val argFlags: CommandHandlerFlags = flags(RangeFlag.RANGE_FORBIDDEN, ArgumentFlag.ARGUMENT_FORBIDDEN) override val argFlags: CommandHandlerFlags = flags(RangeFlag.RANGE_FORBIDDEN, ArgumentFlag.ARGUMENT_FORBIDDEN, Access.READ_ONLY)
override fun execute(editor: Editor, context: DataContext, cmd: ExCommand): Boolean { override fun execute(editor: Editor, context: DataContext, cmd: ExCommand): Boolean {
VimPlugin.getFile().displayAsciiInfo(editor) VimPlugin.getFile().displayAsciiInfo(editor)

View File

@@ -21,19 +21,14 @@ package com.maddyhome.idea.vim.ex.handler
import com.intellij.openapi.actionSystem.DataContext import com.intellij.openapi.actionSystem.DataContext
import com.intellij.openapi.editor.Editor import com.intellij.openapi.editor.Editor
import com.maddyhome.idea.vim.VimPlugin import com.maddyhome.idea.vim.VimPlugin
import com.maddyhome.idea.vim.ex.CommandHandler import com.maddyhome.idea.vim.ex.*
import com.maddyhome.idea.vim.ex.CommandHandlerFlags
import com.maddyhome.idea.vim.ex.CommandName
import com.maddyhome.idea.vim.ex.ExCommand
import com.maddyhome.idea.vim.ex.commands
import com.maddyhome.idea.vim.ex.flags
class CmdClearHandler : CommandHandler.SingleExecution() { class CmdClearHandler : CommandHandler.SingleExecution() {
override val names: Array<CommandName> = commands("comc[lear]") override val names: Array<CommandName> = commands("comc[lear]")
override val argFlags: CommandHandlerFlags = flags(RangeFlag.RANGE_FORBIDDEN, ArgumentFlag.ARGUMENT_FORBIDDEN) override val argFlags: CommandHandlerFlags = flags(RangeFlag.RANGE_FORBIDDEN, ArgumentFlag.ARGUMENT_FORBIDDEN, Access.READ_ONLY)
override fun execute(editor: Editor, context: DataContext, cmd: ExCommand): Boolean { override fun execute(editor: Editor, context: DataContext, cmd: ExCommand): Boolean {
VimPlugin.getCommand().resetAliases() VimPlugin.getCommand().resetAliases()
return true return true
} }
} }

View File

@@ -22,20 +22,14 @@ import com.intellij.openapi.actionSystem.DataContext
import com.intellij.openapi.diagnostic.Logger import com.intellij.openapi.diagnostic.Logger
import com.intellij.openapi.editor.Editor import com.intellij.openapi.editor.Editor
import com.maddyhome.idea.vim.VimPlugin import com.maddyhome.idea.vim.VimPlugin
import com.maddyhome.idea.vim.ex.CommandHandler import com.maddyhome.idea.vim.ex.*
import com.maddyhome.idea.vim.ex.CommandHandler.Flag.WRITABLE
import com.maddyhome.idea.vim.ex.ExCommand
import com.maddyhome.idea.vim.ex.ExException
import com.maddyhome.idea.vim.ex.ExOutputModel
import com.maddyhome.idea.vim.ex.commands
import com.maddyhome.idea.vim.ex.flags
import com.maddyhome.idea.vim.helper.MessageHelper import com.maddyhome.idea.vim.helper.MessageHelper
import com.maddyhome.idea.vim.helper.Msg import com.maddyhome.idea.vim.helper.Msg
import java.io.IOException import java.io.IOException
class CmdFilterHandler : CommandHandler.SingleExecution() { class CmdFilterHandler : CommandHandler.SingleExecution() {
override val names = commands("!") override val names = commands("!")
override val argFlags = flags(RangeFlag.RANGE_OPTIONAL, ArgumentFlag.ARGUMENT_OPTIONAL, WRITABLE) override val argFlags = flags(RangeFlag.RANGE_OPTIONAL, ArgumentFlag.ARGUMENT_OPTIONAL, Access.WRITABLE)
override fun execute(editor: Editor, context: DataContext, cmd: ExCommand): Boolean { override fun execute(editor: Editor, context: DataContext, cmd: ExCommand): Boolean {
logger.info("execute") logger.info("execute")

View File

@@ -22,13 +22,7 @@ import com.intellij.openapi.actionSystem.DataContext
import com.intellij.openapi.editor.Editor import com.intellij.openapi.editor.Editor
import com.maddyhome.idea.vim.VimPlugin import com.maddyhome.idea.vim.VimPlugin
import com.maddyhome.idea.vim.common.Alias import com.maddyhome.idea.vim.common.Alias
import com.maddyhome.idea.vim.ex.CommandHandler import com.maddyhome.idea.vim.ex.*
import com.maddyhome.idea.vim.ex.CommandHandlerFlags
import com.maddyhome.idea.vim.ex.CommandName
import com.maddyhome.idea.vim.ex.ExCommand
import com.maddyhome.idea.vim.ex.ExOutputModel
import com.maddyhome.idea.vim.ex.commands
import com.maddyhome.idea.vim.ex.flags
import com.maddyhome.idea.vim.ex.vimscript.VimScriptCommandHandler import com.maddyhome.idea.vim.ex.vimscript.VimScriptCommandHandler
import com.maddyhome.idea.vim.group.CommandGroup.Companion.BLACKLISTED_ALIASES import com.maddyhome.idea.vim.group.CommandGroup.Companion.BLACKLISTED_ALIASES
@@ -37,7 +31,7 @@ import com.maddyhome.idea.vim.group.CommandGroup.Companion.BLACKLISTED_ALIASES
*/ */
class CmdHandler : CommandHandler.SingleExecution(), VimScriptCommandHandler { class CmdHandler : CommandHandler.SingleExecution(), VimScriptCommandHandler {
override val names: Array<CommandName> = commands("com[mand]") override val names: Array<CommandName> = commands("com[mand]")
override val argFlags: CommandHandlerFlags = flags(RangeFlag.RANGE_FORBIDDEN, ArgumentFlag.ARGUMENT_OPTIONAL, Flag.DONT_REOPEN) override val argFlags: CommandHandlerFlags = flags(RangeFlag.RANGE_FORBIDDEN, ArgumentFlag.ARGUMENT_OPTIONAL, Access.READ_ONLY)
// Static definitions needed for aliases. // Static definitions needed for aliases.
private companion object { private companion object {
@@ -180,4 +174,4 @@ class CmdHandler : CommandHandler.SingleExecution(), VimScriptCommandHandler {
return true return true
} }
} }

View File

@@ -22,18 +22,13 @@ import com.intellij.openapi.actionSystem.DataContext
import com.intellij.openapi.editor.Editor import com.intellij.openapi.editor.Editor
import com.maddyhome.idea.vim.VimPlugin import com.maddyhome.idea.vim.VimPlugin
import com.maddyhome.idea.vim.command.SelectionType import com.maddyhome.idea.vim.command.SelectionType
import com.maddyhome.idea.vim.ex.CommandHandler import com.maddyhome.idea.vim.ex.*
import com.maddyhome.idea.vim.ex.CommandHandler.Flag.WRITABLE
import com.maddyhome.idea.vim.ex.CommandParser
import com.maddyhome.idea.vim.ex.ExCommand
import com.maddyhome.idea.vim.ex.commands
import com.maddyhome.idea.vim.ex.flags
import com.maddyhome.idea.vim.group.copy.PutData import com.maddyhome.idea.vim.group.copy.PutData
import com.maddyhome.idea.vim.helper.EditorHelper import com.maddyhome.idea.vim.helper.EditorHelper
class CopyTextHandler : CommandHandler.SingleExecution() { class CopyTextHandler : CommandHandler.SingleExecution() {
override val names = commands("co[py]", "t") override val names = commands("co[py]", "t")
override val argFlags = flags(RangeFlag.RANGE_OPTIONAL, ArgumentFlag.ARGUMENT_REQUIRED, WRITABLE) override val argFlags = flags(RangeFlag.RANGE_OPTIONAL, ArgumentFlag.ARGUMENT_REQUIRED, Access.WRITABLE)
override fun execute(editor: Editor, context: DataContext, cmd: ExCommand): Boolean { override fun execute(editor: Editor, context: DataContext, cmd: ExCommand): Boolean {
val carets = EditorHelper.getOrderedCaretsList(editor) val carets = EditorHelper.getOrderedCaretsList(editor)
for (caret in carets) { for (caret in carets) {

View File

@@ -28,7 +28,7 @@ import com.maddyhome.idea.vim.ex.flags
class DelCmdHandler : CommandHandler.SingleExecution() { class DelCmdHandler : CommandHandler.SingleExecution() {
override val names = commands("delc[ommand]") override val names = commands("delc[ommand]")
override val argFlags = flags(RangeFlag.RANGE_FORBIDDEN, ArgumentFlag.ARGUMENT_REQUIRED) override val argFlags = flags(RangeFlag.RANGE_FORBIDDEN, ArgumentFlag.ARGUMENT_REQUIRED, Access.READ_ONLY)
override fun execute(editor: Editor, context: DataContext, cmd: ExCommand): Boolean { override fun execute(editor: Editor, context: DataContext, cmd: ExCommand): Boolean {
if (!VimPlugin.getCommand().hasAlias(cmd.argument)) { if (!VimPlugin.getCommand().hasAlias(cmd.argument)) {
VimPlugin.showMessage("E184: No such user-defined command: ${cmd.argument}") VimPlugin.showMessage("E184: No such user-defined command: ${cmd.argument}")
@@ -38,4 +38,4 @@ class DelCmdHandler : CommandHandler.SingleExecution() {
VimPlugin.getCommand().removeAlias(cmd.argument) VimPlugin.getCommand().removeAlias(cmd.argument)
return true return true
} }
} }

View File

@@ -23,17 +23,11 @@ import com.intellij.openapi.editor.Caret
import com.intellij.openapi.editor.Editor import com.intellij.openapi.editor.Editor
import com.maddyhome.idea.vim.VimPlugin import com.maddyhome.idea.vim.VimPlugin
import com.maddyhome.idea.vim.command.SelectionType import com.maddyhome.idea.vim.command.SelectionType
import com.maddyhome.idea.vim.ex.CommandHandler import com.maddyhome.idea.vim.ex.*
import com.maddyhome.idea.vim.ex.CommandHandler.Flag.WRITABLE
import com.maddyhome.idea.vim.ex.CommandHandlerFlags
import com.maddyhome.idea.vim.ex.CommandName
import com.maddyhome.idea.vim.ex.ExCommand
import com.maddyhome.idea.vim.ex.commands
import com.maddyhome.idea.vim.ex.flags
class DeleteLinesHandler : CommandHandler.ForEachCaret() { class DeleteLinesHandler : CommandHandler.ForEachCaret() {
override val names: Array<CommandName> = commands("d[elete]") override val names: Array<CommandName> = commands("d[elete]")
override val argFlags: CommandHandlerFlags = flags(RangeFlag.RANGE_OPTIONAL, ArgumentFlag.ARGUMENT_OPTIONAL, WRITABLE) override val argFlags: CommandHandlerFlags = flags(RangeFlag.RANGE_OPTIONAL, ArgumentFlag.ARGUMENT_OPTIONAL, Access.WRITABLE)
override fun execute(editor: Editor, caret: Caret, context: DataContext, override fun execute(editor: Editor, caret: Caret, context: DataContext,
cmd: ExCommand): Boolean { cmd: ExCommand): Boolean {

View File

@@ -29,7 +29,7 @@ import com.maddyhome.idea.vim.ex.flags
class DigraphHandler : CommandHandler.SingleExecution() { class DigraphHandler : CommandHandler.SingleExecution() {
override val names = commands("dig[raphs]") override val names = commands("dig[raphs]")
override val argFlags = flags(RangeFlag.RANGE_OPTIONAL, ArgumentFlag.ARGUMENT_OPTIONAL) override val argFlags = flags(RangeFlag.RANGE_OPTIONAL, ArgumentFlag.ARGUMENT_OPTIONAL, Access.READ_ONLY)
override fun execute(editor: Editor, context: DataContext, cmd: ExCommand): Boolean { override fun execute(editor: Editor, context: DataContext, cmd: ExCommand): Boolean {
val arg = cmd.argument val arg = cmd.argument

View File

@@ -28,7 +28,7 @@ import com.maddyhome.idea.vim.ex.flags
class DumpLineHandler : CommandHandler.SingleExecution() { class DumpLineHandler : CommandHandler.SingleExecution() {
override val names = commands("dump[line]") override val names = commands("dump[line]")
override val argFlags = flags(RangeFlag.RANGE_OPTIONAL, ArgumentFlag.ARGUMENT_OPTIONAL) override val argFlags = flags(RangeFlag.RANGE_OPTIONAL, ArgumentFlag.ARGUMENT_OPTIONAL, Access.READ_ONLY)
override fun execute(editor: Editor, context: DataContext, cmd: ExCommand): Boolean { override fun execute(editor: Editor, context: DataContext, cmd: ExCommand): Boolean {
if (!logger.isDebugEnabled) return false if (!logger.isDebugEnabled) return false

View File

@@ -20,11 +20,7 @@ package com.maddyhome.idea.vim.ex.handler
import com.intellij.openapi.actionSystem.DataContext import com.intellij.openapi.actionSystem.DataContext
import com.intellij.openapi.editor.Editor import com.intellij.openapi.editor.Editor
import com.maddyhome.idea.vim.ex.CommandHandler import com.maddyhome.idea.vim.ex.*
import com.maddyhome.idea.vim.ex.ExCommand
import com.maddyhome.idea.vim.ex.ExOutputModel
import com.maddyhome.idea.vim.ex.commands
import com.maddyhome.idea.vim.ex.flags
import com.maddyhome.idea.vim.ex.vimscript.VimScriptGlobalEnvironment import com.maddyhome.idea.vim.ex.vimscript.VimScriptGlobalEnvironment
import com.maddyhome.idea.vim.ex.vimscript.VimScriptParser import com.maddyhome.idea.vim.ex.vimscript.VimScriptParser
@@ -33,7 +29,7 @@ import com.maddyhome.idea.vim.ex.vimscript.VimScriptParser
*/ */
class EchoHandler : CommandHandler.SingleExecution() { class EchoHandler : CommandHandler.SingleExecution() {
override val names = commands("ec[ho]") override val names = commands("ec[ho]")
override val argFlags = flags(RangeFlag.RANGE_FORBIDDEN, ArgumentFlag.ARGUMENT_OPTIONAL) override val argFlags = flags(RangeFlag.RANGE_FORBIDDEN, ArgumentFlag.ARGUMENT_OPTIONAL, Access.READ_ONLY)
override fun execute(editor: Editor, context: DataContext, cmd: ExCommand): Boolean { override fun execute(editor: Editor, context: DataContext, cmd: ExCommand): Boolean {
val env = VimScriptGlobalEnvironment.getInstance() val env = VimScriptGlobalEnvironment.getInstance()

View File

@@ -24,7 +24,6 @@ import com.intellij.openapi.editor.Editor
import com.maddyhome.idea.vim.KeyHandler import com.maddyhome.idea.vim.KeyHandler
import com.maddyhome.idea.vim.VimPlugin import com.maddyhome.idea.vim.VimPlugin
import com.maddyhome.idea.vim.ex.CommandHandler import com.maddyhome.idea.vim.ex.CommandHandler
import com.maddyhome.idea.vim.ex.CommandHandler.Flag.DONT_REOPEN
import com.maddyhome.idea.vim.ex.ExCommand import com.maddyhome.idea.vim.ex.ExCommand
import com.maddyhome.idea.vim.ex.commands import com.maddyhome.idea.vim.ex.commands
import com.maddyhome.idea.vim.ex.flags import com.maddyhome.idea.vim.ex.flags
@@ -32,7 +31,7 @@ import com.maddyhome.idea.vim.helper.EditorDataContext
class EditFileHandler : CommandHandler.SingleExecution() { class EditFileHandler : CommandHandler.SingleExecution() {
override val names = commands("bro[wse]", "e[dit]") override val names = commands("bro[wse]", "e[dit]")
override val argFlags = flags(RangeFlag.RANGE_FORBIDDEN, ArgumentFlag.ARGUMENT_OPTIONAL, DONT_REOPEN) override val argFlags = flags(RangeFlag.RANGE_FORBIDDEN, ArgumentFlag.ARGUMENT_OPTIONAL, Access.READ_ONLY)
override fun execute(editor: Editor, context: DataContext, cmd: ExCommand): Boolean { override fun execute(editor: Editor, context: DataContext, cmd: ExCommand): Boolean {
val arg = cmd.argument val arg = cmd.argument
if (arg == "#") { if (arg == "#") {

View File

@@ -22,14 +22,13 @@ import com.intellij.openapi.actionSystem.DataContext
import com.intellij.openapi.editor.Editor import com.intellij.openapi.editor.Editor
import com.maddyhome.idea.vim.VimPlugin import com.maddyhome.idea.vim.VimPlugin
import com.maddyhome.idea.vim.ex.CommandHandler import com.maddyhome.idea.vim.ex.CommandHandler
import com.maddyhome.idea.vim.ex.CommandHandler.Flag.DONT_REOPEN
import com.maddyhome.idea.vim.ex.ExCommand import com.maddyhome.idea.vim.ex.ExCommand
import com.maddyhome.idea.vim.ex.commands import com.maddyhome.idea.vim.ex.commands
import com.maddyhome.idea.vim.ex.flags import com.maddyhome.idea.vim.ex.flags
class ExitHandler : CommandHandler.SingleExecution() { class ExitHandler : CommandHandler.SingleExecution() {
override val names = commands("qa[ll]", "quita[ll]", "wqa[ll]", "xa[ll]") override val names = commands("qa[ll]", "quita[ll]", "wqa[ll]", "xa[ll]")
override val argFlags = flags(RangeFlag.RANGE_OPTIONAL, ArgumentFlag.ARGUMENT_OPTIONAL, DONT_REOPEN) override val argFlags = flags(RangeFlag.RANGE_OPTIONAL, ArgumentFlag.ARGUMENT_OPTIONAL, Access.READ_ONLY)
override fun execute(editor: Editor, context: DataContext, cmd: ExCommand): Boolean { override fun execute(editor: Editor, context: DataContext, cmd: ExCommand): Boolean {
VimPlugin.getWindow().closeAll(context) VimPlugin.getWindow().closeAll(context)

View File

@@ -29,7 +29,7 @@ import com.maddyhome.idea.vim.ex.flags
class FileHandler : CommandHandler.SingleExecution() { class FileHandler : CommandHandler.SingleExecution() {
override val names = commands("f[ile]") override val names = commands("f[ile]")
override val argFlags = flags(RangeFlag.RANGE_IS_COUNT, ARGUMENT_FORBIDDEN) override val argFlags = flags(RangeFlag.RANGE_IS_COUNT, ARGUMENT_FORBIDDEN, Access.READ_ONLY)
override fun execute(editor: Editor, context: DataContext, cmd: ExCommand): Boolean { override fun execute(editor: Editor, context: DataContext, cmd: ExCommand): Boolean {
val count = cmd.getCount(editor, context, 0, false) val count = cmd.getCount(editor, context, 0, false)
VimPlugin.getFile().displayFileInfo(editor, count > 0) VimPlugin.getFile().displayFileInfo(editor, count > 0)

View File

@@ -24,14 +24,13 @@ import com.intellij.openapi.editor.Editor
import com.maddyhome.idea.vim.KeyHandler import com.maddyhome.idea.vim.KeyHandler
import com.maddyhome.idea.vim.VimPlugin import com.maddyhome.idea.vim.VimPlugin
import com.maddyhome.idea.vim.ex.CommandHandler import com.maddyhome.idea.vim.ex.CommandHandler
import com.maddyhome.idea.vim.ex.CommandHandler.Flag.DONT_REOPEN
import com.maddyhome.idea.vim.ex.ExCommand import com.maddyhome.idea.vim.ex.ExCommand
import com.maddyhome.idea.vim.ex.commands import com.maddyhome.idea.vim.ex.commands
import com.maddyhome.idea.vim.ex.flags import com.maddyhome.idea.vim.ex.flags
class FindClassHandler : CommandHandler.SingleExecution() { class FindClassHandler : CommandHandler.SingleExecution() {
override val names = commands("cla[ss]") override val names = commands("cla[ss]")
override val argFlags = flags(RangeFlag.RANGE_FORBIDDEN, ArgumentFlag.ARGUMENT_OPTIONAL, DONT_REOPEN) override val argFlags = flags(RangeFlag.RANGE_FORBIDDEN, ArgumentFlag.ARGUMENT_OPTIONAL, Access.READ_ONLY)
override fun execute(editor: Editor, context: DataContext, cmd: ExCommand): Boolean { override fun execute(editor: Editor, context: DataContext, cmd: ExCommand): Boolean {
val arg = cmd.argument val arg = cmd.argument
if (arg.isNotEmpty()) { if (arg.isNotEmpty()) {

View File

@@ -24,14 +24,13 @@ import com.intellij.openapi.editor.Editor
import com.maddyhome.idea.vim.KeyHandler import com.maddyhome.idea.vim.KeyHandler
import com.maddyhome.idea.vim.VimPlugin import com.maddyhome.idea.vim.VimPlugin
import com.maddyhome.idea.vim.ex.CommandHandler import com.maddyhome.idea.vim.ex.CommandHandler
import com.maddyhome.idea.vim.ex.CommandHandler.Flag.DONT_REOPEN
import com.maddyhome.idea.vim.ex.ExCommand import com.maddyhome.idea.vim.ex.ExCommand
import com.maddyhome.idea.vim.ex.commands import com.maddyhome.idea.vim.ex.commands
import com.maddyhome.idea.vim.ex.flags import com.maddyhome.idea.vim.ex.flags
class FindFileHandler : CommandHandler.SingleExecution() { class FindFileHandler : CommandHandler.SingleExecution() {
override val names = commands("fin[d]") override val names = commands("fin[d]")
override val argFlags = flags(RangeFlag.RANGE_FORBIDDEN, ArgumentFlag.ARGUMENT_OPTIONAL, DONT_REOPEN) override val argFlags = flags(RangeFlag.RANGE_FORBIDDEN, ArgumentFlag.ARGUMENT_OPTIONAL, Access.READ_ONLY)
override fun execute(editor: Editor, context: DataContext, cmd: ExCommand): Boolean { override fun execute(editor: Editor, context: DataContext, cmd: ExCommand): Boolean {
val arg = cmd.argument val arg = cmd.argument
if (arg.isNotEmpty()) { if (arg.isNotEmpty()) {

View File

@@ -23,14 +23,13 @@ import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.editor.Editor import com.intellij.openapi.editor.Editor
import com.maddyhome.idea.vim.KeyHandler import com.maddyhome.idea.vim.KeyHandler
import com.maddyhome.idea.vim.ex.CommandHandler import com.maddyhome.idea.vim.ex.CommandHandler
import com.maddyhome.idea.vim.ex.CommandHandler.Flag.DONT_REOPEN
import com.maddyhome.idea.vim.ex.ExCommand import com.maddyhome.idea.vim.ex.ExCommand
import com.maddyhome.idea.vim.ex.commands import com.maddyhome.idea.vim.ex.commands
import com.maddyhome.idea.vim.ex.flags import com.maddyhome.idea.vim.ex.flags
class FindSymbolHandler : CommandHandler.SingleExecution() { class FindSymbolHandler : CommandHandler.SingleExecution() {
override val names = commands("sym[bol]") override val names = commands("sym[bol]")
override val argFlags = flags(RangeFlag.RANGE_FORBIDDEN, ArgumentFlag.ARGUMENT_OPTIONAL, DONT_REOPEN) override val argFlags = flags(RangeFlag.RANGE_FORBIDDEN, ArgumentFlag.ARGUMENT_OPTIONAL, Access.READ_ONLY)
override fun execute(editor: Editor, context: DataContext, cmd: ExCommand): Boolean { override fun execute(editor: Editor, context: DataContext, cmd: ExCommand): Boolean {
// TODO: Check the command argument and jump to a specific symbol // TODO: Check the command argument and jump to a specific symbol
ApplicationManager.getApplication().invokeLater { KeyHandler.executeAction("GotoSymbol", context) } ApplicationManager.getApplication().invokeLater { KeyHandler.executeAction("GotoSymbol", context) }

View File

@@ -23,19 +23,14 @@ import com.intellij.openapi.editor.Caret
import com.intellij.openapi.editor.Editor import com.intellij.openapi.editor.Editor
import com.maddyhome.idea.vim.VimPlugin import com.maddyhome.idea.vim.VimPlugin
import com.maddyhome.idea.vim.command.CommandFlags import com.maddyhome.idea.vim.command.CommandFlags
import com.maddyhome.idea.vim.ex.CommandHandler import com.maddyhome.idea.vim.ex.*
import com.maddyhome.idea.vim.ex.CommandHandlerFlags
import com.maddyhome.idea.vim.ex.CommandName
import com.maddyhome.idea.vim.ex.ExCommand
import com.maddyhome.idea.vim.ex.commands
import com.maddyhome.idea.vim.ex.flags
import com.maddyhome.idea.vim.group.MotionGroup import com.maddyhome.idea.vim.group.MotionGroup
import com.maddyhome.idea.vim.helper.enumSetOf import com.maddyhome.idea.vim.helper.enumSetOf
import java.util.* import java.util.*
class GotoCharacterHandler : CommandHandler.ForEachCaret() { class GotoCharacterHandler : CommandHandler.ForEachCaret() {
override val names: Array<CommandName> = commands("go[to]") override val names: Array<CommandName> = commands("go[to]")
override val argFlags: CommandHandlerFlags = flags(RangeFlag.RANGE_IS_COUNT, ArgumentFlag.ARGUMENT_OPTIONAL) override val argFlags: CommandHandlerFlags = flags(RangeFlag.RANGE_IS_COUNT, ArgumentFlag.ARGUMENT_OPTIONAL, Access.READ_ONLY)
override val optFlags: EnumSet<CommandFlags> = enumSetOf(CommandFlags.FLAG_MOT_EXCLUSIVE) override val optFlags: EnumSet<CommandFlags> = enumSetOf(CommandFlags.FLAG_MOT_EXCLUSIVE)
override fun execute(editor: Editor, caret: Caret, context: DataContext, cmd: ExCommand): Boolean { override fun execute(editor: Editor, caret: Caret, context: DataContext, cmd: ExCommand): Boolean {

View File

@@ -36,7 +36,7 @@ import kotlin.math.min
*/ */
class GotoLineHandler : CommandHandler.ForEachCaret() { class GotoLineHandler : CommandHandler.ForEachCaret() {
override val names: Array<CommandName> = arrayOf() override val names: Array<CommandName> = arrayOf()
override val argFlags: CommandHandlerFlags = flags(RangeFlag.RANGE_REQUIRED, ArgumentFlag.ARGUMENT_OPTIONAL) override val argFlags: CommandHandlerFlags = flags(RangeFlag.RANGE_REQUIRED, ArgumentFlag.ARGUMENT_OPTIONAL, Access.READ_ONLY)
override val optFlags: EnumSet<CommandFlags> = enumSetOf(CommandFlags.FLAG_MOT_EXCLUSIVE) override val optFlags: EnumSet<CommandFlags> = enumSetOf(CommandFlags.FLAG_MOT_EXCLUSIVE)
/** /**

View File

@@ -33,7 +33,7 @@ import java.net.URLEncoder
*/ */
class HelpHandler : CommandHandler.SingleExecution() { class HelpHandler : CommandHandler.SingleExecution() {
override val names = commands("h[elp]") override val names = commands("h[elp]")
override val argFlags = flags(RangeFlag.RANGE_OPTIONAL, ArgumentFlag.ARGUMENT_OPTIONAL) override val argFlags = flags(RangeFlag.RANGE_OPTIONAL, ArgumentFlag.ARGUMENT_OPTIONAL, Access.READ_ONLY)
override fun execute(editor: Editor, context: DataContext, cmd: ExCommand): Boolean { override fun execute(editor: Editor, context: DataContext, cmd: ExCommand): Boolean {
BrowserUtil.browse(helpTopicUrl(cmd.argument)) BrowserUtil.browse(helpTopicUrl(cmd.argument))
return true return true

View File

@@ -22,19 +22,12 @@ import com.intellij.openapi.actionSystem.DataContext
import com.intellij.openapi.diagnostic.Logger import com.intellij.openapi.diagnostic.Logger
import com.intellij.openapi.editor.Editor import com.intellij.openapi.editor.Editor
import com.maddyhome.idea.vim.VimPlugin import com.maddyhome.idea.vim.VimPlugin
import com.maddyhome.idea.vim.ex.CommandHandler import com.maddyhome.idea.vim.ex.*
import com.maddyhome.idea.vim.ex.ExCommand import com.maddyhome.idea.vim.group.HistoryGroup.*
import com.maddyhome.idea.vim.ex.ExOutputModel
import com.maddyhome.idea.vim.ex.commands
import com.maddyhome.idea.vim.ex.flags
import com.maddyhome.idea.vim.group.HistoryGroup.COMMAND
import com.maddyhome.idea.vim.group.HistoryGroup.EXPRESSION
import com.maddyhome.idea.vim.group.HistoryGroup.INPUT
import com.maddyhome.idea.vim.group.HistoryGroup.SEARCH
class HistoryHandler : CommandHandler.SingleExecution() { class HistoryHandler : CommandHandler.SingleExecution() {
override val names = commands("his[tory]") override val names = commands("his[tory]")
override val argFlags = flags(RangeFlag.RANGE_FORBIDDEN, ArgumentFlag.ARGUMENT_OPTIONAL) override val argFlags = flags(RangeFlag.RANGE_FORBIDDEN, ArgumentFlag.ARGUMENT_OPTIONAL, Access.READ_ONLY)
override fun execute(editor: Editor, context: DataContext, cmd: ExCommand): Boolean { override fun execute(editor: Editor, context: DataContext, cmd: ExCommand): Boolean {
logger.debug("execute") logger.debug("execute")

View File

@@ -23,17 +23,11 @@ import com.intellij.openapi.editor.Caret
import com.intellij.openapi.editor.Editor import com.intellij.openapi.editor.Editor
import com.maddyhome.idea.vim.VimPlugin import com.maddyhome.idea.vim.VimPlugin
import com.maddyhome.idea.vim.common.TextRange import com.maddyhome.idea.vim.common.TextRange
import com.maddyhome.idea.vim.ex.CommandHandler import com.maddyhome.idea.vim.ex.*
import com.maddyhome.idea.vim.ex.CommandHandler.Flag.WRITABLE
import com.maddyhome.idea.vim.ex.CommandHandlerFlags
import com.maddyhome.idea.vim.ex.CommandName
import com.maddyhome.idea.vim.ex.ExCommand
import com.maddyhome.idea.vim.ex.commands
import com.maddyhome.idea.vim.ex.flags
class JoinLinesHandler : CommandHandler.ForEachCaret() { class JoinLinesHandler : CommandHandler.ForEachCaret() {
override val names: Array<CommandName> = commands("j[oin]") override val names: Array<CommandName> = commands("j[oin]")
override val argFlags: CommandHandlerFlags = flags(RangeFlag.RANGE_OPTIONAL, ArgumentFlag.ARGUMENT_OPTIONAL, WRITABLE) override val argFlags: CommandHandlerFlags = flags(RangeFlag.RANGE_OPTIONAL, ArgumentFlag.ARGUMENT_OPTIONAL, Access.WRITABLE)
override fun execute(editor: Editor, caret: Caret, context: DataContext, cmd: ExCommand): Boolean { override fun execute(editor: Editor, caret: Caret, context: DataContext, cmd: ExCommand): Boolean {
val arg = cmd.argument val arg = cmd.argument

View File

@@ -21,11 +21,7 @@ package com.maddyhome.idea.vim.ex.handler
import com.intellij.openapi.actionSystem.DataContext import com.intellij.openapi.actionSystem.DataContext
import com.intellij.openapi.editor.Editor import com.intellij.openapi.editor.Editor
import com.maddyhome.idea.vim.VimPlugin import com.maddyhome.idea.vim.VimPlugin
import com.maddyhome.idea.vim.ex.CommandHandler import com.maddyhome.idea.vim.ex.*
import com.maddyhome.idea.vim.ex.ExCommand
import com.maddyhome.idea.vim.ex.ExOutputModel
import com.maddyhome.idea.vim.ex.commands
import com.maddyhome.idea.vim.ex.flags
import com.maddyhome.idea.vim.helper.EditorHelper import com.maddyhome.idea.vim.helper.EditorHelper
import com.maddyhome.idea.vim.helper.StringHelper.stringToKeys import com.maddyhome.idea.vim.helper.StringHelper.stringToKeys
import com.maddyhome.idea.vim.helper.StringHelper.toKeyNotation import com.maddyhome.idea.vim.helper.StringHelper.toKeyNotation
@@ -33,7 +29,7 @@ import kotlin.math.absoluteValue
class JumpsHandler : CommandHandler.SingleExecution() { class JumpsHandler : CommandHandler.SingleExecution() {
override val names = commands("ju[mps]") override val names = commands("ju[mps]")
override val argFlags = flags(RangeFlag.RANGE_OPTIONAL, ArgumentFlag.ARGUMENT_FORBIDDEN) override val argFlags = flags(RangeFlag.RANGE_OPTIONAL, ArgumentFlag.ARGUMENT_FORBIDDEN, Access.READ_ONLY)
override fun execute(editor: Editor, context: DataContext, cmd: ExCommand): Boolean { override fun execute(editor: Editor, context: DataContext, cmd: ExCommand): Boolean {
val jumps = VimPlugin.getMark().jumps val jumps = VimPlugin.getMark().jumps
val spot = VimPlugin.getMark().jumpSpot val spot = VimPlugin.getMark().jumpSpot

View File

@@ -20,11 +20,7 @@ package com.maddyhome.idea.vim.ex.handler
import com.intellij.openapi.actionSystem.DataContext import com.intellij.openapi.actionSystem.DataContext
import com.intellij.openapi.editor.Editor import com.intellij.openapi.editor.Editor
import com.maddyhome.idea.vim.ex.CommandHandler import com.maddyhome.idea.vim.ex.*
import com.maddyhome.idea.vim.ex.ExCommand
import com.maddyhome.idea.vim.ex.ExException
import com.maddyhome.idea.vim.ex.commands
import com.maddyhome.idea.vim.ex.flags
import com.maddyhome.idea.vim.ex.vimscript.VimScriptCommandHandler import com.maddyhome.idea.vim.ex.vimscript.VimScriptCommandHandler
import com.maddyhome.idea.vim.ex.vimscript.VimScriptGlobalEnvironment import com.maddyhome.idea.vim.ex.vimscript.VimScriptGlobalEnvironment
import com.maddyhome.idea.vim.ex.vimscript.VimScriptParser import com.maddyhome.idea.vim.ex.vimscript.VimScriptParser
@@ -35,7 +31,7 @@ import java.util.regex.Pattern
*/ */
class LetHandler : CommandHandler.SingleExecution(), VimScriptCommandHandler { class LetHandler : CommandHandler.SingleExecution(), VimScriptCommandHandler {
override val names = commands("let") override val names = commands("let")
override val argFlags = flags(RangeFlag.RANGE_FORBIDDEN, ArgumentFlag.ARGUMENT_OPTIONAL) override val argFlags = flags(RangeFlag.RANGE_FORBIDDEN, ArgumentFlag.ARGUMENT_OPTIONAL, Access.READ_ONLY)
@Throws(ExException::class) @Throws(ExException::class)
override fun execute(editor: Editor, context: DataContext, cmd: ExCommand): Boolean { override fun execute(editor: Editor, context: DataContext, cmd: ExCommand): Boolean {

View File

@@ -22,13 +22,7 @@ import com.intellij.openapi.actionSystem.DataContext
import com.intellij.openapi.editor.Editor import com.intellij.openapi.editor.Editor
import com.maddyhome.idea.vim.VimPlugin import com.maddyhome.idea.vim.VimPlugin
import com.maddyhome.idea.vim.command.MappingMode import com.maddyhome.idea.vim.command.MappingMode
import com.maddyhome.idea.vim.ex.CommandHandler import com.maddyhome.idea.vim.ex.*
import com.maddyhome.idea.vim.ex.CommandHandlerFlags
import com.maddyhome.idea.vim.ex.CommandName
import com.maddyhome.idea.vim.ex.ExCommand
import com.maddyhome.idea.vim.ex.ExException
import com.maddyhome.idea.vim.ex.commands
import com.maddyhome.idea.vim.ex.flags
import com.maddyhome.idea.vim.ex.handler.MapHandler.SpecialArgument.EXPR import com.maddyhome.idea.vim.ex.handler.MapHandler.SpecialArgument.EXPR
import com.maddyhome.idea.vim.ex.handler.MapHandler.SpecialArgument.SCRIPT import com.maddyhome.idea.vim.ex.handler.MapHandler.SpecialArgument.SCRIPT
import com.maddyhome.idea.vim.ex.vimscript.VimScriptCommandHandler import com.maddyhome.idea.vim.ex.vimscript.VimScriptCommandHandler
@@ -41,7 +35,7 @@ import javax.swing.KeyStroke
*/ */
class MapHandler : CommandHandler.SingleExecution(), VimScriptCommandHandler { class MapHandler : CommandHandler.SingleExecution(), VimScriptCommandHandler {
override val names: Array<CommandName> = COMMAND_NAMES override val names: Array<CommandName> = COMMAND_NAMES
override val argFlags: CommandHandlerFlags = flags(RangeFlag.RANGE_FORBIDDEN, ArgumentFlag.ARGUMENT_OPTIONAL) override val argFlags: CommandHandlerFlags = flags(RangeFlag.RANGE_FORBIDDEN, ArgumentFlag.ARGUMENT_OPTIONAL, Access.READ_ONLY)
@Throws(ExException::class) @Throws(ExException::class)
override fun execute(editor: Editor, context: DataContext, cmd: ExCommand): Boolean { override fun execute(editor: Editor, context: DataContext, cmd: ExCommand): Boolean {

View File

@@ -31,7 +31,7 @@ import com.maddyhome.idea.vim.helper.Msg
class MarkHandler : CommandHandler.SingleExecution() { class MarkHandler : CommandHandler.SingleExecution() {
override val names = commands("ma[rk]", "k") override val names = commands("ma[rk]", "k")
override val argFlags = flags(RangeFlag.RANGE_OPTIONAL, ArgumentFlag.ARGUMENT_REQUIRED) override val argFlags = flags(RangeFlag.RANGE_OPTIONAL, ArgumentFlag.ARGUMENT_REQUIRED, Access.READ_ONLY)
override fun execute(editor: Editor, context: DataContext, cmd: ExCommand): Boolean { override fun execute(editor: Editor, context: DataContext, cmd: ExCommand): Boolean {
val mark = cmd.argument[0] val mark = cmd.argument[0]

View File

@@ -21,20 +21,14 @@ package com.maddyhome.idea.vim.ex.handler
import com.intellij.openapi.actionSystem.DataContext import com.intellij.openapi.actionSystem.DataContext
import com.intellij.openapi.editor.Editor import com.intellij.openapi.editor.Editor
import com.maddyhome.idea.vim.VimPlugin import com.maddyhome.idea.vim.VimPlugin
import com.maddyhome.idea.vim.ex.CommandHandler import com.maddyhome.idea.vim.ex.*
import com.maddyhome.idea.vim.ex.CommandHandlerFlags
import com.maddyhome.idea.vim.ex.CommandName
import com.maddyhome.idea.vim.ex.ExCommand
import com.maddyhome.idea.vim.ex.ExOutputModel
import com.maddyhome.idea.vim.ex.commands
import com.maddyhome.idea.vim.ex.flags
import com.maddyhome.idea.vim.helper.EditorHelper import com.maddyhome.idea.vim.helper.EditorHelper
import com.maddyhome.idea.vim.helper.StringHelper.stringToKeys import com.maddyhome.idea.vim.helper.StringHelper.stringToKeys
import com.maddyhome.idea.vim.helper.StringHelper.toKeyNotation import com.maddyhome.idea.vim.helper.StringHelper.toKeyNotation
class MarksHandler : CommandHandler.SingleExecution() { class MarksHandler : CommandHandler.SingleExecution() {
override val names: Array<CommandName> = commands("marks") override val names: Array<CommandName> = commands("marks")
override val argFlags: CommandHandlerFlags = flags(RangeFlag.RANGE_OPTIONAL, ArgumentFlag.ARGUMENT_OPTIONAL) override val argFlags: CommandHandlerFlags = flags(RangeFlag.RANGE_OPTIONAL, ArgumentFlag.ARGUMENT_OPTIONAL, Access.READ_ONLY)
override fun execute(editor: Editor, context: DataContext, cmd: ExCommand): Boolean { override fun execute(editor: Editor, context: DataContext, cmd: ExCommand): Boolean {

View File

@@ -25,7 +25,6 @@ import com.maddyhome.idea.vim.VimPlugin
import com.maddyhome.idea.vim.command.SelectionType import com.maddyhome.idea.vim.command.SelectionType
import com.maddyhome.idea.vim.common.TextRange import com.maddyhome.idea.vim.common.TextRange
import com.maddyhome.idea.vim.ex.* import com.maddyhome.idea.vim.ex.*
import com.maddyhome.idea.vim.ex.CommandHandler.Flag.WRITABLE
import com.maddyhome.idea.vim.group.copy.PutData import com.maddyhome.idea.vim.group.copy.PutData
import com.maddyhome.idea.vim.helper.EditorHelper import com.maddyhome.idea.vim.helper.EditorHelper
import com.maddyhome.idea.vim.helper.MessageHelper import com.maddyhome.idea.vim.helper.MessageHelper
@@ -35,7 +34,7 @@ import kotlin.math.min
class MoveTextHandler : CommandHandler.SingleExecution() { class MoveTextHandler : CommandHandler.SingleExecution() {
override val names = commands("m[ove]") override val names = commands("m[ove]")
override val argFlags = flags(RangeFlag.RANGE_OPTIONAL, ArgumentFlag.ARGUMENT_REQUIRED, WRITABLE) override val argFlags = flags(RangeFlag.RANGE_OPTIONAL, ArgumentFlag.ARGUMENT_REQUIRED, Access.WRITABLE)
@Throws(ExException::class) @Throws(ExException::class)
override fun execute(editor: Editor, context: DataContext, cmd: ExCommand): Boolean { override fun execute(editor: Editor, context: DataContext, cmd: ExCommand): Boolean {
val carets = EditorHelper.getOrderedCaretsList(editor) val carets = EditorHelper.getOrderedCaretsList(editor)

View File

@@ -22,14 +22,13 @@ import com.intellij.openapi.actionSystem.DataContext
import com.intellij.openapi.editor.Editor import com.intellij.openapi.editor.Editor
import com.maddyhome.idea.vim.VimPlugin import com.maddyhome.idea.vim.VimPlugin
import com.maddyhome.idea.vim.ex.CommandHandler import com.maddyhome.idea.vim.ex.CommandHandler
import com.maddyhome.idea.vim.ex.CommandHandler.Flag.DONT_REOPEN
import com.maddyhome.idea.vim.ex.ExCommand import com.maddyhome.idea.vim.ex.ExCommand
import com.maddyhome.idea.vim.ex.commands import com.maddyhome.idea.vim.ex.commands
import com.maddyhome.idea.vim.ex.flags import com.maddyhome.idea.vim.ex.flags
class NextFileHandler : CommandHandler.SingleExecution() { class NextFileHandler : CommandHandler.SingleExecution() {
override val names = commands("n[ext]") override val names = commands("n[ext]")
override val argFlags = flags(RangeFlag.RANGE_IS_COUNT, ArgumentFlag.ARGUMENT_OPTIONAL, DONT_REOPEN) override val argFlags = flags(RangeFlag.RANGE_IS_COUNT, ArgumentFlag.ARGUMENT_OPTIONAL, Access.READ_ONLY)
override fun execute(editor: Editor, context: DataContext, cmd: ExCommand): Boolean { override fun execute(editor: Editor, context: DataContext, cmd: ExCommand): Boolean {
val count = cmd.getCount(editor, context, 1, true) val count = cmd.getCount(editor, context, 1, true)

View File

@@ -28,7 +28,7 @@ import com.maddyhome.idea.vim.ex.flags
class NextTabHandler : CommandHandler.SingleExecution() { class NextTabHandler : CommandHandler.SingleExecution() {
override val names = commands("tabn[ext]") override val names = commands("tabn[ext]")
override val argFlags = flags(RangeFlag.RANGE_FORBIDDEN, ArgumentFlag.ARGUMENT_OPTIONAL) override val argFlags = flags(RangeFlag.RANGE_FORBIDDEN, ArgumentFlag.ARGUMENT_OPTIONAL, Access.READ_ONLY)
override fun execute(editor: Editor, context: DataContext, cmd: ExCommand): Boolean { override fun execute(editor: Editor, context: DataContext, cmd: ExCommand): Boolean {
VimPlugin.getMotion().moveCaretGotoNextTab(editor, context, cmd.argument.toIntOrNull() ?: 0) VimPlugin.getMotion().moveCaretGotoNextTab(editor, context, cmd.argument.toIntOrNull() ?: 0)
return true return true

View File

@@ -27,7 +27,7 @@ import com.maddyhome.idea.vim.ex.flags
class NoHLSearchHandler : CommandHandler.SingleExecution() { class NoHLSearchHandler : CommandHandler.SingleExecution() {
override val names = commands("noh[lsearch]") override val names = commands("noh[lsearch]")
override val argFlags = flags(RangeFlag.RANGE_FORBIDDEN, ArgumentFlag.ARGUMENT_FORBIDDEN) override val argFlags = flags(RangeFlag.RANGE_FORBIDDEN, ArgumentFlag.ARGUMENT_FORBIDDEN, Access.READ_ONLY)
override fun execute(editor: Editor, context: DataContext, cmd: ExCommand): Boolean { override fun execute(editor: Editor, context: DataContext, cmd: ExCommand): Boolean {
VimPlugin.getSearch().clearSearchHighlight() VimPlugin.getSearch().clearSearchHighlight()
return true return true

View File

@@ -21,16 +21,11 @@ package com.maddyhome.idea.vim.ex.handler
import com.intellij.openapi.actionSystem.DataContext import com.intellij.openapi.actionSystem.DataContext
import com.intellij.openapi.editor.Editor import com.intellij.openapi.editor.Editor
import com.maddyhome.idea.vim.VimPlugin import com.maddyhome.idea.vim.VimPlugin
import com.maddyhome.idea.vim.ex.CommandHandler import com.maddyhome.idea.vim.ex.*
import com.maddyhome.idea.vim.ex.CommandHandlerFlags
import com.maddyhome.idea.vim.ex.CommandName
import com.maddyhome.idea.vim.ex.ExCommand
import com.maddyhome.idea.vim.ex.commands
import com.maddyhome.idea.vim.ex.flags
class OnlyHandler : CommandHandler.SingleExecution() { class OnlyHandler : CommandHandler.SingleExecution() {
override val names: Array<CommandName> = commands("on[ly]") override val names: Array<CommandName> = commands("on[ly]")
override val argFlags: CommandHandlerFlags = flags(RangeFlag.RANGE_OPTIONAL, ArgumentFlag.ARGUMENT_OPTIONAL) override val argFlags: CommandHandlerFlags = flags(RangeFlag.RANGE_OPTIONAL, ArgumentFlag.ARGUMENT_OPTIONAL, Access.READ_ONLY)
override fun execute(editor: Editor, context: DataContext, cmd: ExCommand): Boolean { override fun execute(editor: Editor, context: DataContext, cmd: ExCommand): Boolean {
VimPlugin.getWindow().closeAllExceptCurrent(context) VimPlugin.getWindow().closeAllExceptCurrent(context)

View File

@@ -22,14 +22,13 @@ import com.intellij.openapi.actionSystem.DataContext
import com.intellij.openapi.editor.Editor import com.intellij.openapi.editor.Editor
import com.maddyhome.idea.vim.VimPlugin import com.maddyhome.idea.vim.VimPlugin
import com.maddyhome.idea.vim.ex.CommandHandler import com.maddyhome.idea.vim.ex.CommandHandler
import com.maddyhome.idea.vim.ex.CommandHandler.Flag.DONT_REOPEN
import com.maddyhome.idea.vim.ex.ExCommand import com.maddyhome.idea.vim.ex.ExCommand
import com.maddyhome.idea.vim.ex.commands import com.maddyhome.idea.vim.ex.commands
import com.maddyhome.idea.vim.ex.flags import com.maddyhome.idea.vim.ex.flags
class PreviousFileHandler : CommandHandler.SingleExecution() { class PreviousFileHandler : CommandHandler.SingleExecution() {
override val names = commands("N[ext]", "prev[ious]") override val names = commands("N[ext]", "prev[ious]")
override val argFlags = flags(RangeFlag.RANGE_IS_COUNT, ArgumentFlag.ARGUMENT_OPTIONAL, DONT_REOPEN) override val argFlags = flags(RangeFlag.RANGE_IS_COUNT, ArgumentFlag.ARGUMENT_OPTIONAL, Access.READ_ONLY)
override fun execute(editor: Editor, context: DataContext, cmd: ExCommand): Boolean { override fun execute(editor: Editor, context: DataContext, cmd: ExCommand): Boolean {
val count = cmd.getCount(editor, context, 1, true) val count = cmd.getCount(editor, context, 1, true)

View File

@@ -28,7 +28,7 @@ import com.maddyhome.idea.vim.ex.flags
class PreviousTabHandler : CommandHandler.SingleExecution() { class PreviousTabHandler : CommandHandler.SingleExecution() {
override val names = commands("tabp[revious]", "tabN[ext]") override val names = commands("tabp[revious]", "tabN[ext]")
override val argFlags = flags(RangeFlag.RANGE_FORBIDDEN, ArgumentFlag.ARGUMENT_OPTIONAL) override val argFlags = flags(RangeFlag.RANGE_FORBIDDEN, ArgumentFlag.ARGUMENT_OPTIONAL, Access.READ_ONLY)
override fun execute(editor: Editor, context: DataContext, cmd: ExCommand): Boolean { override fun execute(editor: Editor, context: DataContext, cmd: ExCommand): Boolean {
VimPlugin.getMotion().moveCaretGotoPreviousTab(editor, context, cmd.argument.toIntOrNull() ?: 0) VimPlugin.getMotion().moveCaretGotoPreviousTab(editor, context, cmd.argument.toIntOrNull() ?: 0)
return true return true

View File

@@ -28,7 +28,7 @@ import com.maddyhome.idea.vim.ex.flags
class PromptFindHandler : CommandHandler.SingleExecution() { class PromptFindHandler : CommandHandler.SingleExecution() {
override val names = commands("pro[mptfind]") override val names = commands("pro[mptfind]")
override val argFlags = flags(RangeFlag.RANGE_FORBIDDEN, ArgumentFlag.ARGUMENT_OPTIONAL) override val argFlags = flags(RangeFlag.RANGE_FORBIDDEN, ArgumentFlag.ARGUMENT_OPTIONAL, Access.READ_ONLY)
override fun execute(editor: Editor, context: DataContext, cmd: ExCommand) = override fun execute(editor: Editor, context: DataContext, cmd: ExCommand) =
KeyHandler.executeAction("Find", context) KeyHandler.executeAction("Find", context)
} }

View File

@@ -28,7 +28,7 @@ import com.maddyhome.idea.vim.ex.flags
class PromptReplaceHandler : CommandHandler.SingleExecution() { class PromptReplaceHandler : CommandHandler.SingleExecution() {
override val names = commands("promptr[epl]") override val names = commands("promptr[epl]")
override val argFlags = flags(RangeFlag.RANGE_FORBIDDEN, ArgumentFlag.ARGUMENT_OPTIONAL) override val argFlags = flags(RangeFlag.RANGE_FORBIDDEN, ArgumentFlag.ARGUMENT_OPTIONAL, Access.READ_ONLY)
override fun execute(editor: Editor, context: DataContext, cmd: ExCommand) = override fun execute(editor: Editor, context: DataContext, cmd: ExCommand) =
KeyHandler.executeAction("Replace", context) KeyHandler.executeAction("Replace", context)
} }

View File

@@ -30,7 +30,7 @@ import com.maddyhome.idea.vim.group.copy.PutData
class PutLinesHandler : CommandHandler.SingleExecution() { class PutLinesHandler : CommandHandler.SingleExecution() {
override val names = commands("pu[t]") override val names = commands("pu[t]")
override val argFlags = flags(RangeFlag.RANGE_OPTIONAL, ArgumentFlag.ARGUMENT_OPTIONAL) override val argFlags = flags(RangeFlag.RANGE_OPTIONAL, ArgumentFlag.ARGUMENT_OPTIONAL, Access.READ_ONLY)
override fun execute(editor: Editor, context: DataContext, cmd: ExCommand): Boolean { override fun execute(editor: Editor, context: DataContext, cmd: ExCommand): Boolean {
if (editor.isOneLineMode) return false if (editor.isOneLineMode) return false

View File

@@ -22,14 +22,13 @@ import com.intellij.openapi.actionSystem.DataContext
import com.intellij.openapi.editor.Editor import com.intellij.openapi.editor.Editor
import com.maddyhome.idea.vim.VimPlugin import com.maddyhome.idea.vim.VimPlugin
import com.maddyhome.idea.vim.ex.CommandHandler import com.maddyhome.idea.vim.ex.CommandHandler
import com.maddyhome.idea.vim.ex.CommandHandler.Flag.DONT_REOPEN
import com.maddyhome.idea.vim.ex.ExCommand import com.maddyhome.idea.vim.ex.ExCommand
import com.maddyhome.idea.vim.ex.commands import com.maddyhome.idea.vim.ex.commands
import com.maddyhome.idea.vim.ex.flags import com.maddyhome.idea.vim.ex.flags
class QuitHandler : CommandHandler.SingleExecution() { class QuitHandler : CommandHandler.SingleExecution() {
override val names = commands("q[uit]", "clo[se]", "hid[e]") override val names = commands("q[uit]", "clo[se]", "hid[e]")
override val argFlags = flags(RangeFlag.RANGE_OPTIONAL, ArgumentFlag.ARGUMENT_OPTIONAL, DONT_REOPEN) override val argFlags = flags(RangeFlag.RANGE_OPTIONAL, ArgumentFlag.ARGUMENT_OPTIONAL, Access.READ_ONLY)
override fun execute(editor: Editor, context: DataContext, cmd: ExCommand): Boolean { override fun execute(editor: Editor, context: DataContext, cmd: ExCommand): Boolean {
VimPlugin.getFile().closeFile(editor, context) VimPlugin.getFile().closeFile(editor, context)
return true return true

View File

@@ -21,7 +21,6 @@ package com.maddyhome.idea.vim.ex.handler
import com.intellij.openapi.actionSystem.DataContext import com.intellij.openapi.actionSystem.DataContext
import com.intellij.openapi.editor.Editor import com.intellij.openapi.editor.Editor
import com.maddyhome.idea.vim.ex.CommandHandler import com.maddyhome.idea.vim.ex.CommandHandler
import com.maddyhome.idea.vim.ex.CommandHandler.Flag.WRITABLE
import com.maddyhome.idea.vim.ex.ExCommand import com.maddyhome.idea.vim.ex.ExCommand
import com.maddyhome.idea.vim.ex.commands import com.maddyhome.idea.vim.ex.commands
import com.maddyhome.idea.vim.ex.flags import com.maddyhome.idea.vim.ex.flags
@@ -29,6 +28,6 @@ import com.maddyhome.idea.vim.helper.UndoRedoHelper
class RedoHandler : CommandHandler.SingleExecution() { class RedoHandler : CommandHandler.SingleExecution() {
override val names = commands("red[o]") override val names = commands("red[o]")
override val argFlags = flags(RangeFlag.RANGE_FORBIDDEN, ArgumentFlag.ARGUMENT_FORBIDDEN, WRITABLE) override val argFlags = flags(RangeFlag.RANGE_FORBIDDEN, ArgumentFlag.ARGUMENT_FORBIDDEN, Access.WRITABLE)
override fun execute(editor: Editor, context: DataContext, cmd: ExCommand) = UndoRedoHelper.redo(context) override fun execute(editor: Editor, context: DataContext, cmd: ExCommand) = UndoRedoHelper.redo(context)
} }

View File

@@ -21,16 +21,12 @@ package com.maddyhome.idea.vim.ex.handler
import com.intellij.openapi.actionSystem.DataContext import com.intellij.openapi.actionSystem.DataContext
import com.intellij.openapi.editor.Editor import com.intellij.openapi.editor.Editor
import com.maddyhome.idea.vim.VimPlugin import com.maddyhome.idea.vim.VimPlugin
import com.maddyhome.idea.vim.ex.CommandHandler import com.maddyhome.idea.vim.ex.*
import com.maddyhome.idea.vim.ex.ExCommand
import com.maddyhome.idea.vim.ex.ExOutputModel
import com.maddyhome.idea.vim.ex.commands
import com.maddyhome.idea.vim.ex.flags
import com.maddyhome.idea.vim.helper.StringHelper import com.maddyhome.idea.vim.helper.StringHelper
class RegistersHandler : CommandHandler.SingleExecution() { class RegistersHandler : CommandHandler.SingleExecution() {
override val names = commands("di[splay]", "reg[isters]") override val names = commands("di[splay]", "reg[isters]")
override val argFlags = flags(RangeFlag.RANGE_OPTIONAL, ArgumentFlag.ARGUMENT_OPTIONAL) override val argFlags = flags(RangeFlag.RANGE_OPTIONAL, ArgumentFlag.ARGUMENT_OPTIONAL, Access.READ_ONLY)
override fun execute(editor: Editor, context: DataContext, cmd: ExCommand): Boolean { override fun execute(editor: Editor, context: DataContext, cmd: ExCommand): Boolean {
val regs = VimPlugin.getRegister().registers.joinToString("\n", prefix = "--- Registers ---\n") { reg -> val regs = VimPlugin.getRegister().registers.joinToString("\n", prefix = "--- Registers ---\n") { reg ->
""""${reg.name} ${StringHelper.toKeyNotation(reg.keys)}""" """"${reg.name} ${StringHelper.toKeyNotation(reg.keys)}"""

View File

@@ -22,20 +22,13 @@ import com.intellij.openapi.actionSystem.DataContext
import com.intellij.openapi.editor.Caret import com.intellij.openapi.editor.Caret
import com.intellij.openapi.editor.Editor import com.intellij.openapi.editor.Editor
import com.maddyhome.idea.vim.VimPlugin import com.maddyhome.idea.vim.VimPlugin
import com.maddyhome.idea.vim.ex.CommandHandler import com.maddyhome.idea.vim.ex.*
import com.maddyhome.idea.vim.ex.CommandHandler.Flag.DONT_SAVE_LAST import com.maddyhome.idea.vim.ex.CommandHandler.Flag.DONT_SAVE_LAST
import com.maddyhome.idea.vim.ex.CommandHandlerFlags
import com.maddyhome.idea.vim.ex.CommandName
import com.maddyhome.idea.vim.ex.CommandParser
import com.maddyhome.idea.vim.ex.ExCommand
import com.maddyhome.idea.vim.ex.ExException
import com.maddyhome.idea.vim.ex.commands
import com.maddyhome.idea.vim.ex.flags
import com.maddyhome.idea.vim.group.MotionGroup import com.maddyhome.idea.vim.group.MotionGroup
class RepeatHandler : CommandHandler.ForEachCaret() { class RepeatHandler : CommandHandler.ForEachCaret() {
override val names: Array<CommandName> = commands("@") override val names: Array<CommandName> = commands("@")
override val argFlags: CommandHandlerFlags = flags(RangeFlag.RANGE_OPTIONAL, ArgumentFlag.ARGUMENT_REQUIRED, DONT_SAVE_LAST) override val argFlags: CommandHandlerFlags = flags(RangeFlag.RANGE_OPTIONAL, ArgumentFlag.ARGUMENT_REQUIRED, Access.SELF_SYNCHRONIZED, DONT_SAVE_LAST)
private var lastArg = ':' private var lastArg = ':'

View File

@@ -22,14 +22,13 @@ import com.intellij.openapi.actionSystem.DataContext
import com.intellij.openapi.editor.Editor import com.intellij.openapi.editor.Editor
import com.maddyhome.idea.vim.VimPlugin import com.maddyhome.idea.vim.VimPlugin
import com.maddyhome.idea.vim.ex.CommandHandler import com.maddyhome.idea.vim.ex.CommandHandler
import com.maddyhome.idea.vim.ex.CommandHandler.Flag.DONT_REOPEN
import com.maddyhome.idea.vim.ex.ExCommand import com.maddyhome.idea.vim.ex.ExCommand
import com.maddyhome.idea.vim.ex.commands import com.maddyhome.idea.vim.ex.commands
import com.maddyhome.idea.vim.ex.flags import com.maddyhome.idea.vim.ex.flags
class SelectFileHandler : CommandHandler.SingleExecution() { class SelectFileHandler : CommandHandler.SingleExecution() {
override val names = commands("argu[ment]") override val names = commands("argu[ment]")
override val argFlags = flags(RangeFlag.RANGE_IS_COUNT, ArgumentFlag.ARGUMENT_OPTIONAL, DONT_REOPEN) override val argFlags = flags(RangeFlag.RANGE_IS_COUNT, ArgumentFlag.ARGUMENT_OPTIONAL, Access.READ_ONLY)
override fun execute(editor: Editor, context: DataContext, cmd: ExCommand): Boolean { override fun execute(editor: Editor, context: DataContext, cmd: ExCommand): Boolean {
val count = cmd.getCount(editor, context, 0, true) val count = cmd.getCount(editor, context, 0, true)

View File

@@ -23,14 +23,13 @@ import com.intellij.openapi.editor.Editor
import com.maddyhome.idea.vim.VimPlugin import com.maddyhome.idea.vim.VimPlugin
import com.maddyhome.idea.vim.ex.CommandHandler import com.maddyhome.idea.vim.ex.CommandHandler
import com.maddyhome.idea.vim.ex.CommandHandler.ArgumentFlag.ARGUMENT_OPTIONAL import com.maddyhome.idea.vim.ex.CommandHandler.ArgumentFlag.ARGUMENT_OPTIONAL
import com.maddyhome.idea.vim.ex.CommandHandler.Flag.DONT_REOPEN
import com.maddyhome.idea.vim.ex.ExCommand import com.maddyhome.idea.vim.ex.ExCommand
import com.maddyhome.idea.vim.ex.commands import com.maddyhome.idea.vim.ex.commands
import com.maddyhome.idea.vim.ex.flags import com.maddyhome.idea.vim.ex.flags
class SelectFirstFileHandler : CommandHandler.SingleExecution() { class SelectFirstFileHandler : CommandHandler.SingleExecution() {
override val names = commands("fir[st]", "rew[ind]") override val names = commands("fir[st]", "rew[ind]")
override val argFlags = flags(RangeFlag.RANGE_OPTIONAL, ARGUMENT_OPTIONAL, DONT_REOPEN) override val argFlags = flags(RangeFlag.RANGE_OPTIONAL, ARGUMENT_OPTIONAL, Access.READ_ONLY)
override fun execute(editor: Editor, context: DataContext, cmd: ExCommand): Boolean { override fun execute(editor: Editor, context: DataContext, cmd: ExCommand): Boolean {
val res = VimPlugin.getFile().selectFile(0, context) val res = VimPlugin.getFile().selectFile(0, context)
if (res) { if (res) {

View File

@@ -22,14 +22,13 @@ import com.intellij.openapi.actionSystem.DataContext
import com.intellij.openapi.editor.Editor import com.intellij.openapi.editor.Editor
import com.maddyhome.idea.vim.VimPlugin import com.maddyhome.idea.vim.VimPlugin
import com.maddyhome.idea.vim.ex.CommandHandler import com.maddyhome.idea.vim.ex.CommandHandler
import com.maddyhome.idea.vim.ex.CommandHandler.Flag.DONT_REOPEN
import com.maddyhome.idea.vim.ex.ExCommand import com.maddyhome.idea.vim.ex.ExCommand
import com.maddyhome.idea.vim.ex.commands import com.maddyhome.idea.vim.ex.commands
import com.maddyhome.idea.vim.ex.flags import com.maddyhome.idea.vim.ex.flags
class SelectLastFileHandler : CommandHandler.SingleExecution() { class SelectLastFileHandler : CommandHandler.SingleExecution() {
override val names = commands("la[st]") override val names = commands("la[st]")
override val argFlags = flags(RangeFlag.RANGE_OPTIONAL, ArgumentFlag.ARGUMENT_OPTIONAL, DONT_REOPEN) override val argFlags = flags(RangeFlag.RANGE_OPTIONAL, ArgumentFlag.ARGUMENT_OPTIONAL, Access.READ_ONLY)
override fun execute(editor: Editor, context: DataContext, cmd: ExCommand): Boolean { override fun execute(editor: Editor, context: DataContext, cmd: ExCommand): Boolean {
val res = VimPlugin.getFile().selectFile(999, context) val res = VimPlugin.getFile().selectFile(999, context)
if (res) { if (res) {

View File

@@ -29,7 +29,7 @@ import com.maddyhome.idea.vim.option.OptionsManager
class SetHandler : CommandHandler.SingleExecution(), VimScriptCommandHandler { class SetHandler : CommandHandler.SingleExecution(), VimScriptCommandHandler {
override val names = commands("se[t]") override val names = commands("se[t]")
override val argFlags = flags(RangeFlag.RANGE_OPTIONAL, ArgumentFlag.ARGUMENT_OPTIONAL) override val argFlags = flags(RangeFlag.RANGE_OPTIONAL, ArgumentFlag.ARGUMENT_OPTIONAL, Access.READ_ONLY)
override fun execute(editor: Editor, context: DataContext, cmd: ExCommand) = override fun execute(editor: Editor, context: DataContext, cmd: ExCommand) =
parseOptionLine(editor, cmd, true) parseOptionLine(editor, cmd, true)

View File

@@ -30,7 +30,7 @@ import com.maddyhome.idea.vim.ex.flags
*/ */
class ShellHandler : CommandHandler.SingleExecution() { class ShellHandler : CommandHandler.SingleExecution() {
override val names = commands("sh[ell]") override val names = commands("sh[ell]")
override val argFlags = flags(RangeFlag.RANGE_FORBIDDEN, ArgumentFlag.ARGUMENT_FORBIDDEN) override val argFlags = flags(RangeFlag.RANGE_FORBIDDEN, ArgumentFlag.ARGUMENT_FORBIDDEN, Access.READ_ONLY)
override fun execute(editor: Editor, context: DataContext, cmd: ExCommand) = override fun execute(editor: Editor, context: DataContext, cmd: ExCommand) =
KeyHandler.executeAction("ActivateTerminalToolWindow", context) KeyHandler.executeAction("ActivateTerminalToolWindow", context)
} }

View File

@@ -23,17 +23,11 @@ import com.intellij.openapi.editor.Caret
import com.intellij.openapi.editor.Editor import com.intellij.openapi.editor.Editor
import com.maddyhome.idea.vim.VimPlugin import com.maddyhome.idea.vim.VimPlugin
import com.maddyhome.idea.vim.common.TextRange import com.maddyhome.idea.vim.common.TextRange
import com.maddyhome.idea.vim.ex.CommandHandler import com.maddyhome.idea.vim.ex.*
import com.maddyhome.idea.vim.ex.CommandHandler.Flag.WRITABLE
import com.maddyhome.idea.vim.ex.CommandHandlerFlags
import com.maddyhome.idea.vim.ex.CommandName
import com.maddyhome.idea.vim.ex.ExCommand
import com.maddyhome.idea.vim.ex.commands
import com.maddyhome.idea.vim.ex.flags
class ShiftLeftHandler : CommandHandler.ForEachCaret() { class ShiftLeftHandler : CommandHandler.ForEachCaret() {
override val names: Array<CommandName> = commands("<[${"<".repeat(31)}]") override val names: Array<CommandName> = commands("<[${"<".repeat(31)}]")
override val argFlags: CommandHandlerFlags = flags(RangeFlag.RANGE_OPTIONAL, ArgumentFlag.ARGUMENT_OPTIONAL, WRITABLE) override val argFlags: CommandHandlerFlags = flags(RangeFlag.RANGE_OPTIONAL, ArgumentFlag.ARGUMENT_OPTIONAL, Access.WRITABLE)
override fun execute(editor: Editor, caret: Caret, context: DataContext, cmd: ExCommand): Boolean { override fun execute(editor: Editor, caret: Caret, context: DataContext, cmd: ExCommand): Boolean {
val range = cmd.getTextRange(editor, caret, context, true) val range = cmd.getTextRange(editor, caret, context, true)

View File

@@ -23,17 +23,11 @@ import com.intellij.openapi.editor.Caret
import com.intellij.openapi.editor.Editor import com.intellij.openapi.editor.Editor
import com.maddyhome.idea.vim.VimPlugin import com.maddyhome.idea.vim.VimPlugin
import com.maddyhome.idea.vim.common.TextRange import com.maddyhome.idea.vim.common.TextRange
import com.maddyhome.idea.vim.ex.CommandHandler import com.maddyhome.idea.vim.ex.*
import com.maddyhome.idea.vim.ex.CommandHandler.Flag.WRITABLE
import com.maddyhome.idea.vim.ex.CommandHandlerFlags
import com.maddyhome.idea.vim.ex.CommandName
import com.maddyhome.idea.vim.ex.ExCommand
import com.maddyhome.idea.vim.ex.commands
import com.maddyhome.idea.vim.ex.flags
class ShiftRightHandler : CommandHandler.ForEachCaret() { class ShiftRightHandler : CommandHandler.ForEachCaret() {
override val names: Array<CommandName> = commands(">[${">".repeat(31)}]") override val names: Array<CommandName> = commands(">[${">".repeat(31)}]")
override val argFlags: CommandHandlerFlags = flags(RangeFlag.RANGE_OPTIONAL, ArgumentFlag.ARGUMENT_OPTIONAL, WRITABLE) override val argFlags: CommandHandlerFlags = flags(RangeFlag.RANGE_OPTIONAL, ArgumentFlag.ARGUMENT_OPTIONAL, Access.WRITABLE)
override fun execute(editor: Editor, caret: Caret, context: DataContext, cmd: ExCommand): Boolean { override fun execute(editor: Editor, caret: Caret, context: DataContext, cmd: ExCommand): Boolean {
val range = cmd.getTextRange(editor, caret, context, true) val range = cmd.getTextRange(editor, caret, context, true)

View File

@@ -23,13 +23,7 @@ import com.intellij.openapi.editor.Caret
import com.intellij.openapi.editor.Editor import com.intellij.openapi.editor.Editor
import com.intellij.openapi.util.text.StringUtil import com.intellij.openapi.util.text.StringUtil
import com.maddyhome.idea.vim.VimPlugin import com.maddyhome.idea.vim.VimPlugin
import com.maddyhome.idea.vim.ex.CommandHandler import com.maddyhome.idea.vim.ex.*
import com.maddyhome.idea.vim.ex.CommandHandler.Flag.WRITABLE
import com.maddyhome.idea.vim.ex.ExCommand
import com.maddyhome.idea.vim.ex.ExException
import com.maddyhome.idea.vim.ex.LineRange
import com.maddyhome.idea.vim.ex.commands
import com.maddyhome.idea.vim.ex.flags
import com.maddyhome.idea.vim.helper.inBlockSubMode import com.maddyhome.idea.vim.helper.inBlockSubMode
import java.util.* import java.util.*
@@ -38,7 +32,7 @@ import java.util.*
*/ */
class SortHandler : CommandHandler.SingleExecution() { class SortHandler : CommandHandler.SingleExecution() {
override val names = commands("sor[t]") override val names = commands("sor[t]")
override val argFlags = flags(RangeFlag.RANGE_OPTIONAL, ArgumentFlag.ARGUMENT_OPTIONAL, WRITABLE) override val argFlags = flags(RangeFlag.RANGE_OPTIONAL, ArgumentFlag.ARGUMENT_OPTIONAL, Access.WRITABLE)
@Throws(ExException::class) @Throws(ExException::class)
override fun execute(editor: Editor, context: DataContext, cmd: ExCommand): Boolean { override fun execute(editor: Editor, context: DataContext, cmd: ExCommand): Boolean {

View File

@@ -33,7 +33,7 @@ import java.io.File
*/ */
class SourceHandler : CommandHandler.SingleExecution(), VimScriptCommandHandler { class SourceHandler : CommandHandler.SingleExecution(), VimScriptCommandHandler {
override val names = commands("so[urce]") override val names = commands("so[urce]")
override val argFlags = flags(RangeFlag.RANGE_FORBIDDEN, ArgumentFlag.ARGUMENT_REQUIRED) override val argFlags = flags(RangeFlag.RANGE_FORBIDDEN, ArgumentFlag.ARGUMENT_REQUIRED, Access.READ_ONLY)
override fun execute(editor: Editor, context: DataContext, cmd: ExCommand): Boolean { override fun execute(editor: Editor, context: DataContext, cmd: ExCommand): Boolean {
execute(cmd) execute(cmd)
return true return true

View File

@@ -22,14 +22,13 @@ import com.intellij.openapi.actionSystem.DataContext
import com.intellij.openapi.editor.Editor import com.intellij.openapi.editor.Editor
import com.maddyhome.idea.vim.VimPlugin import com.maddyhome.idea.vim.VimPlugin
import com.maddyhome.idea.vim.ex.CommandHandler import com.maddyhome.idea.vim.ex.CommandHandler
import com.maddyhome.idea.vim.ex.CommandHandler.Flag.DONT_REOPEN
import com.maddyhome.idea.vim.ex.ExCommand import com.maddyhome.idea.vim.ex.ExCommand
import com.maddyhome.idea.vim.ex.commands import com.maddyhome.idea.vim.ex.commands
import com.maddyhome.idea.vim.ex.flags import com.maddyhome.idea.vim.ex.flags
class SplitHandler : CommandHandler.SingleExecution() { class SplitHandler : CommandHandler.SingleExecution() {
override val names = commands("vs[plit]", "sp[lit]") override val names = commands("vs[plit]", "sp[lit]")
override val argFlags = flags(RangeFlag.RANGE_FORBIDDEN, ArgumentFlag.ARGUMENT_OPTIONAL, DONT_REOPEN) override val argFlags = flags(RangeFlag.RANGE_FORBIDDEN, ArgumentFlag.ARGUMENT_OPTIONAL, Access.READ_ONLY)
override fun execute(editor: Editor, context: DataContext, cmd: ExCommand): Boolean { override fun execute(editor: Editor, context: DataContext, cmd: ExCommand): Boolean {
if (cmd.command.startsWith("v")) { if (cmd.command.startsWith("v")) {
VimPlugin.getWindow().splitWindowVertical(context, cmd.argument) VimPlugin.getWindow().splitWindowVertical(context, cmd.argument)

View File

@@ -22,14 +22,13 @@ import com.intellij.openapi.actionSystem.DataContext
import com.intellij.openapi.editor.Editor import com.intellij.openapi.editor.Editor
import com.maddyhome.idea.vim.VimPlugin import com.maddyhome.idea.vim.VimPlugin
import com.maddyhome.idea.vim.ex.CommandHandler import com.maddyhome.idea.vim.ex.CommandHandler
import com.maddyhome.idea.vim.ex.CommandHandler.Flag.WRITABLE
import com.maddyhome.idea.vim.ex.ExCommand import com.maddyhome.idea.vim.ex.ExCommand
import com.maddyhome.idea.vim.ex.commands import com.maddyhome.idea.vim.ex.commands
import com.maddyhome.idea.vim.ex.flags import com.maddyhome.idea.vim.ex.flags
class SubstituteHandler : CommandHandler.SingleExecution() { class SubstituteHandler : CommandHandler.SingleExecution() {
override val names = commands("s[ubstitute]", "&", "~") override val names = commands("s[ubstitute]", "&", "~")
override val argFlags = flags(RangeFlag.RANGE_OPTIONAL, ArgumentFlag.ARGUMENT_OPTIONAL, WRITABLE) override val argFlags = flags(RangeFlag.RANGE_OPTIONAL, ArgumentFlag.ARGUMENT_OPTIONAL, Access.SELF_SYNCHRONIZED)
override fun execute(editor: Editor, context: DataContext, cmd: ExCommand): Boolean { override fun execute(editor: Editor, context: DataContext, cmd: ExCommand): Boolean {
var result = true var result = true
for (caret in editor.caretModel.allCarets) { for (caret in editor.caretModel.allCarets) {

View File

@@ -28,7 +28,7 @@ import com.maddyhome.idea.vim.ex.flags
class TabOnlyHandler : CommandHandler.SingleExecution() { class TabOnlyHandler : CommandHandler.SingleExecution() {
override val names = commands("tabo[nly]") override val names = commands("tabo[nly]")
override val argFlags = flags(RangeFlag.RANGE_IS_COUNT, ArgumentFlag.ARGUMENT_FORBIDDEN) override val argFlags = flags(RangeFlag.RANGE_IS_COUNT, ArgumentFlag.ARGUMENT_FORBIDDEN, Access.READ_ONLY)
override fun execute(editor: Editor, context: DataContext, cmd: ExCommand): Boolean { override fun execute(editor: Editor, context: DataContext, cmd: ExCommand): Boolean {
VimPlugin.getWindow().closeAllExceptCurrentTab(context) VimPlugin.getWindow().closeAllExceptCurrentTab(context)
return true return true

View File

@@ -21,7 +21,6 @@ package com.maddyhome.idea.vim.ex.handler
import com.intellij.openapi.actionSystem.DataContext import com.intellij.openapi.actionSystem.DataContext
import com.intellij.openapi.editor.Editor import com.intellij.openapi.editor.Editor
import com.maddyhome.idea.vim.ex.CommandHandler import com.maddyhome.idea.vim.ex.CommandHandler
import com.maddyhome.idea.vim.ex.CommandHandler.Flag.WRITABLE
import com.maddyhome.idea.vim.ex.ExCommand import com.maddyhome.idea.vim.ex.ExCommand
import com.maddyhome.idea.vim.ex.commands import com.maddyhome.idea.vim.ex.commands
import com.maddyhome.idea.vim.ex.flags import com.maddyhome.idea.vim.ex.flags
@@ -29,6 +28,6 @@ import com.maddyhome.idea.vim.helper.UndoRedoHelper
class UndoHandler : CommandHandler.SingleExecution() { class UndoHandler : CommandHandler.SingleExecution() {
override val names = commands("u[ndo]") override val names = commands("u[ndo]")
override val argFlags = flags(RangeFlag.RANGE_FORBIDDEN, ArgumentFlag.ARGUMENT_FORBIDDEN, WRITABLE) override val argFlags = flags(RangeFlag.RANGE_FORBIDDEN, ArgumentFlag.ARGUMENT_FORBIDDEN, Access.WRITABLE)
override fun execute(editor: Editor, context: DataContext, cmd: ExCommand) = UndoRedoHelper.undo(context) override fun execute(editor: Editor, context: DataContext, cmd: ExCommand) = UndoRedoHelper.undo(context)
} }

View File

@@ -28,7 +28,7 @@ import com.maddyhome.idea.vim.ex.flags
class WriteAllHandler : CommandHandler.SingleExecution() { class WriteAllHandler : CommandHandler.SingleExecution() {
override val names = commands("wa[ll]") override val names = commands("wa[ll]")
override val argFlags = flags(RangeFlag.RANGE_OPTIONAL, ArgumentFlag.ARGUMENT_OPTIONAL) override val argFlags = flags(RangeFlag.RANGE_OPTIONAL, ArgumentFlag.ARGUMENT_OPTIONAL, Access.READ_ONLY)
override fun execute(editor: Editor, context: DataContext, cmd: ExCommand): Boolean { override fun execute(editor: Editor, context: DataContext, cmd: ExCommand): Boolean {
VimPlugin.getFile().saveFiles(context) VimPlugin.getFile().saveFiles(context)
return true return true

View File

@@ -28,7 +28,7 @@ import com.maddyhome.idea.vim.ex.flags
class WriteHandler : CommandHandler.SingleExecution() { class WriteHandler : CommandHandler.SingleExecution() {
override val names = commands("w[rite]") override val names = commands("w[rite]")
override val argFlags = flags(RangeFlag.RANGE_OPTIONAL, ArgumentFlag.ARGUMENT_OPTIONAL) override val argFlags = flags(RangeFlag.RANGE_OPTIONAL, ArgumentFlag.ARGUMENT_OPTIONAL, Access.READ_ONLY)
override fun execute(editor: Editor, context: DataContext, cmd: ExCommand): Boolean { override fun execute(editor: Editor, context: DataContext, cmd: ExCommand): Boolean {
VimPlugin.getFile().saveFile(context) VimPlugin.getFile().saveFile(context)
return true return true

View File

@@ -28,7 +28,7 @@ import com.maddyhome.idea.vim.ex.flags
class WriteNextFileHandler : CommandHandler.SingleExecution() { class WriteNextFileHandler : CommandHandler.SingleExecution() {
override val names = commands("wn[ext]") override val names = commands("wn[ext]")
override val argFlags = flags(RangeFlag.RANGE_IS_COUNT, ArgumentFlag.ARGUMENT_OPTIONAL) override val argFlags = flags(RangeFlag.RANGE_IS_COUNT, ArgumentFlag.ARGUMENT_OPTIONAL, Access.READ_ONLY)
override fun execute(editor: Editor, context: DataContext, cmd: ExCommand): Boolean { override fun execute(editor: Editor, context: DataContext, cmd: ExCommand): Boolean {
val count = cmd.getCount(editor, context, 1, true) val count = cmd.getCount(editor, context, 1, true)

View File

@@ -28,7 +28,7 @@ import com.maddyhome.idea.vim.ex.flags
class WritePreviousFileHandler : CommandHandler.SingleExecution() { class WritePreviousFileHandler : CommandHandler.SingleExecution() {
override val names = commands("wN[ext]", "wp[revious]") override val names = commands("wN[ext]", "wp[revious]")
override val argFlags = flags(RangeFlag.RANGE_OPTIONAL, ArgumentFlag.ARGUMENT_OPTIONAL) override val argFlags = flags(RangeFlag.RANGE_OPTIONAL, ArgumentFlag.ARGUMENT_OPTIONAL, Access.READ_ONLY)
override fun execute(editor: Editor, context: DataContext, cmd: ExCommand): Boolean { override fun execute(editor: Editor, context: DataContext, cmd: ExCommand): Boolean {
val count = cmd.getCount(editor, context, 1, true) val count = cmd.getCount(editor, context, 1, true)

View File

@@ -22,14 +22,13 @@ import com.intellij.openapi.actionSystem.DataContext
import com.intellij.openapi.editor.Editor import com.intellij.openapi.editor.Editor
import com.maddyhome.idea.vim.VimPlugin import com.maddyhome.idea.vim.VimPlugin
import com.maddyhome.idea.vim.ex.CommandHandler import com.maddyhome.idea.vim.ex.CommandHandler
import com.maddyhome.idea.vim.ex.CommandHandler.Flag.DONT_REOPEN
import com.maddyhome.idea.vim.ex.ExCommand import com.maddyhome.idea.vim.ex.ExCommand
import com.maddyhome.idea.vim.ex.commands import com.maddyhome.idea.vim.ex.commands
import com.maddyhome.idea.vim.ex.flags import com.maddyhome.idea.vim.ex.flags
class WriteQuitHandler : CommandHandler.SingleExecution() { class WriteQuitHandler : CommandHandler.SingleExecution() {
override val names = commands("wq", "exi[t]", "x[it]") override val names = commands("wq", "exi[t]", "x[it]")
override val argFlags = flags(RangeFlag.RANGE_OPTIONAL, ArgumentFlag.ARGUMENT_OPTIONAL, DONT_REOPEN) override val argFlags = flags(RangeFlag.RANGE_OPTIONAL, ArgumentFlag.ARGUMENT_OPTIONAL, Access.READ_ONLY)
override fun execute(editor: Editor, context: DataContext, cmd: ExCommand): Boolean { override fun execute(editor: Editor, context: DataContext, cmd: ExCommand): Boolean {
VimPlugin.getFile().saveFile(context) VimPlugin.getFile().saveFile(context)
VimPlugin.getFile().closeFile(editor, context) VimPlugin.getFile().closeFile(editor, context)

View File

@@ -23,15 +23,11 @@ import com.intellij.openapi.editor.Editor
import com.maddyhome.idea.vim.VimPlugin import com.maddyhome.idea.vim.VimPlugin
import com.maddyhome.idea.vim.command.SelectionType import com.maddyhome.idea.vim.command.SelectionType
import com.maddyhome.idea.vim.common.TextRange import com.maddyhome.idea.vim.common.TextRange
import com.maddyhome.idea.vim.ex.CommandHandler import com.maddyhome.idea.vim.ex.*
import com.maddyhome.idea.vim.ex.ExCommand
import com.maddyhome.idea.vim.ex.ExException
import com.maddyhome.idea.vim.ex.commands
import com.maddyhome.idea.vim.ex.flags
class YankLinesHandler : CommandHandler.SingleExecution() { class YankLinesHandler : CommandHandler.SingleExecution() {
override val names = commands("y[ank]") override val names = commands("y[ank]")
override val argFlags = flags(RangeFlag.RANGE_OPTIONAL, ArgumentFlag.ARGUMENT_OPTIONAL) override val argFlags = flags(RangeFlag.RANGE_OPTIONAL, ArgumentFlag.ARGUMENT_OPTIONAL, Access.READ_ONLY)
@Throws(ExException::class) @Throws(ExException::class)
override fun execute(editor: Editor, context: DataContext, cmd: ExCommand): Boolean { override fun execute(editor: Editor, context: DataContext, cmd: ExCommand): Boolean {

View File

@@ -127,7 +127,7 @@ public class VimExtensionFacade {
else { else {
final Ref<String> text = Ref.create(""); final Ref<String> text = Ref.create("");
// XXX: The Ex entry panel is used only for UI here, its logic might be inappropriate for input() // XXX: The Ex entry panel is used only for UI here, its logic might be inappropriate for input()
final ExEntryPanel exEntryPanel = ExEntryPanel.getInstance(); final ExEntryPanel exEntryPanel = ExEntryPanel.getInstanceWithoutShortcuts();
exEntryPanel.activate(editor, new EditorDataContext(editor), prompt.isEmpty() ? " " : prompt, "", 1); exEntryPanel.activate(editor, new EditorDataContext(editor), prompt.isEmpty() ? " " : prompt, "", 1);
ModalEntry.activate(key -> { ModalEntry.activate(key -> {
if (StringHelper.isCloseKeyStroke(key)) { if (StringHelper.isCloseKeyStroke(key)) {

View File

@@ -36,8 +36,6 @@ import com.maddyhome.idea.vim.group.ChangeGroup;
import com.maddyhome.idea.vim.helper.EditorHelper; import com.maddyhome.idea.vim.helper.EditorHelper;
import com.maddyhome.idea.vim.key.OperatorFunction; import com.maddyhome.idea.vim.key.OperatorFunction;
import com.maddyhome.idea.vim.option.ClipboardOptionsData; import com.maddyhome.idea.vim.option.ClipboardOptionsData;
import com.maddyhome.idea.vim.option.ListOption;
import com.maddyhome.idea.vim.option.OptionsManager;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
@@ -197,6 +195,8 @@ public class VimSurroundExtension extends VimNonDisposableExtension {
List<KeyStroke> innerValue = getRegister(REGISTER); List<KeyStroke> innerValue = getRegister(REGISTER);
if (innerValue == null) { if (innerValue == null) {
innerValue = new ArrayList<>(); innerValue = new ArrayList<>();
} else {
innerValue = new ArrayList<>(innerValue);
} }
// Delete the surrounding // Delete the surrounding
@@ -222,11 +222,9 @@ public class VimSurroundExtension extends VimNonDisposableExtension {
} }
private static void perform(@NotNull String sequence, @NotNull Editor editor) { private static void perform(@NotNull String sequence, @NotNull Editor editor) {
ListOption options = OptionsManager.INSTANCE.getClipboard(); try (ClipboardOptionsData.IdeaputDisabler ignored = new ClipboardOptionsData.IdeaputDisabler()) {
final boolean containedBefore = options.contains(ClipboardOptionsData.ideaput); executeNormal(parseKeys("\"" + REGISTER + sequence), editor);
options.remove(ClipboardOptionsData.ideaput); }
executeNormal(parseKeys("\"" + REGISTER + sequence), editor);
if (containedBefore) options.append(ClipboardOptionsData.ideaput);
} }
private static void pasteSurround(@NotNull List<KeyStroke> innerValue, @NotNull Editor editor) { private static void pasteSurround(@NotNull List<KeyStroke> innerValue, @NotNull Editor editor) {

View File

@@ -575,10 +575,13 @@ public class ChangeGroup {
int len = EditorHelper.getLineLength(editor, EditorHelper.visualLineToLogicalLine(editor, vp.line)); int len = EditorHelper.getLineLength(editor, EditorHelper.visualLineToLogicalLine(editor, vp.line));
if (vp.column < len) { if (vp.column < len) {
int offset = EditorHelper.visualPositionToOffset(editor, vp); int offset = EditorHelper.visualPositionToOffset(editor, vp);
char ch = editor.getDocument().getCharsSequence().charAt(offset); CharSequence charsSequence = editor.getDocument().getCharsSequence();
editor.getDocument().insertString(caret.getOffset(), Character.toString(ch)); if (offset < charsSequence.length()) {
MotionGroup.moveCaret(editor, caret, VimPlugin.getMotion().moveCaretHorizontal(editor, caret, 1, true)); char ch = charsSequence.charAt(offset);
res = true; editor.getDocument().insertString(caret.getOffset(), Character.toString(ch));
MotionGroup.moveCaret(editor, caret, VimPlugin.getMotion().moveCaretHorizontal(editor, caret, 1, true));
res = true;
}
} }
return res; return res;

View File

@@ -258,7 +258,10 @@ public class EditorGroup {
if (VimPlugin.isEnabled() && EditorHelper.isFileEditor(editor)) { if (VimPlugin.isEnabled() && EditorHelper.isFileEditor(editor)) {
final boolean relativeLineNumber = OptionsManager.INSTANCE.getRelativenumber().isSet(); final boolean relativeLineNumber = OptionsManager.INSTANCE.getRelativenumber().isSet();
final boolean lineNumber = OptionsManager.INSTANCE.getNumber().isSet(); final boolean lineNumber = OptionsManager.INSTANCE.getNumber().isSet();
if (relativeLineNumber && lineNumber && isCaretLine(line, editor)) { if (editor.getDocument().getLineCount() == 0) {
return null;
}
else if (relativeLineNumber && lineNumber && isCaretLine(line, editor)) {
return lineNumberToString(getLineNumber(line), editor); return lineNumberToString(getLineNumber(line), editor);
} }
else if (relativeLineNumber) { else if (relativeLineNumber) {

View File

@@ -154,7 +154,7 @@ public class FileGroup {
final EditorWindow window = fileEditorManager.getCurrentWindow(); final EditorWindow window = fileEditorManager.getCurrentWindow();
final VirtualFile virtualFile = EditorHelper.getVirtualFile(editor); final VirtualFile virtualFile = EditorHelper.getVirtualFile(editor);
if (virtualFile != null) { if (virtualFile != null && window != null) {
window.closeFile(virtualFile); window.closeFile(virtualFile);
} }
} }
@@ -220,7 +220,7 @@ public class FileGroup {
if (project == null) return; if (project == null) return;
FileEditorManager fem = FileEditorManager.getInstance(project); // API change - don't merge FileEditorManager fem = FileEditorManager.getInstance(project); // API change - don't merge
VirtualFile vf = lastSelections.get(fem); VirtualFile vf = lastSelections.get(fem);
if (vf != null) { if (vf != null && vf.isValid()) {
fem.openFile(vf, true); fem.openFile(vf, true);
} }
else { else {
@@ -234,7 +234,10 @@ public class FileGroup {
FileEditor[] feditors = fMgr.openFile(file, true); FileEditor[] feditors = fMgr.openFile(file, true);
if (feditors.length > 0) { if (feditors.length > 0) {
if (feditors[0] instanceof TextEditor) { if (feditors[0] instanceof TextEditor) {
return ((TextEditor)feditors[0]).getEditor(); Editor editor = ((TextEditor) feditors[0]).getEditor();
if (!editor.isDisposed()) {
return editor;
}
} }
} }
@@ -243,7 +246,9 @@ public class FileGroup {
public void displayAsciiInfo(@NotNull Editor editor) { public void displayAsciiInfo(@NotNull Editor editor) {
int offset = editor.getCaretModel().getOffset(); int offset = editor.getCaretModel().getOffset();
char ch = editor.getDocument().getCharsSequence().charAt(offset); CharSequence charsSequence = editor.getDocument().getCharsSequence();
if (charsSequence.length() == 0 || offset >= charsSequence.length()) return;
char ch = charsSequence.charAt(offset);
VimPlugin.showMessage("<" + VimPlugin.showMessage("<" +
StringHelper.toKeyNotation(KeyStroke.getKeyStroke(ch)) + StringHelper.toKeyNotation(KeyStroke.getKeyStroke(ch)) +

View File

@@ -1301,9 +1301,7 @@ public class MotionGroup {
} }
public static void fileEditorManagerSelectionChangedCallback(@NotNull FileEditorManagerEvent event) { public static void fileEditorManagerSelectionChangedCallback(@NotNull FileEditorManagerEvent event) {
if (ExEntryPanel.getInstance().isActive()) { ExEntryPanel.deactivateAll();
ExEntryPanel.getInstance().deactivate(false);
}
final FileEditor fileEditor = event.getOldEditor(); final FileEditor fileEditor = event.getOldEditor();
if (fileEditor instanceof TextEditor) { if (fileEditor instanceof TextEditor) {
final Editor editor = ((TextEditor)fileEditor).getEditor(); final Editor editor = ((TextEditor)fileEditor).getEditor();

View File

@@ -188,7 +188,7 @@ class NotificationService(private val project: Project?) {
const val IDEAVIM_STICKY_NOTIFICATION_ID = "ideavim-sticky" const val IDEAVIM_STICKY_NOTIFICATION_ID = "ideavim-sticky"
const val IDEAVIM_NOTIFICATION_ID = "ideavim" const val IDEAVIM_NOTIFICATION_ID = "ideavim"
const val IDEAVIM_NOTIFICATION_TITLE = "IdeaVim" const val IDEAVIM_NOTIFICATION_TITLE = "IdeaVim"
const val ideajoinExamplesUrl = "https://github.com/JetBrains/ideavim/blob/master/doc/ideajoin-examples.md" const val ideajoinExamplesUrl = "https://github.com/JetBrains/ideavim/wiki/%60ideajoin%60-examples"
const val selectModeUrl = "https://vimhelp.org/visual.txt.html#Select-mode" const val selectModeUrl = "https://vimhelp.org/visual.txt.html#Select-mode"
} }
} }

View File

@@ -71,10 +71,8 @@ public class ProcessGroup {
} }
public void startExCommand(@NotNull Editor editor, DataContext context, @NotNull Command cmd) { public void startExCommand(@NotNull Editor editor, DataContext context, @NotNull Command cmd) {
if (editor.isOneLineMode()) // Don't allow ex commands in one line editors // Don't allow ex commands in one line editors
{ if (editor.isOneLineMode()) return;
return;
}
String initText = getRange(editor, cmd); String initText = getRange(editor, cmd);
CommandState.getInstance(editor).pushState(CommandState.Mode.EX_ENTRY, CommandState.SubMode.NONE, MappingMode.CMD_LINE); CommandState.getInstance(editor).pushState(CommandState.Mode.EX_ENTRY, CommandState.SubMode.NONE, MappingMode.CMD_LINE);
@@ -104,7 +102,6 @@ public class ProcessGroup {
ExEntryPanel panel = ExEntryPanel.getInstance(); ExEntryPanel panel = ExEntryPanel.getInstance();
panel.deactivate(true); panel.deactivate(true);
boolean res = true; boolean res = true;
int flags;
try { try {
CommandState.getInstance(editor).popState(); CommandState.getInstance(editor).popState();
logger.debug("processing command"); logger.debug("processing command");
@@ -112,8 +109,7 @@ public class ProcessGroup {
record(editor, text); record(editor, text);
if (logger.isDebugEnabled()) logger.debug("swing=" + SwingUtilities.isEventDispatchThread()); if (logger.isDebugEnabled()) logger.debug("swing=" + SwingUtilities.isEventDispatchThread());
if (panel.getLabel().equals(":")) { if (panel.getLabel().equals(":")) {
flags = CommandParser.getInstance().processCommand(editor, context, text, 1); CommandParser.getInstance().processCommand(editor, context, text, 1);
if (logger.isDebugEnabled()) logger.debug("flags=" + flags);
} }
else { else {
int pos = VimPlugin.getSearch().search(editor, text, panel.getCount(), int pos = VimPlugin.getSearch().search(editor, text, panel.getCount(),

View File

@@ -18,6 +18,7 @@
package com.maddyhome.idea.vim.group; package com.maddyhome.idea.vim.group;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.*; import com.intellij.openapi.editor.*;
import com.intellij.openapi.editor.colors.EditorColors; import com.intellij.openapi.editor.colors.EditorColors;
@@ -31,7 +32,6 @@ import com.intellij.openapi.project.ProjectManager;
import com.intellij.openapi.util.Ref; import com.intellij.openapi.util.Ref;
import com.maddyhome.idea.vim.VimPlugin; import com.maddyhome.idea.vim.VimPlugin;
import com.maddyhome.idea.vim.command.CommandFlags; import com.maddyhome.idea.vim.command.CommandFlags;
import com.maddyhome.idea.vim.command.CommandState;
import com.maddyhome.idea.vim.command.SelectionType; import com.maddyhome.idea.vim.command.SelectionType;
import com.maddyhome.idea.vim.common.CharacterPosition; import com.maddyhome.idea.vim.common.CharacterPosition;
import com.maddyhome.idea.vim.common.TextRange; import com.maddyhome.idea.vim.common.TextRange;
@@ -40,13 +40,13 @@ import com.maddyhome.idea.vim.helper.*;
import com.maddyhome.idea.vim.option.ListOption; import com.maddyhome.idea.vim.option.ListOption;
import com.maddyhome.idea.vim.option.OptionChangeListener; import com.maddyhome.idea.vim.option.OptionChangeListener;
import com.maddyhome.idea.vim.option.OptionsManager; import com.maddyhome.idea.vim.option.OptionsManager;
import com.maddyhome.idea.vim.regexp.CharHelper;
import com.maddyhome.idea.vim.regexp.CharPointer; import com.maddyhome.idea.vim.regexp.CharPointer;
import com.maddyhome.idea.vim.regexp.CharacterClasses; import com.maddyhome.idea.vim.regexp.CharacterClasses;
import com.maddyhome.idea.vim.regexp.RegExp; import com.maddyhome.idea.vim.regexp.RegExp;
import com.maddyhome.idea.vim.ui.ExEntryPanel; import com.maddyhome.idea.vim.ui.ExEntryPanel;
import com.maddyhome.idea.vim.ui.ModalEntry; import com.maddyhome.idea.vim.ui.ModalEntry;
import org.jdom.Element; import org.jdom.Element;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
@@ -164,7 +164,7 @@ public class SearchGroup {
private static ReplaceConfirmationChoice confirmChoice(@NotNull Editor editor, @NotNull String match) { private static ReplaceConfirmationChoice confirmChoice(@NotNull Editor editor, @NotNull String match) {
final Ref<ReplaceConfirmationChoice> result = Ref.create(ReplaceConfirmationChoice.QUIT); final Ref<ReplaceConfirmationChoice> result = Ref.create(ReplaceConfirmationChoice.QUIT);
// XXX: The Ex entry panel is used only for UI here, its logic might be inappropriate for this method // XXX: The Ex entry panel is used only for UI here, its logic might be inappropriate for this method
final ExEntryPanel exEntryPanel = ExEntryPanel.getInstance(); final ExEntryPanel exEntryPanel = ExEntryPanel.getInstanceWithoutShortcuts();
exEntryPanel.activate(editor, new EditorDataContext(editor), "Replace with " + match + " (y/n/a/q/l)?", "", 1); exEntryPanel.activate(editor, new EditorDataContext(editor), "Replace with " + match + " (y/n/a/q/l)?", "", 1);
ModalEntry.activate(key -> { ModalEntry.activate(key -> {
final ReplaceConfirmationChoice choice; final ReplaceConfirmationChoice choice;
@@ -217,7 +217,7 @@ public class SearchGroup {
return res; return res;
} }
public int search(@NotNull Editor editor, @NotNull String command, int startOffset, int count, EnumSet<CommandFlags> flags) { public int search(@NotNull Editor editor, @NotNull String command, int startOffset, int count, @NotNull EnumSet<CommandFlags> flags) {
int dir = DIR_FORWARDS; int dir = DIR_FORWARDS;
char type = '/'; char type = '/';
String pattern = lastSearch; String pattern = lastSearch;
@@ -348,7 +348,7 @@ public class SearchGroup {
updateSearchHighlights(lastSearch, lastIgnoreSmartCase, showSearchHighlight, true); updateSearchHighlights(lastSearch, lastIgnoreSmartCase, showSearchHighlight, true);
} }
public void updateIncsearchHighlights(Editor editor, String pattern, boolean forwards, int caretOffset, @Nullable LineRange searchRange) { public void updateIncsearchHighlights(@NotNull Editor editor, @NotNull String pattern, boolean forwards, int caretOffset, @Nullable LineRange searchRange) {
// searchStartOffset is used to find the closest match. caretOffset is used to reset the caret if there is no match. // searchStartOffset is used to find the closest match. caretOffset is used to reset the caret if there is no match.
// If searching based on e.g. :%s/... then these values are not going to be the same // If searching based on e.g. :%s/... then these values are not going to be the same
final int searchStartOffset = searchRange != null ? EditorHelper.getLineStartOffset(editor, searchRange.getStartLine()) : caretOffset; final int searchStartOffset = searchRange != null ? EditorHelper.getLineStartOffset(editor, searchRange.getStartLine()) : caretOffset;
@@ -400,7 +400,7 @@ public class SearchGroup {
final boolean wrap = OptionsManager.INSTANCE.getWrapscan().isSet(); final boolean wrap = OptionsManager.INSTANCE.getWrapscan().isSet();
final TextRange result = findIt(editor, pattern, initialOffset, 1, final TextRange result = findIt(editor, pattern, initialOffset, 1,
forwards ? DIR_FORWARDS : DIR_BACKWARDS, shouldIgnoreSmartCase, wrap, false, true); forwards ? DIR_FORWARDS : DIR_BACKWARDS, shouldIgnoreSmartCase, wrap, false, true);
if (result != null) { if (result != null && pattern != null) {
currentMatchOffset = result.getStartOffset(); currentMatchOffset = result.getStartOffset();
final List<TextRange> results = Collections.singletonList(result); final List<TextRange> results = Collections.singletonList(result);
highlightSearchResults(editor, pattern, results, currentMatchOffset); highlightSearchResults(editor, pattern, results, currentMatchOffset);
@@ -415,6 +415,7 @@ public class SearchGroup {
/** /**
* Remove current search highlights if hlSearch is false, or if the pattern is changed * Remove current search highlights if hlSearch is false, or if the pattern is changed
*/ */
@Contract("_, _, false -> true; _, null, true -> false")
private boolean shouldRemoveSearchHighlight(@NotNull Editor editor, String newPattern, boolean hlSearch) { private boolean shouldRemoveSearchHighlight(@NotNull Editor editor, String newPattern, boolean hlSearch) {
return !hlSearch || (newPattern != null && !newPattern.equals(UserDataManager.getVimLastSearch(editor))); return !hlSearch || (newPattern != null && !newPattern.equals(UserDataManager.getVimLastSearch(editor)));
} }
@@ -422,6 +423,7 @@ public class SearchGroup {
/** /**
* Add search highlights if hlSearch is true and the pattern is changed * Add search highlights if hlSearch is true and the pattern is changed
*/ */
@Contract("_, _, false -> false; _, null, true -> false")
private boolean shouldAddSearchHighlight(@NotNull Editor editor, @Nullable String newPattern, boolean hlSearch) { private boolean shouldAddSearchHighlight(@NotNull Editor editor, @Nullable String newPattern, boolean hlSearch) {
return hlSearch && newPattern != null && !newPattern.equals(UserDataManager.getVimLastSearch(editor)) && !Objects.equals(newPattern, ""); return hlSearch && newPattern != null && !newPattern.equals(UserDataManager.getVimLastSearch(editor)) && !Objects.equals(newPattern, "");
} }
@@ -433,7 +435,7 @@ public class SearchGroup {
} }
} }
private int findClosestMatch(@NotNull Editor editor, List<TextRange> results, int initialOffset, boolean forwards) { private int findClosestMatch(@NotNull Editor editor, @NotNull List<TextRange> results, int initialOffset, boolean forwards) {
if (results.isEmpty() || initialOffset == -1) { if (results.isEmpty() || initialOffset == -1) {
return -1; return -1;
} }
@@ -895,19 +897,18 @@ public class SearchGroup {
} }
} }
@RWLockLabel.SelfSynchronized
public boolean searchAndReplace(@NotNull Editor editor, @NotNull Caret caret, @NotNull LineRange range, public boolean searchAndReplace(@NotNull Editor editor, @NotNull Caret caret, @NotNull LineRange range,
@NotNull String excmd, String exarg) { @NotNull String excmd, String exarg) {
// Explicitly exit visual mode here, so that visual mode marks don't change when we move the cursor to a match. // Explicitly exit visual mode here, so that visual mode marks don't change when we move the cursor to a match.
if (CommandState.getInstance(editor).getMode() == CommandState.Mode.VISUAL) { if (CommandStateHelper.inVisualMode(editor)) {
VimPlugin.getVisualMotion().exitVisual(editor); VimPlugin.getVisualMotion().exitVisual(editor);
} }
CharPointer cmd = new CharPointer(new StringBuffer(exarg)); CharPointer cmd = new CharPointer(new StringBuffer(exarg));
//sub_nsubs = 0;
//sub_nlines = 0;
int which_pat; int which_pat;
if (excmd.equals("~")) { if ("~".equals(excmd)) {
which_pat = RE_LAST; /* use last used regexp */ which_pat = RE_LAST; /* use last used regexp */
} }
else { else {
@@ -943,7 +944,8 @@ public class SearchGroup {
delimiter = cmd.charAt(); /* remember delimiter character */ delimiter = cmd.charAt(); /* remember delimiter character */
cmd.inc(); cmd.inc();
} }
else /* find the end of the regexp */ { else {
/* find the end of the regexp */
which_pat = RE_LAST; /* use last used regexp */ which_pat = RE_LAST; /* use last used regexp */
delimiter = cmd.charAt(); /* remember delimiter character */ delimiter = cmd.charAt(); /* remember delimiter character */
cmd.inc(); cmd.inc();
@@ -971,8 +973,10 @@ public class SearchGroup {
cmd.inc(); cmd.inc();
} }
} }
else /* use previous pattern and substitution */ { else {
if (lastReplace == null) /* there is no previous command */ { /* use previous pattern and substitution */
if (lastReplace == null) {
/* there is no previous command */
VimPlugin.showMessage(MessageHelper.message(Msg.e_nopresub)); VimPlugin.showMessage(MessageHelper.message(Msg.e_nopresub));
return false; return false;
} }
@@ -990,7 +994,6 @@ public class SearchGroup {
do_all = OptionsManager.INSTANCE.getGdefault().isSet(); do_all = OptionsManager.INSTANCE.getGdefault().isSet();
do_ask = false; do_ask = false;
do_error = true; do_error = true;
//do_print = false;
do_ic = 0; do_ic = 0;
} }
while (!cmd.isNul()) { while (!cmd.isNul()) {
@@ -1007,13 +1010,16 @@ public class SearchGroup {
else if (cmd.charAt() == 'e') { else if (cmd.charAt() == 'e') {
do_error = !do_error; do_error = !do_error;
} }
else if (cmd.charAt() == 'r') /* use last used regexp */ { else if (cmd.charAt() == 'r') {
/* use last used regexp */
which_pat = RE_LAST; which_pat = RE_LAST;
} }
else if (cmd.charAt() == 'i') /* ignore case */ { else if (cmd.charAt() == 'i') {
/* ignore case */
do_ic = 'i'; do_ic = 'i';
} }
else if (cmd.charAt() == 'I') /* don't ignore case */ { else if (cmd.charAt() == 'I') {
/* don't ignore case */
do_ic = 'I'; do_ic = 'I';
} }
else if (cmd.charAt() != 'p') { else if (cmd.charAt() != 'p') {
@@ -1032,9 +1038,9 @@ public class SearchGroup {
/* /*
* check for a trailing count * check for a trailing count
*/ */
CharHelper.skipwhite(cmd); cmd.skipWhitespaces();
if (CharacterClasses.isDigit(cmd.charAt())) { if (Character.isDigit(cmd.charAt())) {
int i = CharHelper.getdigits(cmd); int i = cmd.getDigits();
if (i <= 0 && do_error) { if (i <= 0 && do_error) {
VimPlugin.showMessage(MessageHelper.message(Msg.e_zerocount)); VimPlugin.showMessage(MessageHelper.message(Msg.e_zerocount));
return false; return false;
@@ -1046,8 +1052,9 @@ public class SearchGroup {
/* /*
* check for trailing command or garbage * check for trailing command or garbage
*/ */
CharHelper.skipwhite(cmd); cmd.skipWhitespaces();
if (!cmd.isNul() && cmd.charAt() != '"') /* if not end-of-line or comment */ { if (!cmd.isNul() && cmd.charAt() != '"') {
/* if not end-of-line or comment */
VimPlugin.showMessage(MessageHelper.message(Msg.e_trailing)); VimPlugin.showMessage(MessageHelper.message(Msg.e_trailing));
return false; return false;
} }
@@ -1076,8 +1083,6 @@ public class SearchGroup {
setLastPattern(editor, pattern); setLastPattern(editor, pattern);
} }
//int start = editor.logicalPositionToOffset(new LogicalPosition(line1, 0));
//int end = editor.logicalPositionToOffset(new LogicalPosition(line2, EditorHelper.getLineLength(editor, line2)));
int start = editor.getDocument().getLineStartOffset(line1); int start = editor.getDocument().getLineStartOffset(line1);
int end = editor.getDocument().getLineEndOffset(line2); int end = editor.getDocument().getLineEndOffset(line2);
@@ -1147,7 +1152,6 @@ public class SearchGroup {
if (match == null) { if (match == null) {
return false; return false;
} }
//logger.debug("found match[" + spos + "," + epos + "] - replace " + match);
int line = lnum + regmatch.startpos[0].lnum; int line = lnum + regmatch.startpos[0].lnum;
CharacterPosition startpos = new CharacterPosition(lnum + regmatch.startpos[0].lnum, regmatch.startpos[0].col); CharacterPosition startpos = new CharacterPosition(lnum + regmatch.startpos[0].lnum, regmatch.startpos[0].col);
@@ -1187,7 +1191,7 @@ public class SearchGroup {
} }
if (doReplace) { if (doReplace) {
editor.getDocument().replaceString(startoff, endoff, match); ApplicationManager.getApplication().runWriteAction(() -> editor.getDocument().replaceString(startoff, endoff, match));
lastMatch = startoff; lastMatch = startoff;
newpos = CharacterPosition.Companion.fromOffset(editor, newend); newpos = CharacterPosition.Companion.fromOffset(editor, newend);
@@ -1352,6 +1356,7 @@ public class SearchGroup {
public static DocumentSearchListener INSTANCE = new DocumentSearchListener(); public static DocumentSearchListener INSTANCE = new DocumentSearchListener();
@Contract(pure = true)
private DocumentSearchListener () { private DocumentSearchListener () {
} }

View File

@@ -457,7 +457,9 @@ class PutGroup {
} }
private fun notifyAboutIdeaPut(project: Project?) { private fun notifyAboutIdeaPut(project: Project?) {
if (VimPlugin.getVimState().isIdeaPutNotified || ClipboardOptionsData.ideaput in OptionsManager.clipboard) return if (VimPlugin.getVimState().isIdeaPutNotified
|| ClipboardOptionsData.ideaput in OptionsManager.clipboard
|| ClipboardOptionsData.ideaputDisabled) return
VimPlugin.getVimState().isIdeaPutNotified = true VimPlugin.getVimState().isIdeaPutNotified = true
@@ -467,4 +469,4 @@ class PutGroup {
companion object { companion object {
private val logger = Logger.getInstance(PutGroup::class.java.name) private val logger = Logger.getInstance(PutGroup::class.java.name)
} }
} }

View File

@@ -46,6 +46,8 @@ class YankGroup {
val motion = argument.motion ?: return false val motion = argument.motion ?: return false
val caretModel = editor.caretModel val caretModel = editor.caretModel
if (caretModel.caretCount <= 0) return false
val ranges = ArrayList<Pair<Int, Int>>(caretModel.caretCount) val ranges = ArrayList<Pair<Int, Int>>(caretModel.caretCount)
val startOffsets = HashMap<Caret, Int>(caretModel.caretCount) val startOffsets = HashMap<Caret, Int>(caretModel.caretCount)
for (caret in caretModel.allCarets) { for (caret in caretModel.allCarets) {
@@ -100,6 +102,17 @@ class YankGroup {
val selectionType = if (type == SelectionType.CHARACTER_WISE && range.isMultiple) SelectionType.BLOCK_WISE else type val selectionType = if (type == SelectionType.CHARACTER_WISE && range.isMultiple) SelectionType.BLOCK_WISE else type
if (type == SelectionType.LINE_WISE) {
for (i in 0 until range.size()) {
if (editor.offsetToLogicalPosition(range.startOffsets[i]).column != 0) {
range.startOffsets[i] = EditorHelper.getLineStartForOffset(editor, range.startOffsets[i])
}
if (editor.offsetToLogicalPosition(range.endOffsets[i]).column != 0) {
range.endOffsets[i] = (EditorHelper.getLineEndForOffset(editor, range.endOffsets[i]) + 1).coerceAtMost(EditorHelper.getFileSize(editor))
}
}
}
val caretModel = editor.caretModel val caretModel = editor.caretModel
val rangeStartOffsets = range.startOffsets val rangeStartOffsets = range.startOffsets
val rangeEndOffsets = range.endOffsets val rangeEndOffsets = range.endOffsets
@@ -152,4 +165,4 @@ class YankGroup {
return VimPlugin.getRegister().storeText(editor, range, type, false) return VimPlugin.getRegister().storeText(editor, range, type, false)
} }
} }

View File

@@ -0,0 +1,68 @@
package com.maddyhome.idea.vim.group.visual
import com.maddyhome.idea.vim.command.CommandState
import com.maddyhome.idea.vim.group.visual.VimVisualTimer.mode
import com.maddyhome.idea.vim.group.visual.VimVisualTimer.singleTask
import com.maddyhome.idea.vim.helper.hasVisualSelection
import com.maddyhome.idea.vim.option.OptionsManager
import javax.swing.Timer
/**
* Timer to control non-vim visual selection adjustment.
*
* Some actions in IJ use selection as a helper to reach desired behavior. E.g. backspace in python or yaml uses
* selection to remove indent on the empty line. It selects indent and after that performs "remove selection" action.
* If IdeaVim had reacted to this selection immediately, its listeners were called twice: after selection set and
* after selection removing. After there both operations vim would get normal mode, what is inconvenient because user
* expects vim to stay in insert mode.
* Same approach is used in some accented characters on MacOs and for Romaji layout in Japanese language (VIM-1725).
*
* Because of this IdeaVim doesn't react to selection change immediately. After selection was changed, vim waits some
* time (100 ms by default) and enables visual mode (or any another) if selection was not changed during this time.
*
* If during timer sleep another selection change was performed, the old timer get's disabled and
* replaced with a new one.
*
* So, how does IdeaVim recognize that it should stay in insert mode?
* Timer also gets an information about the current mode and whenever editor has selection.
* [mode] property stores information about mode of *the first timer call*. So, if there were several calls
* to timer, the first mode state will be stored in [mode] property. When the last timer acts, it compares state
* of selection before first call and expected selection state after current call. Selection adjustment gets
* performed only if there are changes in selection.
*
* Examples:
* 1) User performs "extend selection" action from normal mode
*
* There will be only one call to [singleTask]. [mode] is command, editorHasSelection is true. So, selection adjustment
* is called, IdeaVim starts visual (or select) mode.
*
* 2) Some action performs "extend selection" and "shrink selection" actions sequentially from insert mode.
*
* First call to [singleTask]. [mode] is insert, editorHasSelection is true. Timer starts.
* Second call to [singleTask]. First timer gets interrupted. [mode] stays insert because it's not null.
* editorHasSelection is false. Insert mode ([mode]) has no selection and editor also has no selection, so
* no adjustment gets performed and IdeaVim stays in insert mode.
*/
object VimVisualTimer {
var swingTimer: Timer? = null
var mode: CommandState.Mode? = null
inline fun singleTask(editorHasSelection: Boolean, currentMode: CommandState.Mode, crossinline task: () -> Unit) {
swingTimer?.stop()
if (mode == null) mode = currentMode
// Default delay - 100 ms
val timer = Timer(OptionsManager.visualEnterDelay.value()) {
if (mode?.hasVisualSelection == true || editorHasSelection) {
task()
}
swingTimer = null
mode = null
}
timer.isRepeats = false
timer.start()
swingTimer = timer
}
}

View File

@@ -18,26 +18,13 @@
package com.maddyhome.idea.vim.group.visual package com.maddyhome.idea.vim.group.visual
import com.intellij.openapi.editor.Caret import com.intellij.openapi.editor.*
import com.intellij.openapi.editor.CaretVisualAttributes
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.editor.LogicalPosition
import com.intellij.openapi.editor.VisualPosition
import com.intellij.openapi.editor.colors.EditorColors import com.intellij.openapi.editor.colors.EditorColors
import com.maddyhome.idea.vim.VimPlugin import com.maddyhome.idea.vim.VimPlugin
import com.maddyhome.idea.vim.command.CommandState import com.maddyhome.idea.vim.command.CommandState
import com.maddyhome.idea.vim.group.ChangeGroup import com.maddyhome.idea.vim.group.ChangeGroup
import com.maddyhome.idea.vim.group.MotionGroup import com.maddyhome.idea.vim.group.MotionGroup
import com.maddyhome.idea.vim.helper.EditorHelper import com.maddyhome.idea.vim.helper.*
import com.maddyhome.idea.vim.helper.inBlockSubMode
import com.maddyhome.idea.vim.helper.inSelectMode
import com.maddyhome.idea.vim.helper.inVisualMode
import com.maddyhome.idea.vim.helper.isEndAllowed
import com.maddyhome.idea.vim.helper.mode
import com.maddyhome.idea.vim.helper.sort
import com.maddyhome.idea.vim.helper.subMode
import com.maddyhome.idea.vim.helper.vimLastColumn
import com.maddyhome.idea.vim.helper.vimSelectionStart
/** /**
* @author Alex Plate * @author Alex Plate
@@ -201,9 +188,9 @@ fun toNativeSelection(editor: Editor, start: Int, end: Int, mode: CommandState.M
else -> sort(start, end) else -> sort(start, end)
} }
fun moveCaretOneCharLeftFromSelectionEnd(editor: Editor) { fun moveCaretOneCharLeftFromSelectionEnd(editor: Editor, predictedMode: CommandState.Mode) {
if (!editor.inVisualMode) { if (predictedMode != CommandState.Mode.VISUAL) {
if (!editor.mode.isEndAllowed) { if (!predictedMode.isEndAllowed) {
editor.caretModel.allCarets.forEach { caret -> editor.caretModel.allCarets.forEach { caret ->
val lineEnd = EditorHelper.getLineEndForOffset(editor, caret.offset) val lineEnd = EditorHelper.getLineEndForOffset(editor, caret.offset)
val lineStart = EditorHelper.getLineStartForOffset(editor, caret.offset) val lineStart = EditorHelper.getLineStartForOffset(editor, caret.offset)

View File

@@ -41,8 +41,7 @@ import com.maddyhome.idea.vim.option.SelectModeOptionData
*/ */
class VisualMotionGroup { class VisualMotionGroup {
companion object { companion object {
var modeBeforeEnteringNonVimVisual: CommandState.Mode? = null val logger = Logger.getInstance(VisualMotionGroup::class.java)
val logger = Logger.getInstance(VisualMotionGroup.javaClass)
} }
fun selectPreviousVisualMode(editor: Editor): Boolean { fun selectPreviousVisualMode(editor: Editor): Boolean {
@@ -107,56 +106,84 @@ class VisualMotionGroup {
} }
fun controlNonVimSelectionChange(editor: Editor, selectionSource: VimListenerManager.SelectionSource = VimListenerManager.SelectionSource.OTHER) { fun controlNonVimSelectionChange(editor: Editor, selectionSource: VimListenerManager.SelectionSource = VimListenerManager.SelectionSource.OTHER) {
logger.info("Adjust non-vim selection. Source: $selectionSource") VimVisualTimer.singleTask(editor.caretModel.allCarets.any(Caret::hasSelection), editor.mode) {
if (editor.caretModel.allCarets.any(Caret::hasSelection)) { logger.info("Adjust non-vim selection. Source: $selectionSource")
val commandState = CommandState.getInstance(editor) if (editor.caretModel.allCarets.any(Caret::hasSelection)) {
logger.info("Some carets have selection. State before adjustment: ${commandState.toSimpleString()}") val commandState = CommandState.getInstance(editor)
modeBeforeEnteringNonVimVisual = commandState.mode logger.info("Some carets have selection. State before adjustment: ${commandState.toSimpleString()}")
logger.info("Mode before entering non-vim visual: $modeBeforeEnteringNonVimVisual") while (commandState.mode != CommandState.Mode.COMMAND) {
while (commandState.mode != CommandState.Mode.COMMAND) { commandState.popState()
commandState.popState() }
val autodetectedMode = autodetectVisualMode(editor)
val selectMode = OptionsManager.selectmode
when {
editor.isOneLineMode -> {
logger.info("Enter select mode. Reason: one line mode")
enterSelectMode(editor, autodetectedMode)
}
selectionSource == VimListenerManager.SelectionSource.MOUSE && SelectModeOptionData.mouse in selectMode -> {
logger.info("Enter select mode. Selection source is mouse and selectMode option has mouse")
enterSelectMode(editor, autodetectedMode)
}
editor.isTemplateActive() && SelectModeOptionData.template in selectMode -> {
logger.info("Enter select mode. Template is active and selectMode has template")
enterSelectMode(editor, autodetectedMode)
}
selectionSource == VimListenerManager.SelectionSource.OTHER && SelectModeOptionData.refactoring in selectMode -> {
logger.info("Enter select mode. Selection source is OTHER and selectMode has refactoring")
enterSelectMode(editor, autodetectedMode)
}
else -> {
logger.info("Enter visual mode")
enterVisualMode(editor, autodetectedMode)
}
}
KeyHandler.getInstance().reset(editor)
} else {
val commandState = CommandState.getInstance(editor)
logger.info("None of carets have selection. State before adjustment: ${commandState.toSimpleString()}")
exitVisual(editor)
exitSelectModeAndResetKeyHandler(editor, true)
val templateActive = editor.isTemplateActive()
if (templateActive && editor.mode == CommandState.Mode.COMMAND) {
VimPlugin.getChange().insertBeforeCursor(editor, EditorDataContext(editor))
}
updateCaretState(editor)
KeyHandler.getInstance().reset(editor)
} }
val autodetectedMode = autodetectVisualMode(editor) logger.info("${editor.mode} is enabled")
val project = editor.project }
}
// TODO: 2019-07-30 This method should be used for [controlNonVimSelectionChange]
fun predictMode(editor: Editor, selectionSource: VimListenerManager.SelectionSource): CommandState.Mode {
if (editor.caretModel.allCarets.any(Caret::hasSelection)) {
val selectMode = OptionsManager.selectmode val selectMode = OptionsManager.selectmode
when { return when {
editor.isOneLineMode -> { editor.isOneLineMode -> {
logger.info("Enter select mode. Reason: one line mode") CommandState.Mode.SELECT
enterSelectMode(editor, autodetectedMode)
} }
selectionSource == VimListenerManager.SelectionSource.MOUSE && SelectModeOptionData.mouse in selectMode -> { selectionSource == VimListenerManager.SelectionSource.MOUSE && SelectModeOptionData.mouse in selectMode -> {
logger.info("Enter select mode. Selection source is mouse and selectMode option has mouse") CommandState.Mode.SELECT
enterSelectMode(editor, autodetectedMode)
} }
editor.isTemplateActive() && SelectModeOptionData.template in selectMode -> { editor.isTemplateActive() && SelectModeOptionData.template in selectMode -> {
logger.info("Enter select mode. Template is active and selectMode has template") CommandState.Mode.SELECT
enterSelectMode(editor, autodetectedMode)
} }
selectionSource == VimListenerManager.SelectionSource.OTHER && SelectModeOptionData.refactoring in selectMode -> { selectionSource == VimListenerManager.SelectionSource.OTHER && SelectModeOptionData.refactoring in selectMode -> {
logger.info("Enter select mode. Selection source is OTHER and selectMode has refactoring") CommandState.Mode.SELECT
enterSelectMode(editor, autodetectedMode)
} }
else -> { else -> {
logger.info("Enter visual mode") CommandState.Mode.VISUAL
enterVisualMode(editor, autodetectedMode)
} }
} }
KeyHandler.getInstance().reset(editor)
} else { } else {
val commandState = CommandState.getInstance(editor)
logger.info("None of carets have selection. State before adjustment: ${commandState.toSimpleString()}")
exitVisual(editor)
exitSelectModeAndResetKeyHandler(editor, true)
val templateActive = editor.isTemplateActive() val templateActive = editor.isTemplateActive()
if ((templateActive || modeBeforeEnteringNonVimVisual == CommandState.Mode.INSERT) && editor.mode == CommandState.Mode.COMMAND) { if (templateActive && editor.mode == CommandState.Mode.COMMAND || editor.mode == CommandState.Mode.INSERT) {
logger.info("Enter insert mode because ${if (templateActive) "template is active" else "mode before entering non vim visual: $modeBeforeEnteringNonVimVisual"}") return CommandState.Mode.INSERT
VimPlugin.getChange().insertBeforeCursor(editor, EditorDataContext(editor))
} }
updateCaretState(editor) return CommandState.Mode.COMMAND
KeyHandler.getInstance().reset(editor)
} }
logger.info("${editor.mode} is enabled")
} }
//=============================== ENTER VISUAL and SELECT MODE ============================================== //=============================== ENTER VISUAL and SELECT MODE ==============================================
@@ -383,6 +410,7 @@ class VisualMotionGroup {
} }
} }
@RWLockLabel.NoLockRequired
fun exitVisual(editor: Editor) { fun exitVisual(editor: Editor) {
resetVisual(editor) resetVisual(editor)
if (editor.inVisualMode) { if (editor.inVisualMode) {

View File

@@ -26,7 +26,6 @@ import com.intellij.openapi.editor.actionSystem.EditorActionHandler
import com.maddyhome.idea.vim.VimPlugin import com.maddyhome.idea.vim.VimPlugin
import com.maddyhome.idea.vim.command.Command import com.maddyhome.idea.vim.command.Command
import com.maddyhome.idea.vim.command.CommandState import com.maddyhome.idea.vim.command.CommandState
import com.maddyhome.idea.vim.group.visual.VisualMotionGroup
import com.maddyhome.idea.vim.helper.getTopLevelEditor import com.maddyhome.idea.vim.helper.getTopLevelEditor
/** /**
@@ -101,7 +100,6 @@ sealed class EditorActionHandlerBase(myRunForEachCaret: Boolean) : EditorActionH
public final override fun doExecute(_editor: Editor, caret: Caret?, context: DataContext) { public final override fun doExecute(_editor: Editor, caret: Caret?, context: DataContext) {
if (!VimPlugin.isEnabled()) return if (!VimPlugin.isEnabled()) return
preAction()
val editor = _editor.getTopLevelEditor() val editor = _editor.getTopLevelEditor()
logger.debug("Execute command with handler: " + this.javaClass.name) logger.debug("Execute command with handler: " + this.javaClass.name)
@@ -114,10 +112,6 @@ sealed class EditorActionHandlerBase(myRunForEachCaret: Boolean) : EditorActionH
if (!baseExecute(editor, caret, context, cmd)) VimPlugin.indicateError() if (!baseExecute(editor, caret, context, cmd)) VimPlugin.indicateError()
} }
private fun preAction() {
VisualMotionGroup.modeBeforeEnteringNonVimVisual = null
}
open fun process(cmd: Command) { open fun process(cmd: Command) {
// No-op // No-op
} }

View File

@@ -5,13 +5,17 @@ package com.maddyhome.idea.vim.helper
import com.intellij.openapi.editor.Editor import com.intellij.openapi.editor.Editor
import com.maddyhome.idea.vim.command.CommandState import com.maddyhome.idea.vim.command.CommandState
/**
* @author Alex Plate
*/
private val modesWithEndAllowed = setOf(CommandState.Mode.INSERT, CommandState.Mode.REPEAT, CommandState.Mode.VISUAL, CommandState.Mode.SELECT)
val CommandState.Mode.isEndAllowed val CommandState.Mode.isEndAllowed
get() = this in modesWithEndAllowed get() = when (this) {
CommandState.Mode.INSERT, CommandState.Mode.REPEAT, CommandState.Mode.VISUAL, CommandState.Mode.SELECT -> true
CommandState.Mode.COMMAND, CommandState.Mode.EX_ENTRY, CommandState.Mode.REPLACE -> false
}
val CommandState.Mode.hasVisualSelection
get() = when (this) {
CommandState.Mode.VISUAL, CommandState.Mode.SELECT -> true
CommandState.Mode.REPLACE, CommandState.Mode.EX_ENTRY, CommandState.Mode.COMMAND, CommandState.Mode.INSERT, CommandState.Mode.REPEAT -> false
}
val Editor.mode val Editor.mode
get() = CommandState.getInstance(this).mode get() = CommandState.getInstance(this).mode

View File

@@ -543,6 +543,7 @@ public class EditorHelper {
public static boolean isLineEmpty(@NotNull final Editor editor, final int line, final boolean allowBlanks) { public static boolean isLineEmpty(@NotNull final Editor editor, final int line, final boolean allowBlanks) {
CharSequence chars = editor.getDocument().getCharsSequence(); CharSequence chars = editor.getDocument().getCharsSequence();
if (chars.length() == 0) return true;
int offset = getLineStartOffset(editor, line); int offset = getLineStartOffset(editor, line);
if (offset >= chars.length() || chars.charAt(offset) == '\n') { if (offset >= chars.length() || chars.charAt(offset) == '\n') {
return true; return true;

View File

@@ -106,3 +106,38 @@ fun Editor.isTemplateActive(): Boolean {
val project = this.project ?: return false val project = this.project ?: return false
return TemplateManager.getInstance(project).getActiveTemplate(this) != null return TemplateManager.getInstance(project).getActiveTemplate(this) != null
} }
/**
* This annotations marks if annotated function required read or write lock
*/
@Target
annotation class RWLockLabel {
/**
* [Readonly] annotation means that annotated function should be called from read action
* This annotation is only a marker and doesn't enable r/w lock automatically
*/
@Target(AnnotationTarget.FUNCTION)
annotation class Readonly
/**
* [Writable] annotation means that annotated function should be called from write action
* This annotation is only a marker and doesn't enable r/w lock automatically
*/
@Target(AnnotationTarget.FUNCTION)
annotation class Writable
/**
* [SelfSynchronized] annotation means that annotated function handles read/write lock by itself
* This annotation is only a marker and doesn't enable r/w lock automatically
*/
@Target(AnnotationTarget.FUNCTION)
annotation class SelfSynchronized
/**
* [NoLockRequired] annotation means that annotated function doesn't require any lock
* This annotation is only a marker and doesn't enable r/w lock automatically
*/
@Target(AnnotationTarget.FUNCTION)
annotation class NoLockRequired
}

View File

@@ -623,7 +623,7 @@ public class SearchHelper {
boolean isOuter) { boolean isOuter) {
final CharSequence chars = editor.getDocument().getCharsSequence(); final CharSequence chars = editor.getDocument().getCharsSequence();
final int pos = caret.getOffset(); final int pos = caret.getOffset();
if (chars.charAt(pos) == '\n') { if (pos >= chars.length() || chars.charAt(pos) == '\n') {
return null; return null;
} }
@@ -662,6 +662,7 @@ public class SearchHelper {
} }
private static boolean checkInString(@NotNull CharSequence chars, int pos, boolean str) { private static boolean checkInString(@NotNull CharSequence chars, int pos, boolean str) {
if (chars.length() == 0) return false;
int offset = pos; int offset = pos;
while (offset > 0 && chars.charAt(offset) != '\n') { while (offset > 0 && chars.charAt(offset) != '\n') {
offset--; offset--;
@@ -1110,6 +1111,9 @@ public class SearchHelper {
int stop = EditorHelper.getLineEndOffset(editor, caret.getLogicalPosition().line, true); int stop = EditorHelper.getLineEndOffset(editor, caret.getLogicalPosition().line, true);
int pos = caret.getOffset(); int pos = caret.getOffset();
// Technically the first condition is covered by the second one, but let it be
if (chars.length() == 0 || chars.length() <= pos) return null;
int start = pos; int start = pos;
CharacterHelper.CharacterType[] types = new CharacterHelper.CharacterType[]{CharacterHelper.CharacterType.KEYWORD, CharacterHelper.CharacterType[] types = new CharacterHelper.CharacterType[]{CharacterHelper.CharacterType.KEYWORD,
CharacterHelper.CharacterType.PUNCTUATION}; CharacterHelper.CharacterType.PUNCTUATION};
@@ -1174,6 +1178,8 @@ public class SearchHelper {
} }
int pos = caret.getOffset(); int pos = caret.getOffset();
if (chars.length() <= pos) return new TextRange(chars.length() - 1, chars.length() - 1);
boolean startSpace = CharacterHelper.charType(chars.charAt(pos), isBig) == CharacterHelper.CharacterType.WHITESPACE; boolean startSpace = CharacterHelper.charType(chars.charAt(pos), isBig) == CharacterHelper.CharacterType.WHITESPACE;
// Find word start // Find word start
boolean onWordStart = pos == min || boolean onWordStart = pos == min ||
@@ -1328,16 +1334,6 @@ public class SearchHelper {
boolean found = false; boolean found = false;
// For forward searches, skip any current whitespace so we start at the start of a word // For forward searches, skip any current whitespace so we start at the start of a word
if (step > 0 && pos < size - 1) { if (step > 0 && pos < size - 1) {
/*
if (CharacterHelper.charType(chars[pos + step], false) == CharacterHelper.WHITESPACE)
{
if (!stayEnd)
{
pos += step;
}
pos = skipSpace(chars, pos, step, size);
}
*/
if (CharacterHelper.charType(chars.charAt(pos + 1), bigWord) == CharacterHelper.CharacterType.WHITESPACE && if (CharacterHelper.charType(chars.charAt(pos + 1), bigWord) == CharacterHelper.CharacterType.WHITESPACE &&
!spaceWords) { !spaceWords) {
pos = skipSpace(chars, pos + 1, step, size) - 1; pos = skipSpace(chars, pos + 1, step, size) - 1;
@@ -1379,11 +1375,11 @@ public class SearchHelper {
} }
if (found) { if (found) {
if (res < 0) //(pos <= 0) if (res < 0)
{ {
res = 0; res = 0;
} }
else if (res >= size) //(pos >= size) else if (res >= size)
{ {
res = size - 1; res = size - 1;
} }
@@ -1406,7 +1402,7 @@ public class SearchHelper {
* @param size The size of the document * @param size The size of the document
* @return The new position. This will be the first non-whitespace character found or an empty line * @return The new position. This will be the first non-whitespace character found or an empty line
*/ */
public static int skipSpace(@NotNull CharSequence chars, int offset, int step, int size) { private static int skipSpace(@NotNull CharSequence chars, int offset, int step, int size) {
char prev = 0; char prev = 0;
while (offset >= 0 && offset < size) { while (offset >= 0 && offset < size) {
final char c = chars.charAt(offset); final char c = chars.charAt(offset);
@@ -1420,7 +1416,7 @@ public class SearchHelper {
offset += step; offset += step;
} }
return offset; return offset < size ? offset : size - 1;
} }
/** /**
@@ -1875,7 +1871,7 @@ public class SearchHelper {
} }
if (res < 0 || count > 0) { if (res < 0 || count > 0) {
res = dir > 0 ? max - 1 : 0; res = dir > 0 ? (max > 0 ? max - 1 : 0) : 0;
} }
else if (isOuter && ((dir < 0 && findend) || (dir > 0 && !findend))) { else if (isOuter && ((dir < 0 && findend) || (dir > 0 && !findend))) {
if (res != 0 && res != max - 1) { if (res != 0 && res != max - 1) {
@@ -1893,6 +1889,7 @@ public class SearchHelper {
@NotNull @NotNull
public static TextRange findSentenceRange(@NotNull Editor editor, @NotNull Caret caret, int count, boolean isOuter) { public static TextRange findSentenceRange(@NotNull Editor editor, @NotNull Caret caret, int count, boolean isOuter) {
CharSequence chars = editor.getDocument().getCharsSequence(); CharSequence chars = editor.getDocument().getCharsSequence();
if (chars.length() == 0) return new TextRange(0, 0);
int max = EditorHelper.getFileSize(editor); int max = EditorHelper.getFileSize(editor);
int offset = caret.getOffset(); int offset = caret.getOffset();
int ssel = caret.getSelectionStart(); int ssel = caret.getSelectionStart();

View File

@@ -72,7 +72,8 @@ object IdeaSpecifics {
// Rider moves caret to the end of selection // Rider moves caret to the end of selection
editor?.caretModel?.addCaretListener(object : CaretListener { editor?.caretModel?.addCaretListener(object : CaretListener {
override fun caretPositionChanged(event: CaretEvent) { override fun caretPositionChanged(event: CaretEvent) {
moveCaretOneCharLeftFromSelectionEnd(event.editor) val predictedMode = VimPlugin.getVisualMotion().predictMode(event.editor, VimListenerManager.SelectionSource.OTHER)
moveCaretOneCharLeftFromSelectionEnd(event.editor, predictedMode)
event.editor.caretModel.removeCaretListener(this) event.editor.caretModel.removeCaretListener(this)
} }
}) })

View File

@@ -37,7 +37,6 @@ import com.maddyhome.idea.vim.VimTypedActionHandler
import com.maddyhome.idea.vim.command.CommandState import com.maddyhome.idea.vim.command.CommandState
import com.maddyhome.idea.vim.ex.ExOutputModel import com.maddyhome.idea.vim.ex.ExOutputModel
import com.maddyhome.idea.vim.group.* import com.maddyhome.idea.vim.group.*
import com.maddyhome.idea.vim.group.visual.VisualMotionGroup
import com.maddyhome.idea.vim.group.visual.moveCaretOneCharLeftFromSelectionEnd import com.maddyhome.idea.vim.group.visual.moveCaretOneCharLeftFromSelectionEnd
import com.maddyhome.idea.vim.group.visual.vimSetSystemSelectionSilently import com.maddyhome.idea.vim.group.visual.vimSetSystemSelectionSilently
import com.maddyhome.idea.vim.helper.* import com.maddyhome.idea.vim.helper.*
@@ -131,7 +130,10 @@ object VimListenerManager {
@JvmStatic @JvmStatic
fun enable() { fun enable() {
val typedAction = EditorActionManager.getInstance().typedAction val typedAction = EditorActionManager.getInstance().typedAction
EventFacade.getInstance().setupTypedActionHandler(VimTypedActionHandler(typedAction.rawHandler)) if (typedAction.rawHandler !is VimTypedActionHandler) {
// Actually this if should always be true, but just as protection
EventFacade.getInstance().setupTypedActionHandler(VimTypedActionHandler(typedAction.rawHandler))
}
OptionsManager.number.addOptionChangeListener(EditorGroup.NumberChangeListener.INSTANCE) OptionsManager.number.addOptionChangeListener(EditorGroup.NumberChangeListener.INSTANCE)
OptionsManager.relativenumber.addOptionChangeListener(EditorGroup.NumberChangeListener.INSTANCE) OptionsManager.relativenumber.addOptionChangeListener(EditorGroup.NumberChangeListener.INSTANCE)
@@ -295,14 +297,14 @@ object VimListenerManager {
} }
override fun mouseReleased(event: EditorMouseEvent) { override fun mouseReleased(event: EditorMouseEvent) {
VisualMotionGroup.modeBeforeEnteringNonVimVisual = null
if (mouseDragging) { if (mouseDragging) {
logger.debug("Release mouse after dragging") logger.debug("Release mouse after dragging")
val editor = event.editor val editor = event.editor
val caret = editor.caretModel.primaryCaret val caret = editor.caretModel.primaryCaret
SelectionVimListenerSuppressor.use { SelectionVimListenerSuppressor.use {
val predictedMode = VimPlugin.getVisualMotion().predictMode(editor, VimListenerManager.SelectionSource.MOUSE)
VimPlugin.getVisualMotion().controlNonVimSelectionChange(editor, VimListenerManager.SelectionSource.MOUSE) VimPlugin.getVisualMotion().controlNonVimSelectionChange(editor, VimListenerManager.SelectionSource.MOUSE)
moveCaretOneCharLeftFromSelectionEnd(editor) moveCaretOneCharLeftFromSelectionEnd(editor, predictedMode)
caret.vimLastColumn = editor.caretModel.visualPosition.column caret.vimLastColumn = editor.caretModel.visualPosition.column
} }
@@ -352,9 +354,10 @@ object VimListenerManager {
private object ComponentMouseListener : MouseAdapter() { private object ComponentMouseListener : MouseAdapter() {
override fun mousePressed(e: MouseEvent?) { override fun mousePressed(e: MouseEvent?) {
val editor = (e?.component as? EditorComponentImpl)?.editor ?: return val editor = (e?.component as? EditorComponentImpl)?.editor ?: return
val predictedMode = VimPlugin.getVisualMotion().predictMode(editor, VimListenerManager.SelectionSource.MOUSE)
when (e.clickCount) { when (e.clickCount) {
1 -> { 1 -> {
if (!editor.inInsertMode) { if (!predictedMode.isEndAllowed) {
editor.caretModel.runForEachCaret { caret -> editor.caretModel.runForEachCaret { caret ->
val lineEnd = EditorHelper.getLineEndForOffset(editor, caret.offset) val lineEnd = EditorHelper.getLineEndForOffset(editor, caret.offset)
val lineStart = EditorHelper.getLineStartForOffset(editor, caret.offset) val lineStart = EditorHelper.getLineStartForOffset(editor, caret.offset)
@@ -364,7 +367,7 @@ object VimListenerManager {
} }
} }
} }
2 -> moveCaretOneCharLeftFromSelectionEnd(editor) 2 -> moveCaretOneCharLeftFromSelectionEnd(editor, predictedMode)
} }
} }
} }

View File

@@ -70,6 +70,7 @@ object OptionsManager {
val viminfo = addOption(ListOption("viminfo", "vi", arrayOf("'100", "<50", "s10", "h"), null)) val viminfo = addOption(ListOption("viminfo", "vi", arrayOf("'100", "<50", "s10", "h"), null))
val visualbell = addOption(ToggleOption("visualbell", "vb", false)) val visualbell = addOption(ToggleOption("visualbell", "vb", false))
val wrapscan = addOption(ToggleOption("wrapscan", "ws", true)) val wrapscan = addOption(ToggleOption("wrapscan", "ws", true))
val visualEnterDelay = addOption(NumberOption("visualdelay", "visualdelay", 100, 0, Int.MAX_VALUE))
init { init {
registerExtensionOptions() registerExtensionOptions()
@@ -407,6 +408,27 @@ object ClipboardOptionsData {
const val abbr = "cb" const val abbr = "cb"
const val ideaput = "ideaput" const val ideaput = "ideaput"
var ideaputDisabled = false
private set
/**
* This autocloseable class allows temporary disable ideaput option
* [ClipboardOptionsData.ideaputDisabled] property indicates if ideaput was disabled
*/
class IdeaputDisabler : AutoCloseable {
private val containedBefore: Boolean
override fun close() {
if (containedBefore) OptionsManager.clipboard.append(ideaput)
ideaputDisabled = false
}
init {
val options = OptionsManager.clipboard
containedBefore = options.contains(ideaput)
options.remove(ideaput)
ideaputDisabled = true
}
}
} }
object IdeaJoinOptionsData { object IdeaJoinOptionsData {
@@ -431,4 +453,4 @@ object SmartCaseOptionsData {
object IgnoreCaseOptionsData { object IgnoreCaseOptionsData {
const val name = "ignorecase" const val name = "ignorecase"
const val abbr = "ic" const val abbr = "ic"
} }

Some files were not shown because too many files have changed in this diff Show More