Skip to content

mikesmithgh/kitty-scrollback.nvim

Repository files navigation

kitty-scrollback

😽 kitty-scrollback.nvim

Navigate your Kitty scrollback buffer to quickly search, copy, and execute commands in Neovim.

neovim: v0.9+ kitty v0.32.2+ semantic-release: angular test status nightly test status

kitty-scrollback.nvim demo
(click for video)

📖 Contents

✨ Features

Tip

Expand each section under the Features section to see a demo.

Check out the wiki for detailed demos of each configuration option, useful configurations, and more.

😻 Navigate Kitty's scrollback buffer with Neovim
  • Open Kitty's scrollback history (default mapping <C-S-h>)
  • That's it! You are in Neovim, navigate the scrollback buffer.
🐱 Copy scrollback contents to system clipboard

copy_visual_selection_to_clipboard

  • Open Kitty's scrollback history (default mapping <C-S-h>)
  • Search backward for a pattern in Neovim ?{pattern}<CR>
  • Enter Visual mode v and select desired text
  • Copy selection to clipboard (default mapping <leader>y)
  • kitty-scrollback.nvim automatically closes
😺 Paste visual selection to Kitty

kitty_scrollback_screencapture_03_should_paste_visual_selection_to_kitty.gif

  • Open Kitty's scrollback history (default mapping <C-S-h>)
  • Search backward for a pattern in Neovim ?{pattern}<CR>
  • Enter Visual mode v and select desired text
  • Paste visual selection to Kitty (default mapping <S-CR>)
  • kitty-scrollback.nvim automatically closes and pastes the contents for further editing
🙀 Execute visual selection in Kitty

kitty_scrollback_screencapture_05_should_execute_visual_selection_in_kitty.mov

  • Open Kitty's scrollback history (default mapping <C-S-h>)
  • Search backward for a pattern in Neovim ?{pattern}<CR>
  • Enter Visual mode v and select desired text
  • Execute visual selection in Kitty (default mapping <C-CR>)
  • kitty-scrollback.nvim automatically closes and executes the visual selection
😸 Modify and send content from paste window to Kitty

kitty_scrollback_screencapture_02_should_paste_paste_window_text_to_kitty.gif

  • Open Kitty's scrollback history (default mapping <C-S-h>)
  • Search backward for a pattern in Neovim ?{pattern}<CR>
  • Enter Visual mode v and select desired text
  • Copy selection to the paste window in kitty-scrollback.nvim for further edits
    • Alternatively, you could just enter Insert mode (i or a) to open an empty floating window (similar to <C-x><C-e> in Bash)
  • Modify the content in the paste window
  • Paste the content of the paste window to Kitty (default mapping <S-CR>)
  • kitty-scrollback.nvim automatically closes and pastes the contents for further editing
😼 Modify and execute content from paste window to Kitty

kitty_scrollback_screencapture_04_should_execute_paste_window_text_in_kitty.gif

  • Open Kitty's scrollback history (default mapping <C-S-h>)
  • Search backward for a pattern in Neovim ?{pattern}<CR>
  • Enter Visual mode v and select desired text
  • Copy selection to the paste window in kitty-scrollback.nvim for further edits
    • Alternatively, you could just enter Insert mode (i or a) to open an empty floating window (similar to <C-x><C-e> in Bash)
  • Modify the content in the paste window
  • Execute the content of the paste window in Kitty (default mapping <C-CR>)
  • kitty-scrollback.nvim automatically closes and executes the content of the paste window
😾 tmux support (🧪 experimental )
  • Open a tmux pane's scrollback history (default mapping <C-b>[)
  • That's it! You are in Neovim, navigate the scrollback buffer.

🚀 Migrating to v6.0.0

Important

v6.0.0 has breaking changes.

You can ignore this section if you have not previously installed any version of kitty-scrollback.nvim

Migration Steps

If you have any problems or questions migrating to v6.0.0, please open an issue or discussion.

