1
0
mirror of https://github.com/chylex/IntelliJ-IdeaVim.git synced 2025-05-04 16:34:02 +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:
- 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`.
- Notifications: `NotificationService`.
- Status bar icon: `StatusBar.kt`.

View File

@ -1,6 +1,6 @@
# suppress inspection "UnusedProperty" for whole file
ideaVersion=LATEST-EAP-SNAPSHOT
ideaVersion=2022.1.1
downloadIdeaSources=true
instrumentPluginCode=true
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.listener.VimListenerManager;
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.ui.StatusBarIconFactory;
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
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
getSearch().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.ex.ExException
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.OptionScope
import com.maddyhome.idea.vim.statistic.PluginState
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 {
internal val registeredExtensions: MutableSet<String> = HashSet()
@ -68,7 +67,6 @@ object VimExtensionRegistrar : VimExtensionRegistrator {
registeredExtensions.add(name)
registerAliases(extensionBean)
OptionsManager.addOption(com.maddyhome.idea.vim.option.ToggleOption(name, getAbbrev(name), false))
VimPlugin.getOptionServiceImpl().addOption(ToggleOption(name, getAbbrev(name), false))
VimPlugin.getOptionService().addListener(
name,
@ -115,7 +113,6 @@ object VimExtensionRegistrar : VimExtensionRegistrator {
removeAliases(extension)
extension.instance.dispose()
VimPlugin.getOptionService().removeOption(name)
OptionsManager.removeOption(name)
remove(name)
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.maddyhome.idea.vim.VimPlugin
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.extension.VimExtension
import com.maddyhome.idea.vim.helper.MessageHelper
import com.maddyhome.idea.vim.helper.VimNlsSafe
import com.maddyhome.idea.vim.listener.VimInsertListener
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 org.jetbrains.annotations.NonNls
import java.awt.Color
@ -137,12 +139,18 @@ class VimHighlightedYank : VimExtension, VimYankListener, VimInsertListener {
fun clearAllYankHighlighters() {
yankHighlighters.forEach { highlighter ->
editor?.markupModel?.removeHighlighter(highlighter) ?: StrictMode.fail("Highlighters without an editor")
editor?.markupModel?.removeHighlighter(highlighter) ?: failIfStrictMode("Highlighters without an editor")
}
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>) {
val highlighter = editor.markupModel.addRangeHighlighter(
range.start,
@ -165,7 +173,7 @@ class VimHighlightedYank : VimExtension, VimYankListener, VimInsertListener {
Executors.newSingleThreadScheduledExecutor().schedule(
{
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

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.VimListenerSuppressor;
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.OptionScope;
import com.maddyhome.idea.vim.register.Register;
@ -1308,7 +1307,9 @@ public class ChangeGroup extends VimChangeGroupBase {
int endOffset = range.getEndOffset();
int fileSize = EditorHelperRt.getFileSize(((IjVimEditor) editor).getEditor());
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;
}
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.newapi.IjVimEditor
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.OptionScope
import com.maddyhome.idea.vim.options.helpers.KeywordOptionChangeListener
import com.maddyhome.idea.vim.ui.ShowCmdOptionChangeListener
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
EventFacade.getInstance().setupTypedActionHandler(VimTypedActionHandler(typedAction.rawHandler))
} 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)

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.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.datatypes.VimDataType
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) {
val parsedValue = VimscriptParser.parseExpression((expression.data as VimString).value)
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
} else {
VimInt.ZERO

View File

@ -22,12 +22,12 @@ import com.intellij.openapi.application.ApplicationNamesInfo
import com.intellij.openapi.diagnostic.logger
import com.intellij.openapi.util.SystemInfo
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.helper.localEditors
import com.maddyhome.idea.vim.newapi.IjVimEditor
import com.maddyhome.idea.vim.newapi.IjVimLocalOptions
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.OptionConstants
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.VimString
import com.maddyhome.idea.vim.vimscript.model.datatypes.parseNumber
import com.maddyhome.idea.vim.vimscript.model.options.NumberOption
import com.maddyhome.idea.vim.vimscript.model.options.Option
import com.maddyhome.idea.vim.vimscript.model.options.StringOption
import com.maddyhome.idea.vim.vimscript.model.options.ToggleOption
import com.maddyhome.idea.vim.options.NumberOption
import com.maddyhome.idea.vim.options.Option
import com.maddyhome.idea.vim.options.StringOption
import com.maddyhome.idea.vim.options.ToggleOption
import com.maddyhome.idea.vim.vimscript.model.options.helpers.GuiCursorOptionHelper
internal class OptionServiceImpl : OptionService {
@ -107,7 +107,7 @@ internal class OptionServiceImpl : OptionService {
object : StringOption(OptionConstants.matchpairsName, OptionConstants.matchpairsAlias, "(:),{:},[:]", isList = true) {
override fun checkIfValueValid(value: VimDataType, token: String) {
super.checkIfValueValid(value, token)
for (v in split((value as VimString).value)!!) {
for (v in split((value as VimString).value)) {
if (!v.matches(Regex(".:."))) {
throw ExException("E474: Invalid argument: $token")
}
@ -188,8 +188,14 @@ internal class OptionServiceImpl : OptionService {
}
}
override fun split(value: String): List<String>? {
return KeywordOptionHelper.parseValues(value)
override fun split(value: String): List<String> {
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(
@ -224,27 +230,11 @@ internal class OptionServiceImpl : OptionService {
is OptionScope.GLOBAL -> setGlobalOptionValue(option.name, value)
}
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 {
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>? {
@ -375,10 +365,7 @@ internal class OptionServiceImpl : OptionService {
return options.secondaryKeys
}
/**
* TODO this should be moved to the interface
*/
fun addOption(option: Option<out VimDataType>) {
override fun addOption(option: Option<out VimDataType>) {
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.listener.SelectionVimListenerSuppressor
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.OptionScope
import com.maddyhome.idea.vim.ui.ex.ExEntryPanel
@ -109,7 +108,6 @@ abstract class VimTestCase : UsefulTestCase() {
KeyHandler.getInstance().fullReset(editor.vim)
}
VimPlugin.getOptionService().resetAllOptions()
OptionsManager.resetAllOptions()
VimPlugin.getKey().resetKeyMappings()
VimPlugin.getSearch().resetState()
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.newapi.ij
import com.maddyhome.idea.vim.newapi.vim
import com.maddyhome.idea.vim.option.OptionsManager
import com.maddyhome.idea.vim.option.ToggleOption
import com.maddyhome.idea.vim.options.OptionScope
import junit.framework.TestCase
import org.jetbrains.plugins.ideavim.SkipNeovimReason
import org.jetbrains.plugins.ideavim.TestWithoutNeovim
@ -296,22 +295,22 @@ class PlugMissingKeysTest : VimTestCase() {
@TestWithoutNeovim(SkipNeovimReason.PLUGIN)
fun `test packadd`() {
assertFalse((OptionsManager.getOption("matchit") as ToggleOption).isSet)
assertFalse(injector.optionService.isSet(OptionScope.GLOBAL, "matchit"))
executeLikeVimrc(
"packadd matchit",
)
assertTrue((OptionsManager.getOption("matchit") as ToggleOption).isSet)
assertTrue(injector.optionService.isSet(OptionScope.GLOBAL, "matchit"))
}
@TestWithoutNeovim(SkipNeovimReason.PLUGIN)
fun `test packadd ex`() {
assertFalse((OptionsManager.getOption("matchit") as ToggleOption).isSet)
assertFalse(injector.optionService.isSet(OptionScope.GLOBAL, "matchit"))
executeLikeVimrc(
"packadd! matchit",
)
assertTrue((OptionsManager.getOption("matchit") as ToggleOption).isSet)
assertTrue(injector.optionService.isSet(OptionScope.GLOBAL, "matchit"))
}
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 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.options.OptionScope
import com.maddyhome.idea.vim.vimscript.model.ExecutionResult
import com.maddyhome.idea.vim.vimscript.model.datatypes.VimString
import java.util.*
import kotlin.math.ceil
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) {
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 {
isExecutingCommand = true
val result = parseOptionLine(editor, argument, OptionScope.GLOBAL, failOnBad = true)
isExecutingCommand = false
return if (result) {
ExecutionResult.Success
} else {