/quicker.nvim

Improved UI and workflow for the Neovim quickfix

Primary LanguageLuaMIT LicenseMIT

quicker.nvim

Improved UI and workflow for the Neovim quickfix

Requirements

  • Neovim 0.10+

Features

  • Improved styling - including syntax highlighting of grep results.
  • Show context lines - easily view lines above and below the quickfix results.
  • Editable buffer - make changes across your whole project by editing the quickfix buffer and :w.
  • API helpers - some helper methods for common tasks, such as toggling the quickfix.

Improved styling (colorscheme: Duskfox)
Before
Screenshot 2024-07-30 at 6 03 39 PM

After
Screenshot 2024-07-30 at 2 05 49 PM

Context lines around the results
Screenshot 2024-07-30 at 2 06 17 PM

Editing the quickfix to apply changes across multiple files

Screen.Recording.2024-07-30.at.2.35.23.PM.mov

Installation

quicker.nvim supports all the usual plugin managers

lazy.nvim
{
  'stevearc/quicker.nvim',
  ---@module "quicker"
  ---@type quicker.SetupOptions
  opts = {},
}
Packer
require("packer").startup(function()
  use({
    "stevearc/quicker.nvim",
    config = function()
      require("quicker").setup()
    end,
  })
end)
Paq
require("paq")({
  { "stevearc/quicker.nvim" },
})
vim-plug
Plug 'stevearc/quicker.nvim'
dein
call dein#add('stevearc/quicker.nvim')
Pathogen
git clone --depth=1 https://github.com/stevearc/quicker.nvim.git ~/.vim/bundle/
Neovim native package
git clone --depth=1 https://github.com/stevearc/quicker.nvim.git \
  "${XDG_DATA_HOME:-$HOME/.local/share}"/nvim/site/pack/quicker/start/quicker.nvim

Setup

You will need to call setup() for quicker to start working

require("quicker").setup()

It's not required to pass in any options, but you may wish to to set some keymaps.

vim.keymap.set("n", "<leader>q", function()
  require("quicker").toggle()
end, {
  desc = "Toggle quickfix",
})
vim.keymap.set("n", "<leader>l", function()
  require("quicker").toggle({ loclist = true })
end, {
  desc = "Toggle loclist",
})
require("quicker").setup({
  keys = {
    {
      ">",
      function()
        require("quicker").expand({ before = 2, after = 2, add_to_existing = true })
      end,
      desc = "Expand quickfix context",
    },
    {
      "<",
      function()
        require("quicker").collapse()
      end,
      desc = "Collapse quickfix context",
    },
  },
})

Options

A complete list of all configuration options

require("quicker").setup({
  -- Local options to set for quickfix
  opts = {
    buflisted = false,
    number = false,
    relativenumber = false,
    signcolumn = "auto",
    winfixheight = true,
    wrap = false,
  },
  -- Set to false to disable the default options in `opts`
  use_default_opts = true,
  -- Keymaps to set for the quickfix buffer
  keys = {
    -- { ">", "<cmd>lua require('quicker').expand()<CR>", desc = "Expand quickfix content" },
  },
  -- Callback function to run any custom logic or keymaps for the quickfix buffer
  on_qf = function(bufnr) end,
  edit = {
    -- Enable editing the quickfix like a normal buffer
    enabled = true,
    -- Set to true to write buffers after applying edits.
    -- Set to "unmodified" to only write unmodified buffers.
    autosave = "unmodified",
  },
  -- Keep the cursor to the right of the filename and lnum columns
  constrain_cursor = true,
  highlight = {
    -- Use treesitter highlighting
    treesitter = true,
    -- Use LSP semantic token highlighting
    lsp = true,
    -- Load the referenced buffers to apply more accurate highlights (may be slow)
    load_buffers = true,
  },
  -- Map of quickfix item type to icon
  type_icons = {
    E = "󰅚 ",
    W = "󰀪 ",
    I = "",
    N = "",
    H = "",
  },
  -- Border characters
  borders = {
    vert = "",
    -- Strong headers separate results from different files
    strong_header = "",
    strong_cross = "",
    strong_end = "",
    -- Soft headers separate results within the same file
    soft_header = "",
    soft_cross = "",
    soft_end = "",
  },
  -- Trim the leading whitespace from results
  trim_leading_whitespace = true,
  -- Maximum width of the filename column
  max_filename_width = function()
    return math.floor(math.min(95, vim.o.columns / 2))
  end,
  -- How far the header should extend to the right
  header_length = function(type, start_col)
    return vim.o.columns - start_col
  end,
})