sad-kitty-thumps-up
  • kitty-scrollback.nvim v6.0.0 changes the default keymap for quitting kitty-scrollback.nvim from <Esc> to q. No steps are necessary if you prefer this new behavior.

    If you prefer the previous behavior of using <Esc> to exit kitty-scrollback.nvim, this can be reconfigured by adding the following to your kitty-scrollback.nvim setup.

    vim.keymap.set({ 'n' }, '<Esc>', '<Plug>(KsbCloseOrQuitAll)', {})

    For example, if you are using lazy.nvim, it would look something like this

    return {
      {
        'mikesmithgh/kitty-scrollback.nvim',
        lazy = true,
        cmd = { 'KittyScrollbackGenerateKittens', 'KittyScrollbackCheckHealth' },
        event = { 'User KittyScrollbackLaunch' },
        config = function()
          vim.keymap.set({ 'n' }, '<Esc>', '<Plug>(KsbCloseOrQuitAll)', {}) -- quit kitty-scrollback.nvim with Esc key
          -- vim.keymap.set({ 'n' }, 'q', '<Plug>(KsbCloseOrQuitAll)', {}) -- uncomment if you would like to also quit with the q key
          require('kitty-scrollback').setup()
        end,
      },
    }

📚 Prerequisites

🏃 Quickstart

To quickly test this plugin without changing your configuration run the command:

sh -c "$(curl -s https://raw.githubusercontent.com/mikesmithgh/kitty-scrollback.nvim/main/scripts/mini.sh)"

Note

It is good practice to first read the script before running sh -c directly from the web

📦 Installation

Using lazy.nvim
  {
    'mikesmithgh/kitty-scrollback.nvim',
    enabled = true,
    lazy = true,
    cmd = { 'KittyScrollbackGenerateKittens', 'KittyScrollbackCheckHealth' },
    event = { 'User KittyScrollbackLaunch' },
    -- version = '*', -- latest stable version, may have breaking changes if major version changed
    -- version = '^6.0.0', -- pin major version, include fixes and features that do not have breaking changes
    config = function()
      require('kitty-scrollback').setup()
    end,
  }
Using packer.nvim
  use({
    'mikesmithgh/kitty-scrollback.nvim',
    disable = false,
    opt = true,
    cmd = { 'KittyScrollbackGenerateKittens', 'KittyScrollbackCheckHealth' },
    event = { 'User KittyScrollbackLaunch' },
    -- tag = '*', -- latest stable version, may have breaking changes if major version changed
    -- tag = 'v6.0.0', -- pin specific tag
    config = function()
      require('kitty-scrollback').setup()
    end,
  })
Using Neovim's built-in package support pack
mkdir -p "$HOME/.local/share/nvim/site/pack/mikesmithgh/start/"
cd $HOME/.local/share/nvim/site/pack/mikesmithgh/start
git clone [email protected]:mikesmithgh/kitty-scrollback.nvim.git
nvim -u NONE -c "helptags kitty-scrollback.nvim/doc" -c q
mkdir -p "$HOME/.config/nvim"
echo "require('kitty-scrollback').setup()" >> "$HOME/.config/nvim/init.lua"

🛠️ Setup

This section outlines the required configuration for kitty-scrollback.nvim.

  • Enable allow_remote_control in kitty.conf

    • Valid values are yes, socket, socket-only
    • If kitty-scrollback.nvim is the only application controlling Kitty then socket-only is preferred to continue denying TTY requests.
  • Set listen_on to a Unix socket in kitty.conf

    • For example, listen_on unix:/tmp/kitty
  • Enable shell_integration in kitty.conf

    • Set shell_integration to enabled
    • Do not add the option no-prompt-mark
  • Generate the default kitty-scrollback.nvim Kitten mappings and add them to kitty.conf

    nvim --headless +'KittyScrollbackGenerateKittens'
  • Completely close and reopen Kitty

  • Check the health of kitty-scrollback.nvim

    nvim +'KittyScrollbackCheckHealth'
    • Follow the instructions of any ERROR or WARNINGS reported during the healthcheck
  • Test kitty-scrollback.nvim is working as expected by pressing kitty_mod+h to open the scrollback history in Neovim

    • kitty_mod is a special modifier key alias for default shortcuts. You can change the value of this option to alter all default shortcuts that use kitty_mod. The default value of kitty_mod is ctrl+shift. In this example, kitty_mod+h represents ctrl+shift+h.
  • See example kitty.conf for reference.

    allow_remote_control yes
    listen_on unix:/tmp/kitty
    shell_integration enabled
    
    # kitty-scrollback.nvim Kitten alias
    action_alias kitty_scrollback_nvim kitten /path/to/your/install/kitty-scrollback.nvim/python/kitty_scrollback_nvim.py
    
    # Browse scrollback buffer in nvim
    map kitty_mod+h kitty_scrollback_nvim
    # Browse output of the last shell command in nvim
    map kitty_mod+g kitty_scrollback_nvim --config ksb_builtin_last_cmd_output
    # Show clicked command output in nvim
    mouse_map ctrl+shift+right press ungrabbed combine : mouse_select_command_output : kitty_scrollback_nvim --config ksb_builtin_last_visited_cmd_output

