1
0
mirror of https://github.com/chylex/IntelliJ-IdeaVim.git synced 2025-05-29 10:34:10 +02:00

Delete deprecated OptionsManager.kt

This commit is contained in:
filipp 2022-06-07 01:08:10 +06:00
parent e248bb5565
commit 01e367cadf
27 changed files with 46 additions and 2732 deletions

View File

@ -74,7 +74,7 @@ If you are looking for:
- Common features: - Common features:
- State machine. How every particular keystroke is parsed in IdeaVim: `KeyHandler.handleKey()`. - State machine. How every particular keystroke is parsed in IdeaVim: `KeyHandler.handleKey()`.
- Options (`incsearch`, `iskeyword`, `relativenumber`): `OptionsManager`. - Options (`incsearch`, `iskeyword`, `relativenumber`): `OptionServiceImpl`.
- Plugin startup: `PluginStartup`. - Plugin startup: `PluginStartup`.
- Notifications: `NotificationService`. - Notifications: `NotificationService`.
- Status bar icon: `StatusBar.kt`. - Status bar icon: `StatusBar.kt`.

View File

@ -1,6 +1,6 @@
# suppress inspection "UnusedProperty" for whole file # suppress inspection "UnusedProperty" for whole file
ideaVersion=LATEST-EAP-SNAPSHOT ideaVersion=2022.1.1
downloadIdeaSources=true downloadIdeaSources=true
instrumentPluginCode=true instrumentPluginCode=true
version=SNAPSHOT version=SNAPSHOT

View File

@ -48,7 +48,6 @@ import com.maddyhome.idea.vim.group.visual.VisualMotionGroup;
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.newapi.IjVimInjector; import com.maddyhome.idea.vim.newapi.IjVimInjector;
import com.maddyhome.idea.vim.option.OptionsManager;
import com.maddyhome.idea.vim.options.OptionService; import com.maddyhome.idea.vim.options.OptionService;
import com.maddyhome.idea.vim.ui.StatusBarIconFactory; import com.maddyhome.idea.vim.ui.StatusBarIconFactory;
import com.maddyhome.idea.vim.ui.VimEmulationConfigurable; import com.maddyhome.idea.vim.ui.VimEmulationConfigurable;
@ -362,11 +361,6 @@ public class VimPlugin implements PersistentStateComponent<Element>, Disposable
// 3.2) Initialize extensions. Always after 3.1 // 3.2) Initialize extensions. Always after 3.1
VimExtensionRegistrar.enableDelayedExtensions(); VimExtensionRegistrar.enableDelayedExtensions();
// 4) Components initialization
// Some options' default values are based on values set in .ideavimrc, e.g. 'shellxquote' on Windows when 'shell'
// is cmd.exe has a different default to when 'shell' contains "sh"
OptionsManager.INSTANCE.completeInitialisation();
// Turing on should be performed after all commands registration // Turing on should be performed after all commands registration
getSearch().turnOn(); getSearch().turnOn();
VimListenerManager.INSTANCE.turnOn(); VimListenerManager.INSTANCE.turnOn();

View File

