Docs / Guides
Decorations
A decoration is something an extension paints on top of the text of a file: a background behind a color, a wavy underline, a note after a line, a star in the gutter. It does not change the file. It is only drawn, and it disappears when the extension is turned off.
Decorations arrived with extension API level 0.1.1: an extension that uses them should say "engines": { "ferrum": "^0.1.1" }, so editors that do not have them do not install it. They need no permission, because they only affect the file the person already has open.
exports.activate = function (context) {
// 1. Make a type: how it looks.
const warn = ferrum.editor.createDecorationType({
backgroundColor: 'rgba(245, 158, 11, 0.25)',
textDecoration: 'underline wavy',
});
context.subscriptions.push(warn);
// 2. Say where to use it, in the open file.
async function paint() {
const doc = await ferrum.editor.active();
if (!doc) return;
const ranges = [];
doc.text.split('\n').forEach((line, i) => {
const col = line.indexOf('TODO');
if (col >= 0) ranges.push({ start: { line: i, col }, end: { line: i, col: col + 4 }, hoverMessage: 'Something to do' });
});
await ferrum.editor.setDecorations(warn, ranges);
}
// 3. Paint again when the text changes.
context.subscriptions.push(
ferrum.events.on('change', paint),
ferrum.events.on('activeChanged', paint),
);
paint();
};
ferrum.editor.createDecorationType(options)
Returns a type: { id, dispose() }. Disposing it removes every decoration of that type. An extension can make 30 types; make them once, at activation, and reuse them.
| Option | Description |
|---|---|
color |
Text color. |
backgroundColor |
Background behind the range. |
fontWeight |
normal, bold, or 100 to 900. |
fontStyle |
normal or italic. |
textDecoration |
underline, line-through, overline, underline wavy, underline dotted, underline dashed or underline double. |
border |
For example 1px solid #ff0000. Width 1 to 99 px; solid, dashed or dotted. |
borderRadius |
A number of pixels, 0 to 20. |
opacity |
0.1 to 1. |
outline |
Like border. |
isWholeLine |
true makes the background cover the whole line, not only the range. |
gutterText |
One or two characters shown next to the line number, such as ★ or !. |
gutterColor |
The color of that text. |
after |
{ contentText, color?, backgroundColor?, fontStyle?, fontWeight? }: a note drawn after the end of the line. |
Colors are #rgb, #rrggbb, #rrggbbaa, rgb(), rgba(), hsl(), hsla(), a color name, or var(--accent) (and the other editor variables) so a decoration can follow the theme. Anything else is ignored. Values are checked: url(...) and other CSS tricks never reach the page.
ferrum.editor.setDecorations(type, ranges, path?)
Sets where type is used, replacing what it marked before in that file. Pass an empty array to clear it. By default it applies to the file being edited; pass path (from ferrum.editor.active()) to target another open file.
Each range:
| Key | Description |
|---|---|
start, end |
Positions { line, col }, both from 0. A range can span lines. An end equal to start marks nothing inline but still draws the gutter mark, whole-line background and after note of that line. |
hoverMessage |
Text shown when the pointer rests on the range. |
after |
A note after this line, replacing the type's own. |
style |
Any of the type options above, for this range only. This is how a color extension gives each color its own background. |
Limits: 10,000 ranges per call, 200 characters per note. Notes appear after the end of the line (after the blame or inlay hint, if there is one). They do not push the code sideways.
Keeping decorations up to date
Decorations are positions in the text, so they go stale when the text changes. Subscribe to these events:
| Event | When |
|---|---|
change |
The text of the open file changed (typing, undo, a command). Sent once things settle, about 150 ms after the last change. |
activeChanged |
The person switched to another file. |
open |
A file was opened. |
save |
A file was saved. |
Repaint on change, and make paint cheap: scan only what you need and cap the work (for example the first few thousand lines of a huge file).
Tips
- One type per look. Create types at activation, not inside
paint. - Whole-line highlights:
isWholeLine: truewithbackgroundColor, and a range whosestartandendare the same position on the line. - Gutter marks:
gutterText: '★'with a zero-width range on the line. - Notes after a line (like an error lens): give the range an
after: { contentText: '...' }of its own. - Do not decorate everything. Thousands of ranges per file are fine; hundreds of thousands are not.
- Decorations are drawn over the syntax colors, so a
colorreplaces the token color for that range and abackgroundColorsits behind it.
Examples
These official extensions use decorations and are good to read: Color Swatches, TODO Highlight, Trailing Whitespace, Indent Rainbow, Long Lines and Bookmarks (gutter star and line highlight).