⚙️ Configuration

This section provides details on how to customize your kitty-scrollback.nvim configuration.

Important

Please review the Recommended Configurations for other plugins section of the wiki to prevent conflicts with other plugins.

The Advanced Configuration section of the wiki provides useful configurations and detailed demos of each configuration option.

Kitten Arguments

Arguments that can be passed to the kitty_scrollback_nvim Kitten defined in kitty.conf. You can provide the arguments to the action_alias kitty_scrollback_nvim or each individual mapping referencing kitty_scrollback_nvim.

The following examples show you how you could reference a kitty-scrollback.nvim user configuration by name (.e.g, myconfig), set the environment variable NVIM_APPNAME for Neovim, and pass the argument -n to Neovim to disable swap files.

  • Example of adding arguments to action_alias in kitty.conf.

    • This will apply the arguments to all the mappings of kitty_scrollback_nvim.
    action_alias kitty_scrollback_nvim kitten /path/to/your/install/kitty-scrollback.nvim/python/kitty_scrollback_nvim.py --env NVIM_APPNAME=mynvim --config myconfig --nvim-args -n
    
  • Example of adding arguments to a map in kitty.conf.

    • This will apply the arguments only to the kitty_mod+h mappings of kitty_scrollback_nvim.
    map kitty_mod+h kitty_scrollback_nvim --env NVIM_APPNAME=mynvim --config myconfig --nvim-args -n
    
Argument Description
--config The name of the kitty-scrollback.nvim plugin configuration. The configuration can be defined during plugin setup (i.e., require('kitty-scrollback').setup({ ... })).
--nvim-args All arguments after this flag are passed to Neovim. This must be the last of the kitty_scrollback_nvim Kitten arguments. Otherwise, you may unintentionally send the wrong arguments to Neovim.
--env Environment variable that is passed to Neovim. Format is --env var_name=var_value. You may specify multiple config files that will merge all configuration options. Useful for setting NVIM_APPNAME.
--cwd The current working directory of the Neovim

Plugin Configuration

kitty-scrollback.nvim is configured using the require('kitty-scrollback').setup() function. setup() accepts an options table in the form of table<string, KsbOpts|fun(KsbKittyData):KsbOpts>. The structure of KsbOpts is defined in lua/kitty-scrollback/configs/defaults.lua.

The key for an entry in the options table is the name of a configuration that you wish to define. The key can be referenced as the name of the configuration that is passed to the Kitten argument --config. For example, with a configuration named myconfig that disables ANSI colors:

require('kitty-scrollback').setup({
    myconfig = {
      kitty_get_text = {
        ansi = false,
      },
    }
})

You can reference this specific configuration as follows in kitty.conf to disable ANSI colors for the kitty_mod+h mapping.

map kitty_mod+h kitty_scrollback_nvim --config myconfig

The value of an entry in the options table can either be a table (KsbOpts) or a function (fun(KsbKittyData):KsbOpts). KsbKittyData contains metadata about Kitty and the scrollback buffer that may be useful when defining a configuration. The structure of KsbKittyData is defined in lua/kitty-scrollback/launch.lua. For example, you could add an additional configuration named myfnconfig 😹 that only loads the entire scrollback history if the user scrolled past the number of lines on the screen.

require('kitty-scrollback').setup({
    myconfig = {
      kitty_get_text = {
        ansi = false,
      },
    },
    myfnconfig = function(kitty_data)
      return {
        kitty_get_text = {
          extent = (kitty_data.scrolled_by > kitty_data.lines) and 'all' or 'screen',
        },
      }
    end,
})

If you update the reference in kitty.conf to myfnconfig then the kitty_mod+h mapping will use the configuration returned by the function defined by myfnconfig.

