All Projects → kevinhwang91 → Nvim Bqf

kevinhwang91 / Nvim Bqf

Licence: bsd-3-clause
Better quickfix window in Neovim, polish old quickfix window.

Programming Languages

lua
6591 projects

Projects that are alternatives of or similar to Nvim Bqf

Lsp Status.nvim
Utility functions for getting diagnostic status and progress messages from LSP servers, for use in the Neovim statusline
Stars: ✭ 201 (+67.5%)
Mutual labels:  neovim, nvim, neovim-plugin
nvim-ghost.nvim
👻 GhostText plugin for Neovim with zero dependencies 🎉 Supports neovim running inside WSL too! 🥳 Windows/Linux/macOS supported out-of-the-box! 😄 (Other OSes need python3.6+ installed)
Stars: ✭ 32 (-73.33%)
Mutual labels:  neovim, nvim, neovim-plugin
Comment.nvim
🧠 💪 // Smart and powerful comment plugin for neovim. Supports treesitter, dot repeat, left-right/up-down motions, hooks, and more
Stars: ✭ 796 (+563.33%)
Mutual labels:  neovim, nvim, neovim-plugin
Nvim Hlslens
Hlsearch Lens for Neovim
Stars: ✭ 55 (-54.17%)
Mutual labels:  neovim, nvim, neovim-plugin
Packer.nvim
A use-package inspired plugin manager for Neovim. Uses native packages, supports Luarocks dependencies, written in Lua, allows for expressive config
Stars: ✭ 418 (+248.33%)
Mutual labels:  neovim, nvim, neovim-plugin
Lualine.nvim
A blazing fast and easy to configure neovim statusline written in pure lua.
Stars: ✭ 198 (+65%)
Mutual labels:  neovim, nvim, neovim-plugin
close-buffers.nvim
📑 Delete multiple vim buffers based on different conditions
Stars: ✭ 54 (-55%)
Mutual labels:  neovim, nvim, neovim-plugin
Acid.nvim
Asynchronous Clojure Interactive Development
Stars: ✭ 147 (+22.5%)
Mutual labels:  neovim, nvim, neovim-plugin
Iron.nvim
Interactive Repl Over Neovim
Stars: ✭ 265 (+120.83%)
Mutual labels:  neovim, nvim, neovim-plugin
neogen
A better annotation generator. Supports multiple languages and annotation conventions.
Stars: ✭ 339 (+182.5%)
Mutual labels:  neovim, nvim, neovim-plugin
lir.nvim
Neovim file explorer
Stars: ✭ 194 (+61.67%)
Mutual labels:  neovim, nvim, neovim-plugin
Chadtree
File manager for Neovim. Better than NERDTree.
Stars: ✭ 653 (+444.17%)
Mutual labels:  neovim, nvim, neovim-plugin
agitator.nvim
No description or website provided.
Stars: ✭ 16 (-86.67%)
Mutual labels:  neovim, nvim, neovim-plugin
Nvim Compe
Auto completion plugin for nvim that written in Lua.
Stars: ✭ 433 (+260.83%)
Mutual labels:  neovim, nvim, neovim-plugin
Semshi
🌈 Semantic Highlighting for Python in Neovim
Stars: ✭ 758 (+531.67%)
Mutual labels:  neovim, nvim, neovim-plugin
Nvim Completion Manager
⚠️ PLEASE USE https://github.com/ncm2/ncm2 INSTEAD
Stars: ✭ 950 (+691.67%)
Mutual labels:  neovim, nvim
Vimrc
📝 Vim Configuration for nerds with vim-plug
Stars: ✭ 33 (-72.5%)
Mutual labels:  neovim, nvim
Wishlist
A public catalogue of Lua plugins Neovim users would like to see exist
Stars: ✭ 74 (-38.33%)
Mutual labels:  neovim, neovim-plugin
Vim Dirvish
Directory viewer for Vim ⚡️
Stars: ✭ 929 (+674.17%)
Mutual labels:  neovim, nvim
Dotfiles
🏠
Stars: ✭ 60 (-50%)
Mutual labels:  neovim, nvim

nvim-bqf

The goal of nvim-bqf is to make Neovim's quickfix window better.


In today's era of floating windows, are you afraid to toggle quickfix window to make your eyes uncomfortable? Are you constantly jumping between the edit window and the quickfix window when you use quickfix window to refactor because of lacking a sustainability preview window? Do you think quickfix window lacks a fuzzy search function? At present, nvim-bqf can solve the above problems.

You really don't need any search and replace plugins, because nvim-bqf with the built-in function of the quickfix window allows you to easily search and replace targets.

