-
Notifications
You must be signed in to change notification settings - Fork 798
Plugin API quick start guide
⚠️ EXPERIMENTAL API WARNINGThe Plugin API is currently in an experimental stage and is not yet recommended for production use.
- The API is subject to breaking changes without notice
- Features may be added, modified, or removed in future releases
- Documentation may not fully reflect the current implementation
- Use at your own risk for experimental purposes only
We welcome feedback and bug reports to help improve the API, but please be aware that stability is not guaranteed at this time.
This guide will help you get started with developing plugins for IdeaVim. We'll cover the essential concepts and show you how to create a simple plugin.
For now, you can create plugin in the IdeaVim extensions package - link.
The entry point for an IdeaVim plugin is a function annotated with @VimPlugin
:
@VimPlugin(name = "MyFirstPlugin")
fun VimApi.init() {
// Plugin initialization code goes here
}
Here we will register mappings, listeners, commands etc.
Let's add a simple mapping that displays a message in the output panel:
@VimPlugin(name = "MyFirstPlugin")
fun VimApi.init() {
mappings {
nmap(keys = "<leader>h", label = "HelloWorld") {
outputPanel {
setText("Hello from my first IdeaVim plugin!")
}
}
}
}
You can define mappings for different Vim modes:
mappings {
// Normal mode mapping
nmap(keys = "<leader>x", label = "MyNormalAction") {
// Action implementation
}
// Visual mode mapping
vmap(keys = "<leader>y", label = "MyVisualAction") {
// Action implementation
}
// Insert mode mapping
imap(keys = "<C-d>", label = "MyInsertAction") {
// Action implementation
}
}
You can get and set Vim variables:
// Get a variable
val count = getVariable<Int>("v:count1") ?: 1
val register = getVariable<String>("v:register") ?: "\""
// Set a variable
setVariable("g:my_plugin_enabled", true)
You can execute normal mode commands and Ex commands:
// Execute a normal mode command
normal("dd")
// Execute an Ex command
execute(":set number")
You can manipulate text in the editor:
editor {
change {
forEachCaret {
// Insert text at the current caret position
insertText(offset, "Hello, world!")
// Replace text in a range
replaceText(startOffset, endOffset, "New text")
// Delete text in a range
deleteText(startOffset, endOffset)
}
}
}
Since JetBrains IDEs have multiple-caret support, in IdeaVim every caret has its own registers and marks. You can read from and write to registers like this:
// Read from register 'a'
val text = editor {
read {
withPrimaryCaret { getReg('a') }
}
}
runBlocking { println(text.await()) }
// Write to register 'b'
val job = editor {
change {
withPrimaryCaret {
setReg('b', "New content", TextType.CHARACTER_WISE)
}
}
}
runBlocking { job.join() }
Here's a simple plugin that adds a mapping to uppercase the selected text:
@VimPlugin(name = "ToUppercase")
fun VimApi.init() {
mappings {
vmap(keys = "<leader>ll", label = "ToUpperCase") {
editor {
val job = change {
forEachCaret {
// Get the current selection
val selectionStart = (selection as Range.Simple).start
val selectionEnd = (selection as Range.Simple).end
// Get the selected text
val selectedText = text.substring(selectionStart, selectionEnd)
// Replace with uppercase version
replaceText(selectionStart, selectionEnd, selectedText.uppercase())
}
}
}
}
}
}