map kitty_mod+h kitty_scrollback_nvim --config myfnconfig

Overriding Builtin Configurations

The key for an entry in the options table can be any string. However, if the key matches a builtin name (prefixed with ksb_builtin_) then the configuration will be merged with the builtin configuration. All of the builtin configurations are defined in lua/kitty-scrollback/configs/builtin.lua. The user defined configuration will take precedence and override any fields that are defined in both the builtin and user defined configuration.

Having the ability to merge a user defined configuration with the builtin in configuration is useful for scenarios that you wish to keep the default kitten mappings generated by the :KittyScrollbackGenerateKittens command.

For example, imagine a scenario where you wish to modify the configuration for the ksb_builtin_get_text_all but do not wish to provide you own configuration name myconfig and have to update the reference in kitty.conf to map kitty_mod+h kitty_scrollback_nvim --config myconfig. In this scenario, the default mapping is defined in kitty.conf as

map kitty_mod+h kitty_scrollback_nvim

Note

When no explicit configuration is passed to kitty_scrollback_nvim, the config ksb_builtin_get_text_all is used. Effectively, the command becomes map kitty_mod+h kitty_scrollback_nvim --config ksb_builtin_get_text_all

You can achieve this by creating a user defined configuration with the key ksb_builtin_get_text_all as follows.

  ksb_builtin_get_text_all = {
    kitty_get_text = {
      ansi = false,
    },
  }

The builtin configuration for ksb_builtin_get_text_all is

  ksb_builtin_get_text_all = {
    kitty_get_text = {
      extent = 'all',
    },
  },

The user and builtin configurations will be merged resulting in

  ksb_builtin_get_text_all = {
    kitty_get_text = {
      ansi = false,
      extent = 'all',
    },
  },

This approach can be used to modify the builtin configuration (e.g., ksb_builtin_get_text_all, ksb_builtin_last_cmd_output, and ksb_builtin_last_visited_cmd_output). But, if you have a common configuration that you wish to have applied to all of configurations, then it is better to use a global configuration.

Global Configuration

So far, all entries in the options table have been in the form a key/value pair where the key is a string representing the name of the configuration. There is an additional reserved entry for the global configuration which is the first element of the options table without a key (technically the key is 1 but it does not have to be defined).

If you would like to provide a global configuration to automatically hide the status window, this can be achieved as follows. Notice the first entry in the options table does not define a key, this will be considered global options and applied to all builtin and user defined configurations.

require('kitty-scrollback').setup({
    -- global configuration
    {
      status_window = {
        autoclose = true,
      },
    },
    -- builtin configuration override
    ksb_builtin_get_text_all = {
      kitty_get_text = {
        ansi = false,
      },
    },
    -- user defined configuration table
    myconfig = {
      kitty_get_text = {
        ansi = false,
      },
    },
    -- user defined configuration function
    myfnconfig = function(kitty_data)
      return {
        kitty_get_text = {
          extent = (kitty_data.scrolled_by > kitty_data.lines) and 'all' or 'screen',
        },
      }
    end,
})

Configuration Precedence

The configuration precedence is default > global > builtin > user where default has the lowest and user has the highest precedence.

Type Description
default Standard options defined by kitty-scrollback.nvim and can be found in the file lua/kitty-scrollback/configs/defaults.lua.
global Global options that apply to all builtin and user defined configurations. The first element in the options table without a key is considered the global options.
builtin Options defined by kitty-scrollback.nvim for each kitty_scrollback_nvim kitten command generated by :KittyScrollbackGenerateKittens (e.g., ksb_builtin_get_text_all, ksb_builtin_last_cmd_output, and ksb_builtin_last_visited_cmd_output). The builtin options can be found in the file lua/kitty-scrollback/configs/builtin.lua.
user Options defined by the user in the options table with a string name that is referenced in kitty.conf using the --config flag when defining a mapping for the kitty_scrollback_nvim kitten (e.g., map kitty_mod+h kitty_scrollback_nvim --config myconfig). User defined options can be any string and will merge with builtin options if they share the same key such as ksb_builtin_get_text_all.

Configuration Options

