*cord.txt*             For NVIM v0.6.0             Last change: 2025 August 20

==============================================================================
Table of Contents                                     *cord-table-of-contents*

1. Configuration                                          |cord-configuration|
  - Editor                                         |cord-configuration-editor|
  - Display                                       |cord-configuration-display|
  - Timestamp                                   |cord-configuration-timestamp|
  - Idle                                             |cord-configuration-idle|
  - Text                                             |cord-configuration-text|
  - Buttons                                       |cord-configuration-buttons|
  - Assets                                         |cord-configuration-assets|
  - Variables                                   |cord-configuration-variables|
  - Hooks                                           |cord-configuration-hooks|
  - Plugins                                       |cord-configuration-plugins|
  - Advanced                                     |cord-configuration-advanced|
  - User Commands                           |cord-configuration-user-commands|
  - Options Table                           |cord-configuration-options-table|
  - ActivityManager Methods       |cord-configuration-activitymanager-methods|
  - Activity Options                     |cord-configuration-activity-options|
2. Custom Assets                                          |cord-custom-assets|
  - Structure                                   |cord-custom-assets-structure|
  - Asset Keys                                 |cord-custom-assets-asset-keys|
  - Asset Options                           |cord-custom-assets-asset-options|
  - Examples                                     |cord-custom-assets-examples|
  - Overriding Defaults               |cord-custom-assets-overriding-defaults|
  - Tip                                               |cord-custom-assets-tip|
3. Plugins                                                      |cord-plugins|
  - Enabling Plugins                           |cord-plugins-enabling-plugins|
  - Available Plugins                         |cord-plugins-available-plugins|
4. Examples                                                    |cord-examples|
  - Features                                          |cord-examples-features|
  - Installation                                  |cord-examples-installation|
  - Themes                                              |cord-examples-themes|
  - Support the Project                    |cord-examples-support-the-project|

==============================================================================
1. Configuration                                          *cord-configuration*


TABLE OF CONTENTS ~

- |cord-default-configuration|
- |cord-useful-functions|
- |cord-manual-plugin-startup|
- |cord-editor|
- |cord-display|
- |cord-timestamp|
- |cord-idle|
- |cord-text|
- |cord-buttons|
- |cord-assets|
- |cord-variables|
- |cord-hooks|
- |cord-plugins|
- |cord-advanced|
- |cord-user-commands|
- |cord-options-table|
- |cord-activitymanager-methods|
- |cord-activity-options|

A comprehensive guide to configuring the plugin to your liking. All options are
set through the `setup()` function:

>lua
    require('cord').setup {
        -- Your configuration options go here
    }
<


DEFAULT CONFIGURATION ~

If you want a fresh start, you can copy the default config and tweak it. I
suggest only changing what you need, since the rest falls back to defaults.

Default Configuration ~

>lua
    {
      enabled = true,
      log_level = vim.log.levels.OFF,
      editor = {
        client = 'neovim',
        tooltip = 'The Superior Text Editor',
        icon = nil,
      },
      display = {
        theme = 'default',
        flavor = 'dark',
        view = 'full',
        swap_fields = false,
        swap_icons = false,
      },
      timestamp = {
        enabled = true,
        reset_on_idle = false,
        reset_on_change = false,
        shared = false,
      },
      idle = {
        enabled = true,
        timeout = 300000,
        show_status = true,
        ignore_focus = true,
        unidle_on_focus = true,
        smart_idle = true,
        details = 'Idling',
        state = nil,
        tooltip = '💤',
        icon = nil,
      },
      text = {
        default = nil,
        workspace = function(opts) return 'In ' .. opts.workspace end,
        viewing = function(opts) return 'Viewing ' .. opts.filename end,
        editing = function(opts) return 'Editing ' .. opts.filename end,
        file_browser = function(opts) return 'Browsing files in ' .. opts.name end,
        plugin_manager = function(opts) return 'Managing plugins in ' .. opts.name end,
        lsp = function(opts) return 'Configuring LSP in ' .. opts.name end,
        docs = function(opts) return 'Reading ' .. opts.name end,
        vcs = function(opts) return 'Committing changes in ' .. opts.name end,
        notes = function(opts) return 'Taking notes in ' .. opts.name end,
        debug = function(opts) return 'Debugging in ' .. opts.name end,
        test = function(opts) return 'Testing in ' .. opts.name end,
        diagnostics = function(opts) return 'Fixing problems in ' .. opts.name end,
        games = function(opts) return 'Playing ' .. opts.name end,
        terminal = function(opts) return 'Running commands in ' .. opts.name end,
        dashboard = 'Home',
      }, 
      buttons = nil,
      -- buttons = {
      --   {
      --     label = 'View Repository',
      --     url = function(opts) return opts.repo_url end,
      --   },
      -- },
      assets = nil,
      variables = nil,
      hooks = {
        ready = nil,
        shutdown = nil,
        pre_activity = nil,
        post_activity = nil,
        idle_enter = nil,
        idle_leave = nil,
        workspace_change = nil,
      },
      plugins = nil,
      advanced = {
        plugin = {
          autocmds = true,
          cursor_update = 'on_hold',
          match_in_mappings = true,
        },
        server = {
          update = 'fetch',
          pipe_path = nil,
          executable_path = nil,
          timeout = 300000,
        },
        discord = {
          pipe_paths = nil,
          reconnect = {
            enabled = false,
            interval = 5000,
            initial = true,
          },
        },
        workspace = {
          root_markers = {
            '.git',
            '.hg',
            '.svn',
          },
          limit_to_cwd = false,
        },
      },
    }
<


MANUAL PLUGIN STARTUP ~

If you need to delay the initialization of the plugin, you can prevent it from
starting automatically by setting a global variable:

>lua
    vim.g.cord_defer_startup = true
<

With this option set to true, the plugin **will not start automatically**.
Instead, you’ll need to manually initialize it by calling
`require('cord').setup()`.


USEFUL FUNCTIONS ~

- `require('cord.api.icon').get(name: string, theme?: string, flavor?: string): string`
    - **Get Icon URL:** Returns the URL for the specified icon `name`, optional `theme`, and optional `flavor`. If `theme` or `flavor` is not provided, they default to the configured `display.theme` and `display.flavor`, respectively. Useful for referencing Cord’s built-in icons in your custom configurations.


EDITOR                                             *cord-configuration-editor*

  ---------------------------------------------------------------------------------------------------------------
  Option           Type            Default                      Description
  ---------------- --------------- ---------------------------- -------------------------------------------------
  editor.client    string          'neovim'                     Client identifier. Can be 'vim', 'neovim',
                                                                'lunarvim', 'nvchad', 'astronvim', 'lazyvim', or
                                                                a custom Discord application ID

  editor.tooltip   string          'The Superior Text Editor'   Tooltip shown when hovering over editor icon

  editor.icon      string \| nil   nil                          Custom icon URL or asset ID when using custom
                                                                client ID
  ---------------------------------------------------------------------------------------------------------------

DISPLAY                                           *cord-configuration-display*

  ----------------------------------------------------------------------------------------
  Option                Type      Default   Description
  --------------------- --------- --------- ----------------------------------------------
  display.theme         string    default   Choose between different icon themes;
                                            ‘default’, ‘atom’, ‘catppuccin’

  display.flavor        string    dark      Choose between different theme flavors;
                                            typically ‘dark’, ‘light’, ‘accent’

  display.view          string    full      Control what shows up as the large and small
                                            images

  display.swap_fields   boolean   false     Show workspace name before filename

  display.swap_icons    boolean   false     Use editor icon as large image
  ----------------------------------------------------------------------------------------

  [!TIP] Check out our icon showcase <https://github.com/vyfor/icons#showcase>!

VIEW ~

- `full` - always shows both of the icons
- `editor` - only shows the editor icon
- `asset` - only shows the asset (language, file browser, plugin manager, etc.) icon
- `auto` - shows both icons, but drops the language icon if in a new/empty buffer


TIMESTAMP                                       *cord-configuration-timestamp*

  ----------------------------------------------------------------------------------
  Option                      Type      Default   Description
  --------------------------- --------- --------- ----------------------------------
  timestamp.enabled           boolean   true      Show elapsed time in presence

  timestamp.reset_on_idle     boolean   false     Reset timestamp when entering idle
                                                  state

  timestamp.reset_on_change   boolean   false     Reset timestamp when presence
                                                  changes

  timestamp.shared            boolean   false     Synchronize timestamps between
                                                  clients
  ----------------------------------------------------------------------------------

IDLE                                                 *cord-configuration-idle*

  ---------------------------------------------------------------------------------------------------------
  Option                 Type                       Default                           Description
  ---------------------- -------------------------- --------------------------------- ---------------------
  idle.enabled           boolean                    true                              Enable idle status
                                                                                      detection

  idle.timeout           number                     300000                            Milliseconds before
                                                                                      marking the session
                                                                                      as idle

  idle.show_status       boolean                    true                              Show idle status in
                                                                                      presence, or hide the
                                                                                      presence if false

  idle.ignore_focus      boolean                    true                              Show idle despite
                                                                                      Neovim having focus

  idle.unidle_on_focus   boolean                    true                              Unidle the session
                                                                                      when Neovim gains
                                                                                      focus

  idle.smart_idle        boolean                    true                              Enable smart idle
                                                                                      feature. See below

  idle.details           string \| function(opts)   'Idling'                          Details shown when
                                                                                      idle

  idle.state             string \| function(opts)   nil                               State shown when idle

  idle.tooltip           string \| function(opts)   '💤'                              Tooltip shown when
                                                                                      hovering over idle
                                                                                      icon

  idle.icon              string \| function(opts)   default idle icon                 Custom icon URL or
                                                                                      asset ID
  ---------------------------------------------------------------------------------------------------------

  Smart idle ensures that: - When an instance goes idle, it switches to show the
  most recent active one - You’re only shown as idle when all instances are
  actually idle

TEXT                                                 *cord-configuration-text*

  ----------------------------------------------------------------------------------------------------------------
  Option           Type                                  Default                        Description
  ---------------- ------------------------------------- ------------------------------ --------------------------
  default          string \| function(opts) \| boolean   nil                            Default text for all
                                                                                        unspecified text options

  workspace        string \| function(opts) \| boolean   In {workspace}                 Text shown when in a
                                                                                        workspace

  viewing          string \| function(opts) \| boolean   Viewing {filename}             Text shown when viewing a
                                                                                        file

  editing          string \| function(opts) \| boolean   Editing {filename}             Text shown when editing a
                                                                                        file

  file_browser     string \| function(opts) \| boolean   Browsing files in {name}       Text shown when in a file
                                                                                        browser

  plugin_manager   string \| function(opts) \| boolean   Managing plugins in {name}     Text shown when in a
                                                                                        plugin manager

  lsp              string \| function(opts) \| boolean   Configuring LSP in {name}      Text shown when in an LSP
                                                                                        manager

  docs             string \| function(opts) \| boolean   Reading {name}                 Text shown when in a docs
                                                                                        buffer

  vcs              string \| function(opts) \| boolean   Committing changes in {name}   Text shown when in a VCS
                                                                                        buffer

  notes            string \| function(opts) \| boolean   Taking notes in {name}         Text shown when in a notes
                                                                                        buffer

  debug            string \| function(opts) \| boolean   Debugging in {name}            Text shown when in a
                                                                                        debug-related plugin
                                                                                        buffer

  test             string \| function(opts) \| boolean   Testing in {name}              Text shown when in a
                                                                                        testing-related plugin
                                                                                        buffer

  diagnostics      string \| function(opts) \| boolean   Fixing problems in {name}      Text shown when in a
                                                                                        diagnostics buffer

  games            string \| function(opts) \| boolean   Playing {name}                 Text shown when in a game
                                                                                        buffer

  terminal         string \| function(opts) \| boolean   Running commands in {name}     Text shown when in a
                                                                                        terminal buffer

  dashboard        string \| function(opts) \| boolean   'Home'                         Home
  ----------------------------------------------------------------------------------------------------------------

