Initially, injector was initialized in VimPlugin, assuming that almost every interaction with the plugin goes through it. However, with the plugin evolution, this class starts to be less used.
As IJ doesn't have any single entry point for the plugins, we initialize it in multiple places.
However, the architecture where the plugin might be not initizlied is considered as a bad acrhitecture and should be reviewed.
Related ticket: VIM-3369
Why is the old interface bad?
- it is not obvious. You cannot create a new panel or check if it is already created. Only "getOrCreate" it
- output panel is bound to editor while in Vim it is global
- we have the `isActive` field and the `clear()` method at the same time, because interface implies that you store the same instance of the panel and reactivate it for each output and I don't like it. We also can forget to call `clear()` after reusing panel
- we cannot "build" output before showing to make the panel more efficient. With multiple carets we can only cal `output(oldText + newText)` for each caret, and it is bad. (imagine we have global command with a lot of matches and for each time we will need to call the `output(oldText + newText)`)
- the `output()` method shows panel, activates it and updates it
- there are more things that I do not like, but the points above should be already enough
This bug was caused by two reasons:
1. KeyHandler state is not longer per-editor and we can't reset it on editor creation
2. We do not need to do such things on editor creation. What actually matters is focusing the editor
IJ has it's own kotlin libs, as well as fleet. So, let's use kotlin reflection library only to compile the project without bundling these jars into the resulting plugin
Explicit API mode has been removed due to several reasons impacting developer productivity and the natural coding style in Kotlin.
Firstly, the mode was found to be more irritating than beneficial, as it forced unnecessary verbosity without enhancing thoughtfulness in coding. It often prompted automatic 'public' insertion reactions to red-highlighted code, which did not genuinely encourage more deliberate coding decisions.
Secondly, our aim is to form a robust API primarily through interfaces, which inherently define public scope and duty, rendering explicit API mode somewhat redundant.
Lastly, the additional verbosity caused by explicit API mode expanded code lines affecting code readability.
The compatibility with the existing plugins is verified via the compatibility checker, so no JetBrains plugins will be affected
IntelliJ has multiple soft wrap options. One for main editors, another for consoles and a third for previews. This can lead to inconsistencies if initialising a console based on a main editor when both have default values, versus the same scenario when the main editor has an explicit value. Furthermore, the run console's soft-wraps toggle button uses the global value, so can get out of sync if the local value is initialised to an explicit value. This change will only copy the soft wrap value over during initialisation for similar editors (main editor, preview, diff) and not for different editors (console).
Fixes VIM-3450
The option should be "local-noglobal", and reset to default. Copying the value could cause the file to be converted immediately, possibly with a warning dialog
Fixes VIM-3467
Previously, we executed processings first and updated the state afterward. This approach could be problematic for asynchronous key processing, as Fleet might access the current state, which, in the context of async key processing, is a snapshot before execution and does not reflect the actual current KeyHandlerState
Removes a workaround that would break moving a range to the current line because it would always move the caret to the start of the range. Now positions the caret to the start of the selection if there is one. This also means we can remove the SAVE_VISUAL flag from JoinLinesCommand
Fixes VIM-2936
Handles validation of count and correctly moves caret to end of range after execution. Also fix issue where the results of :print are accumulated and not cleared.
Fixes VIM-2570
Made it explicit to get the count from argument and/or range. Default count is not passed, because it was never used. Added some tests where possible, but hard to test select file and friends
This is a messy quick fix, as the search group needs a lot of tidying up right now. Perhaps a better implementation would be to move the implementation of the global command into the search group - processGlobalCommand, like we already have processSearchCommand and processSubstituteCommand
Fixes VIM-3348
We should calculate the line above based on logical position rather than visual position.
This issue was detected thanks to newly introduced soft wraps and proprty tests
1. Now we have two parallel commandBuilders: for the editor and for the command prompt. It's done for sequence of keys like `d/foo<C-R>"<CR>` where we have two different commands that are built at the same time.
2. We simplified the CommandConsumer and made the logic more straightforward. `/`, `?` and `:` enter the command mode, while pressing final `<CR>` fires the command execution.
In a future commit, I'm going to make ProcessExEntryAction responsible for processing both search and ex commands. Search commands are motions that are executed for each caret, while ex-commands are executed once. The per-caret code is held internally by the ex commands themselves.
The current solution is definitely not the right one, and the whole ex command subsystem needs to be reviewed and refactored:
1. Some commands can be motions, which is currently not supported.
2. We need to figure out a gentle way of handling multiple carets.
Options are not reset if they've been explicitly set by the user (e.g. `:set list` or _View | Active Editor | Show Whitespaces_). They are reset if they were explicitly set in `~/.ideavimrc`.
Also bumps the IDE build number to 233.11799.241 in order to use EditorSettingsExternalizable.PropNames
String and number/toggle options have different and opposite behaviour for `:set {option}<` and `:setlocal {option}<`. This change matches Vim's behaviour.
While they are core Vim options, they are implemented by the host, not by the engine. If another host wants to support these options, they can add them in their implementation layer.
IntelliJ ties the hard wrap right margin guide with the other visual guides, and it's not possible to show one without the other. In Vim, you can show the hard wrap margin by adding "+0" to 'colorcolumn', so in IdeaVim, we automatically add this.
Also supports overriding local-to-buffer options with IDE values, ensuring that changes to the option/IDE value are applied to all editors for the buffer.
Fixes VIM-1310
There is no need to clean up the requiredShortcuts after turning off the plugin. Also, previously this set was not populated properly and keys that were added by ideavimrc or by user were not restored
EditorDataContext cannot be used because the platform cannot convert it to the async data context. Taking the fact that it's not clear why this custom context exists, I decided to get rid of it at all.
```
Cannot convert to AsyncDataContext at 'keyboard shortcut' DataContextWrapper(CaretSpecificDataContext(com.maddyhome.idea.vim.helper.EditorDataContext)). Please use CustomizedDataContext or its inheritors like SimpleDataContext
```
Class EditorDataContext cannot be removed because it's used in github.zgqq.intellij-enhance plugin
EditorDataContext cannot be used because the platform cannot convert it to the async data context. Taking the fact that it's not clear why this custom context exists, I decided to get rid of it at all.
```
Cannot convert to AsyncDataContext at 'keyboard shortcut' DataContextWrapper(CaretSpecificDataContext(com.maddyhome.idea.vim.helper.EditorDataContext)). Please use CustomizedDataContext or its inheritors like SimpleDataContext
```
This is a part of VIM-3376. This context will not be a custom EditorDataContext, but some context created by the platform.
In some places we don't have any kind of "current context", but we have to use it for the function. However, such context can be simply retrieved from the editor.
EditorDataContext cannot be used because the platform cannot convert it to the async data context. Taking the fact that it's not clear why this custom context exists, I decided to get rid of it at all.
```
Cannot convert to AsyncDataContext at 'keyboard shortcut' DataContextWrapper(CaretSpecificDataContext(com.maddyhome.idea.vim.helper.EditorDataContext)). Please use CustomizedDataContext or its inheritors like SimpleDataContext
```
This context was added long ago, but I wasn't able to find specific reasons for that. Currently, such custom contexts cannot work with the intellij platform and should be refactored or removed. The issues with this context are that it cannot be converted to the async data context by the platform.
Taking the fact that the reason for this context was not found, I decided to get rid of it.
The issue from the platform looks like this
```
Cannot convert to AsyncDataContext at 'keyboard shortcut' DataContextWrapper(CaretSpecificDataContext(com.maddyhome.idea.vim.helper.EditorDataContext)). Please use CustomizedDataContext or its inheritors like SimpleDataContext
```
Here the EditorDataContext is mentioned instead of CaretAndEditorData context, however, I'll clean up both contexts during this refactoring
It was used in the action system for mapping to the `<Action>` keyword and in commit 256f5fcd0e it's mentioned that the EditorActionHandler was not working without this context. However, currently both cases work fine without addition wrapping.
The tests shows that the depth of `epsilonVisited` is usually around 0-3, so there is no need to use the set. However, when the set is used, we have to make a new copy everytime we create a new `SimulationStackFrame`.
Now, the previous stack is reused.
Register groups for the caret do not use some fields from the base class, however the listener for these fiels is still registered. Now we don't register this listener.
Generally it looks like a bigger refactoring can be performed in order to separate the common registers logic from caret registers logic.
This change should improve the performance of the IjVimCaret initialization because now we won't register a new disposable on each instance of IjVimCaret
This is a part of VIM-3336
In the future, it should become a container for all the search methods that we have in IdeaVim
At the moment we have a bunch of SearchGroups and SearchHelpers, and it may be confusing.
We also want to avoid using unnecessary OOP.
We want to avoid unnecessary OOP and use interfaces only for cases where we will have different implementations for different IDEs
This service will help us in our future refactorings of SearchGroup and SearchHelper
The fact that these methods only return local editors (i.e., editors for the local user while hosting a Code With Me session) is an implementation detail
Applying default values may lead to unexpected results, especially if we sometimes want to use the global state (IJ), and at other times, its clone for asynchronous processing (Fleet).
It unnecessarily binds mappingState to mode and thus to editor. And we want to simplify things and have a single MappingState instead of multiple of them
Rationale:
1. A much more experienced developer, whom I highly respect, suggested to empty VimStateMachineImpl constructor in his TODO comment.
2. I aim for VimStateMachine to be a data class rather than being a container for both data and complex logic.
3. From an architectural perspective, it is more correct. Editors do have state (or they may possess a single global state if the corresponding option is set), but a state does not own an editor.