Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Better quickfix window in Neovim, polish old quickfix window.

License

NotificationsYou must be signed in to change notification settings

kevinhwang91/nvim-bqf

Repository files navigation

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

bqf-demo.mp4

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

You really don't need any search replace plugins, because nvim-bqf with the built-in function of thequickfix 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, seeFunction table below
  • Optimize the buffer preview under treesitter to get extreme performance
  • Using signs to filter the items of quickfix window
  • Integratefzf as a picker/filter in quickfix window
  • Mouse supported for preview window

TODO

  • Find a better way to list history and switch to one
  • Use context field to override the existed configuration
  • Add tests

Quickstart

Requirements

Installation

Install withPacker.nvim:

use {'kevinhwang91/nvim-bqf'}

Minimal configuration

use {'kevinhwang91/nvim-bqf',ft='qf'}-- optionaluse {'junegunn/fzf',run=function()vim.fn['fzf#install']()end}-- optional, highly recommendeduse {'nvim-treesitter/nvim-treesitter',run=':TSUpdate'}

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

nvim-bqf has optimized the preview performance for treesitter

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 insidenvim to get started quickly.
  3. If you want to taste quickfix like demo, check outIntegrate with other plugins, and pick up the configuration youlike.

Filter with signs

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

Fzf mode

Presszf in quickfix window will enter fzf mode.

fzf in nvim-bqf supportsctrl-t/ctrl-x/ctrl-v key bindings that allow you to open up an itemin 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 andaccepted.

nvim-bqf also supportsctrl-q to toggle items' sign and adaptspreview-half-page-up,preview-half-page-down andtoggle-preview fzf's actions for preview.

Please runman fzf and check outKEY/EVENT BINDINGS section for details.

There're two ways to adapt fzf's actions for preview function, usectrl-fandctrl-b keys asexample.

  1. Make$FZF_DEFAULT_OPTS contains--bind=ctrl-f:preview-half-page-down,ctrl-b:preview-half-page-up;
  2. Injectextra_opts = {'--bind', 'ctrl-f:preview-half-page-down,ctrl-b:preview-half-page-up'} tosetup function;

Filter items with signs demo

bqf-sign.mp4

input^^ in fzf prompt will find all signed items,ctrl-o in fzf mode has bindtoggle-all

Search and replace demo

Using external grep-like program to searchdisplay and replace it toshow, but excludesession.lua file.

bqf-search-replace.mp4

Demonstrating batch undo just show that quickfix has this feature

Documentation

Setup and description

{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=false    },preview= {auto_preview= {description=[[Enable preview in quickfix window automatically]],default=true        },border= {description=[[The border for preview window,                `:h nvim_open_win() | call search('border:')`]],default='rounded',        },show_title= {description=[[Show the window title]],default=true        },show_scroll_bar= {description=[[Show the scroll bar]],default=true        },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,                large value (like 999) perform preview window as a "full" mode]],default=15        },win_vheight= {description=[[The height of preview window for vertical layout]],default=15        },winblend= {description=[[The winblend for preview window, `:h winblend`]],default=12        },wrap= {description=[[Wrap the line, `:h wrap` for detail]],default=false        },buf_label= {description=[[Add label of current item buffer at the end of the item line]],default=true        },should_preview_cb= {description=[[A callback function to decide whether to preview while switching buffer,                with (bufnr: number, qwinid: number) parameters]],default=nil        }    },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-q']= {description=[[Press ctrl-q to toggle sign for the selected items]],default='signtoggle'                },                ['ctrl-c']= {description=[[Press ctrl-c to close quickfix window and abort fzf]],default='closeall'                }            },extra_opts= {description='Extra options for fzf',default= {'--bind','ctrl-o:toggle-all'}            }        }    }}

Before loading any modules,:lua =require('bqf.config') will show you everythingabout current configuration.

Function table

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

You can referenceCustomize configuration to configurefunc_map.