{
  -- KsbCallbacks? fire and forget callback functions
  callbacks = {
    -- fun(kitty_data: KsbKittyData, opts: KsbOpts)? callback executed after initializing kitty-scrollback.nvim
    after_setup = nil,
    -- fun(kitty_data: KsbKittyData, opts: KsbOpts)? callback executed after launch started to process the scrollback buffer
    after_launch = nil,
    -- fun(kitty_data: KsbKittyData, opts: KsbOpts)?  callback executed after scrollback buffer is loaded and cursor is positioned
    after_ready = nil,
    -- fun(paste_window_data: KsbPasteWindowData, kitty_data: KsbKittyData, opts: KsbOpts)? callback executed after the paste window is opened or resized
    after_paste_window_ready = nil,
  },
  -- boolean? if true, enabled all default keymaps
  keymaps_enabled = true,
  -- boolean? if true, restore options that were modified while processing the scrollback buffer
  restore_options = false,
  -- KsbHighlights? highlight overrides
  highlight_overrides = {
    -- table? status window Normal highlight group
    KittyScrollbackNvimStatusWinNormal = {},
    -- table? status window heart icon highlight group
    KittyScrollbackNvimStatusWinHeartIcon = {},
    -- table? status window spinner icon highlight group 
    KittyScrollbackNvimStatusWinSpinnerIcon = {},
    -- table? status window ready icon highlight group
    KittyScrollbackNvimStatusWinReadyIcon = {},
    -- table? status window kitty icon highlight group
    KittyScrollbackNvimStatusWinKittyIcon = {},
    -- table? status window vim icon highlight group
    KittyScrollbackNvimStatusWinNvimIcon = {},
    -- table? paste window Normal highlight group
    KittyScrollbackNvimPasteWinNormal = {},
    -- table? paste window FloatBorder highlight group
    KittyScrollbackNvimPasteWinFloatBorder = {},
    -- table? paste window FloatTitle highlight group
    KittyScrollbackNvimPasteWinFloatTitle = {},
    -- table? scrollback buffer window Visual selection highlight group
    KittyScrollbackNvimVisual = {},
    -- table? scrollback buffer window Normal highlight group
    KittyScrollbackNvimNormal = {},
  },
  -- KsbStatusWindowOpts? options for status window indicating that kitty-scrollback.nvim is ready
  status_window = {
    -- boolean If true, show status window in upper right corner of the screen
    enabled = true,
    -- boolean If true, use plaintext instead of nerd font icons
    style_simple = false,
    -- boolean If true, close the status window after kitty-scrollback.nvim is ready
    autoclose = false,
    -- boolean If true, show a timer in the status window while kitty-scrollback.nvim is loading
    show_timer = false,
    -- KsbStatusWindowIcons? Icons displayed in the status window
    icons = {
      -- string kitty status window icon
      kitty = '󰄛',
      -- string heart string heart status window icon
      heart = '󰣐', -- variants 󰣐 |  |  | ♥ |  | 󱢠 | 
      -- string nvim status window icon
      nvim = '', -- variants  |  |  | 
    },
  },

  -- KsbPasteWindowOpts? options for paste window that sends commands to Kitty
  paste_window = {
    --- BoolOrFn? If true, use Normal highlight group. If false, use NormalFloat
    highlight_as_normal_win = nil,
    -- string? The filetype of the paste window. If nil, use the shell that is configured for kitty
    filetype = nil,
    -- boolean? If true, hide mappings in the footer when the paste window is initially opened
    hide_footer = false,
    -- integer? The winblend setting of the window, see :help winblend
    winblend = 0,
    -- KsbWinOptsOverride? Paste float window overrides, see nvim_open_win() for configuration
    winopts_overrides = nil,
    -- KsbFooterWinOptsOverride? Paste footer window overrides, see nvim_open_win() for configuration
    footer_winopts_overrides = nil,
    -- string? register used during yanks to paste window, see :h registers
    yank_register = '',
    -- boolean? If true, the yank_register copies content to the paste window. If false, disable yank to paste window
    yank_register_enabled = true,
  },

  -- KsbKittyGetText? options passed to get-text when reading scrollback buffer, see kitty @ get-text --help
  kitty_get_text = {
    -- boolean If true, the text will include the ANSI formatting escape codes for colors, bold, italic, etc.
    ansi = true,
    -- string What text to get. The default of screen means all text currently on the screen. all means all the screen+scrollback and selection means the currently selected text. first_cmd_output_on_screen means the output of the first command that was run in the window on screen. last_cmd_output means the output of the last command that was run in the window. last_visited_cmd_output means the first command output below the last scrolled position via scroll_to_prompt. last_non_empty_output is the output from the last command run in the window that had some non empty output. The last four require shell_integration to be enabled. Choices: screen, all, first_cmd_output_on_screen, last_cmd_output, last_non_empty_output, last_visited_cmd_output, selection
    extent = 'all',
    -- boolean If true, clear the selection in the matched window, if any.
    clear_selection = true,
  },
  -- boolean? if true execute :checkhealth kitty-scrollback and skip setup
  checkhealth = false,
  -- string? Sets the mode for coloring the Visual highlight group in the scrollback buffer window. darken uses a darkened version of the Normal highlight group to improve readability. kitty uses the colors defined for selection_foreground and selection_background in your Kitty configuration. nvim uses the default colors defined in the Visual highlight group. reverse reverses the foreground and background colors of the visual selection.
  visual_selection_highlight_mode = 'darken',
}

