Build plugins for notesy

Build plugins for notesy: small Rune scripts that add panels, commands and more, and do only what the user allows.

The API

Basics

  • log: Lines for its log on the Plugins page
  • events: Hearing what happens, and every event
  • commands: Adding commands, and running notesy's
  • store: Keeping its own data
  • settings: Reading its settings
  • secrets: Keys and tokens, in the system keychain

Notes and files

  • notes: Reading and changing the vault's notes
  • editor: The note in front
  • templates: What templates fill in, and functions of its own for them
  • files: A folder of its own
  • links: Opening pages in the browser, naming links after their pages
  • clipboard: Copying and pasting

Interface

  • view: What panels, tabs and sections show
  • sections: Sidebar sections
  • hidden: Hiding notes, files and folders from the tree
  • status: Status bar items
  • tools: Buttons in the formatting bar
  • notices: Notices
  • dialogs: Asking in a dialog, notesy's kinds or its own
  • wizards: Pages one after another, like a setup
  • boards: Boards' cards and arrows, and kinds of card of its own
  • blocks: Drawing its fenced blocks
  • icons: Drawing its own icons

The web and this computer

  • net: Requests to the sites it names
  • ipc: Talking to a program on this computer
  • accounts: Signing in to a service

Data and helpers

  • json: Reading and writing JSON
  • toml: Reading and writing TOML
  • yaml: Reading and writing YAML, and a note's front matter
  • time: Now, written in the user's time zone, dates read, how long ago
  • math: Trigonometry and the like, for drawing
  • names: Notesy's names as enums

Tools

  • preview: Its own screens for notesy preview
  • perf: Timing its own work

How plugins work

A notesy plugin is a folder with a plugin.toml in it. Some plugins only add looks (themes, icon packs, syntax, colors, code languages): notesy reads what they declare and does it itself, and they run nothing. Others run a script, written in Rune, which notesy runs in a sandbox of its own after the user has said yes to what the plugin asks for.

Plugins are a walled garden. A plugin does only what its manifest declares and the user approved; it reaches only the web hosts it names, through notesy's own fetch; it hears only the events its permissions cover. A script has no files, sockets, processes or native code, only notesy's modules.

#A first plugin

Make a folder called you.saves anywhere you like, with two files, then load it: Settings, Plugins, "Load a plugin folder". notesy links it in as it is (nothing to pack) and reloads it each time you save.

plugin.toml:

tomlid = "you.saves"
name = "Saves"
version = "0.1.0"
author = "You"
license = "MIT"
main = "main.rn"
permissions = ["notes.read"]

main.rn:

rustuse notesy::{events, log, store, Event};

pub fn ready() {
    events::on(Event::NoteSaved, |event| {
        let saves = store::get("saves").unwrap_or(0) + 1;
        store::set("saves", saves);
        log::info(`${event.path} saved; ${saves} saves so far`);
    });
}

Open the Plugins page: the plugin asks to read your notes. Say yes, and each time a note is saved, its log (under it on the Plugins page) says so.

#An example to start from

examples/plugins/example.tasks is a whole plugin: a Tasks panel beside the note (its - [ ] lines, what's left and done), a status bar item saying how many are left, and a command. Copy its folder into your plugins folder to try it.

examples/plugins/example.discord talks to a program on this computer rather than a website: it finds the Discord you're already signed in to, over the socket Discord opens for that, and puts what you're writing on your profile. It's the short one to read for notesy::ipc, and for building and reading a protocol's own bytes from a script.

examples/plugins/example.code-editor opens the vault's code, scripts, data and text files in a code editor tab of their own, rather than in another app: each line numbered, in its language's colors, saved back as the file it is. It's one [[opens]] in its manifest (plugin.toml), with no script at all.

examples/plugins/example.weather fetches from the sites its manifest names and draws what comes back: a panel of forecasts with folds, bars and tiles, and the temperature in the status bar. It's the short one for notesy::net.

examples/plugins/example.typing-notes plays a note for every key you strike, the next of a tune wandering up and down a scale its settings pick, made as it plays with no sound files. It hears that a key went down, never which. It's the short one for notesy::sound, and for hearing keys.

examples/plugins/example.goals keeps a daily word goal: the words written today across every note, in the status bar (and its card) and a panel with the streak and the last two weeks. It's the short one for keeping a count from events in the store, and for a setting changed from a command.

examples/plugins/example.flashcards makes cards of the question :: answer lines in notes tagged #flashcards, and reviews them in a tab, each answer setting when the card comes back. It's the one for a tab built from the vault's notes.

examples/plugins/example.kanban shows a note with kanban: true as a board across a whole tab, a lane for each ## heading and a card for each - [ ] line, dragged between lanes, ticked and added to, written back to the note with the rest of it as it was. Boards are made from the palette, the New note and folder menus, or any note's own menu. It's the one for changing notes (notes.write) and for lanes (view::lanes).

examples/plugins/example.queries draws a fenced query block as a table of the notes a search finds, with the columns, filters and order it asks for, and lists them in a panel beside the note to open. It's the one for fenced blocks (notesy::blocks) that read the vault.

examples/plugins/example.import brings notes in from Notion, Evernote and Bear exports the user picks: names cleaned, links between pages made notesy's, tags and dates kept, nothing written over. It's the one for reading what the user picks (files.pick) and for big work done a step at a time.

examples/plugins/example.docx saves the note in front as a Word document, built part by part and zipped: headings, lists, tables, links and code. It's the one for files::zip and saving where the user says (files.save).

examples/plugins/example.vim is a vim mode for the editor: normal, insert and visual, motions with counts, operators, a register, and the mode in the status bar. It's the one for taking the editor's keys (keys.take).

examples/plugins/example.kitchen-sink uses as much of the API as one plugin can: a gallery tab of every part a view can draw, panels, dialogs and wizards, its own kinds of board card and fenced block, functions your templates call, and items in notesy's own menus. It's the one to look something up in rather than to read start to finish.

#Folder layout

plugins/
  you.saves/          one folder per plugin, named after its id
    plugin.toml
    main.rn           its script, when it has one
  grants.toml         what the user allowed each plugin (notesy's own)
plugin-data/
  you.saves/
    store.toml        its settings' values and what it keeps (see api/store.md)

plugin-data is kept apart from plugins so updating a plugin keeps its data.

Every page