Skip to content
This repository has been archived by the owner on Apr 1, 2020. It is now read-only.

API Examples

Paul Roberts edited this page Aug 30, 2018 · 13 revisions

Introduction

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/

Examples

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 👍

Bind a key to a command

oni.input.bind("<c-space>", "quickOpen.show")

Bind a key to a function

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!"))

Bind a key to insert a snippet

snippet

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)

Bind a key to open a file and set contents

open-file

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)

Bind a key to a simple menu

menu

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

Bind a key to take a screenshot

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.

Bind a key to toggle recording a video

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)

Toggle relativenumber depending on mode

toggle-config

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})
        } 
    })

Load init.vim in a workspace, if it exists

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 clock in the statusbar

clock

// 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 */)

Load configuration from JSON

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 the json 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.

List of Commands and Defaults

The actual default bindings are presented in the browser/src/Input/KeyBindings.ts file.