Nerd Fonts

By default, kitty-scrollback.nvim uses Nerd Fonts in the status window. If you would like to use ASCII instead, set the option status_window.style_simple to true.

  • Status window with Nerd Fonts v3.1.0+ opts.status_window.icons.nvim = '' opts.status_window.style_simple = false
status-win-icon-nvim
  • Status window with Nerd Fonts < v3.1.0 opts.status_window.icons.nvim = '' opts.status_window.style_simple = false
status-win-icon-vim
  • Status window with ASCII text opts.status_window.style_simple = true
status-win-icon-simple

Separate Neovim Configuration

By default, kitty-scrollback.nvim uses your default Neovim configuration. The benefit of this, is that all of your commands, keymaps, and plugins are available to use. However, depending on your setup, having all of your configuration load may be overkill and slow the start time of kitty-scrollback.nvim. There are a couple approaches that can be taken to separate kitty-scrollback.nvim's Neovim configuration from the default Neovim configuration.

No Configuration

If you prefer not to load any Neovim configuration, the arguments --nvim-args --clean --noplugin -n are recommended to be passed to the kitty_scrollback_nvim kitten

Details on these flags can be found by running the command :help startup-options.

--clean     Mimics a fresh install of Nvim.
--noplugin  Skip loading plugins.  
-n          No swap-file will be used.  

To provide this configuration to kitty-scrollback.nvim, pass the --nvim-args flag to the kitty_scrollback_nvim kitten defined in kitty.conf. See Kitten Arguments for more details on configuration the kitty_scrollback_nvim kitten. The following is an example of what the configuration should look like in your kitty.conf.

action_alias kitty_scrollback_nvim kitten /path/to/your/install/kitty-scrollback.nvim/python/kitty_scrollback_nvim.py --nvim-args --clean --noplugin -n

User Configuration

If you prefer to load only a few simple configurations, creating a minimal vimrc (.e.g, init.lua or init.vim) and passing the -u argument to the kitty_scrollback_nvim kitten is recommended.

First, start off by creating your vimrc file. In this example, I will create the file kitty-scrollback-nvim-kitten-config.lua at /path/to/your/config/ with the contents:

-- kitty-scrollback-nvim-kitten-config.lua

-- put your general Neovim configurations here
vim.g.mapleader = ' '
vim.g.maplocalleader = ','

vim.keymap.set({ 'n' }, '<C-e>', '5<C-e>', {})
vim.keymap.set({ 'n' }, '<C-y>', '5<C-y>', {})

-- add kitty-scrollback.nvim to the runtimepath to allow us to require the kitty-scrollback module
-- pick a runtimepath that corresponds with your package manager, if you are not sure leave them all it will not cause any issues
vim.opt.runtimepath:append(vim.fn.stdpath('data') .. '/lazy/kitty-scrollback.nvim') -- lazy.nvim
vim.opt.runtimepath:append(vim.fn.stdpath('data') .. '/site/pack/packer/opt/kitty-scrollback.nvim') -- packer
vim.opt.runtimepath:append(vim.fn.stdpath('data') .. '/site/pack/mikesmithgh/start/kitty-scrollback.nvim') -- pack
require('kitty-scrollback').setup({
  -- put your kitty-scrollback.nvim configurations here
})

