Scripts
A plugin with main = "main.rn" in its manifest runs that script, written
in Rune. notesy compiles it when the
plugin starts and runs it on a thread of its own, so the window never waits
for it.
#More than one file
A script can be split up with Rune's modules: mod helpers; in main.rn
takes in helpers.rn beside it (or helpers/mod.rn), and its public
functions are then helpers::name(). Modules can have modules of their own
the same way, a folder down each time.
rust// main.rn
use notesy::log;
mod helpers;
pub fn ready() {
log::info(`twice 2 is ${helpers::double(2)}`);
}
// helpers.rn
pub fn double(n) { n * 2 }
Every file comes from the plugin's own folder, and none through a link: a script can't take in a file from anywhere else. Packing takes every file in the folder, so the modules go with it.
#What a script can reach
Rune itself has no files, network or processes. notesy adds its own
modules, under notesy::, and only the ones the plugin's permissions cover:
a script that uses a module it wasn't given doesn't compile.
rustuse notesy::{events, log, settings, store};
| Module | Needs | Page |
|---|---|---|
notesy::log |
nothing | notesy::log |
notesy::events |
per event | notesy::events |
notesy::store |
nothing | notesy::store |
notesy::settings |
nothing | notesy::settings |
notesy::secrets |
nothing | notesy::secrets |
notesy::json |
nothing | notesy::json |
notesy::toml |
nothing | notesy::toml |
notesy::yaml |
nothing | notesy::yaml |
notesy::files |
nothing (its own folder only) | notesy::files |
notesy::icons, notesy::canvas |
nothing (its [[icons]] without a file) |
notesy::icons |
notesy::Event |
nothing: what events::on takes |
notesy::events |
notesy::{Icon, Color, Tone, Side, Method, Command, Zone} |
nothing: notesy's names, as enums | Names: Icon, Color, Tone, Side, Method, Command, Zone, Event |
notesy::view |
nothing | notesy::view |
notesy::commands |
commands |
notesy::commands |
notesy::views |
ui |
notesy::views |
notesy::sections |
ui |
notesy::sections |
notesy::status |
ui |
notesy::status |
notesy::tools |
ui |
notesy::tools |
notesy::zones |
ui |
notesy::zones |
notesy::notices |
notify |
notesy::notices |
notesy::clipboard |
clipboard.write to copy, clipboard.read to paste |
notesy::clipboard |
notesy::sound |
sound (and [[sounds]] for files of its own) |
notesy::sound |
notesy::links |
links.open to open pages; [net] to name links to its sites |
notesy::links |
notesy::notes |
notes.read to read, notes.write to change |
notesy::notes |
notesy::editor |
editor |
notesy::editor |
notesy::net |
net (hosts in [net]) |
notesy::net |
notesy::ipc |
ipc (sockets in [ipc]) |
notesy::ipc |
notesy::accounts |
accounts (and [[accounts]]) |
notesy::accounts |
notesy::blocks |
markdown (languages in [contributes] blocks) |
notesy::blocks |
How the runtime was built, and why: plan.md.
#Its lifecycle
A script may define any of these; notesy calls each one it defines, in this order over a plugin's life:
| Function | When |
|---|---|
pub fn load() |
It's loaded, before anything else reaches it: set yourself up here. |
pub fn updated(from, to) |
It runs another version than last time (from and to are version strings): bring your store along. |
pub fn ready() |
notesy is up, with a vault open and its tabs back: start what needs the app or the notes. A plugin turned on later hears this right after load. |
pub fn setting_changed(key) |
The user changed one of its settings. |
pub fn held_back(permissions) |
The vault that's open keeps some of what it was granted from it: permissions is a list of ids (notes.read, editor), empty when the vault keeps nothing. Told when it starts and again whenever a vault is opened. |
pub fn unloading() |
It's being turned off, or notesy is quitting: save and let go, quickly. |
A vault kept in one encrypted file holds plugins off its notes unless it's
been asked about them. Your plugin still runs, draws and adds its commands;
what it can't do is read or change what's in the vault, or hear the events
about it. held_back is how you find out, so you can say so in your panel
rather than appearing to work and do nothing. The user can let you in by name
from your plugin's page in Settings.
Events it subscribed to with events::on arrive in between, one at a time,
in the order they happened.
#Limits
Every call into a script (a lifecycle function, an event handler) runs within limits:
| Limit | Default | When it's reached |
|---|---|---|
| Instructions per call | 1,000,000 | the call is halted: "it ran too long" |
| Instructions per view | 5,000,000 | the view is halted |
| Memory, across its calls | 64 MiB | the allocation fails, and the call with it (what earlier calls kept counts too) |
| Failures a minute | 3 | the plugin is stopped |
Values going between a script and notesy (what it keeps, shares, sends as JSON, or builds a view from) nest at most 64 deep: a list or object nested deeper is an error where it's handed over.
A failure is a call that errors (a panic, a ? on an error, a wrong type)
or is halted. Each goes to the plugin's log on the Plugins page. The third
in a minute stops the plugin, with a notice saying which and why; it stays
stopped until notesy starts again or it's turned off and on.
Waiting costs nothing: a script that has nothing to do isn't running.
#Errors
If the script doesn't compile, the plugin doesn't start, and its log shows what the compiler said, with the file and line:
error: Expected expression but got `;`
┌─ main.rn:1:26
│
1 │ pub fn ready() { let x = ; }
│ ^
Errors while it runs show the function or event they happened in, like
note.saved: there's no event “note.eaten”.
Warnings go to its log as it starts, and notesy plugin check prints
them: the compiler's (a template with nothing in it), and what notesy
knows Rune runs wrong (the trap below), each with
its file and line.
#Values
What a script keeps and is given are plain values: true and false,
integers, floats, strings, vectors and objects (#{ key: value }) of those.
An event is an object with its name and its fields
(notesy::events). Paths are always relative to the vault
(Daily/2026-09-12.md), never the machine's.
#A trap in Rune 0.14
In a match on text or a number, an arm whose block ends in a variable of
its own gives nothing, not the variable:
rustuse notesy::view;
fn part(kind) {
match kind {
// Comes out as nothing: a view with it says “item 2: nothing can't be kept”.
"tags" => { let chips = view::chips(["#a"]); chips.target = "tag"; chips },
_ => view::note(kind),
}
}
Build such a part in a function of its own ("tags" => tag_chips()), or end
the block in a call (view::chips(…)). A match on an Option
(Some(x) => { … }) is fine.
#More of Rune 0.14's ways
- An arm matches one pattern:
"a" | "b" => …doesn't compile. Give each its own arm. len(), a note'swords()and other counts are unsigned. A sum that goes below nothing (a.len() - b.len()withbthe longer) fails as it runs, not as it compiles: compare first, or keep counts in integers of the script's own.- Taking a tuple apart (
let (a, b) = pair;,for (k, v) in object) is warned about as a pattern that might panic. Read its parts by place (pair.0) or by key (for k in object.keys()), or keep objects (#{ a, b }) instead. - In a closure,
if let Some(x) = x { … }withxthe closure's own argument doesn't compile ("Missing variable"). Give the inner one another name. - Some words are Rune's own and can't be a function's name:
select,is,not,yieldand the like (henceeditor::set_selection). returncan't be followed by a template string:return `a${b}`;doesn't compile ("Expected a closing brace"). Let it be the block's last value, or writereturn "a" + b;.- An object's
insert(key, value)takes the text inkeyaway from the variable it was in: reading that variable after fails as it runs ("Cannot read, value is M-000000"). Insert a copy,key.clone(), when the key is wanted again. - A string's
splitcan be kept, in an object, and read on withnext()in a later call: a long text worked through a step at a time without being cut into a list first (seeexample.import'senml.rn).
Every page
- Overview
- plugin.toml: Every field of plugin.toml
- Permissions: What a plugin can ask for, when notesy asks, and what changes it
- Scripts: How a script runs: its lifecycle, events, limits and errors
- Packing and installing: Making, checking, signing, packing and installing
- notesy::log: Lines for its log on the Plugins page
- notesy::events: Hearing what happens, and every event
- notesy::commands: Adding commands, and running notesy's
- notesy::store: Keeping its own data
- notesy::settings: Reading its settings
- notesy::secrets: Keys and tokens, in the system keychain
- notesy::notes: Reading and changing the vault's notes
- notesy::editor: The note in front
- notesy::templates: What templates fill in, and functions of its own for them
- notesy::files: A folder of its own
- notesy::links: Opening pages in the browser, naming links after their pages
- notesy::clipboard: Copying and pasting
- notesy::view: What panels, tabs and sections show
- notesy::sections: Sidebar sections
- notesy::hidden: Hiding notes, files and folders from the tree
- notesy::status: Status bar items
- notesy::tools: Buttons in the formatting bar
- notesy::notices: Notices
- notesy::dialogs: Asking in a dialog, notesy's kinds or its own
- notesy::wizards: Pages one after another, like a setup
- notesy::boards: Boards' cards and arrows, and kinds of card of its own
- notesy::blocks: Drawing its fenced blocks
- notesy::icons: Drawing its own icons
- notesy::net: Requests to the sites it names
- notesy::ipc: Talking to a program on this computer
- notesy::accounts: Signing in to a service
- notesy::json: Reading and writing JSON
- notesy::toml: Reading and writing TOML
- notesy::yaml: Reading and writing YAML, and a note's front matter
- notesy::time: Now, written in the user's time zone, dates read, how long ago
- notesy::math: Trigonometry and the like, for drawing
- Names: Icon, Color, Tone, Side, Method, Command, Zone, Event: Notesy's names as enums
- notesy::preview: Its own screens for notesy preview
- notesy::perf: Timing its own work
- notesy::drawings: Drawings' shapes, and buttons in their tool strip
- notesy::sound: Playing sounds, and making them as it runs
- notesy::tex: Math macros for every note's formulas
- notesy::views: Side panels, tabs of its own, and its part of the tree's hover cards
- notesy::zones: Notesy's own places — its menus, its bars and its headings