TEXT OPTIONS ~

The `text` table allows you to customize the displayed text for different
states. You can customize it in three different ways:

1. Using simple strings:

>lua
    text = {
        editing = 'Editing a file',
        viewing = 'Viewing a file',
    }
<

1. Using functions for dynamic text:

>lua
    text = {
        editing = function(opts)
            return string.format('Editing %s', opts.filename)
        end,
    }
<

1. Using string templates (requires enabling variables):

>lua
    {
        text = {
            editing = 'Editing ${filename}',
            file_browser = 'Browsing files in ${tooltip}',
        },
        variables = true, -- Enable string templates
    }
<

You can also set a default text for all unspecified options:

>lua
    text = {
        default = 'Using Neovim',  -- This will be used for any unspecified text options, you can use functions and boolean values as well
        workspace = 'In workspace', -- This overrides the default for workspace
        -- other fields not specified will use the default value
    }
<


  To see all available options, refer to the |cord-default-configuration|.
It is also possible to use boolean values to completely disable a category:

>lua
    text = {
        workspace = '',         -- Omit the text from the activity, meaning it will only have one row of text
        games = function() end, -- Returning `nil` is the same as above
    
        file_browser = true,    -- Ignore these types of buffers and the current activity will remain unchanged
        plugin_manager = false, -- Hide the activity for these types of buffers
    
        -- Also applicable to functions
        diagnostics = function(opts)
            -- Only show diagnostics activity if there are problems, otherwise do nothing
            return #vim.diagnostics.get(vim.api.nvim_get_current_buf()) > 0 and 'Fixing problems in ' .. opts.tooltip or true
        end,
    }
<


BUTTONS                                           *cord-configuration-buttons*

Buttons can have static or dynamic labels and URLs:

>lua
    buttons = {
        {
            label = function(opts)
                return opts.repo_url and 'View Repository' or 'Website'
            end,
            url = function(opts)
                return opts.repo_url or 'https://example.com'
            end
        }
    }
<


ASSETS                                             *cord-configuration-assets*

Override icons and text for specific filetypes or filenames. Most of the
options also support functions.

>lua
    assets = {
        ['.rs'] = {
            icon = 'rust',              -- Asset name or URL
            tooltip = 'Rust',           -- Hover text
            text = 'Writing in Rust'    -- Override entire text
        },
        netrw = {
            name = 'Netrw',             -- Override asset name only
            type = 'file_browser'       -- Set asset type
        }
    }
<


  [!TIP] A detailed guide can be found in the Wiki <./Assets.md>.
Some languages cannot be identified solely by their filename or extension. In
such cases, we can utilize the `vim.filetype.add` function to add extra
patterns for filetype detection:

>lua
    vim.filetype.add {
      pattern = {
        ['.*/waybar/config'] = 'jsonc',
        ['.*/hypr/.*%.conf'] = 'hyprlang',
        -- ...
      },
    }
<


VARIABLES                                       *cord-configuration-variables*

  -------------------------------------------------------------------------------------------------------------
  Option      Type                      Default   Description
  ----------- ------------------------- --------- -------------------------------------------------------------
  variables   table \| boolean \| nil   nil       Define custom variables for use in string templates.
                                                  Functions can be used to dynamically generate values. If
                                                  true, uses the default options table, if table, extends the
                                                  default table, if false, disables custom variables

  -------------------------------------------------------------------------------------------------------------

  The `variables` option allows you to define custom variables to be used in
  string templates. These variables can be static values or functions that
  dynamically generate values based on the current context. By default, the table
  is populated with the |cord-options-table| but they can be overridden by
  user-defined variables.
Example configuration:

>lua
    require('cord').setup {
        variables = {
            filename = 'a file',
            problems = function(opts) return #vim.diagnostic.get(0) end,
        },
        text = {
            viewing = 'Viewing ${filename} - ${problems} problems',
        }
    }
<


HOOKS                                               *cord-configuration-hooks*

  --------------------------------------------------------------------------------------------------------------------------------------------------
  Option                   Type                                                                                 Description
  ------------------------ ------------------------------------------------------------------------------------ ------------------------------------
  hooks.ready              function(manager) \| table<fun: function(manager), priority: number>                 Called when connected to the server
                                                                                                                and ready for communication with
                                                                                                                Discord (manager)

  hooks.shutdown           function() \| table<fun: function(), priority: number>                               Called when connection to Discord is
                                                                                                                closed

  hooks.pre_activity       function(opts) \| table<fun: function(opts), priority: number>                       Called before building activity
                                                                                                                (opts)

  hooks.post_activity      function(opts, activity) \| table<fun: function(opts, activity), priority: number>   Called after building activity, but
                                                                                                                before sending it (opts, activity)

  hooks.idle_enter         function(opts) \| table<fun: function(opts), priority: number>                       Called when entering idle state
                                                                                                                (opts)

  hooks.idle_leave         function(opts) \| table<fun: function(opts), priority: number>                       Called when leaving idle state
                                                                                                                (opts)

  hooks.workspace_change   function(opts) \| table<fun: function(opts), priority: number>                       Called when workspace changes (opts)
  --------------------------------------------------------------------------------------------------------------------------------------------------