In this example, I added a few keymaps before calling require('kitty-scrollback').setup(). You can add your desired configuration, the important part of this configuration are the lines related to runtimepath. Pick the line that corresponds to your package manager, if you are not sure it is safe to leave all the lines. If you have a custom or unique installation of kitty-scrollback.nvim, update the runtimepath to append that location so that Neovim can find the module when calling require('kitty-scrollback').

If you would like to confirm that the runtimepath in kitty-scrollback-nvim-kitten-config.lua is correct, run the following command.

nvim -u /path/to/your/config/kitty-scrollback-nvim-kitten-config.lua

If Neovim opens without any errors, then the runtimepath is configured correctly. If there are errors, you may need to manually find your kitty-scrollback.nvim and append that directory to runtimepath in kitty-scrollback-nvim-kitten-config.lua

Second, after your vimrc file is created (e.g., kitty-scrollback-nvim-kitten-config.lua), pass the file to Neovim using the -u flag in kitty.conf. The following is an example of what the configuration should look like in your kitty.conf.

action_alias kitty_scrollback_nvim kitten /path/to/your/install/kitty-scrollback.nvim/python/kitty_scrollback_nvim.py --nvim-args -u /path/to/your/config/kitty-scrollback-nvim-kitten-config.lua

Use KITTY_SCROLLBACK_NVIM Environment Variable

If you want to use your default Neovim configuration but only have a few minors differences, then using the environment variable KITTY_SCROLLBACK_NVIM is recommended. See the Environment Variables section for an example of how this can be used.

NVIM_APPNAME With Separate Configuration

If you prefer to have a completely separate Neovim configuration for kitty-scrollback.nvim, then using the environment variable NVIM_APPNAME is recommended.

First, start off by creating your Neovim configuration directory. In this example, I will create the directory ~/.config/ksb-nvim and add the file init.lua with the contents:

local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim"
if not vim.loop.fs_stat(lazypath) then
  vim.fn.system({ "git", "clone", "--filter=blob:none", "https://github.com/folke/lazy.nvim.git", "--branch=stable", lazypath, })
end
vim.opt.rtp:prepend(lazypath)

require("lazy").setup({
  "mikesmithgh/kitty-scrollback.nvim",
  enabled = true,
  lazy = true,
  cmd = { "KittyScrollbackGenerateKittens", "KittyScrollbackCheckHealth" },
  event = { "User KittyScrollbackLaunch" },
  config = function()
    require("kitty-scrollback").setup({
      {
        callbacks = {
          after_ready = vim.defer_fn(function()
            vim.fn.confirm(vim.env.NVIM_APPNAME .. " kitty-scrollback.nvim example!")
          end, 1000),
        },
      },
    })
  end,
})

In this example, we have a completely separate Neovim configuration with lazy.nvim as the package manager. kitty-scrollback.nvim is a configured package and has a global configuration to print a message a second after kitty-scrollback.nvim loads.

Second, after your Neovim configuration directory is created (e.g., ~/.config/ksb-nvim), set the environment variable NVIM_APPNAME to your directory in kitty.conf. The following is an example of what the configuration should look like in your kitty.conf.

action_alias kitty_scrollback_nvim kitten /path/to/your/install/kitty-scrollback.nvim/python/kitty_scrollback_nvim.py --env NVIM_APPNAME=ksb-nvim

🧬 Environment Variables

The environment variable KITTY_SCROLLBACK_NVIM is set to true while kitty-scrollback.nvim is active.

This can be used to in your Neovim configuration to provide kitty-scrollback.nvim specific behavior that may differ from a regular Neovim instance.

if vim.env.KITTY_SCROLLBACK_NVIM == 'true' then
    -- kitty-scrollback.nvim specific configuration
end

📄 Filetypes

The scrollback buffer's filetype is set to kitty-scrollback after kitty-scrollback.nvim has finished loading.

This can be used in you Neovim configuration to setup an autocommand to trigger when kitty-scrollback.nvim has finished loading the scrollback buffer.

vim.api.nvim_create_autocmd({ 'FileType' }, {
  group = vim.api.nvim_create_augroup('KittyScrollbackNvimFileType', { clear = true }),
  pattern = { 'kitty-scrollback' },
  callback = function()
    -- add your logic here
    vim.print('kitty-scrollback.nvim is open!')
    return true
  end,
})