@ -25,12 +25,11 @@ import com.maddyhome.idea.vim.api.VimExtensionRegistrator
import com.maddyhome.idea.vim.api.injector import com.maddyhome.idea.vim.api.injector
import com.maddyhome.idea.vim.ex.ExException import com.maddyhome.idea.vim.ex.ExException
import com.maddyhome.idea.vim.key.MappingOwner.Plugin.Companion.remove import com.maddyhome.idea.vim.key.MappingOwner.Plugin.Companion.remove
import com.maddyhome.idea.vim.option.OptionsManager
import com.maddyhome.idea.vim.options.OptionChangeListener import com.maddyhome.idea.vim.options.OptionChangeListener
import com.maddyhome.idea.vim.options.OptionScope import com.maddyhome.idea.vim.options.OptionScope
import com.maddyhome.idea.vim.statistic.PluginState import com.maddyhome.idea.vim.statistic.PluginState
import com.maddyhome.idea.vim.vimscript.model.datatypes.VimDataType import com.maddyhome.idea.vim.vimscript.model.datatypes.VimDataType
import com.maddyhome.idea.vim.vimscript.model.options.ToggleOption import com.maddyhome.idea.vim.options.ToggleOption
object VimExtensionRegistrar : VimExtensionRegistrator { object VimExtensionRegistrar : VimExtensionRegistrator {
internal val registeredExtensions: MutableSet<String> = HashSet() internal val registeredExtensions: MutableSet<String> = HashSet()
@ -68,7 +67,6 @@ object VimExtensionRegistrar : VimExtensionRegistrator {
registeredExtensions.add(name) registeredExtensions.add(name)
registerAliases(extensionBean) registerAliases(extensionBean)
OptionsManager.addOption(com.maddyhome.idea.vim.option.ToggleOption(name, getAbbrev(name), false))
VimPlugin.getOptionServiceImpl().addOption(ToggleOption(name, getAbbrev(name), false)) VimPlugin.getOptionServiceImpl().addOption(ToggleOption(name, getAbbrev(name), false))
VimPlugin.getOptionService().addListener( VimPlugin.getOptionService().addListener(
name, name,
@ -115,7 +113,6 @@ object VimExtensionRegistrar : VimExtensionRegistrator {
removeAliases(extension) removeAliases(extension)
extension.instance.dispose() extension.instance.dispose()
VimPlugin.getOptionService().removeOption(name) VimPlugin.getOptionService().removeOption(name)
OptionsManager.removeOption(name)
remove(name) remove(name)
logger.info("IdeaVim extension '$name' disposed") logger.info("IdeaVim extension '$name' disposed")
} }

View File

@ -31,13 +31,15 @@ import com.intellij.openapi.editor.markup.TextAttributes
import com.intellij.openapi.util.Disposer import com.intellij.openapi.util.Disposer
import com.maddyhome.idea.vim.VimPlugin import com.maddyhome.idea.vim.VimPlugin
import com.maddyhome.idea.vim.VimProjectService import com.maddyhome.idea.vim.VimProjectService
import com.maddyhome.idea.vim.api.injector
import com.maddyhome.idea.vim.common.TextRange import com.maddyhome.idea.vim.common.TextRange
import com.maddyhome.idea.vim.extension.VimExtension import com.maddyhome.idea.vim.extension.VimExtension
import com.maddyhome.idea.vim.helper.MessageHelper import com.maddyhome.idea.vim.helper.MessageHelper
import com.maddyhome.idea.vim.helper.VimNlsSafe import com.maddyhome.idea.vim.helper.VimNlsSafe
import com.maddyhome.idea.vim.listener.VimInsertListener import com.maddyhome.idea.vim.listener.VimInsertListener
import com.maddyhome.idea.vim.listener.VimYankListener import com.maddyhome.idea.vim.listener.VimYankListener
import com.maddyhome.idea.vim.option.StrictMode import com.maddyhome.idea.vim.options.OptionConstants
import com.maddyhome.idea.vim.options.OptionScope
import com.maddyhome.idea.vim.vimscript.model.datatypes.VimString import com.maddyhome.idea.vim.vimscript.model.datatypes.VimString
import org.jetbrains.annotations.NonNls import org.jetbrains.annotations.NonNls
import java.awt.Color import java.awt.Color
@ -137,12 +139,18 @@ class VimHighlightedYank : VimExtension, VimYankListener, VimInsertListener {
fun clearAllYankHighlighters() { fun clearAllYankHighlighters() {
yankHighlighters.forEach { highlighter -> yankHighlighters.forEach { highlighter ->
editor?.markupModel?.removeHighlighter(highlighter) ?: StrictMode.fail("Highlighters without an editor") editor?.markupModel?.removeHighlighter(highlighter) ?: failIfStrictMode("Highlighters without an editor")
} }
yankHighlighters.clear() yankHighlighters.clear()
} }
private fun failIfStrictMode(value: String) {
if (injector.optionService.isSet(OptionScope.GLOBAL, OptionConstants.ideastrictmodeName)) {
error(value)
}
}
private fun highlightSingleRange(editor: Editor, range: ClosedRange<Int>) { private fun highlightSingleRange(editor: Editor, range: ClosedRange<Int>) {
val highlighter = editor.markupModel.addRangeHighlighter( val highlighter = editor.markupModel.addRangeHighlighter(
range.start, range.start,
@ -165,7 +173,7 @@ class VimHighlightedYank : VimExtension, VimYankListener, VimInsertListener {
Executors.newSingleThreadScheduledExecutor().schedule( Executors.newSingleThreadScheduledExecutor().schedule(
{ {
ApplicationManager.getApplication().invokeLater { ApplicationManager.getApplication().invokeLater {
editor?.markupModel?.removeHighlighter(highlighter) ?: StrictMode.fail("Highlighters without an editor") editor?.markupModel?.removeHighlighter(highlighter) ?: failIfStrictMode("Highlighters without an editor")
} }
}, },
timeout, TimeUnit.MILLISECONDS timeout, TimeUnit.MILLISECONDS

View File

@ -61,7 +61,6 @@ import com.maddyhome.idea.vim.listener.SelectionVimListenerSuppressor;
import com.maddyhome.idea.vim.listener.VimInsertListener; import com.maddyhome.idea.vim.listener.VimInsertListener;
import com.maddyhome.idea.vim.listener.VimListenerSuppressor; import com.maddyhome.idea.vim.listener.VimListenerSuppressor;
import com.maddyhome.idea.vim.newapi.*; import com.maddyhome.idea.vim.newapi.*;
import com.maddyhome.idea.vim.option.StrictMode;
import com.maddyhome.idea.vim.options.OptionConstants; import com.maddyhome.idea.vim.options.OptionConstants;
import com.maddyhome.idea.vim.options.OptionScope; import com.maddyhome.idea.vim.options.OptionScope;
import com.maddyhome.idea.vim.register.Register; import com.maddyhome.idea.vim.register.Register;
@ -1308,7 +1307,9 @@ public class ChangeGroup extends VimChangeGroupBase {
int endOffset = range.getEndOffset(); int endOffset = range.getEndOffset();
int fileSize = EditorHelperRt.getFileSize(((IjVimEditor) editor).getEditor()); int fileSize = EditorHelperRt.getFileSize(((IjVimEditor) editor).getEditor());
if (endOffset > fileSize) { if (endOffset > fileSize) {
StrictMode.INSTANCE.fail("Incorrect offset. File size: " + fileSize + ", offset: " + endOffset); if (injector.getOptionService().isSet(OptionScope.GLOBAL.INSTANCE, OptionConstants.ideastrictmodeName, OptionConstants.ideastrictmodeName)) {
throw new IllegalStateException("Incorrect offset. File size: " + fileSize + ", offset: " + endOffset);
}
endOffset = fileSize; endOffset = fileSize;
} }
return type == SelectionType.LINE_WISE && return type == SelectionType.LINE_WISE &&

View File

@ -76,8 +76,8 @@ import com.maddyhome.idea.vim.listener.VimListenerManager.EditorListeners.add
import com.maddyhome.idea.vim.listener.VimListenerManager.EditorListeners.remove import com.maddyhome.idea.vim.listener.VimListenerManager.EditorListeners.remove
import com.maddyhome.idea.vim.newapi.IjVimEditor import com.maddyhome.idea.vim.newapi.IjVimEditor
import com.maddyhome.idea.vim.newapi.vim import com.maddyhome.idea.vim.newapi.vim
import com.maddyhome.idea.vim.option.StrictMode
import com.maddyhome.idea.vim.options.OptionConstants import com.maddyhome.idea.vim.options.OptionConstants
import com.maddyhome.idea.vim.options.OptionScope
import com.maddyhome.idea.vim.options.helpers.KeywordOptionChangeListener import com.maddyhome.idea.vim.options.helpers.KeywordOptionChangeListener
import com.maddyhome.idea.vim.ui.ShowCmdOptionChangeListener import com.maddyhome.idea.vim.ui.ShowCmdOptionChangeListener
import com.maddyhome.idea.vim.ui.ex.ExEntryPanel import com.maddyhome.idea.vim.ui.ex.ExEntryPanel
@ -110,7 +110,9 @@ object VimListenerManager {
// Actually this if should always be true, but just as protection // Actually this if should always be true, but just as protection
EventFacade.getInstance().setupTypedActionHandler(VimTypedActionHandler(typedAction.rawHandler)) EventFacade.getInstance().setupTypedActionHandler(VimTypedActionHandler(typedAction.rawHandler))
} else { } else {
StrictMode.fail("typeAction expected to be non-vim.") if (VimPlugin.getOptionService().isSet(OptionScope.GLOBAL, OptionConstants.ideastrictmodeName)) {
error("typeAction expected to be non-vim.")
}
} }
VimPlugin.getOptionService().addListener(OptionConstants.numberName, EditorGroup.NumberChangeListener.INSTANCE) VimPlugin.getOptionService().addListener(OptionConstants.numberName, EditorGroup.NumberChangeListener.INSTANCE)

View File

@ -1,51 +0,0 @@
/*
* IdeaVim - Vim emulator for IDEs based on the IntelliJ platform
* Copyright (C) 2003-2022 The IdeaVim authors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.maddyhome.idea.vim.option;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* @deprecated use {@link com.maddyhome.idea.vim.vimscript.model.options.Option} instead
*/
@Deprecated
@ApiStatus.ScheduledForRemoval(inVersion = "1.11")
public class BoundedStringListOption extends StringListOption {
protected final @NotNull List<String> allowedValues;
public BoundedStringListOption(@NonNls String name,
@NonNls String abbrev,
@NonNls String[] defaultValues,
@NonNls String[] allowedValues) {
super(name, abbrev, defaultValues);
this.allowedValues = new ArrayList<>(Arrays.asList(allowedValues));
}
@Override
protected @Nullable String convertToken(@NotNull String token) {
return allowedValues.contains(token) ? token : null;
}
}

View File

@ -1,84 +0,0 @@
/*
* IdeaVim - Vim emulator for IDEs based on the IntelliJ platform
* Copyright (C) 2003-2022 The IdeaVim authors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.maddyhome.idea.vim.option;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
/**
* @deprecated use {@link com.maddyhome.idea.vim.vimscript.model.options.Option} instead
*/
@Deprecated
@ApiStatus.ScheduledForRemoval(inVersion = "1.11")
public class BoundedStringOption extends StringOption {
protected final String[] values;
BoundedStringOption(@NonNls String name, @NonNls String abbrev, @NonNls String dflt, String[] values) {
super(name, abbrev, dflt);
this.values = values;
}
@Override
public boolean set(String val) {
if (isValid(val)) {
return super.set(val);
}
return false;
}
@Override
public boolean append(String val) {
if (isValid(val) && getValue().length() == 0) {
return super.set(val);
}
return false;
}
@Override
public boolean prepend(String val) {
if (isValid(val) && getValue().length() == 0) {
return super.set(val);
}
return false;
}
@Override
public boolean remove(@NotNull String val) {
if (getValue().equals(val)) {
return super.remove(val);
}
return false;
}
private boolean isValid(String val) {
for (String value : values) {
if (value.equals(val)) {
return true;
}
}
return false;
}
}

View File

@ -1,128 +0,0 @@
/*
* IdeaVim - Vim emulator for IDEs based on the IntelliJ platform
* Copyright (C) 2003-2022 The IdeaVim authors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.maddyhome.idea.vim.option
import com.maddyhome.idea.vim.ex.exExceptionMessage
import com.maddyhome.idea.vim.helper.enumSetOf
import com.maddyhome.idea.vim.vimscript.model.options.helpers.GuiCursorAttributes
import com.maddyhome.idea.vim.vimscript.model.options.helpers.GuiCursorEntry
import com.maddyhome.idea.vim.vimscript.model.options.helpers.GuiCursorMode
import com.maddyhome.idea.vim.vimscript.model.options.helpers.GuiCursorType
import org.jetbrains.annotations.ApiStatus
/**
* @deprecated use {@link com.maddyhome.idea.vim.options.helpers.GuiCursorOptionHelper} instead
*/
@Deprecated("options are now replaced by helper classes")
@ApiStatus.ScheduledForRemoval(inVersion = "1.11")
class GuiCursorOption(name: String, abbrev: String, defaultValue: String) :
ListOption<GuiCursorEntry>(name, abbrev, defaultValue) {
private val effectiveValues = mutableMapOf<GuiCursorMode, GuiCursorAttributes>()
override fun convertToken(token: String): GuiCursorEntry {
val split = token.split(':')
if (split.size == 1) {
throw exExceptionMessage("E545", token)
}
if (split.size != 2) {
throw exExceptionMessage("E546", token)
}
val modeList = split[0]
val argumentList = split[1]
val modes = enumSetOf<GuiCursorMode>()
modes.addAll(
modeList.split('-').map {
GuiCursorMode.fromString(it) ?: throw exExceptionMessage("E546", token)
}
)
var type = GuiCursorType.BLOCK
var thickness = 0
var highlightGroup = ""
var lmapHighlightGroup = ""
val blinkModes = mutableListOf<String>()
argumentList.split('-').forEach {
when {
it == "block" -> type = GuiCursorType.BLOCK
it.startsWith("ver") -> {
type = GuiCursorType.VER
thickness = it.slice(3 until it.length).toIntOrNull() ?: throw exExceptionMessage("E548", token)
if (thickness == 0) {
throw exExceptionMessage("E549", token)
}
}
it.startsWith("hor") -> {
type = GuiCursorType.HOR
thickness = it.slice(3 until it.length).toIntOrNull() ?: throw exExceptionMessage("E548", token)
if (thickness == 0) {
throw exExceptionMessage("E549", token)
}
}
it.startsWith("blink") -> {
// We don't do anything with blink...
blinkModes.add(it)
}
it.contains('/') -> {
val i = it.indexOf('/')
highlightGroup = it.slice(0 until i)
lmapHighlightGroup = it.slice(i + 1 until it.length)
}
else -> highlightGroup = it
}
}
return GuiCursorEntry(token, modes, type, thickness, highlightGroup, lmapHighlightGroup, blinkModes)
}
override fun onChanged(oldValue: String?, newValue: String?) {
effectiveValues.clear()
super.onChanged(oldValue, newValue)
}
fun getAttributes(mode: GuiCursorMode): GuiCursorAttributes {
return effectiveValues.computeIfAbsent(mode) {
var type = GuiCursorType.BLOCK
var thickness = 0
var highlightGroup = ""
var lmapHighlightGroup = ""
var blinkModes = emptyList<String>()
values().forEach { data ->
if (data.modes.contains(mode) || data.modes.contains(GuiCursorMode.ALL)) {
if (data.type != null) {
type = data.type
}
if (data.thickness != null) {
thickness = data.thickness
}
if (data.highlightGroup.isNotEmpty()) {
highlightGroup = data.highlightGroup
}
if (data.lmapHighlightGroup.isNotEmpty()) {
lmapHighlightGroup = data.lmapHighlightGroup
}
if (data.blinkModes.isNotEmpty()) {
blinkModes = data.blinkModes
}
}
}
GuiCursorAttributes(type, thickness, highlightGroup, lmapHighlightGroup, blinkModes)
}
}
}

View File

@ -1,361 +0,0 @@
/*
* IdeaVim - Vim emulator for IDEs based on the IntelliJ platform
* Copyright (C) 2003-2022 The IdeaVim authors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.maddyhome.idea.vim.option;
import com.maddyhome.idea.vim.VimPlugin;
import com.maddyhome.idea.vim.options.OptionScope;
import com.maddyhome.idea.vim.options.helpers.KeywordOptionHelper;
import com.maddyhome.idea.vim.vimscript.model.commands.SetCommand;
import com.maddyhome.idea.vim.vimscript.model.datatypes.VimString;
import org.apache.commons.lang.math.NumberUtils;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
/**
* @deprecated use {@link KeywordOptionHelper} instead
*/
@Deprecated
@ApiStatus.ScheduledForRemoval(inVersion = "1.11")
public final class KeywordOption extends StringListOption {
@NonNls private static final String allLettersRegex = "\\p{L}";
@NonNls private static final String PATTERN =
"(\\^?(([^0-9^]|[0-9]{1,3})-([^0-9]|[0-9]{1,3})|([^0-9^]|[0-9]{1,3})),)*\\^?(([^0-9^]|[0-9]{1,3})-([^0-9]|[0-9]{1,3})|([^0-9]|[0-9]{1,3})),?$";
private final @NotNull Pattern validationPattern;
// KeywordSpecs are the option values in reverse order
private @NotNull List<KeywordSpec> keywordSpecs = new ArrayList<>();
public KeywordOption(@NotNull @NonNls String name, @NotNull @NonNls String abbrev, @NotNull String[] defaultValue) {
super(name, abbrev, defaultValue, PATTERN);
validationPattern = Pattern.compile(PATTERN);
initialSet(defaultValue);
}
@Override
public boolean append(@NotNull String val) {
String oldValue = getValue();
final List<String> vals = parseVals(val);
final List<KeywordSpec> specs = valsToValidatedAndReversedSpecs(vals);
if (vals == null || specs == null) {
return false;
}
this.value.addAll(vals);
keywordSpecs.addAll(0, specs);
onChanged(oldValue, getValue());
// we won't use OptionService if the method was invoked during set command execution (set command will call OptionService by itself)
if (!SetCommand.Companion.isExecutingCommand()) {
try {
String joinedValue = getValue();
if (!((VimString)VimPlugin.getOptionService().getOptionValue(OptionScope.GLOBAL.INSTANCE, name, name)).getValue().equals(joinedValue)) {
VimPlugin.getOptionService().setOptionValue(OptionScope.GLOBAL.INSTANCE, name, new VimString(joinedValue), name);
}
}
catch (Exception e) {
}
}
return true;
}
@Override
public boolean prepend(@NotNull String val) {
String oldValue = getValue();
final List<String> vals = parseVals(val);
final List<KeywordSpec> specs = valsToValidatedAndReversedSpecs(vals);
if (vals == null || specs == null) {
return false;
}
value.addAll(0, vals);
keywordSpecs.addAll(specs);
onChanged(oldValue, getValue());
try {
String joinedValue = getValue();
if (!((VimString)VimPlugin.getOptionService()
.getOptionValue(OptionScope.GLOBAL.INSTANCE, name, name)).getValue().equals(joinedValue)) {
VimPlugin.getOptionService().setOptionValue(OptionScope.GLOBAL.INSTANCE, name, new VimString(joinedValue), name);
}
} catch (Exception e) {}
return true;
}
@Override
public boolean remove(@NotNull String val) {
String oldValue = getValue();
final List<String> vals = parseVals(val);
final List<KeywordSpec> specs = valsToValidatedAndReversedSpecs(vals);
if (vals == null || specs == null) {
return false;
}
value.removeAll(vals);
keywordSpecs.removeAll(specs);
onChanged(oldValue, getValue());
try {
String joinedValue = getValue();
if (!((VimString)VimPlugin.getOptionService()
.getOptionValue(OptionScope.GLOBAL.INSTANCE, name, name)).getValue().equals(joinedValue)) {
VimPlugin.getOptionService().setOptionValue(OptionScope.GLOBAL.INSTANCE, name, new VimString(joinedValue), name);
}
} catch (Exception e) {}
return true;
}
private void initialSet(String[] values) {
String oldValue = getValue();
final List<String> vals = new ArrayList<>(Arrays.asList(values));
final List<KeywordSpec> specs = valsToReversedSpecs(vals);
value = vals;
keywordSpecs = specs;
onChanged(oldValue, getValue());
}
@Override
public boolean set(@NotNull String val) {
String oldValue = getValue();
final List<String> vals = parseVals(val);
final List<KeywordSpec> specs = valsToValidatedAndReversedSpecs(vals);
if (vals == null || specs == null) {
return false;
}
value = vals;
keywordSpecs = specs;
onChanged(oldValue, getValue());
try {
String joinedValue = getValue();
if (!((VimString)VimPlugin.getOptionService()
.getOptionValue(OptionScope.GLOBAL.INSTANCE, name, name)).getValue().equals(joinedValue)) {
VimPlugin.getOptionService().setOptionValue(OptionScope.GLOBAL.INSTANCE, name, new VimString(joinedValue), name);
}
} catch (Exception e) {}
return true;
}
@Override
public void resetDefault() {
if (!defaultValues.equals(value)) {
value = defaultValues;
set(getValue());
}
}
private @NotNull List<KeywordSpec> valsToReversedSpecs(@NotNull List<String> vals) {
final ArrayList<KeywordSpec> res = new ArrayList<>();
for (int i = vals.size() - 1; i >= 0; i--) {
res.add(new KeywordSpec(vals.get(i)));
}
return res;
}
private @Nullable List<KeywordSpec> valsToValidatedAndReversedSpecs(@Nullable List<String> vals) {
final List<KeywordSpec> specs = new ArrayList<>();
if (vals != null) {
for (String val : vals) {
KeywordSpec spec = new KeywordSpec(val);
if (!spec.isValid()) {
return null;
}
specs.add(spec);
}
Collections.reverse(specs);
}
return specs;
}
@Override
protected @Nullable List<String> parseVals(@NotNull String content) {
if (!validationPattern.matcher(content).matches()) {
return null;
}
int index = 0;
boolean firstCharNumOfPart = true;
boolean inRange = false;
final List<String> vals = new ArrayList<>();
StringBuilder option = new StringBuilder();
// We need to split the input string into parts. However, we can't just split on a comma
// since a comma can either be a keyword or a separator depending on its location in the string.
while (index <= content.length()) {
char curChar = 0;
if (index < content.length()) {
curChar = content.charAt(index);
}
index++;
// If we either have a comma separator or are at the end of the content...
if (curChar == ',' && (!firstCharNumOfPart && !inRange) || index == content.length() + 1) {
String part = option.toString();
vals.add(part);
option = new StringBuilder();
inRange = false;
firstCharNumOfPart = true;
continue;
}
option.append(curChar);
if (curChar == '^' && option.length() == 1) {
firstCharNumOfPart = true;
continue;
}
if (curChar == '-' && !firstCharNumOfPart) {
inRange = true;
continue;
}
firstCharNumOfPart = false;
inRange = false;
}
return vals;
}
public boolean isKeyword(char c) {
if ((int)c >= '\u0100') {
return true;
}
for (KeywordSpec spec : keywordSpecs) {
if (spec.contains(c)) {
return !spec.negate();
}
}
return false;
}
// This function is used in AceJump integration plugin
public List<String> toRegex() {
return keywordSpecs.stream().map(spec -> {
spec.initializeValues();
if (spec.isAllLetters) {
return allLettersRegex;
}
else if (spec.isRange) {
return "[" + (char)spec.rangeLow.intValue() + "-" + (char)spec.rangeHigh.intValue() + "]";
}
else {
return String.valueOf((char)spec.rangeLow.intValue());
}
}).collect(Collectors.toList());
}
private static final class KeywordSpec {
private final String part;
private boolean negate;
private boolean isRange = false;
private boolean isAllLetters = false;
private Integer rangeLow;
private Integer rangeHigh;
private boolean initialized = false;
public KeywordSpec(@NotNull String part) {
this.part = part;
}
private void initializeValues() {
if (initialized) return;
initialized = true;
String part = this.part;
negate = part.matches("^\\^.+");
if (negate) {
part = part.substring(1);
}
final String[] keywords = part.split("(?<=.)-(?=.+)");
if (keywords.length > 1 || keywords[0].equals("@")) {
isRange = true;
if (keywords.length > 1) {
rangeLow = toUnicode(keywords[0]);
rangeHigh = toUnicode(keywords[1]);
}
else {
isAllLetters = true;
}
}
else {
int keyword = toUnicode(keywords[0]);
rangeLow = keyword;
rangeHigh = keyword;
}
}
private int toUnicode(@NotNull String str) {
if (NumberUtils.isNumber(str)) {
return Integer.parseInt(str); // If we have a number, it represents the Unicode code point of a letter
}
else {
return str.charAt(0); // If it's not a number we should only have strings consisting of one char
}
}
@Override
public boolean equals(@Nullable Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
KeywordSpec that = (KeywordSpec)o;
return part.equals(that.part);
}
@Override
public int hashCode() {
return part.hashCode();
}
public boolean isValid() {
initializeValues();
return (!isRange || isAllLetters) || (rangeLow <= rangeHigh);
}
public boolean negate() {
initializeValues();
return negate;
}
public boolean contains(int code) {
initializeValues();
if (isAllLetters) {
return Character.isLetter(code);
}
if (isRange) {
return (code >= rangeLow && code <= rangeHigh);
}
return code == rangeLow;
}
}
}

View File

@ -1,305 +0,0 @@
/*
* IdeaVim - Vim emulator for IDEs based on the IntelliJ platform
* Copyright (C) 2003-2022 The IdeaVim authors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.maddyhome.idea.vim.option;
import com.intellij.openapi.diagnostic.Logger;
import com.maddyhome.idea.vim.VimPlugin;
import com.maddyhome.idea.vim.ex.ExException;
import com.maddyhome.idea.vim.helper.VimNlsSafe;
import com.maddyhome.idea.vim.vimscript.model.commands.SetCommand;
import com.maddyhome.idea.vim.vimscript.model.datatypes.VimString;
import com.maddyhome.idea.vim.options.OptionScope;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.StringTokenizer;
/**
* This is an option that accepts an arbitrary list of values
* @deprecated use {@link com.maddyhome.idea.vim.vimscript.model.options.Option} instead
*/
@Deprecated
@ApiStatus.ScheduledForRemoval(inVersion = "1.11")
public abstract class ListOption<T> extends TextOption {
private static final Logger logger = Logger.getInstance(ListOption.class.getName());
protected final @NotNull List<T> defaultValues;
protected @NotNull List<T> value;
/**
* Creates the option
*
* @param name The name of the option
* @param abbrev The short name
* @param defaultValues The option's default values
*/
public ListOption(String name, String abbrev, @VimNlsSafe T[] defaultValues) {
super(name, abbrev);
this.defaultValues = new ArrayList<>(Arrays.asList(defaultValues));
this.value = new ArrayList<>(this.defaultValues);
}
public ListOption(String name, String abbrev, String defaultValue) throws ExException {
super(name, abbrev);
final List<T> defaultValues = parseVals(defaultValue);
this.defaultValues = defaultValues != null ? new ArrayList<>(defaultValues) : new ArrayList<>();
this.value = new ArrayList<>(this.defaultValues);
}
/**
* Gets the value of the option as a comma separated list of values
*
* @return The option's value
*/
@Override
public @NotNull String getValue() {
StringBuilder res = new StringBuilder();
int cnt = 0;
for (T s : value) {
if (cnt > 0) {
res.append(",");
}
res.append(s);
cnt++;
}
return res.toString();
}
/**
* Gets the option's values as a list
*
* @return The option's values
*/
public @NotNull List<T> values() {
return value;
}
/**
* Determines if this option has all the values listed on the supplied value
*
* @param val A comma separated list of values to look for
* @return True if all the supplied values are set in this option, false if not
*/
public boolean contains(@NonNls String val) {
final List<T> vals;
try {
vals = parseVals(val);
}
catch (ExException e) {
logger.warn("Error parsing option", e);
return false;
}
return vals != null && value.containsAll(vals);
}
/**
* Sets this option to contain just the supplied values. If any of the supplied values are invalid then this
* option is not updated at all.
*
* @param val A comma separated list of values
* @return True if all the supplied values were correct, false if not
*/
@Override
public boolean set(String val) throws ExException {
return set(parseVals(val));
}
/**
* Adds the supplied values to the current list of values. If any of the supplied values are invalid then this
* option is not updated at all.
*
* @param val A comma separated list of values
* @return True if all the supplied values were correct, false if not
*/
@Override
public boolean append(String val) throws ExException {
return append(parseVals(val));
}
/**
* Adds the supplied values to the start of the current list of values. If any of the supplied values are invalid
* then this option is not updated at all.
*
* @param val A comma separated list of values
* @return True if all the supplied values were correct, false if not
*/
@Override
public boolean prepend(String val) throws ExException {
return prepend(parseVals(val));
}
/**
* Removes the supplied values from the current list of values. If any of the supplied values are invalid then this
* option is not updated at all.
*
* @param val A comma separated list of values
* @return True if all the supplied values were correct, false if not
*/
@Override
public boolean remove(String val) throws ExException {
return remove(parseVals(val));
}
protected boolean set(@Nullable List<T> vals) {
if (vals == null) {
return false;
}
String oldValue = getValue();
this.value = vals;
onChanged(oldValue, getValue());
// we won't use OptionService if the method was invoked during set command execution (set command will call OptionService by itself)
if (!SetCommand.Companion.isExecutingCommand()) {
try {
String joinedValue = getValue();
if (!((VimString)VimPlugin.getOptionService().getOptionValue(OptionScope.GLOBAL.INSTANCE, name, name)).getValue().equals(joinedValue)) {
VimPlugin.getOptionService().setOptionValue(OptionScope.GLOBAL.INSTANCE, name, new VimString(joinedValue), name);
}
}
catch (Exception e) {
}
}
return true;
}
protected boolean append(@Nullable List<T> vals) {
if (vals == null) {
return false;
}
String oldValue = getValue();
value.removeAll(vals);
value.addAll(vals);
onChanged(oldValue, getValue());
try {
String joinedValue = getValue();
if (!((VimString)VimPlugin.getOptionService()
.getOptionValue(OptionScope.GLOBAL.INSTANCE, name, name)).getValue().equals(joinedValue)) {
VimPlugin.getOptionService().setOptionValue(OptionScope.GLOBAL.INSTANCE, name, new VimString(joinedValue), name);
}
} catch (Exception e) {}
return true;
}
protected boolean prepend(@Nullable List<T> vals) {
if (vals == null) {
return false;
}
String oldValue = getValue();
value.removeAll(vals);
value.addAll(0, vals);
onChanged(oldValue, getValue());
try {
String joinedValue = getValue();
if (!((VimString)VimPlugin.getOptionService()
.getOptionValue(OptionScope.GLOBAL.INSTANCE, name, name)).getValue().equals(joinedValue)) {
VimPlugin.getOptionService().setOptionValue(OptionScope.GLOBAL.INSTANCE, name, new VimString(joinedValue), name);
}
} catch (Exception e) {}
return true;
}
protected boolean remove(@Nullable List<T> vals) {
if (vals == null) {
return false;
}
String oldValue = getValue();
value.removeAll(vals);
onChanged(oldValue, getValue());
try {
String joinedValue = getValue();
if (!((VimString)VimPlugin.getOptionService()
.getOptionValue(OptionScope.GLOBAL.INSTANCE, name, name)).getValue().equals(joinedValue)) {
VimPlugin.getOptionService().setOptionValue(OptionScope.GLOBAL.INSTANCE, name, new VimString(joinedValue), name);
}
} catch (Exception e) {}
return true;
}
/**
* Checks to see if the current value of the option matches the default value
*
* @return True if equal to default, false if not
*/
@Override
public boolean isDefault() {
return defaultValues.equals(value);
}
protected @Nullable List<T> parseVals(String val) throws ExException {
List<T> res = new ArrayList<>();
StringTokenizer tokenizer = new StringTokenizer(val, ",");
while (tokenizer.hasMoreTokens()) {
String token = tokenizer.nextToken().trim();
T item = convertToken(token);
if (item != null) {
res.add(item);
}
else {
return null;
}
}
return res;
}
protected abstract @Nullable T convertToken(@NotNull String token) throws ExException;
/**
* Gets the string representation appropriate for output to :set all
*
* @return The option as a string {name}={value list}
*/
public @NotNull String toString() {
return " " + getName() + "=" + getValue();
}
/**
* Resets the option to its default value
*/
@Override
public void resetDefault() {
if (!defaultValues.equals(value)) {
String oldValue = getValue();
value = new ArrayList<>(defaultValues);
onChanged(oldValue, getValue());
try {
String joinedValue = getValue();
if (!((VimString)VimPlugin.getOptionService()
.getOptionValue(OptionScope.GLOBAL.INSTANCE, name, name)).getValue().equals(joinedValue)) {
VimPlugin.getOptionService().setOptionValue(OptionScope.GLOBAL.INSTANCE, name, new VimString(joinedValue), name);
}
} catch (Exception e) {}
}
}
}

View File

@ -1,287 +0,0 @@
/*
* IdeaVim - Vim emulator for IDEs based on the IntelliJ platform
* Copyright (C) 2003-2022 The IdeaVim authors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.maddyhome.idea.vim.option;
import com.maddyhome.idea.vim.VimPlugin;
import com.maddyhome.idea.vim.helper.VimNlsSafe;
import com.maddyhome.idea.vim.vimscript.model.commands.SetCommand;
import com.maddyhome.idea.vim.vimscript.model.datatypes.VimInt;
import com.maddyhome.idea.vim.options.OptionScope;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* Represents an option with a numeric value
* @deprecated use {@link com.maddyhome.idea.vim.vimscript.model.options.Option} instead
*/
@Deprecated
@ApiStatus.ScheduledForRemoval(inVersion = "1.11")
public class NumberOption extends TextOption {
private final int dflt;
private final int min;
private final int max;
private int value;
/**
* Creates a number option that must contain a zero or positive value
*
* @param name The name of the option
* @param abbrev The short name
* @param dflt The default value
*/
NumberOption(@NonNls String name, @NonNls String abbrev, int dflt) {
this(name, abbrev, dflt, 0, Integer.MAX_VALUE);
}
/**
* Creates a number option
*
* @param name The name of the option
* @param abbrev The short name
* @param dflt The default value
* @param min The option's minimum value
* @param max The option's maximum value
*/
@SuppressWarnings("SameParameterValue")
NumberOption(@VimNlsSafe String name, @VimNlsSafe String abbrev, int dflt, int min, int max) {
super(name, abbrev);
this.dflt = dflt;
this.value = dflt;
this.min = min;
this.max = max;
}
/**
* Gets the option's value as a string
*
* @return The option's value
*/
@Override
public String getValue() {
return Integer.toString(value);
}
/**
* Gets the option's value as an int
*
* @return The option's value
*/
public int value() {
return value;
}
/**
* Sets the option's value if the value is in the proper range
*
* @param val The new value
* @return True if the set, false if new value is invalid
*/
public boolean set(int val) {
return set(Integer.toString(val));
}
/**
* Sets the option's value after parsing the string into a number. The supplied value can be in decimal,
* hex, or octal formats. Octal numbers must be preceded with a zero and all digits must be 0 - 7. Hex values
* must start with 0x or 0X and all digits must be 0 - 9, a - F, or A - F. All others will be tried as a decimal
* number.
*
* @param val The new value
* @return True if the string can be converted to a number and it is in range. False if not.
*/
@Override
public boolean set(String val) {
Integer num = asNumber(val);
if (num == null) {
return false;
}
if (inRange(num)) {
String oldValue = getValue();
this.value = num;
onChanged(oldValue, getValue());
// we won't use OptionService if the method was invoked during set command execution (set command will call OptionService by itself)
if (!SetCommand.Companion.isExecutingCommand()) {
try {
if (!(((VimInt)VimPlugin.getOptionService().getOptionValue(OptionScope.GLOBAL.INSTANCE, name, name)).getValue() == value)) {
VimPlugin.getOptionService().setOptionValue(OptionScope.GLOBAL.INSTANCE, name, new VimInt(value), name);
}
}
catch (Exception e) {
}
}
return true;
}
return false;
}
/**
* Adds the value to the option's value after parsing the string into a number. The supplied value can be in decimal,
* hex, or octal formats. Octal numbers must be preceded with a zero and all digits must be 0 - 7. Hex values
* must start with 0x or 0X and all digits must be 0 - 9, a - F, or A - F. All others will be tried as a decimal
* number.
*
* @param val The new value
* @return True if the string can be converted to a number and the result is in range. False if not.
*/
@Override
public boolean append(String val) {
Integer num = asNumber(val);
if (num == null) {
return false;
}
if (inRange(value + num)) {
String oldValue = getValue();
value += num;
onChanged(oldValue, getValue());
try {
if (!(((VimInt)VimPlugin.getOptionService()
.getOptionValue(OptionScope.GLOBAL.INSTANCE, name, name)).getValue() == value)) {
VimPlugin.getOptionService().setOptionValue(OptionScope.GLOBAL.INSTANCE, name, new VimInt(value), name);
}
} catch (Exception e) {}
return true;
}
return false;
}
/**
* Multiplies the value by the option's value after parsing the string into a number. The supplied value can be in
* decimal, hex, or octal formats. Octal numbers must be preceded with a zero and all digits must be 0 - 7. Hex
* values must start with 0x or 0X and all digits must be 0 - 9, a - F, or A - F. All others will be tried as a
* decimal number.
*
* @param val The new value
* @return True if the string can be converted to a number and the result is in range. False if not.
*/
@Override
public boolean prepend(String val) {
Integer num = asNumber(val);
if (num == null) {
return false;
}
if (inRange(value * num)) {
String oldValue = getValue();
value *= num;
onChanged(oldValue, getValue());
try {
if (!(((VimInt)VimPlugin.getOptionService()
.getOptionValue(OptionScope.GLOBAL.INSTANCE, name, name)).getValue() == value)) {
VimPlugin.getOptionService().setOptionValue(OptionScope.GLOBAL.INSTANCE, name, new VimInt(value), name);
}
} catch (Exception e) {}
return true;
}
return false;
}
/**
* Substracts the value from the option's value after parsing the string into a number. The supplied value can be in
* decimal, hex, or octal formats. Octal numbers must be preceded with a zero and all digits must be 0 - 7. Hex
* values must start with 0x or 0X and all digits must be 0 - 9, a - F, or A - F. All others will be tried as a
* decimal number.
*
* @param val The new value
* @return True if the string can be converted to a number and the result is in range. False if not.
*/
@Override
public boolean remove(String val) {
Integer num = asNumber(val);
if (num == null) {
return false;
}
if (inRange(value - num)) {
String oldValue = getValue();
value -= num;
onChanged(oldValue, getValue());
try {
if (!(((VimInt)VimPlugin.getOptionService()
.getOptionValue(OptionScope.GLOBAL.INSTANCE, name, name)).getValue() == value)) {
VimPlugin.getOptionService().setOptionValue(OptionScope.GLOBAL.INSTANCE, name, new VimInt(value), name);
}
} catch (Exception e) {}
return true;
}
return false;
}
/**
* Checks to see if the option's current value equals the default value
*
* @return True if equal to default, false if not.
*/
@Override
public boolean isDefault() {
return value == dflt;
}
/**
* Sets the option to its default value.
*/
@Override
public void resetDefault() {
if (dflt != value) {
String oldValue = getValue();
value = dflt;
onChanged(oldValue, getValue());
}
try {
if (!(((VimInt)VimPlugin.getOptionService()
.getOptionValue(OptionScope.GLOBAL.INSTANCE, name, name)).getValue() == value)) {
VimPlugin.getOptionService().setOptionValue(OptionScope.GLOBAL.INSTANCE, name, new VimInt(value), name);
}
} catch (Exception e) {}
}
protected @Nullable Integer asNumber(String val) {
try {
return Integer.decode(val);
}
catch (NumberFormatException e) {
return null;
}
}
protected boolean inRange(int val) {
return (val >= min && val <= max);
}
/**
* {name}={value}
*
* @return The option as a string
*/
public @NotNull String toString() {
return " " + getName() + "=" + value;
}
}

View File

@ -1,125 +0,0 @@
/*
* IdeaVim - Vim emulator for IDEs based on the IntelliJ platform
* Copyright (C) 2003-2022 The IdeaVim authors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.maddyhome.idea.vim.option;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import java.util.List;
/**
* Represents an VIM options that can be set with the :set command. Listeners can be set that are interested in knowing
* when the value of the option changes.
* @deprecated use {@link com.maddyhome.idea.vim.vimscript.model.options.Option} instead
*/
@Deprecated
@ApiStatus.ScheduledForRemoval(inVersion = "1.11")
public abstract class Option<T> {
protected final String name;
protected final String abbrev;
private final @NotNull List<OptionChangeListener<T>> listeners = ContainerUtil.createLockFreeCopyOnWriteList();
/**
* Create the option
*
* @param name The name of the option
* @param abbrev The short name
*/
protected Option(String name, String abbrev) {
this.name = name;
this.abbrev = abbrev;
}
/**
* Registers an option change listener. The listener will receive an OptionChangeEvent whenever the value of this
* option changes.
*
* @param listener The listener
*/
public void addOptionChangeListener(OptionChangeListener<T> listener) {
listeners.add(listener);
}
/**
* Registers an option change listener and fire an event.
*
* @param listener The listener
*/
public void addOptionChangeListenerAndExecute(OptionChangeListener<T> listener) {
addOptionChangeListener(listener);
T value = getValue();
onChanged(value, value);
}
/**
* Removes the listener from the list.
*
* @param listener The listener
*/
public void removeOptionChangeListener(OptionChangeListener<T> listener) {
listeners.remove(listener);
}
/**
* The name of the option
*
* @return The option's name
*/
public String getName() {
return name;
}
/**
* The short name of the option
*
* @return The option's short name
*/
public String getAbbreviation() {
return abbrev;
}
/**
* Checks to see if the option's current value equals the default value
*
* @return True if equal to default, false if not.
*/
public abstract boolean isDefault();
/**
* Sets the option to its default value.
*/
public abstract void resetDefault();
/**
* Lets all listeners know that the value has changed. Subclasses are responsible for calling this when their
* value changes.
*/
protected void onChanged(T oldValue, T newValue) {
fireOptionChangeEvent(oldValue, newValue);
}
private void fireOptionChangeEvent(T oldValue, T newValue) {
for (OptionChangeListener<T> listener : listeners) {
listener.valueChange(oldValue, newValue);
}
}
public abstract T getValue();
}

View File

@ -1,30 +0,0 @@
/*
* IdeaVim - Vim emulator for IDEs based on the IntelliJ platform
* Copyright (C) 2003-2022 The IdeaVim authors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.maddyhome.idea.vim.option;
import org.jetbrains.annotations.ApiStatus;
/**
* This interface is used for classes that wish to be notified whenever the value of an option has changed
* @deprecated use {@link com.maddyhome.idea.vim.options.OptionChangeListener} instead
*/
@Deprecated
@ApiStatus.ScheduledForRemoval(inVersion = "1.11")
public interface OptionChangeListener<T> {
void valueChange(T oldValue, T newValue);
}

View File

@ -1,743 +0,0 @@
/*
* IdeaVim - Vim emulator for IDEs based on the IntelliJ platform
* Copyright (C) 2003-2022 The IdeaVim authors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.maddyhome.idea.vim.option
import com.intellij.codeInsight.lookup.LookupEvent
import com.intellij.codeInsight.lookup.LookupListener
import com.intellij.codeInsight.lookup.LookupManager
import com.intellij.codeInsight.lookup.impl.LookupImpl
import com.intellij.codeInsight.template.impl.TemplateManagerImpl
import com.intellij.openapi.application.ApplicationNamesInfo
import com.intellij.openapi.diagnostic.Logger
import com.intellij.openapi.diagnostic.debug
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.util.SystemInfo
import com.maddyhome.idea.vim.VimPlugin
import com.maddyhome.idea.vim.ex.ExException
import com.maddyhome.idea.vim.ex.ExOutputModel
import com.maddyhome.idea.vim.helper.EditorHelper
import com.maddyhome.idea.vim.helper.MessageHelper
import com.maddyhome.idea.vim.helper.Msg
import com.maddyhome.idea.vim.helper.hasBlockOrUnderscoreCaret
import com.maddyhome.idea.vim.helper.hasVisualSelection
import com.maddyhome.idea.vim.helper.mode
import com.maddyhome.idea.vim.helper.subMode
import com.maddyhome.idea.vim.listener.SelectionVimListenerSuppressor
import com.maddyhome.idea.vim.options.OptionScope
import com.maddyhome.idea.vim.vimscript.model.datatypes.VimString
import org.jetbrains.annotations.ApiStatus.ScheduledForRemoval
import org.jetbrains.annotations.Contract
import org.jetbrains.annotations.NonNls
import java.util.*
import kotlin.math.ceil
import kotlin.math.min
/**
* @deprecated use {@link com.maddyhome.idea.vim.options.OptionService} instead
* (VimPlugin.getOptionService())
*/
@Deprecated("was replaced by OptionService")
@ScheduledForRemoval(inVersion = "1.11")
@Suppress("unused", "DEPRECATION")
object OptionsManager {
private val logger = Logger.getInstance(OptionsManager::class.java)
private val options: MutableMap<String, Option<*>> = mutableMapOf()
private val abbrevs: MutableMap<String, Option<*>> = mutableMapOf()
val clipboard = addOption(StringListOption(ClipboardOptionsData.name, ClipboardOptionsData.abbr, arrayOf(ClipboardOptionsData.ideaput, "autoselect,exclude:cons\\|linux")))
val digraph = addOption(ToggleOption("digraph", "dg", false))
val gdefault = addOption(ToggleOption("gdefault", "gd", false))
val guicursor = addOption(GuiCursorOptionData.option)
val history = addOption(NumberOption("history", "hi", 50, 1, Int.MAX_VALUE))
val hlsearch = addOption(ToggleOption("hlsearch", "hls", false))
val ideamarks = addOption(IdeaMarksOptionsData.option)
val ignorecase = addOption(ToggleOption(IgnoreCaseOptionsData.name, IgnoreCaseOptionsData.abbr, false))
val incsearch = addOption(ToggleOption("incsearch", "is", false))
val iskeyword = addOption(KeywordOption("iskeyword", "isk", arrayOf("@", "48-57", "_")))
val keymodel = addOption(KeyModelOptionData.option)
val lookupKeys = addOption(StringListOption(LookupKeysData.name, LookupKeysData.name, LookupKeysData.defaultValues))
val matchpairs = addOption(StringListOption("matchpairs", "mps", arrayOf("(:)", "{:}", "[:]"), ".:."))
val more = addOption(ToggleOption("more", "more", true))
val nrformats = addOption(BoundedStringListOption("nrformats", "nf", arrayOf("hex"), arrayOf("octal", "hex", "alpha"))) // Octal is disabled as in neovim
val number = addOption(ToggleOption("number", "nu", false))
val relativenumber = addOption(ToggleOption("relativenumber", "rnu", false))
val scroll = addOption(NumberOption("scroll", "scr", 0))
val scrolljump = addOption(NumberOption(ScrollJumpData.name, "sj", 1, -100, Integer.MAX_VALUE))
val scrolloff = addOption(NumberOption(ScrollOffData.name, "so", 0))
val selection = addOption(BoundedStringOption("selection", "sel", "inclusive", arrayOf("old", "inclusive", "exclusive")))
val selectmode = addOption(SelectModeOptionData.option)
val shell = addOption(ShellOptionData.option)
val shellcmdflag = addOption(ShellCmdFlagOptionData.option)
val shellxescape = addOption(ShellXEscapeOptionData.option)
val shellxquote = addOption(ShellXQuoteOptionData.option)
val showcmd = addOption(ToggleOption("showcmd", "sc", true)) // Vim: Off by default on platforms with possibly slow tty. On by default elsewhere.
val showmode = addOption(ToggleOption("showmode", "smd", false))
val sidescroll = addOption(NumberOption("sidescroll", "ss", 0))
val sidescrolloff = addOption(NumberOption("sidescrolloff", "siso", 0))
val smartcase = addOption(ToggleOption(SmartCaseOptionsData.name, SmartCaseOptionsData.abbr, false))
val startofline = addOption(ToggleOption("startofline", "sol", true))
val ideajoin = addOption(IdeaJoinOptionsData.option)
val timeout = addOption(ToggleOption("timeout", "to", true))
val timeoutlen = addOption(NumberOption("timeoutlen", "tm", 1000, -1, Int.MAX_VALUE))
val undolevels = addOption(NumberOption("undolevels", "ul", 1000, -1, Int.MAX_VALUE))
val viminfo = addOption(StringListOption("viminfo", "vi", arrayOf("'100", "<50", "s10", "h")))
val virtualedit = addOption(BoundedStringOption(VirtualEditData.name, "ve", "", VirtualEditData.allValues))
val visualbell = addOption(ToggleOption("visualbell", "vb", false))
val wrapscan = addOption(ToggleOption("wrapscan", "ws", true))
val visualEnterDelay = addOption(NumberOption("visualdelay", "visualdelay", 100, 0, Int.MAX_VALUE))
val idearefactormode = addOption(BoundedStringOption(IdeaRefactorMode.name, IdeaRefactorMode.name, IdeaRefactorMode.select, IdeaRefactorMode.availableValues))
val ideastatusicon = addOption(BoundedStringOption(IdeaStatusIcon.name, IdeaStatusIcon.name, IdeaStatusIcon.enabled, IdeaStatusIcon.allValues))
val ideastrictmode = addOption(ToggleOption("ideastrictmode", "ideastrictmode", false))
val ideawrite = addOption(BoundedStringOption("ideawrite", "ideawrite", IdeaWriteData.all, IdeaWriteData.allValues))
val ideavimsupport = addOption(BoundedStringListOption("ideavimsupport", "ideavimsupport", arrayOf("dialog"), arrayOf("dialog", "singleline", "dialoglegacy")))
val ide = addOption(StringOption("ide", "ide", ApplicationNamesInfo.getInstance().fullProductNameWithEdition))
// TODO The default value if 1000, but we can't increase it because of terrible performance of our mappings
val maxmapdepth = addOption(NumberOption("maxmapdepth", "mmd", 20))
// This should be removed in the next versions
val ideacopypreprocess = addOption(ToggleOption("ideacopypreprocess", "ideacopypreprocess", false))
val ideatracetime = addOption(ToggleOption("ideatracetime", "ideatracetime", false))
fun completeInitialisation() {
// These options have default values that are based on the contents of 'shell', which can be set in .ideavimrc
ShellCmdFlagOptionData.updateDefaultValue(shell)
ShellXQuoteOptionData.updateDefaultValue(shell)
}
fun isSet(name: String): Boolean {
val option = getOption(name)
return option is ToggleOption && option.getValue()
}
fun getStringListOption(name: String): StringListOption? = getOption(name) as? StringListOption
fun resetAllOptions() = options.values.forEach { it.resetDefault() }
/**
* Gets an option by the supplied name or short name.
*/
fun getOption(name: String): Option<*>? = options[name] ?: abbrevs[name]
/**
* This parses a set of :set commands. The following types of commands are supported:
*
* * :set - show all changed options
* * :set all - show all options
* * :set all& - reset all options to default values
* * :set {option} - set option of boolean, display others
* * :set {option}? - display option
* * :set no{option} - reset boolean option
* * :set inv{option} - toggle boolean option
* * :set {option}! - toggle boolean option
* * :set {option}& - set option to default
* * :set {option}={value} - set option to new value
* * :set {option}:{value} - set option to new value
* * :set {option}+={value} - append or add to option value
* * :set {option}-={value} - remove or subtract from option value
* * :set {option}^={value} - prepend or multiply option value
*
*
* @param editor The editor the command was entered for, null if no editor - reading .ideavimrc
* @param args The :set command arguments
* @param failOnBad True if processing should stop when a bad argument is found, false if a bad argument is simply
* skipped and processing continues.
* @return True if no errors were found, false if there were any errors
*/
fun parseOptionLine(editor: Editor?, args: String, failOnBad: Boolean): Boolean {
// No arguments so we show changed values
when {
args.isEmpty() -> {
// Show changed options
showOptions(editor, options.values.filter { !it.isDefault }, true)
return true
}
args == "all" -> {
showOptions(editor, options.values, true)
return true
}
args == "all&" -> {
resetAllOptions()
return true
}
}
// We now have 1 or more option operators separator by spaces
var error: String? = null
var token = ""
val tokenizer = StringTokenizer(args)
val toShow = mutableListOf<Option<*>>()
while (tokenizer.hasMoreTokens()) {
token = tokenizer.nextToken()
// See if a space has been backslashed, if no get the rest of the text
while (token.endsWith("\\")) {
token = token.substring(0, token.length - 1) + ' '
if (tokenizer.hasMoreTokens()) {
token += tokenizer.nextToken()
}
}
// Print the value of an option
if (token.endsWith("?")) {
val option = token.dropLast(1)
val opt = getOption(option)
if (opt != null) {
toShow.add(opt)
} else {
error = Msg.unkopt
}
} else if (token.startsWith("no")) {
// Reset a boolean option
val option = token.substring(2)
val opt = getOption(option)
if (opt != null) {
if (opt is ToggleOption) {
opt.reset()
} else {
error = Msg.e_invarg
}
} else {
error = Msg.unkopt
}
} else if (token.startsWith("inv")) {
// Toggle a boolean option
val option = token.substring(3)
val opt = getOption(option)
if (opt != null) {
if (opt is ToggleOption) {
opt.toggle()
} else {
error = Msg.e_invarg
}
} else {
error = Msg.unkopt
}
} else if (token.endsWith("!")) {
// Toggle a boolean option
val option = token.dropLast(1)
val opt = getOption(option)
if (opt != null) {
if (opt is ToggleOption) {
opt.toggle()
} else {
error = Msg.e_invarg
}
} else {
error = Msg.unkopt
}
} else if (token.endsWith("&")) {
// Reset option to default
val option = token.dropLast(1)
val opt = getOption(option)
if (opt != null) {
opt.resetDefault()
} else {
error = Msg.unkopt
}
} else {
// This must be one of =, :, +=, -=, or ^=
// Look for the = or : first
var eq = token.indexOf('=')
if (eq == -1) {
eq = token.indexOf(':')
}
// No operator so only the option name was given
if (eq == -1) {
val opt = getOption(token)
if (opt != null) {
// Valid option so set booleans or display others
(opt as? ToggleOption)?.set() ?: toShow.add(opt)
} else {
error = Msg.unkopt
}
} else {
// Make sure there is an option name
if (eq > 0) {
// See if an operator before the equal sign
val op = token[eq - 1]
var end = eq
if (op in "+-^") {
end--
}
// Get option name and value after operator
val option = token.take(end)
val value = token.substring(eq + 1)
val opt = getOption(option)
if (opt != null) {
// If not a boolean
if (opt is TextOption) {
try {
val res = when (op) {
'+' -> opt.append(value)
'-' -> opt.remove(value)
'^' -> opt.prepend(value)
else -> opt.set(value)
}
if (!res) {
error = Msg.e_invarg
}
} catch (e: ExException) {
// Retrieve the message code, if possible and throw again with the entire set arg string. This assumes
// that any thrown exception has a message code that accepts a single parameter
error = e.code ?: Msg.e_invarg
}
} else {
error = Msg.e_invarg
} // boolean option - no good
} else {
error = Msg.unkopt
}
} else {
error = Msg.unkopt
}
}
}
if (failOnBad && error != null) {
break
}
}
// Now show all options that were individually requested
if (toShow.size > 0) {
showOptions(editor, toShow, false)
}
if (editor != null && error != null) {
throw ExException(MessageHelper.message(error, token))
}
return error == null
}
/**
* Shows the set of options
*
* @param editor The editor to show them in - if null, this is aborted
* @param opts The list of options to display
* @param showIntro True if intro is displayed, false if not
*/
private fun showOptions(editor: Editor?, opts: Collection<Option<*>>, showIntro: Boolean) {
if (editor == null) return
val cols = mutableListOf<Option<*>>()
val extra = mutableListOf<Option<*>>()
for (option in opts) {
if (option.toString().length > 19) extra.add(option) else cols.add(option)
}
cols.sortBy { it.name }
extra.sortBy { it.name }
var width = EditorHelper.getApproximateScreenWidth(editor)
if (width < 20) {
width = 80
}
val colCount = width / 20
val height = ceil(cols.size.toDouble() / colCount.toDouble()).toInt()
var empty = cols.size % colCount
empty = if (empty == 0) colCount else empty
logger.debug { "showOptions, width=$width, colCount=$colCount, height=$height" }
val res = StringBuilder()
if (showIntro) {
res.append("--- Options ---\n")
}
for (h in 0 until height) {
for (c in 0 until colCount) {
if (h == height - 1 && c >= empty) {
break
}
var pos = c * height + h
if (c > empty) {
pos -= c - empty
}
val opt = cols[pos]
res.append(opt.toString().padEnd(20))
}
res.append("\n")
}
for (opt in extra) {
val value = opt.toString()
val seg = (value.length - 1) / width
for (j in 0..seg) {
res.append(value, j * width, min(j * width + width, value.length))
res.append("\n")
}
}
ExOutputModel.getInstance(editor).output(res.toString())
}
@Contract("_ -> param1")
fun <T : Option<*>> addOption(option: T): T {
options += option.name to option
abbrevs += option.abbrev to option
return option
}
fun removeOption(name: String) {
options.remove(name)
abbrevs.values.find { it.name == name }?.let { option -> abbrevs.remove(option.abbrev) }
}
}
@NonNls
@Deprecated("was replaced by OptionService")
@ScheduledForRemoval(inVersion = "1.11")
object KeyModelOptionData {
const val name = "keymodel"
private const val abbr = "km"
const val startsel = "startsel"
const val stopsel = "stopsel"
const val stopselect = "stopselect"
const val stopvisual = "stopvisual"
const val continueselect = "continueselect"
const val continuevisual = "continuevisual"
val options = arrayOf(startsel, stopsel, stopselect, stopvisual, continueselect, continuevisual)
val default = arrayOf(continueselect, stopselect)
val option = BoundedStringListOption(name, abbr, default, options)
}
@NonNls
@Deprecated("was replaced by OptionService")
@ScheduledForRemoval(inVersion = "1.11")
object SelectModeOptionData {
const val name = "selectmode"
private const val abbr = "slm"
const val mouse = "mouse"
const val key = "key"
const val cmd = "cmd"
const val ideaselection = "ideaselection"
@Suppress("DEPRECATION")
val options = arrayOf(mouse, key, cmd, ideaselection)
val default = emptyArray<String>()
val option = BoundedStringListOption(name, abbr, default, options)
fun ideaselectionEnabled(): Boolean {
return ideaselection in (VimPlugin.getOptionService().getOptionValue(OptionScope.GLOBAL, "selectmode") as VimString).value
}
}
@NonNls
@Deprecated("was replaced by OptionService")
@ScheduledForRemoval(inVersion = "1.11")
object ClipboardOptionsData {
const val name = "clipboard"
const val abbr = "cb"
const val ideaput = "ideaput"
const val unnamed = "unnamed"
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
init {
val optionValue = (VimPlugin.getOptionService().getOptionValue(OptionScope.GLOBAL, "clipboard") as VimString).value
containedBefore = optionValue.contains(ideaput)
VimPlugin.getOptionService().removeValue(OptionScope.GLOBAL, "clipboard", ideaput, "clipboard")
ideaputDisabled = true
}
override fun close() {
if (containedBefore) VimPlugin.getOptionService().appendValue(OptionScope.GLOBAL, "clipboard", ideaput, "clipboard")
ideaputDisabled = false
}
}
}
@Suppress("SpellCheckingInspection")
@NonNls
@Deprecated("was replaced by OptionService")
@ScheduledForRemoval(inVersion = "1.11")
object GuiCursorOptionData {
const val name = "guicursor"
private const val abbr = "gcr"
const val defaultValue = "n-v-c:block-Cursor/lCursor," +
"ve:ver35-Cursor," +
"o:hor50-Cursor," +
"i-ci:ver25-Cursor/lCursor," +
"r-cr:hor20-Cursor/lCursor," +
"sm:block-Cursor-blinkwait175-blinkoff150-blinkon175"
val option = GuiCursorOption(name, abbr, defaultValue)
}
@NonNls
@Deprecated("was replaced by OptionService")
@ScheduledForRemoval(inVersion = "1.11")
object IdeaJoinOptionsData {
const val name = "ideajoin"
private const val defaultValue = false
val option = ToggleOption(name, name, defaultValue)
}
@NonNls
@Deprecated("was replaced by OptionService")
@ScheduledForRemoval(inVersion = "1.11")
object IdeaMarksOptionsData {
const val name = "ideamarks"
private const val defaultValue = true
val option = ToggleOption(name, name, defaultValue)
}
@NonNls
@Deprecated("was replaced by OptionService")
@ScheduledForRemoval(inVersion = "1.11")
object SmartCaseOptionsData {
const val name = "smartcase"
const val abbr = "scs"
}
@NonNls
@Deprecated("was replaced by OptionService")
@ScheduledForRemoval(inVersion = "1.11")
object IgnoreCaseOptionsData {
const val name = "ignorecase"
const val abbr = "ic"
}
@NonNls
@Deprecated("was replaced by OptionService")
@ScheduledForRemoval(inVersion = "1.11")
object IdeaRefactorMode {
const val name = "idearefactormode"
const val keep = "keep"
const val select = "select"
const val visual = "visual"
val availableValues = arrayOf(keep, select, visual)
fun keepMode(): Boolean = (VimPlugin.getOptionService().getOptionValue(OptionScope.GLOBAL, "idearefactormode") as VimString).value == keep
fun selectMode(): Boolean = (VimPlugin.getOptionService().getOptionValue(OptionScope.GLOBAL, "idearefactormode") as VimString).value == select
fun correctSelection(editor: Editor) {
val action: () -> Unit = {
if (!editor.mode.hasVisualSelection && editor.selectionModel.hasSelection()) {
SelectionVimListenerSuppressor.lock().use {
editor.selectionModel.removeSelection()
}
}
if (editor.mode.hasVisualSelection && editor.selectionModel.hasSelection()) {
val autodetectedSubmode = VimPlugin.getVisualMotion().autodetectVisualSubmode(editor)
if (editor.subMode != autodetectedSubmode) {
// Update the submode
editor.subMode = autodetectedSubmode
}
}
if (editor.hasBlockOrUnderscoreCaret()) {
TemplateManagerImpl.getTemplateState(editor)?.currentVariableRange?.let { segmentRange ->
if (!segmentRange.isEmpty && segmentRange.endOffset == editor.caretModel.offset && editor.caretModel.offset != 0) {
editor.caretModel.moveToOffset(editor.caretModel.offset - 1)
}
}
}
}
val lookup = LookupManager.getActiveLookup(editor) as? LookupImpl
if (lookup != null) {
val selStart = editor.selectionModel.selectionStart
val selEnd = editor.selectionModel.selectionEnd
lookup.performGuardedChange(action)
lookup.addLookupListener(object : LookupListener {
override fun beforeItemSelected(event: LookupEvent): Boolean {
// FIXME: 01.11.2019 Nasty workaround because of problems in IJ platform
// Lookup replaces selected text and not the template itself. So, if there is no selection
// in the template, lookup value will not replace the template, but just insert value on the caret position
lookup.performGuardedChange { editor.selectionModel.setSelection(selStart, selEnd) }
lookup.removeLookupListener(this)
return true
}
})
} else {
action()
}
}
}
@NonNls
@Deprecated("was replaced by OptionService")
@ScheduledForRemoval(inVersion = "1.11")
object LookupKeysData {
const val name = "lookupkeys"
val defaultValues = arrayOf(
"<Tab>", "<Down>", "<Up>", "<Enter>", "<Left>", "<Right>",
"<C-Down>", "<C-Up>",
"<PageUp>", "<PageDown>",
// New line in vim, but QuickDoc on macOS
"<C-J>",
// QuickDoc for non-mac layouts.
// Vim: Insert next non-digit literally (same as <Ctrl-V>). Not yet supported (19.01.2020)
"<C-Q>"
)
}
@NonNls
@Deprecated("was replaced by OptionService")
@ScheduledForRemoval(inVersion = "1.11")
object IdeaStatusIcon {
const val enabled = "enabled"
const val gray = "gray"
const val disabled = "disabled"
const val name = "ideastatusicon"
val allValues = arrayOf(enabled, gray, disabled)
}
@NonNls
@Deprecated("was replaced by OptionService")
@ScheduledForRemoval(inVersion = "1.11")
object ScrollOffData {
const val name = "scrolloff"
}
@NonNls
@Deprecated("was replaced by OptionService")
@ScheduledForRemoval(inVersion = "1.11")
object ScrollJumpData {
const val name = "scrolljump"
}
@Deprecated("was replaced by OptionService")
@ScheduledForRemoval(inVersion = "1.11")
object ShellOptionData {
const val name = "shell"
val defaultValue = if (SystemInfo.isWindows) "cmd.exe" else System.getenv("SHELL") ?: "sh"
val option = StringOption(name, "sh", defaultValue)
}
@Suppress("SpellCheckingInspection")
@Deprecated("was replaced by OptionService")
@ScheduledForRemoval(inVersion = "1.11")
object ShellCmdFlagOptionData {
const val name = "shellcmdflag"
fun updateDefaultValue(shell: StringOption) {
val resetOption = option.isDefault
defaultValue = calculateDefaultValue(shell.value)
if (resetOption) {
option.resetDefault()
}
}
private var defaultValue = calculateDefaultValue(ShellOptionData.defaultValue)
private fun calculateDefaultValue(shell: String): String {
return if (SystemInfo.isWindows && !shell.contains("sh")) "/c" else "-c"
}
val option = object : StringOption(name, "shcf", defaultValue) {
override fun getDefaultValue() = ShellCmdFlagOptionData.defaultValue
}
}
@Suppress("SpellCheckingInspection")
@Deprecated("was replaced by OptionService")
@ScheduledForRemoval(inVersion = "1.11")
object ShellXEscapeOptionData {
const val name = "shellxescape"
val option = StringOption(name, "sxe", if (SystemInfo.isWindows) "\"&|<>()@^" else "")
}
@Suppress("SpellCheckingInspection")
@Deprecated("was replaced by OptionService")
@ScheduledForRemoval(inVersion = "1.11")
object ShellXQuoteOptionData {
const val name = "shellxquote"
fun updateDefaultValue(shell: StringOption) {
val resetOption = option.isDefault
defaultValue = calculateDefaultValue(shell.value)
if (resetOption) {
option.resetDefault()
}
}
private var defaultValue = calculateDefaultValue(ShellOptionData.defaultValue)
private fun calculateDefaultValue(shell: String): String {
return when {
SystemInfo.isWindows && shell == "cmd.exe" -> "("
SystemInfo.isWindows && shell.contains("sh") -> "\""
else -> ""
}
}
val option = object : StringOption(name, "sxq", defaultValue) {
override fun getDefaultValue() = ShellXQuoteOptionData.defaultValue
}
}
@Deprecated("was replaced by OptionService")
@ScheduledForRemoval(inVersion = "1.11")
object StrictMode {
val on: Boolean
get() = VimPlugin.getOptionService().isSet(OptionScope.GLOBAL, "ideastrictmode")
@NonNls
fun fail(message: @NonNls String) {
if (on) error(message)
}
}
@NonNls
@Deprecated("was replaced by OptionService")
@ScheduledForRemoval(inVersion = "1.11")
object VirtualEditData {
const val name = "virtualedit"
const val onemore = "onemore"
const val block = "block"
const val insert = "insert"
const val all = "all"
val allValues = arrayOf(block, insert, all, onemore)
}
@NonNls
@Deprecated("was replaced by OptionService")
@ScheduledForRemoval(inVersion = "1.11")
object IdeaWriteData {
const val all = "all"
val allValues = arrayOf(all, "file")
}

View File

@ -1,57 +0,0 @@
/*
* IdeaVim - Vim emulator for IDEs based on the IntelliJ platform
* Copyright (C) 2003-2022 The IdeaVim authors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.maddyhome.idea.vim.option
import com.maddyhome.idea.vim.helper.VimNlsSafe
import org.jetbrains.annotations.ApiStatus
import java.util.regex.Pattern
/**
* Creates the option
*
* @param name The name of the option
* @param abbrev The short name
* @param defaultValues The option's default values
* @param pattern A regular expression that is used to validate new values. null if no check needed
* @deprecated use {@link com.maddyhome.idea.vim.vimscript.model.options.Option} instead
*/
@Deprecated("was replaced by OptionService")
@ApiStatus.ScheduledForRemoval(inVersion = "1.11")
open class StringListOption @JvmOverloads constructor(
@VimNlsSafe name: String,
@VimNlsSafe abbrev: String,
@VimNlsSafe defaultValues: Array<String>,
@VimNlsSafe protected val pattern: String? = null
) :
ListOption<String>(name, abbrev, defaultValues) {
companion object {
val empty = StringListOption("", "", emptyArray())
}
override fun convertToken(token: String): String? {
if (pattern == null) {
return token
}
if (Pattern.matches(pattern, token)) {
return token
}
return null
}
}

View File

@ -1,192 +0,0 @@
/*
* IdeaVim - Vim emulator for IDEs based on the IntelliJ platform
* Copyright (C) 2003-2022 The IdeaVim authors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.maddyhome.idea.vim.option;
import com.maddyhome.idea.vim.VimPlugin;
import com.maddyhome.idea.vim.vimscript.model.commands.SetCommand;
import com.maddyhome.idea.vim.vimscript.model.datatypes.VimString;
import com.maddyhome.idea.vim.options.OptionScope;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
/**
* An option that has an arbitrary string value
* @deprecated use {@link com.maddyhome.idea.vim.vimscript.model.options.Option} instead
*/
@Deprecated
@ApiStatus.ScheduledForRemoval(inVersion = "1.11")
public class StringOption extends TextOption {
private final String dflt;
protected String value;
/**
* Creates the string option
*
* @param name The name of the option
* @param abbrev The short name
* @param dflt The default value
*/
StringOption(String name, String abbrev, String dflt) {
super(name, abbrev);
this.dflt = dflt;
this.value = dflt;
}
/**
* The option's value
*
* @return The option's value
*/
@Override
public String getValue() {
return value;
}
/**
* Sets the option to the new value
*
* @param val The new value
* @return True
*/
@Override
public boolean set(String val) {
String oldValue = getValue();
value = val;
onChanged(oldValue, getValue());
// we won't use OptionService if the method was invoked during set command execution (set command will call OptionService by itself)
if (!SetCommand.Companion.isExecutingCommand()) {
try {
if (!((VimString)VimPlugin.getOptionService().getOptionValue(OptionScope.GLOBAL.INSTANCE, name, name)).getValue().equals(value)) {
VimPlugin.getOptionService().setOptionValue(OptionScope.GLOBAL.INSTANCE, name, new VimString(value), name);
}
}
catch (Exception e) {
}
}
return true;
}
/**
* Appends the value to the option's current value
*
* @param val The string to append
* @return True
*/
@Override
public boolean append(String val) {
String oldValue = getValue();
value += val;
onChanged(oldValue, getValue());
try {
if (!((VimString)VimPlugin.getOptionService()
.getOptionValue(OptionScope.GLOBAL.INSTANCE, name, name)).getValue().equals(value)) {
VimPlugin.getOptionService().setOptionValue(OptionScope.GLOBAL.INSTANCE, name, new VimString(value), name);
}
} catch (Exception e) {}
return true;
}
/**
* Prepends the value to the start of the option's current value
*
* @param val The string to prepend
* @return True
*/
@Override
public boolean prepend(String val) {
String oldValue = getValue();
value = val + value;
onChanged(oldValue, getValue());
try {
if (!((VimString)VimPlugin.getOptionService()
.getOptionValue(OptionScope.GLOBAL.INSTANCE, name, name)).getValue().equals(value)) {
VimPlugin.getOptionService().setOptionValue(OptionScope.GLOBAL.INSTANCE, name, new VimString(value), name);
}
} catch (Exception e) {}
return true;
}
/**
* Removes the value if the value is a substring of the option's current value.
*
* @param val The substring to remove from the current value
* @return True if the substring was removed, false if the value is not a substring of the current value
*/
@Override
public boolean remove(@NotNull String val) {
int pos = value.indexOf(val);
if (pos != -1) {
String oldValue = getValue();
value = value.substring(0, pos) + value.substring(pos + val.length());
onChanged(oldValue, getValue());
try {
if (!((VimString)VimPlugin.getOptionService()
.getOptionValue(OptionScope.GLOBAL.INSTANCE, name, name)).getValue().equals(value)) {
VimPlugin.getOptionService().setOptionValue(OptionScope.GLOBAL.INSTANCE, name, new VimString(value), name);
}
} catch (Exception e) {}
return true;
}
return false;
}
/**
* Checks to see if the option's current value equals the default value
*
* @return True if equal to default, false if not.
*/
@Override
public boolean isDefault() {
return getDefaultValue().equals(value);
}
/**
* Sets the option to its default value.
*/
@Override
public void resetDefault() {
if (!getDefaultValue().equals(value)) {
String oldValue = getValue();
value = getDefaultValue();
onChanged(oldValue, getValue());
}
try {
if (!((VimString)VimPlugin.getOptionService()
.getOptionValue(OptionScope.GLOBAL.INSTANCE, name, name)).getValue().equals(dflt)) {
VimPlugin.getOptionService().setOptionValue(OptionScope.GLOBAL.INSTANCE, name, new VimString(dflt), name);
}
} catch (Exception e) {}
}
/**
* The option as {name}={value}
*
* @return The option as a string for display
*/
public @NotNull String toString() {
return " " + getName() + "=" + value;
}
protected @NotNull String getDefaultValue() {
return dflt;
}
}

View File

@ -1,41 +0,0 @@
/*
* IdeaVim - Vim emulator for IDEs based on the IntelliJ platform
* Copyright (C) 2003-2022 The IdeaVim authors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.maddyhome.idea.vim.option;
import com.maddyhome.idea.vim.ex.ExException;
import org.jetbrains.annotations.ApiStatus;
/**
* @deprecated use {@link com.maddyhome.idea.vim.vimscript.model.options.Option} instead
*/
@Deprecated
@ApiStatus.ScheduledForRemoval(inVersion = "1.11")
public abstract class TextOption extends Option<String> {
TextOption(String name, String abbrev) {
super(name, abbrev);
}
public abstract boolean set(String val) throws ExException;
public abstract boolean append(String val) throws ExException;
public abstract boolean prepend(String val) throws ExException;
public abstract boolean remove(String val) throws ExException;
}

View File

@ -1,150 +0,0 @@
/*
* IdeaVim - Vim emulator for IDEs based on the IntelliJ platform
* Copyright (C) 2003-2022 The IdeaVim authors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.maddyhome.idea.vim.option;
import com.maddyhome.idea.vim.VimPlugin;
import com.maddyhome.idea.vim.helper.VimNlsSafe;
import com.maddyhome.idea.vim.vimscript.model.commands.SetCommand;
import com.maddyhome.idea.vim.vimscript.model.datatypes.VimInt;
import com.maddyhome.idea.vim.options.OptionScope;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
/**
* Represents a boolean option
* @deprecated use {@link com.maddyhome.idea.vim.vimscript.model.options.Option} instead
*/
@Deprecated
@ApiStatus.ScheduledForRemoval(inVersion = "1.11")
public class ToggleOption extends Option<Boolean> {
private static final @NonNls String NO_PREFIX = "no";
protected final boolean dflt;
protected boolean value;
/**
* Creates the option
*
* @param name The option's name
* @param abbrev The short name
* @param dflt The default value
*/
public ToggleOption(@VimNlsSafe String name, @VimNlsSafe String abbrev, boolean dflt) {
super(name, abbrev);
this.dflt = dflt;
this.value = dflt;
}
@Override
public Boolean getValue() {
return value;
}
/**
* Sets the on (true)
*/
public void set() {
update(true);
}
/**
* Resets the option (false)
*/
public void reset() {
update(false);
}
/**
* Toggles the option's value (false to true, true to false)
*/
public void toggle() {
update(!value);
}
public boolean isSet() {
return value;
}
/**
* Helper to set the value only it is changing and notify listeners
*
* @param val The new value
*/
private void update(boolean val) {
boolean old = value;
value = val;
if (val != old) {
onChanged(old, val);
}
// we won't use OptionService if the method was invoked during set command execution (set command will call OptionService by itself)
if (!SetCommand.Companion.isExecutingCommand()) {
try {
if (VimPlugin.getOptionService().isSet(OptionScope.GLOBAL.INSTANCE, name, name) != val) {
VimPlugin.getOptionService().setOptionValue(OptionScope.GLOBAL.INSTANCE, name, new VimInt(val ? 1 : 0), name);
}
}
catch (Exception e) {
}
}
}
/**
* The display value of the option [no]{name}
*
* @return The option's display value
*/
public @NotNull String toString() {
StringBuilder res = new StringBuilder();
if (!value) {
res.append(NO_PREFIX);
}
else {
res.append(" ");
}
res.append(getName());
return res.toString();
}
/**
* Checks to see if the option's current value equals the default value
*
* @return True if equal to default, false if not.
*/
@Override
public boolean isDefault() {
return value == dflt;
}
/**
* Sets the option to its default value.
*/
@Override
public void resetDefault() {
value = dflt;
try {
if (VimPlugin.getOptionService().isSet(OptionScope.GLOBAL.INSTANCE, name, name) != dflt) {
VimPlugin.getOptionService().setOptionValue(OptionScope.GLOBAL.INSTANCE, name, new VimInt(dflt ? 1 : 0), name);
}
} catch (Exception e) {}
}
}

View File

@ -20,7 +20,7 @@ package com.maddyhome.idea.vim.vimscript.model.functions.handlers
import com.maddyhome.idea.vim.api.ExecutionContext import com.maddyhome.idea.vim.api.ExecutionContext
import com.maddyhome.idea.vim.api.VimEditor import com.maddyhome.idea.vim.api.VimEditor
import com.maddyhome.idea.vim.option.OptionsManager import com.maddyhome.idea.vim.api.injector
import com.maddyhome.idea.vim.vimscript.model.VimLContext import com.maddyhome.idea.vim.vimscript.model.VimLContext
import com.maddyhome.idea.vim.vimscript.model.datatypes.VimDataType import com.maddyhome.idea.vim.vimscript.model.datatypes.VimDataType
import com.maddyhome.idea.vim.vimscript.model.datatypes.VimInt import com.maddyhome.idea.vim.vimscript.model.datatypes.VimInt
@ -47,7 +47,7 @@ object ExistsFunctionHandler : FunctionHandler() {
return if (expression is SimpleExpression && expression.data is VimString) { return if (expression is SimpleExpression && expression.data is VimString) {
val parsedValue = VimscriptParser.parseExpression((expression.data as VimString).value) val parsedValue = VimscriptParser.parseExpression((expression.data as VimString).value)
if (parsedValue is OptionExpression) { if (parsedValue is OptionExpression) {
if (OptionsManager.getOption(parsedValue.optionName) != null) { if (injector.optionService.getOptions().any { it == parsedValue.optionName } || injector.optionService.getAbbrevs().any { it == parsedValue.optionName }) {
VimInt.ONE VimInt.ONE
} else { } else {
VimInt.ZERO VimInt.ZERO

View File

@ -22,12 +22,12 @@ import com.intellij.openapi.application.ApplicationNamesInfo
import com.intellij.openapi.diagnostic.logger import com.intellij.openapi.diagnostic.logger
import com.intellij.openapi.util.SystemInfo import com.intellij.openapi.util.SystemInfo
import com.maddyhome.idea.vim.api.VimEditor import com.maddyhome.idea.vim.api.VimEditor
import com.maddyhome.idea.vim.api.injector
import com.maddyhome.idea.vim.ex.ExException import com.maddyhome.idea.vim.ex.ExException
import com.maddyhome.idea.vim.helper.localEditors import com.maddyhome.idea.vim.helper.localEditors
import com.maddyhome.idea.vim.newapi.IjVimEditor import com.maddyhome.idea.vim.newapi.IjVimEditor
import com.maddyhome.idea.vim.newapi.IjVimLocalOptions import com.maddyhome.idea.vim.newapi.IjVimLocalOptions
import com.maddyhome.idea.vim.newapi.VimLocalOptions import com.maddyhome.idea.vim.newapi.VimLocalOptions
import com.maddyhome.idea.vim.option.OptionsManager
import com.maddyhome.idea.vim.options.OptionChangeListener import com.maddyhome.idea.vim.options.OptionChangeListener
import com.maddyhome.idea.vim.options.OptionConstants import com.maddyhome.idea.vim.options.OptionConstants
import com.maddyhome.idea.vim.options.OptionScope import com.maddyhome.idea.vim.options.OptionScope
@ -37,10 +37,10 @@ import com.maddyhome.idea.vim.vimscript.model.datatypes.VimDataType
import com.maddyhome.idea.vim.vimscript.model.datatypes.VimInt import com.maddyhome.idea.vim.vimscript.model.datatypes.VimInt
import com.maddyhome.idea.vim.vimscript.model.datatypes.VimString import com.maddyhome.idea.vim.vimscript.model.datatypes.VimString
import com.maddyhome.idea.vim.vimscript.model.datatypes.parseNumber import com.maddyhome.idea.vim.vimscript.model.datatypes.parseNumber
import com.maddyhome.idea.vim.vimscript.model.options.NumberOption import com.maddyhome.idea.vim.options.NumberOption
import com.maddyhome.idea.vim.vimscript.model.options.Option import com.maddyhome.idea.vim.options.Option
import com.maddyhome.idea.vim.vimscript.model.options.StringOption import com.maddyhome.idea.vim.options.StringOption
import com.maddyhome.idea.vim.vimscript.model.options.ToggleOption import com.maddyhome.idea.vim.options.ToggleOption
import com.maddyhome.idea.vim.vimscript.model.options.helpers.GuiCursorOptionHelper import com.maddyhome.idea.vim.vimscript.model.options.helpers.GuiCursorOptionHelper
internal class OptionServiceImpl : OptionService { internal class OptionServiceImpl : OptionService {
@ -107,7 +107,7 @@ internal class OptionServiceImpl : OptionService {
object : StringOption(OptionConstants.matchpairsName, OptionConstants.matchpairsAlias, "(:),{:},[:]", isList = true) { object : StringOption(OptionConstants.matchpairsName, OptionConstants.matchpairsAlias, "(:),{:},[:]", isList = true) {
override fun checkIfValueValid(value: VimDataType, token: String) { override fun checkIfValueValid(value: VimDataType, token: String) {
super.checkIfValueValid(value, token) super.checkIfValueValid(value, token)
for (v in split((value as VimString).value)!!) { for (v in split((value as VimString).value)) {
if (!v.matches(Regex(".:."))) { if (!v.matches(Regex(".:."))) {
throw ExException("E474: Invalid argument: $token") throw ExException("E474: Invalid argument: $token")
} }
@ -188,8 +188,14 @@ internal class OptionServiceImpl : OptionService {
} }
} }
override fun split(value: String): List<String>? { override fun split(value: String): List<String> {
return KeywordOptionHelper.parseValues(value) val result = KeywordOptionHelper.parseValues(value)
if (result == null) {
logger.error("KeywordOptionHelper failed to parse $value")
injector.messages.indicateError()
injector.messages.showStatusBarMessage("Failed to parse iskeyword option value")
}
return result ?: split(getDefaultValue().value)
} }
}, },
object : StringOption( object : StringOption(
@ -224,27 +230,11 @@ internal class OptionServiceImpl : OptionService {
is OptionScope.GLOBAL -> setGlobalOptionValue(option.name, value) is OptionScope.GLOBAL -> setGlobalOptionValue(option.name, value)
} }
option.onChanged(scope, oldValue) option.onChanged(scope, oldValue)
if (scope !is OptionScope.LOCAL) {
val oldOption = OptionsManager.getOption(optionName)
when (oldOption) {
is com.maddyhome.idea.vim.option.ToggleOption -> {
if (value == VimInt(0)) {
oldOption.reset()
} else {
oldOption.set()
}
}
is com.maddyhome.idea.vim.option.TextOption -> {
oldOption.set(value.asString())
}
}
}
} }
override fun contains(scope: OptionScope, optionName: String, value: String): Boolean { override fun contains(scope: OptionScope, optionName: String, value: String): Boolean {
val option = options.get(optionName) as? StringOption ?: return false val option = options.get(optionName) as? StringOption ?: return false
return value in option.split(getOptionValue(scope, optionName, optionName).asString())!! return value in option.split(getOptionValue(scope, optionName, optionName).asString())
} }
override fun getValues(scope: OptionScope, optionName: String): List<String>? { override fun getValues(scope: OptionScope, optionName: String): List<String>? {
@ -375,10 +365,7 @@ internal class OptionServiceImpl : OptionService {
return options.secondaryKeys return options.secondaryKeys
} }
/** override fun addOption(option: Option<out VimDataType>) {
* TODO this should be moved to the interface
*/
fun addOption(option: Option<out VimDataType>) {
options.put(option.name, option.abbrev, option) options.put(option.name, option.abbrev, option)
} }

View File

@ -68,7 +68,6 @@ import com.maddyhome.idea.vim.key.MappingOwner
import com.maddyhome.idea.vim.key.ToKeysMappingInfo import com.maddyhome.idea.vim.key.ToKeysMappingInfo
import com.maddyhome.idea.vim.listener.SelectionVimListenerSuppressor import com.maddyhome.idea.vim.listener.SelectionVimListenerSuppressor
import com.maddyhome.idea.vim.newapi.vim import com.maddyhome.idea.vim.newapi.vim
import com.maddyhome.idea.vim.option.OptionsManager
import com.maddyhome.idea.vim.options.OptionConstants import com.maddyhome.idea.vim.options.OptionConstants
import com.maddyhome.idea.vim.options.OptionScope import com.maddyhome.idea.vim.options.OptionScope
import com.maddyhome.idea.vim.ui.ex.ExEntryPanel import com.maddyhome.idea.vim.ui.ex.ExEntryPanel
@ -109,7 +108,6 @@ abstract class VimTestCase : UsefulTestCase() {
KeyHandler.getInstance().fullReset(editor.vim) KeyHandler.getInstance().fullReset(editor.vim)
} }
VimPlugin.getOptionService().resetAllOptions() VimPlugin.getOptionService().resetAllOptions()
OptionsManager.resetAllOptions()
VimPlugin.getKey().resetKeyMappings() VimPlugin.getKey().resetKeyMappings()
VimPlugin.getSearch().resetState() VimPlugin.getSearch().resetState()
if (!VimPlugin.isEnabled()) VimPlugin.setEnabled(true) if (!VimPlugin.isEnabled()) VimPlugin.setEnabled(true)

View File

@ -39,8 +39,7 @@ import com.maddyhome.idea.vim.group.MotionGroup
import com.maddyhome.idea.vim.helper.isEndAllowed import com.maddyhome.idea.vim.helper.isEndAllowed
import com.maddyhome.idea.vim.newapi.ij import com.maddyhome.idea.vim.newapi.ij
import com.maddyhome.idea.vim.newapi.vim import com.maddyhome.idea.vim.newapi.vim
import com.maddyhome.idea.vim.option.OptionsManager import com.maddyhome.idea.vim.options.OptionScope
import com.maddyhome.idea.vim.option.ToggleOption
import junit.framework.TestCase import junit.framework.TestCase
import org.jetbrains.plugins.ideavim.SkipNeovimReason import org.jetbrains.plugins.ideavim.SkipNeovimReason
import org.jetbrains.plugins.ideavim.TestWithoutNeovim import org.jetbrains.plugins.ideavim.TestWithoutNeovim
@ -296,22 +295,22 @@ class PlugMissingKeysTest : VimTestCase() {
@TestWithoutNeovim(SkipNeovimReason.PLUGIN) @TestWithoutNeovim(SkipNeovimReason.PLUGIN)
fun `test packadd`() { fun `test packadd`() {
assertFalse((OptionsManager.getOption("matchit") as ToggleOption).isSet) assertFalse(injector.optionService.isSet(OptionScope.GLOBAL, "matchit"))
executeLikeVimrc( executeLikeVimrc(
"packadd matchit", "packadd matchit",
) )
assertTrue((OptionsManager.getOption("matchit") as ToggleOption).isSet) assertTrue(injector.optionService.isSet(OptionScope.GLOBAL, "matchit"))
} }
@TestWithoutNeovim(SkipNeovimReason.PLUGIN) @TestWithoutNeovim(SkipNeovimReason.PLUGIN)
fun `test packadd ex`() { fun `test packadd ex`() {
assertFalse((OptionsManager.getOption("matchit") as ToggleOption).isSet) assertFalse(injector.optionService.isSet(OptionScope.GLOBAL, "matchit"))
executeLikeVimrc( executeLikeVimrc(
"packadd! matchit", "packadd! matchit",
) )
assertTrue((OptionsManager.getOption("matchit") as ToggleOption).isSet) assertTrue(injector.optionService.isSet(OptionScope.GLOBAL, "matchit"))
} }
private fun executeLikeVimrc(vararg text: String) { private fun executeLikeVimrc(vararg text: String) {

View File

@ -1,112 +0,0 @@
/*
* IdeaVim - Vim emulator for IDEs based on the IntelliJ platform
* Copyright (C) 2003-2022 The IdeaVim authors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.jetbrains.plugins.ideavim.option
import com.maddyhome.idea.vim.VimPlugin
import com.maddyhome.idea.vim.option.OptionsManager
import com.maddyhome.idea.vim.options.OptionConstants
import com.maddyhome.idea.vim.options.OptionScope
import com.maddyhome.idea.vim.vimscript.model.datatypes.VimInt
import com.maddyhome.idea.vim.vimscript.model.datatypes.VimString
import junit.framework.TestCase
import org.jetbrains.plugins.ideavim.VimTestCase
// this class will be deleted in release 1.11
class OldAndNewOptionTest : VimTestCase() {
fun `test toggle option`() {
TestCase.assertFalse(VimPlugin.getOptionService().isSet(OptionScope.GLOBAL, OptionConstants.relativenumberName))
OptionsManager.relativenumber.set()
TestCase.assertTrue(VimPlugin.getOptionService().isSet(OptionScope.GLOBAL, OptionConstants.relativenumberName))
OptionsManager.relativenumber.reset()
TestCase.assertFalse(VimPlugin.getOptionService().isSet(OptionScope.GLOBAL, OptionConstants.relativenumberName))
}
fun `test toggle option 2`() {
TestCase.assertFalse(VimPlugin.getOptionService().isSet(OptionScope.GLOBAL, OptionConstants.relativenumberName))
VimPlugin.getOptionService().setOption(OptionScope.GLOBAL, OptionConstants.relativenumberName)
TestCase.assertTrue(OptionsManager.relativenumber.isSet)
VimPlugin.getOptionService().unsetOption(OptionScope.GLOBAL, OptionConstants.relativenumberName)
TestCase.assertFalse(VimPlugin.getOptionService().isSet(OptionScope.GLOBAL, OptionConstants.relativenumberName))
}
fun `test number option`() {
TestCase.assertEquals("1", VimPlugin.getOptionService().getOptionValue(OptionScope.GLOBAL, "sj").asString())
OptionsManager.scrolljump.set(10)
TestCase.assertEquals("10", VimPlugin.getOptionService().getOptionValue(OptionScope.GLOBAL, "sj").asString())
OptionsManager.scrolljump.resetDefault()
TestCase.assertEquals("1", VimPlugin.getOptionService().getOptionValue(OptionScope.GLOBAL, "sj").asString())
}
fun `test number option 2`() {
TestCase.assertEquals("1", OptionsManager.scrolljump.value)
VimPlugin.getOptionService().setOptionValue(OptionScope.GLOBAL, "sj", VimInt(10))
TestCase.assertEquals("10", OptionsManager.scrolljump.value)
VimPlugin.getOptionService().resetDefault(OptionScope.GLOBAL, "sj")
TestCase.assertEquals("1", OptionsManager.scrolljump.value)
}
fun `test string option`() {
TestCase.assertEquals("all", VimPlugin.getOptionService().getOptionValue(OptionScope.GLOBAL, OptionConstants.ideawriteName).asString())
OptionsManager.ideawrite.set("file")
TestCase.assertEquals("file", VimPlugin.getOptionService().getOptionValue(OptionScope.GLOBAL, OptionConstants.ideawriteName).asString())
OptionsManager.ideawrite.resetDefault()
TestCase.assertEquals("all", VimPlugin.getOptionService().getOptionValue(OptionScope.GLOBAL, OptionConstants.ideawriteName).asString())
}
fun `test string option 2`() {
TestCase.assertEquals("all", OptionsManager.ideawrite.value)
VimPlugin.getOptionService().setOptionValue(OptionScope.GLOBAL, OptionConstants.ideawriteName, VimString("file"))
TestCase.assertEquals("file", OptionsManager.ideawrite.value)
VimPlugin.getOptionService().resetDefault(OptionScope.GLOBAL, OptionConstants.ideawriteName)
TestCase.assertEquals("all", OptionsManager.ideawrite.value)
}
fun `test list option`() {
TestCase.assertEquals("'100,<50,s10,h", VimPlugin.getOptionService().getOptionValue(OptionScope.GLOBAL, "vi").asString())
OptionsManager.viminfo.append("k")
TestCase.assertEquals("'100,<50,s10,h,k", VimPlugin.getOptionService().getOptionValue(OptionScope.GLOBAL, "vi").asString())
OptionsManager.viminfo.prepend("j")
TestCase.assertEquals("j,'100,<50,s10,h,k", VimPlugin.getOptionService().getOptionValue(OptionScope.GLOBAL, "vi").asString())
OptionsManager.viminfo.remove("s10")
TestCase.assertEquals("j,'100,<50,h,k", VimPlugin.getOptionService().getOptionValue(OptionScope.GLOBAL, "vi").asString())
OptionsManager.viminfo.remove("k")
TestCase.assertEquals("j,'100,<50,h", VimPlugin.getOptionService().getOptionValue(OptionScope.GLOBAL, "vi").asString())
OptionsManager.viminfo.remove("j")
TestCase.assertEquals("'100,<50,h", VimPlugin.getOptionService().getOptionValue(OptionScope.GLOBAL, "vi").asString())
OptionsManager.viminfo.resetDefault()
TestCase.assertEquals("'100,<50,s10,h", VimPlugin.getOptionService().getOptionValue(OptionScope.GLOBAL, "vi").asString())
}
fun `test list option 2`() {
TestCase.assertEquals("'100,<50,s10,h", OptionsManager.viminfo.value)
VimPlugin.getOptionService().appendValue(OptionScope.GLOBAL, "vi", "k", "vi")
TestCase.assertEquals("'100,<50,s10,h,k", OptionsManager.viminfo.value)
VimPlugin.getOptionService().prependValue(OptionScope.GLOBAL, "vi", "j", "vi")
TestCase.assertEquals("j,'100,<50,s10,h,k", OptionsManager.viminfo.value)
VimPlugin.getOptionService().removeValue(OptionScope.GLOBAL, "vi", "s10", "vi")
TestCase.assertEquals("j,'100,<50,h,k", OptionsManager.viminfo.value)
VimPlugin.getOptionService().removeValue(OptionScope.GLOBAL, "vi", "k", "vi")
TestCase.assertEquals("j,'100,<50,h", OptionsManager.viminfo.value)
VimPlugin.getOptionService().removeValue(OptionScope.GLOBAL, "vi", "j", "vi")
TestCase.assertEquals("'100,<50,h", OptionsManager.viminfo.value)
VimPlugin.getOptionService().resetDefault(OptionScope.GLOBAL, "vi")
TestCase.assertEquals("'100,<50,s10,h", OptionsManager.viminfo.value)
}
}

View File

@ -76,4 +76,6 @@ interface OptionService {
fun addListener(optionName: String, listener: OptionChangeListener<VimDataType>, executeOnAdd: Boolean = false) fun addListener(optionName: String, listener: OptionChangeListener<VimDataType>, executeOnAdd: Boolean = false)
fun removeListener(optionName: String, listener: OptionChangeListener<VimDataType>) fun removeListener(optionName: String, listener: OptionChangeListener<VimDataType>)
fun addOption(option: Option<out VimDataType>)
} }

View File

@ -26,7 +26,6 @@ import com.maddyhome.idea.vim.ex.ranges.Ranges
import com.maddyhome.idea.vim.helper.Msg import com.maddyhome.idea.vim.helper.Msg
import com.maddyhome.idea.vim.options.OptionScope import com.maddyhome.idea.vim.options.OptionScope
import com.maddyhome.idea.vim.vimscript.model.ExecutionResult import com.maddyhome.idea.vim.vimscript.model.ExecutionResult
import com.maddyhome.idea.vim.vimscript.model.datatypes.VimString
import java.util.* import java.util.*
import kotlin.math.ceil import kotlin.math.ceil
import kotlin.math.min import kotlin.math.min
@ -37,15 +36,8 @@ import kotlin.math.min
data class SetCommand(val ranges: Ranges, val argument: String) : Command.SingleExecution(ranges, argument) { data class SetCommand(val ranges: Ranges, val argument: String) : Command.SingleExecution(ranges, argument) {
override val argFlags = flags(RangeFlag.RANGE_OPTIONAL, ArgumentFlag.ARGUMENT_OPTIONAL, Access.READ_ONLY) override val argFlags = flags(RangeFlag.RANGE_OPTIONAL, ArgumentFlag.ARGUMENT_OPTIONAL, Access.READ_ONLY)
companion object {
@Deprecated("delete me after the OptionManager removal")
var isExecutingCommand = false
}
override fun processCommand(editor: VimEditor, context: ExecutionContext): ExecutionResult { override fun processCommand(editor: VimEditor, context: ExecutionContext): ExecutionResult {
isExecutingCommand = true
val result = parseOptionLine(editor, argument, OptionScope.GLOBAL, failOnBad = true) val result = parseOptionLine(editor, argument, OptionScope.GLOBAL, failOnBad = true)
isExecutingCommand = false
return if (result) { return if (result) {
ExecutionResult.Success ExecutionResult.Success
} else { } else {