FunctionActionDef Key
openopen the item under the cursor<CR>
opencopen the item, and close quickfix windowo
dropusedrop to open the item, and close quickfix windowO
tabdropusetab drop to open the item, and close quickfix window
tabopen the item in a new tabt
tabbopen the item in a new tab, but stay in quickfix windowT
tabcopen the item in a new tab, and close quickfix window<C-t>
splitopen the item in horizontal split<C-x>
vsplitopen the item in vertical split<C-v>
prevfilego to previous file under the cursor in quickfix window<C-p>
nextfilego to next file under the cursor in quickfix window<C-n>
prevhistcycle to previous quickfix list in quickfix window<
nexthistcycle to next quickfix list in quickfix window>
lastleavego to last selected item in quickfix window'"
stoggleuptoggle sign and move cursor up<S-Tab>
stoggledowntoggle sign and move cursor down<Tab>
stogglevmtoggle multiple signs in visual mode<Tab>
stogglebuftoggle signs for same buffers under the cursor'<Tab>
sclearclear the signs in current quickfix listz<Tab>
pscrollupscroll up half-page in preview window<C-b>
pscrolldownscroll down half-page in preview window<C-f>
pscrollorigscroll back to original position in preview windowzo
ptogglemodetoggle preview window between normal and max sizezp
ptoggleitemtoggle preview for a quickfix list itemp
ptoggleautotoggle auto-preview when cursor movesP
filtercreate new list for signed itemszn
filterrcreate new list for non-signed itemszN
fzffilterenter fzf modezf

Additional mouse supported:

  1. <ScrollWheelUp> and<ScrollWheelDown>: Scroll preview window.
  2. <2-LeftMouse>:
    • In quickfix window: Type<CR>;
    • In preview window: Jump to the location even it has scrolled;

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

API

bqf.lua

Quickfix context

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

Why use an additional context?

nvim-bqf will use the context to implement missing features of quickfix. To get better highlightingexperience, nvim-bqf processeds the vim regrex pattern andlsp range from thecontext additionally.

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

localcontext= {context= {bqf= {}}}

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

Supported keys