PLUGINS                                           *cord-configuration-plugins*

  ----------------------------------------------------------------------------------------
  Option    Type                               Description
  --------- ---------------------------------- -------------------------------------------
  plugins   string[] \| table<string, table>   Extend Cord with plugins. See the Wiki for
                                               more info

  ----------------------------------------------------------------------------------------

  If you want to develop your own plugin, check out Cord’s Plugin System
  <./Plugin-System.md>

ADVANCED                                         *cord-configuration-advanced*


PLUGIN SETTINGS ~

  ----------------------------------------------------------------------------------------------------------
  Option                              Type      Default     Description
  ----------------------------------- --------- ----------- ------------------------------------------------
  advanced.plugin.autocmds            boolean   true        Enable autocmds

  advanced.plugin.cursor_update       string    'on_hold'   When to update cursor position: 'on_move',
                                                            'on_hold', or 'none'. See Cursor Update Mode

  advanced.plugin.match_in_mappings   boolean   true        Whether to match against file extensions in
                                                            mappings
  ----------------------------------------------------------------------------------------------------------

SERVER SETTINGS ~

  --------------------------------------------------------------------------------------------------------------------
  Option                            Type            Default   Description
  --------------------------------- --------------- --------- --------------------------------------------------------
  advanced.server.update            string          'fetch'   Default way to acquire the server executable either if
                                                              the executable is not found or a manual update is
                                                              requested: 'fetch' - fetch from GitHub, 'install' -
                                                              install from crates.io, 'build' - build from source,
                                                              'none' - no-op

  advanced.server.pipe_path         string \| nil   nil       Custom IPC pipe path

  advanced.server.executable_path   string \| nil   nil       Custom server executable path

  advanced.server.timeout           number          300000    Server shutdown timeout (ms)
  --------------------------------------------------------------------------------------------------------------------

DISCORD SETTINGS ~

  --------------------------------------------------------------------------------------------------
  Option                                Type       Default   Description
  ------------------------------------- ---------- --------- ---------------------------------------
  advanced.discord.pipe_paths           string[]   nil       Custom IPC pipe paths to use when
                                                             connecting to Discord

  advanced.discord.reconnect.enabled    boolean    false     Whether reconnection is enabled. Has
                                                             minimal impact on performance

  advanced.discord.reconnect.interval   number     5000      Reconnection interval in milliseconds,
                                                             0 to disable

  advanced.discord.reconnect.initial    boolean    true      Whether to reconnect if initial
                                                             connection fails
  --------------------------------------------------------------------------------------------------

WORKSPACE SETTINGS ~

  --------------------------------------------------------------------------------------------------------------
  Option                            Type       Default    Description
  --------------------------------- ---------- ---------- ------------------------------------------------------
  advanced.workspace.root_markers   string[]   string[]   List of root markers to use when determining the
                                                          workspace directory

  advanced.workspace.limit_to_cwd   boolean    false      Limits workspace detection to the working directory
                                                          (vim.fn.getcwd()). When true, workspace detection
                                                          stops at the CWD if no marker is found, making the
                                                          search more efficient
  --------------------------------------------------------------------------------------------------------------

CURSOR UPDATE MODE ~

The `advanced.cursor_update_mode` option controls how cursor position updates
are handled: - `'on_move'` - Uses `CursorMoved[I]` autocmd, updating on every
cursor movement. Most accurate but triggered very often - `'on_hold'` - Uses
`CursorHold[I]` autocmd, updating only after the cursor has been stationary for
`'updatetime'` milliseconds. Better performance but less accurate - `'none'` -
Disables cursor position updates entirely


USER COMMANDS                               *cord-configuration-user-commands*


  [!NOTE] Autocompletion is fully supported. To see the list of all available
  features, hit `<Tab>` after typing `:Cord enable`
- `:Cord enable` - Show presence
    - `:Cord enable <feature>` - Enable a feature
- `:Cord disable` - Hide presence
    - `:Cord disable <feature>` - Disable a feature
- `:Cord toggle` - Toggle presence
    - `:Cord toggle <feature>` - Toggle a feature
- `:Cord presence` - Toggle presence display
    - `:Cord presence show` - Show presence
    - `:Cord presence hide` - Hide presence
    - `:Cord presence suppress` - Suppress presence for current Neovim session
    - `:Cord presence toggle` - Toggle presence
    - `:Cord presence toggle_suppress` - Toggle presence suppression
- `:Cord idle` - Toggle idle state
    - `:Cord idle toggle` - Toggle idle state
    - `:Cord idle show` - Show idle state
    - `:Cord idle hide` - Hide idle state
    - `:Cord idle force` - Force idle state
- `:Cord update` - Update the server executable using the configured update mode (fetch by default)
    - `:Cord update check` - Check for server updates
    - `:Cord update fetch` - Fetch the server executable from GitHub using `curl`
    - `:Cord update install` - Install the server executable from crates.io using `cargo`
    - `:Cord update build` - Build the server executable locally using `cargo`
- `:Cord status` - Show connection status
- `:Cord version` - Show current server version
- `:Cord restart` - Restart the server
- `:Cord shutdown` - Disconnect from Discord and shutdown the server
- `:Cord health` - Validate user configuration


OPTIONS TABLE                               *cord-configuration-options-table*

The `opts` parameter passed to all functions and hooks contains the following
information:

>lua
    {
      manager           = ActivityManager,  -- Reference to the ActivityManager instance
    
      -- File Information
      name              = string?,          -- Name associated with the current mapping, if any
      tooltip           = string?,          -- Tooltip associated with the current mapping, if any
      filename          = string,           -- Current buffer's filename
      filetype          = string,           -- Current buffer's filetype
      buftype           = string,           -- Current buffer's buftype
      is_read_only      = boolean,          -- Whether the current buffer is read-only
    
      -- Cursor Information
      cursor_line       = number,           -- Current cursor line number
      cursor_char       = number,           -- Current cursor character number
    
      -- Timestamp Information
      timestamp         = number,           -- Timestamp passed to the Rich Presence in milliseconds
    
      -- Workspace Information
      workspace         = string?,          -- Current workspace name
      workspace_dir     = string?,          -- Current workspace directory
      repo_url          = string?,          -- Current Git repository URL, if any
    
      -- Editor Information
      is_focused        = boolean,          -- Whether Neovim is focused
      is_idle           = boolean,          -- Whether the session is idle
      buttons           = table?,           -- List of configured presence buttons
    
      -- Asset Information
      type              = string,           -- Which category the asset belongs to, e.g. 'language' or 'docs'
      icon              = string?,          -- Asset icon URL or name, if any
      text              = string?,          -- Custom text to display, if any
    }
<

The `ActivityManager` contains useful methods:


ACTIVITYMANAGER METHODS           *cord-configuration-activitymanager-methods*

  ------------------------------------------------------------------------------------------------
  Method                                  Description
  --------------------------------------- --------------------------------------------------------
  manager:queue_update(force_update)      Schedules an update to the activity. If force_update is
                                          true, it bypasses checks and updates immediately.

  manager:pause()                         Pauses all events and stops the idle timer.

  manager:resume()                        Resumes events and restarts the idle timer.

  manager:pause_events()                  Disables event handling without affecting the idle
                                          timer.

  manager:resume_events()                 Enables event handling and queues an immediate update.

  manager:skip_update()                   Skips the next update once.

  manager:hide()                          Pauses events and clears rich presence.

  manager:suppress()                      Pauses events and suppresses sending presence updates
                                          for the current Neovim session.

  manager:toggle()                        Toggles between pausing and resuming the activity
                                          updates.

  manager:toggle_suppress()               Toggles between suppressing and resuming sending
                                          presence updates for the current Neovim session.

  manager:idle()                          Sets the session to idle.

  manager:force_idle()                    Forcibly sets the session to idle until unforced.

  manager:unidle()                        Clears the idle state and resumes normal activity.

  manager:toggle_idle()                   Toggles between idle and normal activity.

  manager:set_activity(activity, force)   Sets the rich presence to the provided activity. Setting
                                          force to true will bypass any previous
                                          manager:skip_update() call.

  manager:clear_activity(force)           Clears the current activity from the server. If force is
                                          true, it completely clears the presence.
  ------------------------------------------------------------------------------------------------

ACTIVITY OPTIONS                         *cord-configuration-activity-options*

  -----------------------------------------------------------------------------------------
  Parameter             Type      Description
  --------------------- --------- ---------------------------------------------------------
  type                  string    One of ‘playing’, ‘listening’, ‘watching’, ‘competing’

  status_display_type   string    One of ‘name’, ‘state’, ‘details’. Controls which field
                                  is displayed in the user’s status text in the member list

  details               string    Detailed information about what the user is doing.

  details_url           string    URL for the details field to make it clickable.

  state                 string    The user’s current state (e.g., “Editing a file”).

  state_url             string    URL for the state field to make it clickable.

  timestamps            table     Contains start and end timestamps for the activity.

  assets                table     Defines images and tooltips, including large_image,
                                  large_text, large_url, small_image, small_text, and
                                  small_url.

  buttons               array     Array of objects, each with label and url, defining
                                  interactive buttons in the presence.

  is_idle               boolean   Whether the activity should be considered as idle.
  -----------------------------------------------------------------------------------------

==============================================================================
2. Custom Assets                                          *cord-custom-assets*

Cord allows you to go beyond the default icons and fully customize the assets
used in your Discord Rich Presence. This guide will walk you through how to
override and define custom assets.


STRUCTURE                                       *cord-custom-assets-structure*

Custom assets are configured within the `assets` table in your `cord.setup()`
call. The basic structure is as follows:

>lua
    require('cord').setup {
      assets = {
        -- "key" = "icon" or { asset_options }
      },
    }
<

Here, `"key"` is the identifier for the asset, and `"value"` can be either a
simple string for the asset icon or a table for more detailed asset options.


ASSET KEYS                                     *cord-custom-assets-asset-keys*

The `key` in your asset configuration determines what type of file or context
the custom asset will apply to. You can use the following key types:

- **Filetype**Use a Vim filetype string (e.g., `"lua"`, `"python"`) to set assets for specific languages.
- **Filename**Use a specific filename (e.g., `"Cargo.toml"`, `"README.md"`) to customize assets for particular files.
- **File Extension**Use a file extension (e.g., `".rs"`, `".js"`) to apply assets to all files with that extension.
- **Special Keys**Cord provides special keys for generic scenarios (see |cord-overriding-defaults|).


ASSET OPTIONS                               *cord-custom-assets-asset-options*

When you use a table as the `value` in your asset configuration, you can
specify these options to fine-tune your custom asset:

  --------------------------------------------------------------------------------------
  Option    Type                 Description
  --------- -------------------- -------------------------------------------------------
  icon      string \| function   A direct URL to the icon image or the name of a rich
                                 presence asset (if using your own Discord application).

  tooltip   string \| function   Text that appears when you hover over the icon in
                                 Discord.

  name      string \| function   An optional override for the icon’s name. Generally
                                 used for types other than language.

  text      string \| function   An optional override for the icon’s text. Completely
                                 replaces the default text.

  type      string               Specifies the context of the asset. See Asset Types for
                                 available options.
  --------------------------------------------------------------------------------------

