-
-
Notifications
You must be signed in to change notification settings - Fork 23
Extensions
Cord comes with several built-in extensions that you can easily enable and configure. These extensions provide ready-made functionality for common use cases.
To use an extension, simply add its require path to the extensions table in your cord.setup() configuration. If the extension is built-in, you can simply use the name alone.
require('cord').setup {
extensions = {
-- Enable an extension with its default config
'diagnostics',
-- Enable AND configure an extension
resolver = {
-- ...
}
},
}Name: diagnostics
Purpose: Adds real-time LSP diagnostics (errors, warnings, hints) information to your Rich Presence. Displays the number of diagnostics in the current buffer or workspace.
Configuration Options:
{
scope = 'buffer', -- 'buffer' (default) or 'workspace': Scope of diagnostics to display
severity = { min = vim.diagnostic.severity.WARN }, -- Diagnostic severity filter (see Neovim `:help diagnostic-severity`)
override = true, -- Whether to override default text configurations (recommended: true)
}-
scope:-
'buffer'(default): Show diagnostics count for the current buffer only. Overridestext.viewingandtext.editingto include diagnostics count. -
'workspace': Show diagnostics count for all buffers in the workspace. Overridestext.workspaceto include diagnostics count.
-
-
severity:- A table defining the minimum diagnostic severity level to include in the count. Uses Neovim's diagnostic severity levels (see
:help diagnostic-severity). - Example:
{ min = vim.diagnostic.severity.WARN }will count warnings and errors, but not information messages or hints. - Defaults to showing errors.
- A table defining the minimum diagnostic severity level to include in the count. Uses Neovim's diagnostic severity levels (see
-
override:-
true(default): The extension will automatically override thetext.viewing,text.editing, andtext.workspaceoptions to display diagnostics information. Recommended for seamless integration. -
false: The extension will not override text options. You'll need to manually use the extension's variables in yourtextconfiguration to display diagnostics (see "Usage Example" below).
-
Variables Added:
-
diagnostic: A table containing the scoped diagnostics data (useful for advanced customization). -
diagnostics: A function that returns the number of diagnostics in the current scope (buffer or workspace), based on the extension's configuration.
Usage Example (override = false):
text = {
-- In string templates
editing = 'Editing ${filename} - ${diagnostics} problems',
-- In functions
workspace = function(opts) return 'In ' .. opts.workspace .. ' - ' .. opts.diagnostics(opts) .. ' problems' end,
}Name: resolver
Purpose: Provides specialized metadata resolvers for accurate filetype and workspace detection in edge cases where standard detection falls short.
Configuration Options:
{
sources = {
nestjs = false,
toggleterm = false,
oil = false,
},
}-
sources:- A table of resolver sources that can be individually enabled or disabled.
- Supports global toggle:
sources = trueenables all sources,sources = falsedisables all. - Selective overrides:
sources = { true, nestjs = false }enables all except NestJS.
Usage Examples:
-- Enable all except oil
require('cord').setup {
extensions = {
resolver = {
sources = { true, oil = false },
},
},
}Name: visibility
Purpose: Controls whether the Rich Presence activity is shown for a workspace or buffer based on rules. Useful for hiding activity for specific projects, directories, or file types.
Configuration Options:
{
override = true, -- Whether the extension overrides activity updates directly
precedence = 'blacklist', -- 'blacklist' or 'whitelist' to resolve conflicts
resolve_symlinks = true, -- Resolve symlinks when matching paths
rules = {
blacklist = {},
whitelist = {},
},
action = nil, -- Optional function called when a visibility decision is made
fallback = nil, -- Optional fallback function when no rule matched
}-
override:-
true(default): Extension will automaticallysuppress()orresume()the manager based on rules. -
false: The extension will not change activity directly; use the provided variables.
-
-
precedence:-
'blacklist'(default): Blacklist rules take precedence when both types match. -
'whitelist': Whitelist rules take precedence.
-
-
rules:-
blacklist/whitelist: Tables of rules. Each rule may be:-
string: A path (contains
/or\) is treated as apathrule; otherwise it's anamerule matching workspace name. -
table:
{ type = 'path'|'glob'|'name', value = '...', action = function(opts) end }. -
function: Custom function that receives
{ rule = <rule>, workspace = <string>, workspace_dir = <string> }and returns truthy to match.
-
string: A path (contains
-
-
action/fallback:- Optional functions called with
{ visible = <bool>, rule = <rule>, workspace = <string>, workspace_dir = <string> }to perform custom behavior when a decision is made.
- Optional functions called with
Variables Added:
-
has_match: Function that returns whether the current buffer/workspace matches any configured rule.
Rule Matching Behavior:
- Rules support types:
path,name, andglob. Globs are converted to regex withvim.fn.glob2regpat. - Paths may be normalized and (optionally) resolved to their real paths when
resolve_symlinks = true.
Usage Example (override = true):
require('cord').setup {
extensions = {
visibility = {
precedence = 'blacklist',
rules = {
blacklist = {
-- string examples
'private', -- matches name
'~/projects/private', -- matches path
-- table examples
{ type = 'glob', value = '**/vendor/**' },
-- function example
function(ctx) return ctx.workspace == 'secret' end,
},
},
},
},
}Name: local_time
Purpose: Sets the Rich Presence timestamp to display the current local clock time (hours, minutes and seconds) instead of elapsed time.
Configuration Options:
{
affect_idle = true,
}-
affect_idle:-
true(default): Also sets the timestamp for the idle status to local time. -
false: Only affects the timestamp for active presence, elapsed time will be shown when idle.
-
Variables Added:
-
local_timestamp: A function that returns the zeroed timestamp of the current local time (midnight of the current day).
[!NOTE] Incompatible with any other timestamp-related extensions.
Name: persistent_timer
Purpose: Provides a persistent timer that tracks the total time spent across multiple Neovim sessions. This timer is scoped and saved to a data file, so that your time spent on a certain scope continues from where it was left off previously, even after restarting Neovim. It's also able to handle multiple simultaneously open clients without data races.
Configuration Options:
{
scope = 'workspace', -- 'workspace', 'file', 'filetype', or 'global'
mode = 'all', -- 'all', 'active', or 'idle'
file = vim.fn.stdpath 'data' .. '/cord/extensions/persistent_timer/data.json', -- Path to the timer data file
save_on = { 'exit', 'focus_change', 'periodic' }, -- Events that trigger a save
save_interval = 30, -- Interval in seconds for periodic saves
}-
scope:-
'workspace'(default): Track one continuous timer for the entire workspace. -
'file': Track a separate timer for each individual file. -
'filetype': Track a separate timer for each filetype (e.g., allluafiles share one timer). -
'global': Track a single timer for all activity within Neovim.
-
-
mode:-
'all'(default): Count all time the corresponding scope is active. -
'active': Only accumulate time when you are actively moving or typing. -
'idle': Only accumulate time when the instance is idle.
-
-
file:- Defines the absolute path to the JSON file where time data is stored.
- Defaults to a file within Neovim's standard data directory.
-
save_on:- A table of strings defining when the timer data should be saved to disk.
-
'exit': Saves when Neovim is closed. (Recommended) -
'focus_change': Saves when you focus away from the Neovim window. Important for multi-client sync. -
'periodic': Saves automatically at the interval defined bysave_interval.
-
save_interval:- The number of seconds between automatic saves if
'periodic'is enabled.
- The number of seconds between automatic saves if
[!NOTE] Incompatible with any other timestamp-related extensions.
Name: scoped_timestamps
Purpose: Tracks elapsed time independently for each buffer or workspace. Optionally "pauses" and "resumes" the timestamp when switching between buffers, providing more context-aware time tracking.
Configuration Options:
{
scope = 'buffer', -- 'buffer' (default), 'workspace', or 'idle'
pause = true,
}-
scope:-
'buffer'(default): Track time elapsed per buffer. Timestamp resets when switching buffers (ifpause = false), or pauses/resumes (ifpause = true). -
'workspace': Track time elapsed per workspace. Timestamp is consistent across buffers within the same workspace. -
'idle': Track time spent in idle state. Shows elapsed idle time when in idle, and normal activity time when active.
-
-
pause:-
true(default): When switching scope, the timestamp "pauses" for the previous scope and "resumes" where it left off when you return to that scope. -
false: When switching scope, the timestamp for the previous scope is not untouched, resulting in two scopes.
-
Variables Added:
-
get_scoped_timestamp(): A function that returns the appropriate timestamp value based on the extension'sscopeandpausesettings. This is used internally by the extension.
[!NOTE] Incompatible with any other timestamp-related extensions.
Name: lastfm
Purpose: Displays your current Last.fm "Now Playing" track in Rich Presence. By default, takes full control of the activity. If you want to disable this behavior, set override = false.
Requirements:
-
LASTFM_USERNAMEandLASTFM_API_KEYenvironment variables must be present. You can get them from here by creating an API account. -
curlmust be available on your system (used for HTTP requests).
Configuration Options:
{
interval = 10000,
max_retries = 3,
override = true,
-- fallback_image = '...',
}-
interval: How often to poll Last.fm for the latest track. Minimum is 500ms. -
max_retries: Number of times failed HTTP requests will be retried. -
override:-
true(default): The extension fully manages activity updates. -
false: The extension will not change activity directly; instead, it exposes variables you can use in your own configuration.
-
-
fallback_image: Image URL used when the track has no album art or Last.fm returns a placeholder.
Variables Added:
-
track_title: The current track title (ornilif none). -
track_artist: The current track artist (ornil). -
track_album: The current track album (ornil). -
track_url: The Last.fm track URL (ornil). -
track_image: The best available album image URL or the configuredfallback_image.
Usage Example (override = false):
require('cord').setup {
extensions = {
lastfm = { override = false },
},
text = {
viewing = 'Listening to ${track_title} β ${track_artist}',
editing = 'Listening to ${track_title} β ${track_artist}',
},
}[!NOTE] Incompatible with any other extension if
override = true.