diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4ac22cdbf..a275f4191 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -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`. diff --git a/gradle.properties b/gradle.properties index 83fcb06d8..3e4fd0eb7 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,6 +1,6 @@ # suppress inspection "UnusedProperty" for whole file -ideaVersion=LATEST-EAP-SNAPSHOT +ideaVersion=2022.1.1 downloadIdeaSources=true instrumentPluginCode=true version=SNAPSHOT diff --git a/src/main/java/com/maddyhome/idea/vim/VimPlugin.java b/src/main/java/com/maddyhome/idea/vim/VimPlugin.java index 234023913..dc6cf9cc0 100644 --- a/src/main/java/com/maddyhome/idea/vim/VimPlugin.java +++ b/src/main/java/com/maddyhome/idea/vim/VimPlugin.java @@ -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(); diff --git a/src/main/java/com/maddyhome/idea/vim/extension/VimExtensionRegistrar.kt b/src/main/java/com/maddyhome/idea/vim/extension/VimExtensionRegistrar.kt index b63667f0a..a61171fcb 100644 --- a/src/main/java/com/maddyhome/idea/vim/extension/VimExtensionRegistrar.kt +++ b/src/main/java/com/maddyhome/idea/vim/extension/VimExtensionRegistrar.kt @@ -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") } diff --git a/src/main/java/com/maddyhome/idea/vim/extension/highlightedyank/VimHighlightedYank.kt b/src/main/java/com/maddyhome/idea/vim/extension/highlightedyank/VimHighlightedYank.kt index 64b172add..eb25041a1 100644 --- a/src/main/java/com/maddyhome/idea/vim/extension/highlightedyank/VimHighlightedYank.kt +++ b/src/main/java/com/maddyhome/idea/vim/extension/highlightedyank/VimHighlightedYank.kt @@ -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 diff --git a/src/main/java/com/maddyhome/idea/vim/group/ChangeGroup.java b/src/main/java/com/maddyhome/idea/vim/group/ChangeGroup.java index 3be767d9a..ef9b5b8b0 100644 --- a/src/main/java/com/maddyhome/idea/vim/group/ChangeGroup.java +++ b/src/main/java/com/maddyhome/idea/vim/group/ChangeGroup.java @@ -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 && diff --git a/src/main/java/com/maddyhome/idea/vim/listener/VimListenerManager.kt b/src/main/java/com/maddyhome/idea/vim/listener/VimListenerManager.kt index 3276f0169..50da16df2 100644 --- a/src/main/java/com/maddyhome/idea/vim/listener/VimListenerManager.kt +++ b/src/main/java/com/maddyhome/idea/vim/listener/VimListenerManager.kt @@ -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) diff --git a/src/main/java/com/maddyhome/idea/vim/option/BoundedStringListOption.java b/src/main/java/com/maddyhome/idea/vim/option/BoundedStringListOption.java deleted file mode 100644 index e94b46999..000000000 --- a/src/main/java/com/maddyhome/idea/vim/option/BoundedStringListOption.java +++ /dev/null @@ -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; - } -} diff --git a/src/main/java/com/maddyhome/idea/vim/option/BoundedStringOption.java b/src/main/java/com/maddyhome/idea/vim/option/BoundedStringOption.java deleted file mode 100644 index 0ebbfc17e..000000000 --- a/src/main/java/com/maddyhome/idea/vim/option/BoundedStringOption.java +++ /dev/null @@ -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; - } -} diff --git a/src/main/java/com/maddyhome/idea/vim/option/GuiCursorOption.kt b/src/main/java/com/maddyhome/idea/vim/option/GuiCursorOption.kt deleted file mode 100644 index bf9ed9ccd..000000000 --- a/src/main/java/com/maddyhome/idea/vim/option/GuiCursorOption.kt +++ /dev/null @@ -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) - } - } -} diff --git a/src/main/java/com/maddyhome/idea/vim/option/KeywordOption.java b/src/main/java/com/maddyhome/idea/vim/option/KeywordOption.java deleted file mode 100644 index 59bf88d7e..000000000 --- a/src/main/java/com/maddyhome/idea/vim/option/KeywordOption.java +++ /dev/null @@ -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; - } - } -} diff --git a/src/main/java/com/maddyhome/idea/vim/option/ListOption.java b/src/main/java/com/maddyhome/idea/vim/option/ListOption.java deleted file mode 100644 index 7454c4a5e..000000000 --- a/src/main/java/com/maddyhome/idea/vim/option/ListOption.java +++ /dev/null @@ -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) {} - } - } -} diff --git a/src/main/java/com/maddyhome/idea/vim/option/NumberOption.java b/src/main/java/com/maddyhome/idea/vim/option/NumberOption.java deleted file mode 100644 index f8fcc5694..000000000 --- a/src/main/java/com/maddyhome/idea/vim/option/NumberOption.java +++ /dev/null @@ -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; - } -} diff --git a/src/main/java/com/maddyhome/idea/vim/option/Option.java b/src/main/java/com/maddyhome/idea/vim/option/Option.java deleted file mode 100644 index 89a63c577..000000000 --- a/src/main/java/com/maddyhome/idea/vim/option/Option.java +++ /dev/null @@ -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(); -} diff --git a/src/main/java/com/maddyhome/idea/vim/option/OptionChangeListener.java b/src/main/java/com/maddyhome/idea/vim/option/OptionChangeListener.java deleted file mode 100644 index 2c9267046..000000000 --- a/src/main/java/com/maddyhome/idea/vim/option/OptionChangeListener.java +++ /dev/null @@ -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); -} diff --git a/src/main/java/com/maddyhome/idea/vim/option/OptionsManager.kt b/src/main/java/com/maddyhome/idea/vim/option/OptionsManager.kt deleted file mode 100644 index c5d2c842e..000000000 --- a/src/main/java/com/maddyhome/idea/vim/option/OptionsManager.kt +++ /dev/null @@ -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") -} diff --git a/src/main/java/com/maddyhome/idea/vim/option/StringListOption.kt b/src/main/java/com/maddyhome/idea/vim/option/StringListOption.kt deleted file mode 100644 index 947fccd64..000000000 --- a/src/main/java/com/maddyhome/idea/vim/option/StringListOption.kt +++ /dev/null @@ -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 - } -} diff --git a/src/main/java/com/maddyhome/idea/vim/option/StringOption.java b/src/main/java/com/maddyhome/idea/vim/option/StringOption.java deleted file mode 100644 index b01f0c216..000000000 --- a/src/main/java/com/maddyhome/idea/vim/option/StringOption.java +++ /dev/null @@ -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; - } -} diff --git a/src/main/java/com/maddyhome/idea/vim/option/TextOption.java b/src/main/java/com/maddyhome/idea/vim/option/TextOption.java deleted file mode 100644 index 3d0adce92..000000000 --- a/src/main/java/com/maddyhome/idea/vim/option/TextOption.java +++ /dev/null @@ -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; -} diff --git a/src/main/java/com/maddyhome/idea/vim/option/ToggleOption.java b/src/main/java/com/maddyhome/idea/vim/option/ToggleOption.java deleted file mode 100644 index c194700ba..000000000 --- a/src/main/java/com/maddyhome/idea/vim/option/ToggleOption.java +++ /dev/null @@ -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) {} - } -} diff --git a/src/main/java/com/maddyhome/idea/vim/vimscript/model/functions/handlers/ExistsFunctionHandler.kt b/src/main/java/com/maddyhome/idea/vim/vimscript/model/functions/handlers/ExistsFunctionHandler.kt index 78065a1dc..9a98f2744 100644 --- a/src/main/java/com/maddyhome/idea/vim/vimscript/model/functions/handlers/ExistsFunctionHandler.kt +++ b/src/main/java/com/maddyhome/idea/vim/vimscript/model/functions/handlers/ExistsFunctionHandler.kt @@ -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 diff --git a/src/main/java/com/maddyhome/idea/vim/vimscript/services/OptionServiceImpl.kt b/src/main/java/com/maddyhome/idea/vim/vimscript/services/OptionServiceImpl.kt index 807050ce4..337252e0e 100644 --- a/src/main/java/com/maddyhome/idea/vim/vimscript/services/OptionServiceImpl.kt +++ b/src/main/java/com/maddyhome/idea/vim/vimscript/services/OptionServiceImpl.kt @@ -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) } diff --git a/src/test/java/org/jetbrains/plugins/ideavim/VimTestCase.kt b/src/test/java/org/jetbrains/plugins/ideavim/VimTestCase.kt index 7887815da..865552c90 100644 --- a/src/test/java/org/jetbrains/plugins/ideavim/VimTestCase.kt +++ b/src/test/java/org/jetbrains/plugins/ideavim/VimTestCase.kt @@ -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) diff --git a/src/test/java/org/jetbrains/plugins/ideavim/extension/CommonExtensionTests.kt b/src/test/java/org/jetbrains/plugins/ideavim/extension/CommonExtensionTests.kt index 6e7edaa21..4953094b5 100644 --- a/src/test/java/org/jetbrains/plugins/ideavim/extension/CommonExtensionTests.kt +++ b/src/test/java/org/jetbrains/plugins/ideavim/extension/CommonExtensionTests.kt @@ -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) { diff --git a/src/test/java/org/jetbrains/plugins/ideavim/option/OldAndNewOptionTest.kt b/src/test/java/org/jetbrains/plugins/ideavim/option/OldAndNewOptionTest.kt deleted file mode 100644 index be81ddb93..000000000 --- a/src/test/java/org/jetbrains/plugins/ideavim/option/OldAndNewOptionTest.kt +++ /dev/null @@ -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) - } -} diff --git a/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/options/OptionService.kt b/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/options/OptionService.kt index f9339bcd5..b9696b8bb 100644 --- a/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/options/OptionService.kt +++ b/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/options/OptionService.kt @@ -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>) } diff --git a/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/vimscript/model/commands/SetCommand.kt b/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/vimscript/model/commands/SetCommand.kt index 5eb08215f..3add96944 100644 --- a/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/vimscript/model/commands/SetCommand.kt +++ b/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/vimscript/model/commands/SetCommand.kt @@ -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 {