The approach of using the filetype autocommand is similar to using the option callbacks.after_ready. One key differences, is that the callback receives metadata about kitty as an argument. The following example is similar to the autocommand and is a just a matter of user preference.

require('kitty-scrollback').setup({
  {
    callbacks = {
      after_ready = function(kitty_data)
        vim.print(kitty_data)
      end,
    },
  },
})

🫡 Commands

The API is available via the kitty-scrollback.api module. e.g., require('kitty-scrollback.api')

Command API Description
:KittyScrollbackGenerateKittens [generate_modes] generate_kittens(table<string|'commands'|'maps'>)? Generate Kitten commands used as reference for configuring kitty.conf
:KittyScrollbackCheckHealth checkhealth() Run :checkhealth kitty-scrollback in the context of Kitty

⌨️ Keymaps

The API is available via the kitty-scrollback.api module. e.g., require('kitty-scrollback.api')

<Plug> Mapping Default Mapping Mode API Description
<Plug>(KsbExecuteCmd) <C-CR> n,i execute_command() Execute the contents of the paste window in Kitty
<Plug>(KsbPasteCmd) <S-CR> n,i paste_command() Paste the contents of the paste window to Kitty without executing
<Plug>(KsbExecuteVisualCmd) <C-CR> v execute_visual_command() Execute the contents of visual selection in Kitty
<Plug>(KsbPasteVisualCmd) <S-CR> v paste_visual_command() Paste the contents of visual selection to Kitty without executing
<Plug>(KsbToggleFooter) g? n toggle_footer() Toggle the paste window footer that displays mappings
<Plug>(KsbCloseOrQuitAll) q n close_or_quit_all() If the current buffer is the paste buffer, then close the window. Otherwise quit Neovim
<Plug>(KsbQuitAll) <C-c> n,i,t quit_all() Quit Neovim
<Plug>(KsbVisualYankLine) <Leader>Y v Maps to "+Y
<Plug>(KsbVisualYank) <Leader>y v Maps to "+y
<Plug>(KsbNormalYankEnd) <Leader>Y n Maps to "+y$
<Plug>(KsbNormalYank) <Leader>y n Maps to "+y
<Plug>(KsbNormalYankLine) <Leader>yy n Maps to "+yy

🪛 Optional Setup

tmux (🧪 experimental )

Warning

🧪 tmux support is currently experimental If you have questions or encounter any issues using tmux, please comment on #115

Setup instructions to integrate kitty-scrollback.nvim with tmux. These steps are optional and only necessary if you wish to add tmux support to kitty-scrollback.nvim.

  • Generate the tmux kitty-scrollback.nvim mappings and add them to $HOME/.tmux.conf or $XDG_CONFIG_HOME/tmux/tmux.conf
nvim --headless +'KittyScrollbackGenerateKittens tmux'
  • You may need to source your tmux configuration for these changes to be reflected in a current tmux session.
tmux source $HOME/.tmux.conf 
# or 
tmux source $XDG_CONFIG_HOME/tmux/tmux.conf
  • By default, kitty-scrollback.nvim overrides the default key binding [ for opening copy-mode. If you use the default prefix key <C-b> and the default key binding [, then test opening a tmux's pane scrollback history with kitty-scrollback.nvim by pressing <C-b>[.

    • You can still access Kitty's scrollback history (default mapping <C-S-h>) in a tmux session. However, this is scoped to Kitty and it will only show the current screen. When you open the tmux pane's scrollback history (default mapping <C-b>[), this is scoped to tmux and will display all of the scrollback history for that tmux session.
  • See example .tmux.conf for reference.

# Browse tmux pane in nvim
bind [ run-shell 'kitty @ kitten /path/to/your/kitty-scrollback.nvim/python/kitty_scrollback_nvim.py --env "TMUX=$TMUX" --env "TMUX_PANE=#{pane_id}"'

👏 Recommendations

Developing kitty-scrollback.nvim NeovimConf 2023

  • The following plugins are nice additions to your Neovim and Kitty setup.
    • vim-kitty - Syntax highlighting for Kitty terminal config files
    • smart-splits.nvim - Seamless navigation between Neovim and Kitty split panes

🤝 Acknowledgements

🐶 Alternatives

scared cat