This allows users to easily retrieve values from option scope:
val x = option { get<Int>("history") }
- Changed option() signature from Unit to generic T return type
- Updated VimApiImpl implementation to return the lambda result
- Added test demonstrating the new return value capability
- Convert OptionScope from abstract class to interface
- Extract inline functions with reified types as extension functions
- Make getOptionValue() and setOption() public interface methods
- Remove internal modifier layer functions
- Update OptionScopeImpl to implement new interface
- Add documentation recommending extension function usage
- Update test imports to use new extension functions
- append(): adds values to end of comma-separated list (like Vim's +=)
- prepend(): adds values to beginning of list (like Vim's ^=)
- remove(): removes values from list (like Vim's -=)
- All functions prevent duplicate values from being added
- Comprehensive test coverage for all scenarios
Adds a simple toggle() function that flips boolean option values.
Works with both full option names and abbreviations.
Example usage:
toggle("ignorecase") // true → false, false → true
toggle("ic") // works with abbreviations
Adds a concise String.split() extension function within OptionScope that splits
comma-separated option values into lists. This simplifies working with list-type
options like 'virtualedit', 'whichwrap', etc.
Example usage:
val values = get<String>("virtualedit")?.split() ?: emptyList()
// "block,all" → ["block", "all"]
Added extensive test coverage for the OptionScope API including:
- String list options with various formats (single, multiple, empty values)
- Error handling for invalid values, empty names, and type mismatches
- Boundary conditions for integer options
- Boolean/integer type conversions
- Global vs local option scoping
- Option abbreviations
- Edge cases like trailing/leading commas and very long strings
This is necessary because I would like to use `registerMappings` in
the constructor of `NerdDispatcher` where we have no access to
private methods of `NerdTree`.
Also, `callAction` is moved into `nerdtree.Mappings.Action` and
duplicated `addCommand` is removed.
The user may have pressed `g` accidentally and wish to perform an
operation which is not prefix by `g`.
This gives the user a way to clear the keys entered previously and
matches Vim's behavior.
What we can benefit from this approach:
- User perspective
The SpeedSearch input will pop up immediately to indicate that
`/` has been pressed, and search text can then be entered to
filter the tree nodes.
- Codebase perspective
The `waitForSearch` property can be removed from the Dispatcher
objects, and we can get rid of `ToolWindowManagerListener` and
the concurrency issue in it. This keeps code simple and readable.
In my previous attempt to preserve the `waitForSearch` prop, the
Dispatcher object had to be passed to each action impl as an
argument.
1) ExException is wrapped with the IllegalArgumentException. We cannot use the raw ExException as it's not defined in the API module. So, if any client will have an access only to the API module, they won't be able to handle this kind of the exception.
2) getOption throws IllegalArgumentException if the type classifier is null. I don't know when this might happen, but this looks more like a plugin developer error. Also, this allows to distinguish the wrong option name vs this type of problem
3) In setOption and getOption throw an exception if there is no such option. This clearly explains what is wrong with this call.
Note: there was a question of using exceptions vs some return values, even like `Result`. The decision falls into the using of exceptions as using the wrong arguments in the plugin is a programming error from the user point of view.
This means, if there is a plugin that checks some option that in reality doesn't exist, it's not a fail of the end user and the end user cannot do anything about that.
Also, using the `Result` will force the plugin developer to handle all possible failure branches, what is quite unnecessary when accessing a well-defined option.
Previously, we would drop out of VimShortcutKeyAction when hitting Tab in Insert mode. This allowed Emmet to work because ExpandLiveTemplateByTabAction (one of the many actions registered for Tab) would have a chance to handle it.
Now we let Tab actions try to handle the key before Vim does, so we can let Vim handle Tab. In Insert mode, Vim now inserts the tab (or equivalent spaces) by invoking the "EditorTab" action, which is the same as the TabAction handler in the list of actions. Because Vim does this, we can now easily repeat inserting Tab without workarounds, remap `<Tab>` and `<S-Tab>` and Vim will update scroll locations after inserting the text.
Fixes VIM-2331. FixesJetBrains/ideavim#938. FixesJetBrains/ideavim#280
Would previously normalise against the entire buffer line length rather than just the current visual line length. For short lines, this would not include inlays, and would therefore position the caret wrong when moving up/down at end of line. For long, wrapped lines, this just plain wouldn't work.
Fixes VIM-3997
The way we split plugin.xml was outdated. Also, it started to show errors in highlighting, even there were no errors.
It's better to keep everything in a single file
The suspending operations must not be performed under the read or write actions as this will lead to performance issues or freezes.
Also, the current implementation of launching coroutine under the write action is simply incorrect. The coroutine will escape the write action into another thread.