So why not nvim-bqf?

Table of contents

Features

  • Toggle quickfix window with magic window keep your eyes comfortable
  • Extend built-in context of quickfix to build an eye friendly highlighting at preview
  • Support convenient actions inside quickfix window, see Function table below
  • Support built-in buffer for preview perfectly
  • Fast start time compare with others lua plugins, which almost only spend time on lua require
  • Using signs to filter the items of quickfix window
  • Integrate fzf as a picker/filter in quickfix window

TODO

  • [ ] Provide statusline for information
  • [ ] Find a better way to list history and switch to one
  • [ ] Provide some useful functions to users
  • [ ] Add tests
  • [ ] Use context field to override the existed configuration

Quickstart

Requirements

Preview with fzf needs a pipe command, Windows can't be supported. It must be stated that I'm not working under Windows.

Installation

Install nvim-bqf with your favorite plugin manager! For instance: Vim-plug:

Plug 'kevinhwang91/nvim-bqf'

The default branch is main, please upgrade vim-plug if you encounter any installation issues.

Minimal configuration

Plug 'kevinhwang91/nvim-bqf'

" if you install fzf as system package like `pacman -S fzf` in ArchLinux,
" please comment next line
Plug 'junegunn/fzf', { 'do': { -> fzf#install() } }

" highly recommended
Plug 'nvim-treesitter/nvim-treesitter', {'do': ':TSUpdate'}

The nvim-bqf's preview builds upon the buffers. I highly recommended to use nvim-treesitter to do syntax to the buffer, because vim's syntax is very lagging and is extremely bad for the user experience in large files.

Usage

  1. If you are familiar with quickfix, use quickfix as usual.
  2. If you don't know quickfix well, you can run :vimgrep /\w\+/j % | copen under a buffer inside nvim to get started quickly.
  3. If you want to taste quickfix like demo, check out Integrate with other plugins, and pick up the configuration you like.

Filter with signs

  1. Press <Tab> or <S-Tab> to toggle the sign of item
  2. Press zn or zN will create new quickfix list

Fzf mode

Press zf in quickfix window will enter fzf mode.

fzf in nvim-bqf supports ctrl-t/ctrl-x/ctrl-v key bindings that allow you to open up an item in a new tab, a new horizontal split, or in a new vertical split.

fzf becomes a quickfix filter and create a new quickfix list when multiple items are selected and accepted.

fzf also support ctrl-s to toggle items' sign.

Filter items with signs demo

Key input sequence: <Tab>j<Tab>zn<zN>zf^^<C-o><C-s>zf<C-o><C-s>

input ^^ in fzf will find all signed items, ctrl-o in fzf mode has bind toggle-all

Search and replace demo

Using external grep-like program to search qftool and replace it to mytool, but filter fzf.lua file.

Demonstrating batch undo just show that quickfix has this feature

Documentation

Setup and description

root = {
    auto_enable = {
        description = [[enable nvim-bqf in quickfix window automatically]],
        default = true
    },
    magic_window = {
        description = [[give the window magic, when the window is splited horizontally, keep
            the distance between the current line and the top/bottom border of neovim unchanged.
            It's a bit like a floating window, but the window is indeed a normal window, without
            any floating attributes.]],
        default = true
    },
    auto_resize_height = {
        description = [[resize quickfix window height automatically.
            Shrink higher height to size of list in quickfix window, otherwise extend height
            to size of list or to default height (10)]],
        default = true
    },
    preview = {
        auto_preview = {
            description = [[enable preview in quickfix window automatically]],
            default = true
        },
        border_chars = {
            description = [[border and scroll bar chars, they respectively represent:
                vline, vline, hline, hline, ulcorner, urcorner, blcorner, brcorner, sbar]],
            default = {'│', '│', '─', '─', '╭', '╮', '╰', '╯', '█'}
        },
        delay_syntax = {
            description = [[delay time, to do syntax for previewed buffer, unit is millisecond]],
            default = 50
        },
        win_height = {
            description = [[the height of preview window for horizontal layout]],
            default = 15
        },
        win_vheight = {
            description = [[the height of preview window for vertical layout]],
            default = 15
        }
    },
    func_map = {
        description = [[the table for {function = key}]],
        default = [[see ###Function table for detail]],
    },
    filter = {
        fzf = {
            action_for = {
                ['ctrl-t'] = {
                    description = [[press ctrl-t to open up the item in a new tab]],
                    default = 'tabedit'
                },
                ['ctrl-v'] = {
                    description = [[press ctrl-v to open up the item in a new vertical split]],
                    default = 'vsplit'
                },
                ['ctrl-x'] = {
                    description = [[press ctrl-x to open up the item in a new horizontal split]],
                    default = 'split'
                },
                ['ctrl-s'] = {
                    description = [[press ctrl-s to toggle sign for the selected items]],
                    default = 'signtoggle'
                }
            },
            extra_opts = {
                description = 'extra options for fzf',
                default = {'--bind', 'ctrl-o:toggle-all'}
            }
        }
    }
}

After loaded any modules, lua print(vim.inspect(require('bqf.config'))) will show you all about the current configuration.

You can set value on the fly without any validation, good luck!

Function table

Function only works in the quickfix window, keys can be customized by lua require('bqf').setup({func_map = {}}).

You can reference Customize configuration to configure func_map.

Function Action Def Key
open open the item under the cursor <CR>
openc like open, and close quickfix window o
tab open the item under the curosr in a new tab t
tabb like tab, but stay at quickfix window T
split open the item under the cursor in vertical split <C-x>
vsplit open the item under the cursor in horizontal split <C-v>
prevfile go to previous file under the cursor <C-p>
nextfile go to next file under the cursor <C-n>
prevhist go to previous quickfix list <
nexthist go to next quickfix list >
stoggleup toggle sign and move cursor up <S-Tab>
stoggledown toggle sign and move cursor down <Tab>
stogglevm toggle multiple signs in visual mode <Tab>
sclear clear the signs in current quickfix list z<Tab>
pscrollup scroll up half-page in preview window <C-b>
pscrolldown scroll down half-page in preview window <C-f>
pscrollorig scroll back to original postion in preview window zo
ptogglemode toggle preview window between normal and max size zp
ptoggleitem toggle preview for an item of quickfix list p
ptoggleauto toggle auto preview when cursor moved P
filter create new list for signed items zn
filterr create new list for non-signed items zN
fzffilter enter fzf mode zf

Buffer Commands

  • BqfEnable: Enable nvim-bqf in quickfix window
  • BqfDisable: Disable nvim-bqf in quickfix window
  • BqfToggle: Toggle nvim-bqf in quickfix window

Commands

  • BqfAutoToggle: Toggle nvim-bqf enable automatically

Quickfix context

Vim grant users an ability to stuff a context to quickfix, please run :help quickfix-context for detail.

Why use an additional context?

nvim-bqf will use the context to implement missing features of quickfix. If you are familiar with quickfix, you know quickfix only contains lnum and col to locate a position in an item, but lacks of range. To get better highlighting experience, nvim-bqf processeds the vim regrex pattern and lsp range from the context additionally.

The context's format that can be processed by nvim-bqf is:

" vimscript
let context = {'context': {'bqf': {}}}
-- lua
local context = {context = {bqf = {}}}

nvim-bqf only occupies a key of context, which makes nvim-bqf get along well with other plugins in context of the quickfix window.

Supported keys

context = {
    bqf = {
        pattern_hl = {
            description = [[search pattern from current poistion]],
            type = 'string'
        },
        lsp_ranges_hl = {
            description = [[a list of lsp range. The length of list is equal to the items',
            and each element corresponds one to one]],
            type = 'list in vimscript | table in lua'
        }

    }
}

Simple vimscript tests for understanding

function s:create_qf()
    enew
    let bufnr = bufnr('%')
    for i in range(1, 3)
        call setline(i, i .. ' | ' .. strftime("%F"))
    endfor

    call setqflist([{'bufnr': bufnr, 'lnum': 1, 'col': 5},
                \  {'bufnr': bufnr, 'lnum': 2, 'col': 10},
                \  {'bufnr': bufnr, 'lnum': 3, 'col': 13}])
endfunction

function! Test_bqf_pattern()
    call s:create_qf()
    call setqflist([], 'r', {'context': {'bqf': {'pattern_hl': '\d\+'}},
                \ 'title': 'pattern_hl'})
    cwindow
endfunc

function! Test_bqf_lsp_ranges()
    call s:create_qf()
    let lsp_ranges = []
    call add(lsp_ranges, {
                \ 'start': {'line': 0, 'character': 4},
                \ 'end': {'line': 0, 'character': 8}
                \ })
    call add(lsp_ranges, {
                \ 'start': {'line': 1, 'character': 9},
                \ 'end': {'line': 1, 'character': 11}
                \ })
    call add(lsp_ranges, {
                \ 'start': {'line': 2, 'character': 12},
                \ 'end': {'line': 2, 'character': 14}
                \ })
    call setqflist([], 'r', {'context': {'bqf': {'lsp_ranges_hl': lsp_ranges}},
                \ 'title': 'lsp_ranges_hl'})
    cwindow
endfunc

" Save me, source me. Run `call Test_bqf_pattern()` and `call Test_bqf_lsp_ranges()`

nvim-bqf actually works with context in Integrate with other plugins.

Highlight groups

highlight default link BqfPreviewFloat Normal
highlight default link BqfPreviewBorder Normal
highlight default link BqfPreviewCursor Cursor
highlight default link BqfPreviewRange Search
highlight default link BqfSign SignColumn
  • BqfPreviewFloat: highlight floating window
  • BqfPreviewBorder: highlight border of floating window
  • BqfPreviewCursor: highlight the cursor format [lnum, col] in preview window
  • BqfPreviewRange: highlight the range format [lnum, col, range], pattern_hl and lsp_ranges_hl
  • BqfSign: highlight the sign in quickfix window

Advanced configuration

Customize configuration

call plug#begin('~/.config/nvim/plugged')

Plug 'kevinhwang91/nvim-bqf'

Plug 'junegunn/fzf', { 'do': { -> fzf#install() } }

call plug#end()

highlight BqfPreviewBorder guifg=#50a14f ctermfg=71
highlight link BqfPreviewRange IncSearch

lua <<EOF
require('bqf').setup({
    auto_enable = true,
    preview = {
        win_height = 12,
        win_vheight = 12,
        delay_syntax = 80,
        border_chars = {'┃', '┃', '━', '━', '┏', '┓', '┗', '┛', '█'}
    },
    func_map = {
        vsplit = '',
        ptogglemode = 'z,',
        stoggleup = ''
    },
    filter = {
        fzf = {
            extra_opts = {'--bind', 'ctrl-o:toggle-all', '--prompt', '> '}
        }
    }
})
EOF

Integrate with other plugins

call plug#begin('~/.config/nvim/plugged')

Plug 'kevinhwang91/nvim-bqf'

Plug 'junegunn/fzf', { 'do': { -> fzf#install() } }

Plug 'neoclide/coc.nvim'

" :h CocLocationsChange for detail
let g:coc_enable_locationlist = 0
augroup Coc
    autocmd!
    autocmd User CocLocationsChange ++nested call Coc_qf_jump2loc(g:coc_jump_locations)
augroup END

nmap <silent> gr <Plug>(coc-references)
nnoremap <silent> <leader>qd <Cmd>call Coc_qf_diagnostic()<CR>

function! Coc_qf_diagnostic() abort
    let diagnostic_list = CocAction('diagnosticList')
    let items = []
    let loc_ranges = []
    for d in diagnostic_list
        let text = printf('[%s%s] %s', (empty(d.source) ? 'coc.nvim' : d.source),
                    \ (d.code ? ' ' . d.code : ''), split(d.message, '\n')[0])
        let item = {'filename': d.file, 'lnum': d.lnum, 'col': d.col, 'text': text, 'type':
                    \ d.severity[0]}
        call add(loc_ranges, d.location.range)
        call add(items, item)
    endfor
    call setqflist([], ' ', {'title': 'CocDiagnosticList', 'items': items,
                \ 'context': {'bqf': {'lsp_ranges_hl': loc_ranges}}})
    botright copen
endfunction

function! Coc_qf_jump2loc(locs) abort
    let loc_ranges = map(deepcopy(a:locs), 'v:val.range')
    call setloclist(0, [], ' ', {'title': 'CocLocationList', 'items': a:locs,
                \ 'context': {'bqf': {'lsp_ranges_hl': loc_ranges}}})
    let winid = getloclist(0, {'winid': 0}).winid
    if winid == 0
        aboveleft lwindow
    else
        call win_gotoid(winid)
    endif
endfunction

Plug 'mhinz/vim-grepper'

augroup Grepper
    autocmd!
    autocmd User Grepper call setqflist([], 'r',
                \ {'context': {'bqf': {'pattern_hl': histget('/')}}}) |
                \ botright copen
augroup END

let g:grepper = {
            \ 'open': 0,
            \ 'quickfix': 1,
            \ 'searchreg': 1,
            \ 'highlight': 0,
            \ }

" try `gsiw` under word
nmap gs  <plug>(GrepperOperator)
xmap gs  <plug>(GrepperOperator)

call plug#end()

Feedback

  • If you get an issue or come up with an awesome idea, don't hesitate to open an issue in github.
  • If you think this plugin is useful or cool, consider rewarding it a star.

License

The project is licensed under a BSD-3-clause license. See LICENSE file for details.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].