Added prominent warning notice to all Plugin API documentation files:
- Plugin-API-reference.md
- Plugin-API-introduction.md
- Plugin-API-quick-start-guide.md
- Plugin-API-tutorial-replace-with-register.md
The warning clearly states that the API is experimental and not
recommended for production use, with potential breaking changes.
- Document that option() function now returns a value
- Add comprehensive documentation for list option methods (append, prepend, remove)
- Add utility methods documentation (toggle, split)
- Include practical usage examples and common use cases
- Update method signatures to reflect non-nullable returns
- Add Vim command equivalents for better understanding
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
The implementation always returns a value or throws an exception,
so the return type should be non-nullable to reflect this behavior.
Updated extension functions to remove unnecessary null checks.
- 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