Highlights

These are the highlight groups that are used to style the quickfix buffer. You can set these highlight groups yourself or use :help winhighlight in the setup opts option to override them for just the quickfix window.

  • QuickFixHeaderHard - Used for the header that divides results from different files
  • QuickFixHeaderSoft - Used for the header that divides results within the same file
  • Delimiter - Used for the divider between filename, line number, and text
  • QuickFixLineNr - Used for the line number
  • QuickFixFilename - Used for the filename
  • DiagnosticSign* - Used for the signs that display the quickfix error type

API

expand(opts)

expand(opts)
Expand the context around the quickfix results.

Param Type Desc
opts nil|quicker.ExpandOpts
before nil|integer Number of lines of context to show before the line (default 2)
after nil|integer Number of lines of context to show after the line (default 2)
add_to_existing nil|boolean
loclist_win nil|integer

Note:

If there are multiple quickfix items for the same line of a file, only the first
one will remain after calling expand().

collapse()

collapse()
Collapse the context around quickfix results, leaving only the valid items.

refresh(loclist_win)

refresh(loclist_win)
Update the quickfix list with the current buffer text for each item.

Param Type Desc
loclist_win nil|integer

is_open(loclist_win)

is_open(loclist_win)

Param Type Desc
loclist_win nil|integer Check if loclist is open for the given window. If nil, check quickfix.

toggle(opts)

toggle(opts)
Toggle the quickfix or loclist window.

Param Type Desc
opts nil|quicker.OpenOpts
loclist nil|boolean Toggle the loclist instead of the quickfix list
focus nil|boolean Focus the quickfix window after toggling (default false)
height nil|integer Height of the quickfix window when opened. Defaults to number of items in the list.
min_height nil|integer Minimum height of the quickfix window. Default 4.
max_height nil|integer Maximum height of the quickfix window. Default 10.

open(opts)

open(opts)
Open the quickfix or loclist window.

Param Type Desc
opts nil|quicker.OpenOpts
loclist nil|boolean Toggle the loclist instead of the quickfix list
focus nil|boolean Focus the quickfix window after toggling (default false)
height nil|integer Height of the quickfix window when opened. Defaults to number of items in the list.
min_height nil|integer Minimum height of the quickfix window. Default 4.
max_height nil|integer Maximum height of the quickfix window. Default 10.

close(opts)

close(opts)
Close the quickfix or loclist window.

Param Type Desc
opts nil|quicker.CloseOpts
loclist nil|boolean Close the loclist instead of the quickfix list

Other Plugins

In general quicker.nvim should play nice with other quickfix plugins (🟢), except if they change the format of the quickfix buffer. Quicker.nvim relies on owning the :help quickfixtextfunc for the other features to function, so some other plugins you may need to disable or not use parts of their functionality (🟡). Some plugins have features that completely conflict with quicker.nvim (🔴).

  • 🟢 nvim-bqf - Another bundle of several improvements including a floating preview window and fzf integration.
  • 🟢 vim-qf - Adds some useful mappings and default behaviors.
  • 🟡 trouble.nvim - A custom UI for displaying quickfix and many other lists. Does not conflict with quicker.nvim, but instead presents an alternative way to manage and view the quickfix.
  • 🟡 listish.nvim - Provides utilities for adding items to the quickfix and theming (which conflicts with quicker.nvim).
  • 🔴 quickfix-reflector.vim - Also provides an "editable quickfix". I used this for many years and would recommend it.
  • 🔴 replacer.nvim - Another "editable quickfix" plugin.