ASSET TYPES ~

The `type` option categorizes your asset, influencing how Cord displays it.
Available types include: - `language` (default) - `docs` - `plugin_manager` -
`lsp_manager` - `file_browser` - `vcs` - `workspace` - `dashboard` - `notes` -
`debug` - `test` - `diagnostics` - `games` - `terminal`


EXAMPLES                                         *cord-custom-assets-examples*

**1. Simple Icon Replacement by Extension:**

>lua
    assets = {
      ['.rs'] = 'https://...', -- Use this icon URL for all Rust files
    }
<

This will use the given icon URL for any file with the `.rs` extension.

**2. Custom Icon and Tooltip for a Filetype:**

>lua
    assets = {
      lua = {
        icon = 'lua_custom_icon',
        tooltip = 'Lua Script', -- Custom tooltip for Lua files
      },
    }
<

This example sets a custom icon and tooltip specifically for Lua files (the
`lua` filetype).

**3. Using Cord’s Built-in Icons:**

>lua
    assets = {
      ['.settings'] = require('cord.api.icon').get('settings'),
    }
<

This makes use of Cord’s default icon library, using the "settings" icon for
files with the `.settings` extension.

**4. Plugin Manager Asset with Custom Text:**

>lua
    assets = {
      lazy = {
        name = 'Lazy',
        icon = 'https://...',
        tooltip = 'lazy.nvim Plugin Manager',
        type = 'plugin_manager',
        text = function(opts) -- Dynamic text
          return 'Managing plugins in ' .. opts.name
        end,
      },
    }
<

Here, we define a custom asset for the `lazy.nvim` plugin manager, setting its
name, icon, tooltip, type, and dynamic text.

**5. Overriding Tooltip and Text, Keeping Default Icon:**

>lua
    assets = {
      lua = {
        tooltip = '.lua file',     -- Just change the tooltip
        text = 'Writing Lua Code', -- Override the text
      },
    }
<

This example only modifies the tooltip and text for Lua files, keeping Cord’s
default icon.


OVERRIDING DEFAULTS                   *cord-custom-assets-overriding-defaults*

Cord provides special keys to define assets for generic situations:

- `['Cord.new']`Asset for a new, empty buffer when Neovim starts without file arguments, when both filetype and filename are empty.
- `['Cord.unknown']`Asset when the filetype is not detected/defined in Cord.
- `['Cord.override']`This key overrides _all_ existing icons, applying the specified asset everywhere.

**Example of Default Overrides:**

>lua
    assets = {
      ['Cord.new'] = 'default_file_icon',
      ['Cord.unknown'] = 'question_mark_icon',
      ['Cord.override'] = 'my_brand_icon',
    }
<


TIP                                                   *cord-custom-assets-tip*

Sometimes, filetypes aren’t automatically recognized by Neovim based on
filename or extension alone. Use `vim.filetype.add` to help the editor identify
them:

>lua
    vim.filetype.add {
      pattern = {
        ['.*/waybar/config'] = 'jsonc',    -- Recognize waybar config files as jsonc
        ['.*/hypr/.*%.conf'] = 'hyprlang', -- Hyprland configs as hyprlang
        -- ... add more custom patterns
      },
    }
<


==============================================================================
3. Plugins                                                      *cord-plugins*

Cord comes with several built-in plugins that you can easily enable and
configure. These plugins provide ready-made functionality for common use cases.


ENABLING PLUGINS                               *cord-plugins-enabling-plugins*

To use a built-in plugin, simply add its `require` path to the `plugins` table
in your `cord.setup()` configuration.

**Basic Plugin Enablement:**

>lua
    require('cord').setup {
      plugins = {
        'cord.plugins.diagnostics', -- Enable the diagnostics plugin
      },
    }
<

**Enabling and Configuring a Plugin:**

If a plugin has configuration options, you can provide a configuration table
using the plugin’s require path as the key in the `plugins` table.

>lua
    require('cord').setup {
      plugins = {
        'cord.plugins.diagnostics', -- Enable diagnostics plugin with default settings
    
        ['cord.plugins.diagnostics'] = { -- Enable AND configure diagnostics plugin
          scope = 'workspace', -- Set scope to 'workspace' instead of default 'buffer'
          severity = vim.diagnostic.severity.WARN, -- Show warnings and above
        },
      },
    }
<


AVAILABLE PLUGINS                             *cord-plugins-available-plugins*

Here’s a list of the built-in plugins included with Cord, along with their
descriptions and configuration options:


