Skip to main content
This guide covers common patterns used in Fresh plugins, with examples from the plugin library.

Text Highlighting with Overlays

Overlays allow you to visually highlight text without modifying buffer content. They’re perfect for search results, diagnostics, or temporary annotations.
Use namespace prefixes for overlays to enable batch removal. This is essential for plugins that create many temporary highlights.

Creating Results Panels

Virtual buffers are ideal for displaying search results, diagnostics, or any structured data that users can navigate.
1

Define a Custom Mode

Create keybindings specific to your results panel:
2

Create the Virtual Buffer

Build entries with embedded metadata:
3

Handle Navigation

Implement the “go to” action using embedded properties:

Real Example: Diagnostics Panel

From diagnostics_panel.ts - a production virtual buffer implementation:
Virtual buffers automatically persist when reopened with the same panel_id. This provides a seamless UX for results panels.

Running External Commands

Use spawnProcess to integrate with external tools. All process operations are async.
Always handle both exit_code and exceptions. Non-zero exit codes don’t throw errors - check them explicitly.

LSP Requests

Plugins can invoke custom LSP methods for language-specific features like type hierarchy, switch header, or clangd extensions.
The method name should be the full LSP method (e.g., textDocument/typeHierarchy). Response handling is your responsibility.

File System Operations

Fresh provides async file I/O APIs for reading, writing, and checking files.
writeFile will overwrite existing files without confirmation. Always check file existence first if needed.

Event Handling

Plugins can react to editor events using the editor.on() API.
Event handlers should return true if they handled the event, or false to let it propagate.

Interactive Prompts

Create rich selection interfaces with suggestions and fuzzy matching.
See Events API for complete prompt event handling.

Command Registration

Make your plugin functions discoverable through the command palette.
Use mode filters to prevent command clutter. Mode-specific commands only appear when that mode is active.

State Management

Plugins maintain state using standard JavaScript variables and data structures.
State is not persisted between editor sessions. For persistent state, use file system APIs to save/load configuration.

Best Practices

Always include the Fresh types reference:
This enables autocomplete and catches errors at development time.
Always update status after operations:
Use editor.debug() for development logging:
Remove overlays, close panels, and clear state when done:
Wrap async operations in try-catch:
Prefix overlays and virtual buffers with your plugin name:

Next Steps

Buffer API

Learn about buffer manipulation and text operations

Events API

React to editor events and user actions

Overlays API

Master visual highlighting and annotations

Virtual Buffers API

Create powerful results panels and UI