-
Notifications
You must be signed in to change notification settings - Fork 298
API Examples
- Introduction
-
Examples
- Bind a key to a command
- Bind a key to insert a snippet
- Bind a key to create a file
- Bind a key to toggle take a screenshot
- Bind a key to toggle recording a video
- Bind a key to a simple menu
- Toggle
relativenumber
depending on mode - Load per-workspace
init.vim
- Create a clock in the statusbar
- Load configuration from JSON
- List of Commands and Defaults
Oni provides an extensible javascript API that is accessible via the activate
method in your config.js
. The same API surface area that is provided to Oni plugins is accessible via the config.js
file. This means that it is easy to 'prototype' a plugin in your config, and then refactor it out into a reusable plugin later if necessary.
For a complete overview of our API, see the API documentation here: https://onivim.github.io/oni-api/
These are some quick examples of how you can use our API to accomplish specific customizations. Some might not be quite production-ready, but hopefully they are useful in showing how you can get started using Oni.
The quickest way to try these out is to open your Oni configuration file, and add them to your activate
method:
export const activate = (oni: Oni.Plugin.Api) => {
// Put your customizations here!
}
When you save your configuration file, if there are no errors, your customization will be picked up 👍
oni.input.bind("<c-space>", "quickOpen.show")
oni.input.bind("<C-enter>", () => alert("hello world"))
TIP: You can also pass an array to bind multiple keys, for example:
oni.input.bind(["<down>", "<up>"], () => alert("don't use arrow keys!"))
This example uses a filter function (isInsertMode
) such that the binding is only available in insert mode.
const isInsertMode = () => oni.editors.activeEditor.mode === "insert"
oni.input.bind("<c-space>", () => oni.snippets.insertSnippet("foo ${1:test} bar ${2:test2}"), isInsertMode)
This recipe opens a file in a vertical split, and sets a couple lines.
NOTE: This requires your configuration is using a TypeScript file (.tsx)
const openFileAndSetContents = async () => {
const buf = await oni.editors.activeEditor.openFile("sometest.txt", { openMode: Oni.FileOpenMode.VerticalSplit})
await buf.setLines(0, 1, [
"line 1",
"line 2"
])
}
oni.input.bind("<c-space>", openFileAndSetContents)
It's easy to create lightweight pop-up menus in Oni!
const createMenu = () => {
const menu = oni.menu.create()
menu.show()
menu.setItems([
{ label: "item1", detail: "some details about item1"},
{ label: "item2", detail: "some details about item2"},
{ label: "item3", detail: "some details about item3"},
])
menu.onItemSelected.subscribe((selectedValue) => alert(selectedValue.label))
}
oni.input.bind("<c-space>", createMenu)
Bonus points: Try something more interesting by populating the menu from a shell process... @CrossR has some great examples of more interesting menus in his config here
const activate = (oni) => {
// access the Oni plugin API here
...
oni.input.bind("<c-enter>", () => oni.recorder.takeScreenshot())
...
};
This binds the <c-enter>
key to run the oni.recorder.takeScreenshot
method, which takes a screenshot of Oni and saves to recorder.outputPath
.
const isNormalMode = () => oni.editors.activeEditor.mode === "normal"
const toggleRecording = () => {
if (oni.recorder.isRecording) {
alert("stopped recording")
oni.recorder.stopRecording()
} else {
oni.recorder.startRecording()
alert("started recording")
}
}
oni.input.bind("<c-space>", toggleRecording, isNormalMode)
This example listens to mode changes, and sets the vim.setting.relativenumber
configuration value based on the mode:
oni.editors.anyEditor.onModeChanged.subscribe((newMode) => {
if (newMode === "insert") {
oni.configuration.setValues({"vim.setting.relativenumber": false})
} else {
oni.configuration.setValues({"vim.setting.relativenumber": true})
}
})
This snippet shows how you can use the full set of [Node JavaScript APIs] within your configuration file. We'll use our workspace API to detect when the workspace changes, and use Node's path
and fs
APIs to check if an init.vim
exists in a .oni
folder at the workspace root. If it does, we'll send a command to Neovim to load the init file
.
const path = require("path")
const fs = require("fs")
const loadWorkspaceInitVim = () => {
if (oni.workspace.activeWorkspace) {
// We're assuming it lives in `.oni/init.vim`
const initVimFile = path.join(oni.workspace.activeWorkspace, ".oni", "init.vim")
if (fs.existsSync(initVimFile)) {
oni.editors.activeEditor.neovim.command(":so " + initVimFile)
}
}
}
// Load the per-workspace init vim whenever it changes
oni.workspace.onDirectoryChanged.subscribe(() => loadWorkspaceInitVim())
// And also on startup, in case we already have a workspace
loadWorkspaceInitVim()
// Create a status bar item on the right side
const clockStatusBarItem = oni.statusBar.createItem(1)
// Make it visible
clockStatusBarItem.show()
// Create a function to get the current time
const updateClock = () => {
const currentDate = new Date()
const time = `${currentDate.getHours()}:${currentDate.getMinutes()}:${currentDate.getSeconds()}`
clockStatusBarItem.setContents(<div>{time}</div>)
}
// Run it on initial load
updateClock()
// And again every second.
// NOTE - This isn't a robust solution and WILL impact performance...
// Not recommended to leave this in your config!
window.setInterval(updateClock, 1000 /* Every second */)
This shows how you can dynamically load configuration settings from a JSON
file. First, we'll create a JSON
file to contain our settings - test-config.json
:
{
"ui.colorscheme": "onedark"
}
Save test-config.json
where you'd like, and then add this to the bottom of your activate
method:
oni.configuration.setValues(require("/path/to/test-config.json"))
The
require
method is built-in to Node/Electron, and will parse thejson
file and return an object. It's picky about proper JSON syntax, though!
You'll need to reload Oni for the settings to take effect.
The actual default bindings are presented in the browser/src/Input/KeyBindings.ts file.