context= {bqf= {pattern_hl= {description=[[search pattern from current position]],type='string'        },lsp_ranges_hl= {description=[[a list of lsp range. The length of list is equal to the items',            pairwise correspondence each other]],type='table'        }    }}

Simple lua tests for understanding

localcmd=vim.cmdlocalapi=vim.apilocalfn=vim.fnlocalfunctioncreateQf()cmd('enew')localbufnr=api.nvim_get_current_buf()locallines= {}fori=1,3dotable.insert(lines, ('%d | %s'):format(i,fn.strftime('%F')))endapi.nvim_buf_set_lines(bufnr,0,-1,false,lines)fn.setqflist({        {bufnr=bufnr,lnum=1,col=5}, {bufnr=bufnr,lnum=2,col=10},        {bufnr=bufnr,lnum=3,col=13}    })endfunction_G.bqfPattern()createQf()fn.setqflist({},'r', {context= {bqf= {pattern_hl=[[\d\+]]}},title='patternHl'})cmd('cw')endfunction_G.bqfLspRanges()createQf()locallspRanges= {}table.insert(lspRanges,        {start= {line=0,character=4}, ['end']= {line=0,character=8}})table.insert(lspRanges,        {start= {line=1,character=9}, ['end']= {line=1,character=11}})table.insert(lspRanges,        {start= {line=2,character=12}, ['end']= {line=2,character=14}})fn.setqflist({},'r', {context= {bqf= {lsp_ranges_hl=lspRanges}},title='lspRangesHl'})cmd('cw')endfunction_G.qfRanges()createQf()localitems=fn.getqflist()localit1,it2,it3=items[1],items[2],items[3]it1.end_lnum,it1.end_col=it1.lnum,it1.col+4it2.end_lnum,it2.end_col=it2.lnum,it2.col+2it3.end_lnum,it3.end_col=it3.lnum,it3.col+2fn.setqflist({},'r', {items=items,title='qfRangesHl'})cmd('cw')end-- Save and source me(`so %`). Run `:lua bqfPattern()`, `:lua bqfLspRanges()` and `:lua qfRanges()`

nvim-bqf actually works with context inIntegrate with other plugins.

Highlight groups

hidefaultlinkBqfPreviewFloatNormalhidefaultlinkBqfPreviewBorderFloatBorderhidefaultlinkBqfPreviewTitleTitlehidefaultlinkBqfPreviewThumbPmenuThumbhidefaultlinkBqfPreviewSbarPmenuSbarhidefaultlinkBqfPreviewCursorCursorhidefaultlinkBqfPreviewCursorLineCursorLinehidefaultlinkBqfPreviewRangeIncSearchhidefaultlinkBqfPreviewBufLabelBqfPreviewRangehi default BqfSign ctermfg=14 guifg=Cyan
  • BqfPreviewFloat: Floating window.
  • BqfPreviewBorder: Border of floating window.
  • BqfPreviewTitle: Title of preview window.
  • BqfPreviewThumb: Thumb of preview window.
  • BqfPreviewSbar: Scroll bar of preview window, only take effect if the border is missing right.
  • BqfPreviewCursor: The cursor format[lnum, col] in preview window.
  • BqfPreviewCursorLine: The text line of the cursor in preview window.
  • BqfPreviewRange: The range format[lnum, col, range], which is produced bypattern_hl,lsp_ranges_hl and quickfix range.
  • BqfPreviewBufLabel: The index and count of the buffer under the cursor
  • BqfSign: The sign in quickfix window.

Advanced configuration

Customize configuration

vim.cmd([[    hi BqfPreviewBorder guifg=#3e8e2d ctermfg=71    hi BqfPreviewTitle guifg=#3e8e2d ctermfg=71    hi BqfPreviewThumb guibg=#3e8e2d ctermbg=71    hi link BqfPreviewRange Search]])require('bqf').setup({auto_enable=true,auto_resize_height=true,-- highly recommended enablepreview= {win_height=12,win_vheight=12,delay_syntax=80,border= {'','','','','','','',''},show_title=false,should_preview_cb=function(bufnr,qwinid)localret=truelocalbufname=vim.api.nvim_buf_get_name(bufnr)localfsize=vim.fn.getfsize(bufname)iffsize>100*1024then-- skip file size greater than 100kret=falseelseifbufname:match('^fugitive://')then-- skip fugitive bufferret=falseendreturnretend    },-- make `drop` and `tab drop` to become preferredfunc_map= {drop='o',openc='O',split='<C-s>',tabdrop='<C-t>',-- set to empty string to disabletabc='',ptogglemode='z,',    },filter= {fzf= {action_for= {['ctrl-s']='split', ['ctrl-t']='tab drop'},extra_opts= {'--bind','ctrl-o:toggle-all','--prompt','>'}        }    }})

Integrate with other plugins

localfn=vim.fnlocalcmd=vim.cmdlocalapi=vim.apicmd([[    packadd nvim-bqf    packadd fzf    packadd nvim-treesitter    packadd vim-grepper    packadd coc.nvim]])-- https://github.com/mhinz/vim-greppervim.g.grepper= {tools= {'rg','grep'},searchreg=1}cmd(([[    aug Grepper        au!        au User Grepper ++nested %s    aug END]]):format([[call setqflist([], 'r', {'context': {'bqf': {'pattern_hl': '\%#' . getreg('/')}}})]]))-- try `gsiw` under wordcmd([[    nmap gs  <plug>(GrepperOperator)    xmap gs  <plug>(GrepperOperator)]])-- https://github.com/neoclide/coc.nvim-- if you use coc-fzf, you should disable its CocLocationsChange event-- to make bqf work for <Plug>(coc-references)-- vim.schedule(function()--     cmd('au! CocFzfLocation User CocLocationsChange')-- end)vim.g.coc_enable_locationlist=0cmd([[    aug Coc        au!        au User CocLocationsChange lua _G.jumpToLoc()    aug END]])cmd([[    nmap <silent> gr <Plug>(coc-references)    nnoremap <silent> <leader>qd <Cmd>lua _G.diagnostic()<CR>]])-- just use `_G` prefix as a global function for a demo-- please use module instead in realityfunction_G.jumpToLoc(locs)locs=locsorvim.g.coc_jump_locationsfn.setloclist(0, {},'', {title='CocLocationList',items=locs})localwinid=fn.getloclist(0, {winid=0}).winidifwinid==0thencmd('abo lw')elseapi.nvim_set_current_win(winid)endendfunction_G.diagnostic()fn.CocActionAsync('diagnosticList','',function(err,res)iferr==vim.NILthenlocalitems= {}for_,dinipairs(res)dolocaltext= ('[%s%s] %s'):format((d.source==''and'coc.nvim'ord.source),                    (d.code==vim.NILand''or''..d.code),d.message:match('([^\n]+)\n*'))localitem= {filename=d.file,lnum=d.lnum,end_lnum=d.end_lnum,col=d.col,end_col=d.end_col,text=text,type=d.severity                }table.insert(items,item)endfn.setqflist({},'', {title='CocDiagnosticList',items=items})cmd('bo cope')endend)end-- you can also subscribe User `CocDiagnosticChange` event to reload your diagnostic in quickfix-- dynamically, enjoy yourself :)

Customize quickfix window (Easter egg)

Quickfix window default UI is extremely outdated and low level aesthetics. However, you can dress upyour personal quickfix window:) Here is the configuration for demo:

This section is notnvim-bqf exclusive, you can use the configuration withoutnvim-bqf

Format new quickfix

Setquickfixtextfunc option and write down corresponding function:

localfn=vim.fnfunction_G.qftf(info)localitemslocalret= {}-- The name of item in list is based on the directory of quickfix window.-- Change the directory for quickfix window make the name of item shorter.-- It's a good opportunity to change current directory in quickfixtextfunc :)---- local alterBufnr = fn.bufname('#') -- alternative buffer is the buffer before enter qf window-- local root = getRootByAlterBufnr(alterBufnr)-- vim.cmd(('noa lcd %s'):format(fn.fnameescape(root)))--ifinfo.quickfix==1thenitems=fn.getqflist({id=info.id,items=0}).itemselseitems=fn.getloclist(info.winid, {id=info.id,items=0}).itemsendlocallimit=31localfnameFmt1,fnameFmt2='%-'..limit..'s','…%.'.. (limit-1)..'s'localvalidFmt='%s │%5d:%-3d│%s %s'fori=info.start_idx,info.end_idxdolocale=items[i]localfname=''localstrife.valid==1thenife.bufnr>0thenfname=fn.bufname(e.bufnr)iffname==''thenfname='[No Name]'elsefname=fname:gsub('^'..vim.env.HOME,'~')end-- char in fname may occur more than 1 width, ignore this issue in order to keep performanceif#fname<=limitthenfname=fnameFmt1:format(fname)elsefname=fnameFmt2:format(fname:sub(1-limit))endendlocallnum=e.lnum>99999and-1ore.lnumlocalcol=e.col>999and-1ore.collocalqtype=e.type==''and''or''..e.type:sub(1,1):upper()str=validFmt:format(fname,lnum,col,qtype,e.text)elsestr=e.textendtable.insert(ret,str)endreturnretendvim.o.qftf='{info -> v:lua._G.qftf(info)}'-- Adapt fzf's delimiter in nvim-bqfrequire('bqf').setup({filter= {fzf= {extra_opts= {'--bind','ctrl-o:toggle-all','--delimiter',''}        }    }})

Rebuild syntax for quickfix

Addqf.vim under your syntax path, for instance:~/.config/nvim/syntax/qf.vim

ifexists('b:current_syntax')finishendifsynmatchqfFileName/^[^│]*/nextgroup=qfSeparatorLeftsynmatchqfSeparatorLeft//containednextgroup=qfLineNrsynmatchqfLineNr/[^│]*/containednextgroup=qfSeparatorRightsynmatchqfSeparatorRight''containednextgroup=qfError,qfWarning,qfInfo,qfNotesynmatchqfError/ E .*$/containedsynmatchqfWarning/ W .*$/containedsynmatchqfInfo/ I .*$/containedsynmatchqfNote/ [NH] .*$/containedhideflinkqfFileNameDirectoryhideflinkqfSeparatorLeftDelimiterhideflinkqfSeparatorRightDelimiterhideflinkqfLineNrLineNrhideflinkqfErrorDiagnosticErrorhideflinkqfWarningDiagnosticWarnhideflinkqfInfoDiagnosticInfohideflinkqfNoteDiagnosticHintletb:current_syntax='qf'

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. SeeLICENSE file for details.

About

Better quickfix window in Neovim, polish old quickfix window.

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages


[8]ページ先頭

©2009-2025 Movatter.jp