DIAGNOSTICS (CORD.PLUGINS.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:**

>lua
    {
      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. Overrides `text.viewing` and `text.editing` to include diagnostics count.
    - `'workspace'`Show diagnostics count for _all buffers in the workspace_. Overrides `text.workspace` to include diagnostics count.
- **severity**
    - Atable 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.
- **override**
    - `true`(default): The plugin will automatically override the `text.viewing`, `text.editing`, and `text.workspace` options to display diagnostics information. Recommended for seamless integration.
    - `false`The plugin will _not_ override text options. You’ll need to manually use the plugin’s variables in your `text` configuration 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 plugin’s configuration.

**Usage Example (override = false):**

>lua
    text = {
      -- In string templates
      editing = 'Editing ${filename} - ${diagnostics} problems',
    
      -- In functions
      workspace = function(opts) return 'In ' .. opts.workspace .. ' - ' .. opts.diagnostics(opts) .. ' problems' end,
    }
<


LOCAL TIME (CORD.PLUGINS.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:**

>lua
    {
      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 plugins.

PERSISTENT TIMER (CORD.PLUGINS.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:**

>lua
    {
      scope = 'workspace', -- 'workspace', 'file', 'filetype', or 'global'
      mode = 'all',        -- 'all', 'active', or 'idle'
      file = vim.fn.stdpath 'data' .. '/cord/plugins/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., all `lua` files 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**
    - Definesthe absolute path to the JSON file where time data is stored.
    - Defaults to a file within Neovim’s standard data directory.
- **save_on**
    - Atable 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 by `save_interval`.
- **save_interval**
    - Thenumber of seconds between automatic saves if `'periodic'` is enabled.


  [!NOTE] Incompatible with any other timestamp-related plugins.

SCOPED TIMESTAMPS (CORD.PLUGINS.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:**

>lua
    {
      scope = 'buffer', -- 'buffer' (default), 'workspace', or 'idle'
      pause = true,
    }
<

- **scope**
    - `'buffer'`(default): Track time elapsed _per buffer_. Timestamp resets when switching buffers (if `pause = false`), or pauses/resumes (if `pause = 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 plugin’s `scope` and `pause` settings. This is used internally by the plugin.


  [!NOTE] Incompatible with any other timestamp-related plugins.

LAST.FM (CORD.PLUGINS.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_USERNAME` and `LASTFM_API_KEY` environment variables must be present. You can get them from here <https://www.last.fm/api/accounts> by creating an API account.
- `curl` must be available on your system (used for HTTP requests).

**Configuration Options:**

>lua
    {
      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 plugin fully manages activity updates.
    - `false`The plugin 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 (or `nil` if none).
- **track_artist**The current track artist (or `nil`).
- **track_album**The current track album (or `nil`).
- **track_url**The Last.fm track URL (or `nil`).
- **track_image**The best available album image URL or the configured `fallback_image`.

**Usage Example (override = false):**

>lua
    require('cord').setup {
      plugins = {
        ['cord.plugins.lastfm'] = { override = false },
      },
    
      text = {
        viewing = 'Listening to ${track_title} — ${track_artist}',
        editing = 'Listening to ${track_title} — ${track_artist}',
      },
    }
<


  [!NOTE] Incompatible with any other plugin if `override = true`.

==============================================================================
4. Examples                                                    *cord-examples*

Learn how to customize your Discord presence with examples. The possibilities
are endless, and the only limit is your creativity!


CUSTOMIZING ICONS ~


  [!IMPORTANT] If you use a plugin manager, avoid using `require` directly in
  tables; instead, use them within function initializers.
>lua
    opts = function()
      return {
        display = {
          theme = 'default',
          flavor = 'dark',
        },
        idle = {
          -- change default idle icon to keyboard
          icon = require('cord.api.icon').get('keyboard'),
          -- or use another theme's idle icon
          icon = require('cord.api.icon').get('idle', 'atom'),
          -- or use another theme's idle icon from a different flavor
          icon = require('cord.api.icon').get('idle', 'atom', 'light'),
        }
      }
    end
<


CURSOR POSITION ~

>lua
    text = {
      editing = function(opts)
        return string.format('Editing %s - %s:%s', opts.filename, opts.cursor_line, opts.cursor_char)
      end
    }
<


OMITTING FIELDS ~

>lua
    text = {
      workspace = '',
      -- or
      workspace = function() end,
      -- or
      workspace = function() return '' end
    }
<


NEOVIM VERSION IN SMALL TOOLTIP ~

>lua
    hooks = {
      post_activity = function(opts, activity)
        local version = vim.version()
        activity.assets.small_text = string.format('Neovim %s.%s.%s', version.major, version.minor, version.patch)
      end
    }
<


WORKSPACE BLACKLIST ~

>lua
    local blacklist = {
      'blacklisted_workspace',
      'another_blacklisted_workspace'
    }
    
    local is_blacklisted = function(opts)
      return vim.tbl_contains(blacklist, opts.workspace)
    end
    
    -- EITHER
    -- A. use a custom text for the activity
    text = {
      viewing = function(opts)
        return is_blacklisted(opts) and 'Viewing a file' or ('Viewing ' .. opts.filename)
      end,
      editing = function(opts)
        return is_blacklisted(opts) and 'Editing a file' or ('Editing ' .. opts.filename)
      end,
      workspace = function(opts)
        return is_blacklisted(opts) and 'In a secret workspace' or ('Working on ' .. opts.workspace)
      end
    }
    
    -- OR
    -- B. simply hide the activity when in a blacklisted workspace
    hooks = {
      workspace_change = function(opts)
        if is_blacklisted(opts) then
          opts.manager:hide()
        else 
          opts.manager:resume()
        end
      end
    }
<


GIT BRANCH & STATUS ~

>lua
    local git_branch = vim.fn.system('git branch --show-current'):gsub('\n', '')
    
    variables = {
      git_status = function(opts)
        return git_branch
      end
    }
    
    text = {
      editing = function(opts)
        return string.format('Editing %s - on branch %s', opts.filename, opts.git_status)
      end
    }
    
    hooks = {
      workspace_change = function(opts)
        git_branch = vim.fn.system('git branch --show-current'):gsub('\n', '')
      end
    }
<


TIME-BASED STATUS ~

>lua
    text = {
      workspace = function(opts)
        local hour = tonumber(os.date('%H'))
        local status = 
          hour >= 22 and '🌙 Late night coding' or
          hour >= 18 and '🌆 Evening session' or
          hour >= 12 and '☀️ Afternoon coding' or
          hour >= 5 and '🌅 Morning productivity' or
          '🌙 Midnight hacking'
        
        return string.format('%s: %s', status, opts.filename)
      end
    }
<


DYNAMIC BUTTONS ~

>lua
    buttons = {
      {
        label = function(opts)
          return opts.repo_url and 'View Repository' or 'My Website'
        end
        url = function(opts)
          return opts.repo_url or 'https://example.com'
        end
      }
    }
<


CUSTOM IDLE MESSAGES ~

>lua
    idle = {
      details = function(opts)
        return string.format('Taking a break from %s', opts.workspace)
      end
    }
<


HIDE BUTTONS ON IDLE ~

>lua
    buttons = {
      {
        label = 'View Repository',
        url = function(opts)
          if not opts.is_idle then return opts.repo_url end
        end
      }
    }
<


INDICATE MODIFIED BUFFERS ~

>lua
    text = {
      editing = function(opts)
        local text = 'Editing ' .. opts.filename
        if vim.bo.modified then text = text .. '[+]' end
        return text
      end,
    }
<


RANDOM QUOTES ~

>lua
    local quotes = {
      'GTA VI came out before my Rust program finished compiling. ⏳',
      'When your code works on the first try. 😱',
      'It’s not a bug, it’s a feature. 🐛✨',
      'I don’t always test my code, but when I do, I do it in production. 💥',
      'My code works, I have no idea why. 🤷‍♂️',
      'Hello from the other side... of a merge conflict. 🔀',
      'If it works, don’t touch it. 🛑',
      'May your code never compile on the first try. 🤞',
    }
    
    hooks = {
      post_activity = function(_, activity)
        activity.details = quotes[math.random(#quotes)]
      end
    }
<


KEYMAPPINGS ~

>lua
    vim.keymap.set('n', '<leader>Ct', function() require('cord.api.command').toggle_presence() end)
    vim.keymap.set('n', '<leader>Ci', function() require('cord.api.command').toggle_idle_force() end)
<





  [!IMPORTANT] Cord no longer requires Rust to be installed. Server component
  will be automatically downloaded from GitHub Releases.

FEATURES                                              *cord-examples-features*

- Fast, lightweight, and batteries included.
- Event-driven architecture with instant presence updates.
- Dynamic string templates with custom variables.
- Customizable assets for any file/buffer type.
- Flexible configuration with rich API, function-based fields, hooks, user commands and custom IPC paths.
- Plugin system of its own, with many plugins out-of-the-box.
- Finds repositories and workspaces based on VCS files without relying on command-line tools.
- Manages activities across all instances with a single connection to Discord.
- Detects when you’re idle and switches to the most recent active instance.
- Works with different Discord setups (Snap, Flatpak, WSL, and even the browser version).
- Runs on Windows, Linux, macOS, and FreeBSD.
- Includes 120+ unique icons for over 200 file types and plugins.
- Reconnects automatically if connection to Discord is lost.


INSTALLATION                                      *cord-examples-installation*

lazy.nvim ~

>lua
    {
      'vyfor/cord.nvim',
      build = ':Cord update',
      -- opts = {}
    }
<

packer.nvim ~

>lua
    use {
      'vyfor/cord.nvim',
      run = ':Cord update',
      -- config = function()
      --   require('cord').setup {}
      -- end
    }
<

rocks.nvim ~

Cord is available on LuaRocks <https://luarocks.org/modules/vyfor/cord.nvim>.

>vim
    :Rocks install cord.nvim
<

Invoke `:Cord update` whenever the plugin is updated.

vim.pack (v0.12+) ~

>lua
    vim.pack.add { 'https://github.com/vyfor/cord.nvim' }
    vim.api.nvim_create_autocmd('PackChanged', {
      callback = function(opts)
        if opts.data.spec.name == 'cord.nvim' and opts.data.kind == 'update' then 
          vim.cmd 'Cord update'
        end
      end
    })
<

Vim packages ~

**Unix:**

>bash
    git clone https://github.com/vyfor/cord.nvim ~/.local/share/nvim/site/pack/plugins/start/cord.nvim
<

**Windows (PowerShell):**

>powershell
    git clone https://github.com/vyfor/cord.nvim $LOCALAPPDATA/nvim-data/site/pack/plugins/start/cord.nvim
<

Invoke `:Cord update` whenever the plugin is updated.

Considerations ~

Cord requires the **server executable** to be present. By default, the plugin
automatically fetches it from GitHub, which requires a dependency on **curl**
<https://curl.se>.

Alternatively, you can provide the executable manually:

- **Download from GitHub:** Get the latest release from
    <https://github.com/vyfor/cord.nvim/releases/latest>, rename it to `cord` (or
    `cord.exe` on Windows), and place it under `nvim-data-dir/cord/bin`. This is
    essentially what `:Cord update fetch` does.
- **Build from source:** Run `:Cord update install` to install from crates.io or
    `:Cord update build` to build from source locally.


THEMES                                                  *cord-examples-themes*

Cord features over 120 meticulously crafted icons available in distinct themes:

- **Default**A clean and stylish theme featuring widely recognized icons.
- **Atom**A sleek theme inspired by Atom Material Icons.
- **Catppuccin**A soothing pastel theme inspired by Catppuccin.

See the showcase <https://github.com/vyfor/icons#showcase> for a visual
comparison.


  [!TIP] Each theme includes multiple flavors, typically `dark`, `light`, and
  `accent`, representing the background color of the icons. Choose your theme in
  the `display` <https://github.com/vyfor/cord.nvim/wiki/Configuration#-display>
  configuration option. More themes are coming soon!

SUPPORT THE PROJECT                        *cord-examples-support-the-project*

I’m the sole maintainer of cord.nvim and dedicate much of my free time to
this project. If you find Cord helpful, you can show your support by giving the
repo a star or sponsoring me on GitHub <https://github.com/sponsors/vyfor>.
Every bit of support helps me continue to improve and maintain Cord for
everyone. Thank you!


Generated by panvimdoc <https://github.com/kdheepak/panvimdoc>

vim:tw=78:ts=8:noet:ft=help:norl:
