From bdb090aa22a3585b2f6c549ca4773b4e4e76bed1 Mon Sep 17 00:00:00 2001 From: Romain Lafourcade Date: Wed, 5 May 2021 12:36:43 +0200 Subject: [PATCH 01/18] This is a first attempt at modernising this plugin. - more lambdas - use of the new "method" syntax - use &quickfixtextfunc to format the display - really make :Doline/:Dofile wrappers around :cdo/:ldo/:cfdo/:lfdo by removing legacy code (I will probably remove them anyway) - rename some functions - "filegroup" doesn't depend on the display anymore except for line('.') - "preview" as well - "preview" now also jumps to the column if applicable - new utility functions (WIP) --- after/ftplugin/qf.vim | 2 + autoload/qf.vim | 145 +++++++++++++++++++++++--------------- autoload/qf/do.vim | 42 +++-------- autoload/qf/filegroup.vim | 66 ++++++++++------- autoload/qf/preview.vim | 20 ++++-- autoload/qf/toggle.vim | 10 +-- autoload/qf/wrap.vim | 8 +-- plugin/qf.vim | 16 +++-- 8 files changed, 169 insertions(+), 140 deletions(-) diff --git a/after/ftplugin/qf.vim b/after/ftplugin/qf.vim index 90e81a7..7cabd1f 100644 --- a/after/ftplugin/qf.vim +++ b/after/ftplugin/qf.vim @@ -176,6 +176,8 @@ let b:undo_ftplugin .= "| delcommand Filter" \ . "| unlet! b:qf_isLoc" " decide where to open the location/quickfix window +" :help g:qf_loclist_window_bottom +" :help g:qf_window_bottom if (b:qf_isLoc == 1 && get(g:, 'qf_loclist_window_bottom', 1)) \ || (b:qf_isLoc == 0 && get(g:, 'qf_window_bottom', 1)) wincmd J diff --git a/autoload/qf.vim b/autoload/qf.vim index 91a1539..afaaee6 100644 --- a/autoload/qf.vim +++ b/autoload/qf.vim @@ -19,19 +19,6 @@ let s:save_cpo = &cpo set cpo&vim -" open the current entry in th preview window -function qf#PreviewFileUnderCursor() - let cur_list = b:qf_isLoc == 1 ? getloclist('.') : getqflist() - let cur_line = getline(line('.')) - let cur_file = fnameescape(substitute(cur_line, '|.*$', '', '')) - if cur_line =~ '|\d\+' - let cur_pos = substitute(cur_line, '^\(.\{-}|\)\(\d\+\)\(.*\)', '\2', '') - execute "pedit +" . cur_pos . " " . cur_file - else - execute "pedit " . cur_file - endif -endfunction - " helper function " returns 1 if the window with the given number is a quickfix window " 0 if the window with the given number is not a quickfix window @@ -73,13 +60,26 @@ function! qf#IsLocWindowOpen(nmbr) abort return 0 endfunction -" returns location list of the current loclist if isLoc is set -" qf list otherwise -function! qf#GetList() +" returns current location list or quickfix list +function! qf#GetListItems(idx) + let what = { 'idx': a:->get('idx', 0), 'items': 1 } + if get(b:, 'qf_isLoc', 0) - return getloclist(0) + return getloclist(0, what)["items"] else - return getqflist() + return getqflist(what)["items"] + endif +endfunction + +" helper +" returns the number of items in a loc/qf list +function! qf#GetListSize() + let what = { 'size': 1 } + + if get(b:, 'qf_isLoc', 0) + return getloclist(0, what)["size"] + else + return getqflist(what)["size"] endif endfunction @@ -107,68 +107,97 @@ function! qf#SetList(newlist, ...) endif endfunction -function! qf#GetEntryPath(line) abort - " +- match from the first pipe to the end of line - " | declaring EOL explicitly is faster than implicitly - " | +- replace match with nothing - " | | +- no flags - return substitute(a:line, '|.*$', '', '') -endfunction - " open the quickfix window if there are valid errors -function! qf#OpenQuickfix() +function! qf#OpenQuickfixWindow() if get(g:, 'qf_auto_open_quickfix', 1) " get user-defined maximum height let max_height = get(g:, 'qf_max_height', 10) < 1 ? 10 : get(g:, 'qf_max_height', 10) - let qf_list = getqflist() - - " shorten paths if applicable - if get(g:, 'qf_shorten_path', 0) > 0 - call setqflist(qf#ShortenPathsInList(qf_list)) - endif - - execute get(g:, "qf_auto_resize", 1) ? 'cclose|' . min([ max_height, len(qf_list) ]) . 'cwindow' : 'cclose|cwindow' + execute get(g:, "qf_auto_resize", 1) ? 'cclose|' . min([ max_height, qf#GetListSize() ]) . 'cwindow' : 'cclose|cwindow' endif endfunction " open a location window if there are valid locations -function! qf#OpenLoclist() +function! qf#OpenLocationWindow() if get(g:, 'qf_auto_open_loclist', 1) " get user-defined maximum height let max_height = get(g:, 'qf_max_height', 10) < 1 ? 10 : get(g:, 'qf_max_height', 10) - let loc_list = getloclist(0) + execute get(g:, "qf_auto_resize", 1) ? 'lclose|' . min([ max_height, qf#GetListSize() ]) . 'lwindow' : 'lclose|lwindow' + endif +endfunction - " shorten paths if applicable - if get(g:, 'qf_shorten_path', 0) > 0 - call setloclist(0, qf#ShortenPathsInList(loc_list)) - endif +function! qf#QuickfixTextFunc(options) + let items = a:options["quickfix"] == 1 ? getqflist() : getloclist(a:options["winid"]) + return items->map({ key, val -> val->qf#FormatItem() }) +endfunction + +function! qf#FormatItem(item) + return [ + \ a:item->qf#FormatFilename(), + \ a:item->qf#FormatLocation(), + \ a:item->qf#FormatText(), + \ ]->join('|') +endfunction - execute get(g:, "qf_auto_resize", 1) ? 'lclose|' . min([ max_height, len(loc_list) ]) . 'lwindow' : 'lclose|lwindow' +function! qf#FormatFilename(item) + let filename = a:item["bufnr"]->bufname() + + if has('patch-8.2.1741') + return pathshorten(filename, g:->get("qf_shorten_path", 1)) + else + return pathshorten(filename) endif endfunction -" shorten file paths in given qf/loc list -function! qf#ShortenPathsInList(list) - let index = 0 - while index < len(a:list) - " item is a dict, sample: { lnum: 14, text: 'foo bar', bufnr: 3, ... } - let item = a:list[index] +function! qf#FormatLocation(item) + return [ + \ a:item->get("lnum", 0)->qf#FormatLineNumber(), + \ a:item->get("col", 0)->qf#FormatColumn(), + \ a:item->get("type", '')->qf#FormatType(), + \ a:item->get("nr", 0)->qf#FormatErrorNumber(), + \ ]->join('') +endfunction + +function! qf#FormatText(item) + " return ' ' .. a:item->get("text", '') + return a:item["text"] +endfunction + +function! qf#FormatLineNumber(lnum) + return a:lnum != 0 ? a:lnum : '-' +endfunction - let filepath = bufname(item["bufnr"]) - let trim_len = get(g:, "qf_shorten_path", 1) +function! qf#FormatColumn(col) + return a:col > 0 ? ' col ' .. a:col : '' +endfunction - " set the 'module' field to customise the visual filename in the qf/loc list (available since 8.0.1782) - if has('patch-8.2.1741') - let item["module"] = pathshorten(filepath, trim_len) +function! qf#FormatType(type) + if a:type =~? 'e' + return ' error' + elseif a:type =~? 'i' + return ' info' + elseif a:type =~? 'n' + return ' note' + elseif a:type =~? 'w' + return ' warning' + else + return '' + endif +endfunction + +function! qf#FormatErrorNumber(nr) + if a:nr > 0 + if a:nr->string()->len() == 1 + return ' ' .. a:nr + elseif a:nr->string()->len() == 2 + return ' ' .. a:nr else - let item["module"] = pathshorten(filepath) + return ' ' .. a:nr endif - - let index = index + 1 - endwhile - return a:list + else + return '' + endif endfunction let &cpo = s:save_cpo diff --git a/autoload/qf/do.vim b/autoload/qf/do.vim index 641e17d..2f70f28 100644 --- a/autoload/qf/do.vim +++ b/autoload/qf/do.vim @@ -19,40 +19,18 @@ let s:save_cpo = &cpo set cpo&vim -" do something with each entry -" a single function for :Doline and :Dofile both in a quickfix list and -" a location list -" falls back to :cdo, :cfdo, :ldo, :lfdo when possible +" Do something with each entry +" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +" Handles :Doline and :Dofile, in quickfix and location lists. +" Wrapper aound :cdo, :cfdo, :ldo, :lfdo. function! qf#do#DoList(line, cmd) - if exists("b:qf_isLoc") - let prefix = b:qf_isLoc == 1 ? "l" : "c" - else - let prefix = "c" - endif + let prefix = b:->get("qf_isLoc", 1) ? "l" : "c" + let modifier = a:line == 1 ? "" : "f" - if v:version >= 705 - \ || v:version == 704 && has("patch858") - if a:line == 1 - let modifier = "" - else - let modifier = "f" - endif - - try - execute prefix . modifier . "do " . a:cmd - catch /^Vim\%((\a\+)\)\=:E\%(553\|42\):/ - endtry - else - try - silent execute prefix . "first" - while 1 - execute a:cmd - - silent execute a:line == 1 ? prefix . "next" : prefix . "nfile" - endwhile - catch /^Vim\%((\a\+)\)\=:E\%(553\|42\):/ - endtry - endif + try + execute prefix . modifier . "do " . a:cmd + catch /^Vim\%((\a\+)\)\=:E\%(553\|42\):/ + endtry endfunction let &cpo = s:save_cpo diff --git a/autoload/qf/filegroup.vim b/autoload/qf/filegroup.vim index 9bf2900..05af56f 100644 --- a/autoload/qf/filegroup.vim +++ b/autoload/qf/filegroup.vim @@ -19,40 +19,54 @@ let s:save_cpo = &cpo set cpo&vim -function! s:JumpToFirstItemOfFileChunk() abort - let l:chunk_file_path = qf#GetEntryPath(getline('.')) +function! qf#filegroup#NextFile() abort + if exists("b:qf_isLoc") + let items = qf#GetListItems(0) + let current_index = line('.') - 1 + let current_bufnr = items[current_index]["bufnr"] + let limit = items->len() - while line('.') - 1 != 0 - \ && l:chunk_file_path == qf#GetEntryPath(getline(line('.') - 1)) - normal! k - endwhile + while current_index < limit && items[current_index]["bufnr"] == current_bufnr + let current_index += 1 + endwhile - normal! zz + if current_index == limit + 1 + else + execute current_index + 1 + endif + endif endfunction -function! s:JumpFileChunk(down) abort - let l:start_file_path = qf#GetEntryPath(getline('.')) - let l:direction = a:down ? 'j' : 'k' - let l:end = a:down ? '$' : 1 +function! qf#filegroup#PreviousFile() abort + if exists("b:qf_isLoc") + let items = qf#GetListItems(0) + let current_index = line('.') - 1 + let current_bufnr = items[current_index]["bufnr"] + let limit = 0 - while l:start_file_path - \ == qf#GetEntryPath(getline('.')) - \ && getline('.') != getline(l:end) - execute 'normal! ' . l:direction - endwhile + while current_index > limit && items[current_index]["bufnr"] == current_bufnr + let current_index -= 1 + endwhile - call s:JumpToFirstItemOfFileChunk() -endfunction + if current_index == limit + normal! G + else + execute current_index + 1 + endif -function! qf#filegroup#PreviousFile() abort - if exists("b:qf_isLoc") - call s:JumpFileChunk(0) - endif -endfunction + let current_index = line('.') - 1 + let current_bufnr = items[current_index]["bufnr"] -function! qf#filegroup#NextFile() abort - if exists("b:qf_isLoc") - call s:JumpFileChunk(1) + while current_index > limit && items[current_index]["bufnr"] == current_bufnr + let current_index -= 1 + endwhile + + if current_index == limit + 1 + else + execute current_index + 2 + endif endif endfunction diff --git a/autoload/qf/preview.vim b/autoload/qf/preview.vim index 27ec033..5f507b0 100644 --- a/autoload/qf/preview.vim +++ b/autoload/qf/preview.vim @@ -21,16 +21,22 @@ set cpo&vim " open the current entry in th preview window function! qf#preview#PreviewFileUnderCursor() - let cur_list = qf#GetList() - let cur_line = getline(line('.')) - let cur_file = fnameescape(qf#GetEntryPath(cur_line)) + let winview = winsaveview() - if cur_line =~ '|\d\+' - let cur_pos = substitute(cur_line, '^\(.\{-}|\)\(\d\+\)\(.*\)', '\2', '') - execute "pedit +" . cur_pos . " " . cur_file + let current_item = qf#GetListItems(line('.'))[0] + let current_file_name = current_item["bufnr"]->bufname() + let current_file_line = current_item->get('lnum', 0) + let current_file_column = current_item->get('col', 0) + + if current_file_line && current_file_column + execute "pedit +" .. current_file_line .. " " .. current_file_name .. "|normal! " .. current_file_column .. "G" + elseif current_file_line && !current_file_column + execute "pedit +" .. current_file_line .. " " .. current_file_name else - execute "pedit " . cur_file + execute "pedit " .. current_file_name endif + + call winrestview(winview) endfunction let &cpo = s:save_cpo diff --git a/autoload/qf/toggle.vim b/autoload/qf/toggle.vim index 263e02c..cf732bc 100644 --- a/autoload/qf/toggle.vim +++ b/autoload/qf/toggle.vim @@ -19,7 +19,7 @@ let s:save_cpo = &cpo set cpo&vim -" toggles the quickfix window +" Toggles the quickfix window. function! qf#toggle#ToggleQfWindow(stay) abort " save the view if the current window is not a quickfix window if get(g:, 'qf_save_win_view', 1) && !qf#IsQfWindow(winnr()) @@ -38,7 +38,7 @@ function! qf#toggle#ToggleQfWindow(stay) abort call winrestview(winview) endif else - execute get(g:, 'qf_auto_resize', 1) ? min([ max_height, len(getqflist()) ]) . 'cwindow' : max_height . 'cwindow' + execute get(g:, 'qf_auto_resize', 1) ? min([ max_height, qf#GetListSize() ]) . 'cwindow' : max_height . 'cwindow' if qf#IsQfWindowOpen() wincmd p if !empty(winview) @@ -51,8 +51,8 @@ function! qf#toggle#ToggleQfWindow(stay) abort endif endfunction -" toggles the location window associated with the current window -" or whatever location window has the focus +" Toggles the location window associated with the current window +" or whatever location window has the focus. function! qf#toggle#ToggleLocWindow(stay) abort " save the view if the current window is not a location window if get(g:, 'qf_save_win_view', 1) && !qf#IsLocWindow(winnr()) @@ -70,7 +70,7 @@ function! qf#toggle#ToggleLocWindow(stay) abort call winrestview(winview) endif else - execute get(g:, 'qf_auto_resize', 1) ? min([ max_height, len(getloclist(0)) ]) . 'lwindow' : max_height . 'lwindow' + execute get(g:, 'qf_auto_resize', 1) ? min([ max_height, qf#GetListSize() ]) . 'lwindow' : max_height . 'lwindow' if qf#IsLocWindowOpen(0) wincmd p if !empty(winview) diff --git a/autoload/qf/wrap.vim b/autoload/qf/wrap.vim index b543780..10dca64 100644 --- a/autoload/qf/wrap.vim +++ b/autoload/qf/wrap.vim @@ -19,11 +19,7 @@ let s:save_cpo = &cpo set cpo&vim -" wrap around -" TODO (Nelo-T. Wallus): I actually don't know what this does -" TODO (romainl): Built-in :cn/:cp/:ln/:lp stop at the beginning -" and end of the list. This allows us to wrap -" around. +" Wrap :cn/:cp/:ln/:lp around function! qf#wrap#WrapCommand(direction, prefix) if a:direction == "up" try @@ -41,7 +37,7 @@ function! qf#wrap#WrapCommand(direction, prefix) endtry endif - if &foldopen =~ 'quickfix' && foldclosed(line('.')) != -1 + if &foldopen =~ 'quickfix' && line('.')->foldclosed() != -1 normal! zv endif endfunction diff --git a/plugin/qf.vim b/plugin/qf.vim index 87c488c..bda264b 100644 --- a/plugin/qf.vim +++ b/plugin/qf.vim @@ -86,22 +86,22 @@ augroup qf " automatically open the location/quickfix window after :make, :grep, " :lvimgrep and friends if there are valid locations/errors - exec printf('autocmd QuickFixCmdPost %s nested call qf#OpenQuickfix()', s:GetQuickFixCmdsPattern()) - exec printf('autocmd QuickFixCmdPost %s nested call qf#OpenLoclist()', s:GetLocListCmdsPattern()) + exec printf('autocmd QuickFixCmdPost %s nested call qf#OpenQuickfixWindow()', s:GetQuickFixCmdsPattern()) + exec printf('autocmd QuickFixCmdPost %s nested call qf#OpenLocationWindow()', s:GetLocListCmdsPattern()) " special case for :helpgrep and :lhelpgrep since the help window may not " be opened yet when QuickFixCmdPost triggers if exists('*timer_start') - autocmd QuickFixCmdPost helpgrep nested call timer_start(10, { -> execute('call qf#OpenQuickfix()') }) - autocmd QuickFixCmdPost lhelpgrep nested call timer_start(10, { -> execute('call qf#OpenLoclist()') }) + autocmd QuickFixCmdPost helpgrep nested call timer_start(10, { -> execute('call qf#OpenQuickfixWindow()') }) + autocmd QuickFixCmdPost lhelpgrep nested call timer_start(10, { -> execute('call qf#OpenLocationWindow()') }) else " the window qf is not positioned correctly but at least it's there - autocmd QuickFixCmdPost helpgrep nested call qf#OpenQuickfix() + autocmd QuickFixCmdPost helpgrep nested call qf#OpenQuickfixWindow() " I can't make it work for :lhelpgrep endif " spacial case for $ vim -q - autocmd VimEnter * nested if count(get(v:, 'argv', []), '-q') | call qf#OpenQuickfix() | endif + autocmd VimEnter * nested if count(get(v:, 'argv', []), '-q') | call qf#OpenQuickfixWindow() | endif " automatically close corresponding loclist when quitting a window if exists('##QuitPre') @@ -109,4 +109,8 @@ augroup qf endif augroup END +if exists('+quickfixtextfunc') && get(g:, "qf_shorten_path", 1) + set quickfixtextfunc=qf#QuickfixTextFunc +endif + let &cpo = s:save_cpo From 2e8e2c7cc37d5e92abcac9e9963b5dad347afc80 Mon Sep 17 00:00:00 2001 From: Romain Lafourcade Date: Wed, 5 May 2021 13:08:33 +0200 Subject: [PATCH 02/18] Use dictionary lookup instead of conditional --- autoload/qf.vim | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/autoload/qf.vim b/autoload/qf.vim index afaaee6..7963db9 100644 --- a/autoload/qf.vim +++ b/autoload/qf.vim @@ -173,17 +173,13 @@ function! qf#FormatColumn(col) endfunction function! qf#FormatType(type) - if a:type =~? 'e' - return ' error' - elseif a:type =~? 'i' - return ' info' - elseif a:type =~? 'n' - return ' note' - elseif a:type =~? 'w' - return ' warning' - else - return '' - endif + let types = { + \ 'e': ' error', + \ 'i': ' info', + \ 'n': ' note', + \ 'w': ' warning' + \ } + return a:type != '' ? types[a:type] : '' endfunction function! qf#FormatErrorNumber(nr) From 46dedebaf1b8fcbc11f746a4a9380b813019fd8c Mon Sep 17 00:00:00 2001 From: Romain Lafourcade Date: Thu, 6 May 2021 11:01:53 +0200 Subject: [PATCH 03/18] Remove :Doline and :Dofile :cdo, :ldo, :cfdo, and :lfdo are available in current Vim so there is no need anymore for backward-compatible wrappers. Also, :cdo and friends work from anywhere, whereas :Doline and :Dofile where restricted to the qf/loc window. --- README.md | 4 --- after/ftplugin/qf.vim | 28 +++++---------- autoload/qf/do.vim | 36 ------------------- doc/qf.txt | 82 +++++++++---------------------------------- 4 files changed, 24 insertions(+), 126 deletions(-) delete mode 100644 autoload/qf/do.vim diff --git a/README.md b/README.md index fdbc821..51c7ec5 100644 --- a/README.md +++ b/README.md @@ -36,10 +36,6 @@ Many plugins interact with the quickfix/location list/window in ways that are mo ![filter][1] -- perform commands on each line in the current list - -- perform commands on each file in the current list - - jump to next group of entries belonging to same file ("file grouping"): ![group][2] diff --git a/after/ftplugin/qf.vim b/after/ftplugin/qf.vim index 7cabd1f..7a480e2 100644 --- a/after/ftplugin/qf.vim +++ b/after/ftplugin/qf.vim @@ -119,16 +119,6 @@ command! -buffer -range -nargs=? Reject call qf#filter#FilterList(, 1, < " :Restore command! -buffer -bar Restore call qf#filter#RestoreList() -" do something on each line in the location/quickfix list -" usage: -" :Doline s/^/--- -command! -buffer -nargs=1 Doline call qf#do#DoList(1, ) - -" do something on each file in the location/quickfix list -" usage: -" :Dofile %s/^/--- -command! -buffer -nargs=1 Dofile call qf#do#DoList(0, ) - " save current location/quickfix list and associate it with a given name or the " last used name command! -buffer -nargs=? -complete=customlist,qf#namedlist#CompleteList SaveList call qf#namedlist#SaveList(0, ) @@ -157,12 +147,18 @@ nnoremap (qf_newer) :call qf#history#Newer( nnoremap (qf_previous_file) :call qf#filegroup#PreviousFile() nnoremap (qf_next_file) :call qf#filegroup#NextFile() +" decide where to open the location/quickfix window +" :help g:qf_loclist_window_bottom +" :help g:qf_window_bottom +if (b:qf_isLoc == 1 && get(g:, 'qf_loclist_window_bottom', 1)) + \ || (b:qf_isLoc == 0 && get(g:, 'qf_window_bottom', 1)) + wincmd J +endif + let b:undo_ftplugin .= "| delcommand Filter" \ . "| delcommand Keep" \ . "| delcommand Reject" \ . "| delcommand Restore" - \ . "| delcommand Doline" - \ . "| delcommand Dofile" \ . "| delcommand SaveList" \ . "| delcommand SaveListAdd" \ . "| delcommand LoadList" @@ -175,12 +171,4 @@ let b:undo_ftplugin .= "| delcommand Filter" \ . "| execute 'nunmap (qf_next_file)'" \ . "| unlet! b:qf_isLoc" -" decide where to open the location/quickfix window -" :help g:qf_loclist_window_bottom -" :help g:qf_window_bottom -if (b:qf_isLoc == 1 && get(g:, 'qf_loclist_window_bottom', 1)) - \ || (b:qf_isLoc == 0 && get(g:, 'qf_window_bottom', 1)) - wincmd J -endif - let &cpo = s:save_cpo diff --git a/autoload/qf/do.vim b/autoload/qf/do.vim deleted file mode 100644 index 2f70f28..0000000 --- a/autoload/qf/do.vim +++ /dev/null @@ -1,36 +0,0 @@ -" vim-qf - Tame the quickfix window -" Maintainer: romainl -" Version: 0.2.0 -" License: MIT -" Location: autoload/do.vim -" Website: https://github.com/romainl/vim-qf -" -" Use this command to get help on vim-qf: -" -" :help qf -" -" If this doesn't work and you installed vim-qf manually, use the following -" command to index vim-qf's documentation: -" -" :helptags ~/.vim/doc -" -" or read your runtimepath/plugin manager documentation. - -let s:save_cpo = &cpo -set cpo&vim - -" Do something with each entry -" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -" Handles :Doline and :Dofile, in quickfix and location lists. -" Wrapper aound :cdo, :cfdo, :ldo, :lfdo. -function! qf#do#DoList(line, cmd) - let prefix = b:->get("qf_isLoc", 1) ? "l" : "c" - let modifier = a:line == 1 ? "" : "f" - - try - execute prefix . modifier . "do " . a:cmd - catch /^Vim\%((\a\+)\)\=:E\%(553\|42\):/ - endtry -endfunction - -let &cpo = s:save_cpo diff --git a/doc/qf.txt b/doc/qf.txt index 2649a09..686ce32 100644 --- a/doc/qf.txt +++ b/doc/qf.txt @@ -41,8 +41,6 @@ These "local" features are only available in location/quickfix windows: - disable relative numbers - filter and restore the current list - - perform commands on each line in the current list - - perform commands on each file in the current list - mappings to navigate between older and newer lists - jump to next group of entries belonging to same file ("file grouping") - save and load named lists @@ -58,8 +56,7 @@ Method 1 Method 2 - If you are using Vim 8.0 or above, move this directory to its appropriate - location. + Move this directory to its appropriate location. On Unix-like systems: > @@ -71,27 +68,6 @@ Method 2 < See `:help package`. -Method 3 - - If you are using Vim 7.4 or below, move the files in this directory to their - standard location. - - On Unix-like systems: > - - ~/.vim/after/ftplugin/qf.vim - ~/.vim/autoload/qf.vim - ~/.vim/autoload/qf/*.vim - ~/.vim/doc/qf.txt - ~/.vim/plugin/qf.vim -< - On Windows: > - - %userprofile%\vimfiles\after\ftplugin\qf.vim - %userprofile%\vimfiles\autoload\qf.vim - %userprofile%\vimfiles\autoload\qf\*.vim - %userprofile%\vimfiles\doc\qf.txt - %userprofile%\vimfiles\plugin\qf.vim -< ============================================================================== 3. CONFIGURATION *qf-configuration* @@ -224,7 +200,7 @@ Default: none ~ In a location/quickfix window, navigate to an older or newer list. -Example (in after/ftplugin/qf.vim): > +Example (in `after/ftplugin/qf.vim`): > nmap (qf_older) nmap (qf_newer) @@ -238,7 +214,7 @@ Default: none ~ In a location/quickfix window, jump to the next group of lines corresponding to a file. -Example (in after/ftplugin/qf.vim): > +Example (in `after/ftplugin/qf.vim`): > nmap { (qf_previous_file) nmap } (qf_next_file) @@ -250,12 +226,12 @@ Default: 0 ~ Ack.vim-inspired mappings available only in location/quickfix windows: - s - open entry in a new horizontal window - v - open entry in a new vertical window - t - open entry in a new tab - o - open entry and come back - O - open entry and close the location/quickfix window - p - open entry in a preview window + `s` ........ open entry in a new horizontal window + `v` ........ open entry in a new vertical window + `t` ........ open entry in a new tab + `o` ........ open entry and come back + `O` ........ open entry and close the location/quickfix window + `p` ........ open entry in a preview window Add the line below to your vimrc to enable this feature: > @@ -376,7 +352,7 @@ Default: 1 ~ Save the view of the current window when toggling location/quickfix window. -Add the line below to your vimrc to change the default value: +Add the line below to your vimrc to disable this feature: > > let g:qf_save_win_view = 0 < @@ -388,7 +364,7 @@ Default: 1 ~ Enables or disables soft-wrapping in the location/quickfix window. The default value disables soft-wrapping. -Add the line below to your vimrc to change the default value: +Add the line below to your vimrc to disable this feature: > let g:qf_nowrap = 0 < @@ -403,14 +379,16 @@ window. With the option set to `0` (vanilla Vim): > very/long/path/with/lots/of/subdirectories/filename.ext|87 col 22| … - +< With the option set to `1` (vim-qf default): > v/l/p/w/l/o/s/filename.ext|87 col 22| … - -With the option set to `3` (Vim v8.2.1741 or above): +< +With the option set to `3`: > ver/lon/pat/wit/lot/of/sub/filename.ext|87 col 22| … +< +Etc. Add the line below to your vimrc to change the default value: > @@ -474,24 +452,6 @@ is focused: Restore the list to its original state. -*:Doline* - - Execute an Ex command on every line in the current list. - Aliased to the built-in `:cdo` and `:ldo` when applicable. - - Example: > - - :Doline s/^/-- -< -*:Dofile* - - Execute an Ex command on every file in the current list. - Aliased to the built-in `:cfdo` and `:lfdo` when applicable. - - Example: > - - :Dofile norm @q -< *:SaveList* Save the current quickfix/location under the given name. If no name is @@ -547,8 +507,6 @@ clashing names, you can shorten the commands above to: |:Keep| ....................................... :K |:Reject| ..................................... :Rej |:Restore| .................................... :Res - |:Doline| ..................................... :Dol - |:Dofile| ..................................... :Dof |:SaveList| ................................... :SaveList |:SaveListAdd| ................................ :SaveListA |:LoadList| ................................... :LoadList @@ -605,14 +563,6 @@ The "Ack.vim-inspired mappings" are adapted from Ack.vim: - https://github.com/mileszs/ack.vim -|:Doline| and |:Dofile| are inspired by these online resources: - - - http://vimcasts.org/episodes/project-wide-find-and-replace/ - - https://github.com/nelstrom/vim-qargs - - https://github.com/henrik/vim-qargs - - http://stackoverflow.com/a/4793316/546861 - - http://stackoverflow.com/a/5686810/546861 - |:Keep| and |:Reject| are adapted from the answers in this thread: - http://stackoverflow.com/q/15406138/546861 From be9ee4075cc6e379831f47b60d19b0767bd276e7 Mon Sep 17 00:00:00 2001 From: Romain Lafourcade Date: Thu, 6 May 2021 12:42:40 +0200 Subject: [PATCH 04/18] Remove unnecessary function calls. --- plugin/qf.vim | 46 +++++++++++++++++++--------------------------- 1 file changed, 19 insertions(+), 27 deletions(-) diff --git a/plugin/qf.vim b/plugin/qf.vim index bda264b..95cf36c 100644 --- a/plugin/qf.vim +++ b/plugin/qf.vim @@ -55,39 +55,31 @@ nnoremap (qf_qf_switch) &filetype ==# 'qf' ? 'p " A list of commands used to trigger the QuickFixCmdPost event is documented in " `:help QuickFixCmdPre`. " NOTE: helgrep is excluded because it's a special case (see below). -let s:quickfix_autocmd_trigger_cmds = [ - \ 'make', 'grep', 'grepadd', 'vimgrep', 'vimgrepadd', 'cfile', 'cgetfile', - \ 'caddfile', 'cexpr', 'cgetexpr', 'caddexpr', 'cbuffer', - \ 'cgetbuffer', 'caddbuffer'] - -function! s:GetQuickFixCmdsPattern() abort - return join(s:quickfix_autocmd_trigger_cmds, ',') -endfunction - -function! s:GetLocListCmdsPattern() abort - let l:loclist_cmds = [] - - for l:qf_cmd in s:quickfix_autocmd_trigger_cmds - " If a commands starts with 'c', replace it with 'l'. Otherwise, prepend - " 'l'. - if l:qf_cmd[0] is# 'c' - let l:cmd = 'l' . l:qf_cmd[1:] - else - let l:cmd = 'l' . l:qf_cmd - endif - call add(l:loclist_cmds, l:cmd) - endfor - - return join(l:loclist_cmds, ',') -endfunction +let s:qf_autocmd_triggers = [ + \ 'cbuffer', 'cgetbuffer', 'caddbuffer', + \ 'cexpr', 'cgetexpr', 'caddexpr', + \ 'cfile', 'cgetfile', 'caddfile', + \ 'grep', 'grepadd', + \ 'make', + \ 'vimgrep', 'vimgrepadd', + \ ]->join(',') + +let s:loc_autocmd_triggers = [ + \ 'lbuffer', 'lgetbuffer', 'laddbuffer', + \ 'lexpr', 'lgetexpr', 'laddexpr', + \ 'lfile', 'lgetfile', 'laddfile', + \ 'lgrep', 'grepadd', + \ 'lmake', + \ 'lvimgrep', 'lvimgrepadd', + \ ]->join(',') augroup qf autocmd! " automatically open the location/quickfix window after :make, :grep, " :lvimgrep and friends if there are valid locations/errors - exec printf('autocmd QuickFixCmdPost %s nested call qf#OpenQuickfixWindow()', s:GetQuickFixCmdsPattern()) - exec printf('autocmd QuickFixCmdPost %s nested call qf#OpenLocationWindow()', s:GetLocListCmdsPattern()) + exec printf('autocmd QuickFixCmdPost %s nested call qf#OpenQuickfixWindow()', s:qf_autocmd_triggers) + exec printf('autocmd QuickFixCmdPost %s nested call qf#OpenLocationWindow()', s:loc_autocmd_triggers) " special case for :helpgrep and :lhelpgrep since the help window may not " be opened yet when QuickFixCmdPost triggers From 23a7e58b9d1be2e6fb9b5e28fd486c5f4994f84a Mon Sep 17 00:00:00 2001 From: Romain Lafourcade Date: Thu, 6 May 2021 12:44:14 +0200 Subject: [PATCH 05/18] Rework generic GetListItems() and GetListSize() --- autoload/qf.vim | 21 ++++++++++----------- autoload/qf/filegroup.vim | 4 ++-- autoload/qf/preview.vim | 2 +- 3 files changed, 13 insertions(+), 14 deletions(-) diff --git a/autoload/qf.vim b/autoload/qf.vim index 7963db9..dc4b8b7 100644 --- a/autoload/qf.vim +++ b/autoload/qf.vim @@ -61,10 +61,10 @@ function! qf#IsLocWindowOpen(nmbr) abort endfunction " returns current location list or quickfix list -function! qf#GetListItems(idx) +function! qf#GetListItems(loc, idx) let what = { 'idx': a:->get('idx', 0), 'items': 1 } - if get(b:, 'qf_isLoc', 0) + if get(a:, 'loc', 0) return getloclist(0, what)["items"] else return getqflist(what)["items"] @@ -73,10 +73,10 @@ endfunction " helper " returns the number of items in a loc/qf list -function! qf#GetListSize() +function! qf#GetListSize(loc) let what = { 'size': 1 } - if get(b:, 'qf_isLoc', 0) + if get(a:, 'loc', 0) return getloclist(0, what)["size"] else return getqflist(what)["size"] @@ -101,9 +101,9 @@ function! qf#SetList(newlist, ...) endif if get(b:, 'qf_isLoc', 0) - execute get(g:, "qf_auto_resize", 1) ? 'lclose|' . min([ max_height, len(getloclist(0)) ]) . 'lwindow' : 'lclose|lwindow' + execute get(g:, "qf_auto_resize", 1) ? 'lclose|' . min([ max_height, qf#GetListSize(1) ]) . 'lwindow' : 'lclose|lwindow' else - execute get(g:, "qf_auto_resize", 1) ? 'cclose|' . min([ max_height, len(getqflist()) ]) . 'cwindow' : 'cclose|cwindow' + execute get(g:, "qf_auto_resize", 1) ? 'cclose|' . min([ max_height, qf#GetListSize(0)) . 'cwindow' : 'cclose|cwindow' endif endfunction @@ -113,7 +113,7 @@ function! qf#OpenQuickfixWindow() " get user-defined maximum height let max_height = get(g:, 'qf_max_height', 10) < 1 ? 10 : get(g:, 'qf_max_height', 10) - execute get(g:, "qf_auto_resize", 1) ? 'cclose|' . min([ max_height, qf#GetListSize() ]) . 'cwindow' : 'cclose|cwindow' + execute get(g:, "qf_auto_resize", 1) ? 'cclose|' . min([ max_height, qf#GetListSize(0) ]) . 'cwindow' : 'cclose|cwindow' endif endfunction @@ -123,7 +123,7 @@ function! qf#OpenLocationWindow() " get user-defined maximum height let max_height = get(g:, 'qf_max_height', 10) < 1 ? 10 : get(g:, 'qf_max_height', 10) - execute get(g:, "qf_auto_resize", 1) ? 'lclose|' . min([ max_height, qf#GetListSize() ]) . 'lwindow' : 'lclose|lwindow' + execute get(g:, "qf_auto_resize", 1) ? 'lclose|' . min([ max_height, qf#GetListSize(1) ]) . 'lwindow' : 'lclose|lwindow' endif endfunction @@ -173,13 +173,12 @@ function! qf#FormatColumn(col) endfunction function! qf#FormatType(type) - let types = { + return { \ 'e': ' error', \ 'i': ' info', \ 'n': ' note', \ 'w': ' warning' - \ } - return a:type != '' ? types[a:type] : '' + \ }->get(a:type, '') endfunction function! qf#FormatErrorNumber(nr) diff --git a/autoload/qf/filegroup.vim b/autoload/qf/filegroup.vim index 05af56f..61b6771 100644 --- a/autoload/qf/filegroup.vim +++ b/autoload/qf/filegroup.vim @@ -21,7 +21,7 @@ set cpo&vim function! qf#filegroup#NextFile() abort if exists("b:qf_isLoc") - let items = qf#GetListItems(0) + let items = qf#GetListItems(b:->get("qf_isLoc", 0), 0) let current_index = line('.') - 1 let current_bufnr = items[current_index]["bufnr"] let limit = items->len() @@ -40,7 +40,7 @@ endfunction function! qf#filegroup#PreviousFile() abort if exists("b:qf_isLoc") - let items = qf#GetListItems(0) + let items = qf#GetListItems(b:->get("qf_isLoc", 0), 0) let current_index = line('.') - 1 let current_bufnr = items[current_index]["bufnr"] let limit = 0 diff --git a/autoload/qf/preview.vim b/autoload/qf/preview.vim index 5f507b0..e1b8d31 100644 --- a/autoload/qf/preview.vim +++ b/autoload/qf/preview.vim @@ -23,7 +23,7 @@ set cpo&vim function! qf#preview#PreviewFileUnderCursor() let winview = winsaveview() - let current_item = qf#GetListItems(line('.'))[0] + let current_item = qf#GetListItems(b:->get("qf_isLoc", 0), line('.'))[0] let current_file_name = current_item["bufnr"]->bufname() let current_file_line = current_item->get('lnum', 0) let current_file_column = current_item->get('col', 0) From 0b873341e911b8c436cf8a50be820f2fce70c46b Mon Sep 17 00:00:00 2001 From: Romain Lafourcade Date: Thu, 6 May 2021 13:40:39 +0200 Subject: [PATCH 06/18] Split the content of "Usage" between "Filterung" and "Named lists" --- doc/qf.txt | 256 +++++++++++++++++++++++++++++------------------------ 1 file changed, 141 insertions(+), 115 deletions(-) diff --git a/doc/qf.txt b/doc/qf.txt index 686ce32..c3965ed 100644 --- a/doc/qf.txt +++ b/doc/qf.txt @@ -58,15 +58,15 @@ Method 2 Move this directory to its appropriate location. - On Unix-like systems: > - + On Unix-like systems: +> ~/.vim/pack/{whatever name you want}/start/vim-qf < - On Windows: > - + On Windows: +> %userprofile%\vimfiles\pack\{whatever name you want}\start\vim-qf < - See `:help package`. + See |package|. ============================================================================== 3. CONFIGURATION *qf-configuration* @@ -114,8 +114,8 @@ Default: none ~ Go up and down the quickfix list and wrap around. -Example: > - +Example: +> nmap (qf_qf_previous) nmap (qf_qf_next) < @@ -127,8 +127,8 @@ Default: none ~ Go up and down the current location list and wrap around. -Example: > - +Example: +> nmap (qf_loc_previous) nmap (qf_loc_next) < @@ -139,8 +139,8 @@ Default: none ~ Jump to and from location/quickfix windows. -Example: > - +Example: +> nmap ç (qf_qf_switch) < ------------------------------------------------------------------------------ @@ -151,8 +151,8 @@ Default: none ~ Toggle the quickfix window. Uses |:cwindow| and |:cclose| under the hood. -Example: > - +Example: +> nmap (qf_qf_toggle) < ------------------------------------------------------------------------------ @@ -163,8 +163,8 @@ Default: none ~ Toggle the quickfix window and do not move if toggled open. Uses |:cwindow| and |:cclose| under the hood. -Example: > - +Example: +> nmap (qf_qf_toggle_stay) < ------------------------------------------------------------------------------ @@ -175,8 +175,8 @@ Default: none ~ Toggle the current window's location window or the current location window. Uses |:lwindow| and |:lclose| under the hood. -Example: > - +Example: +> nmap (qf_loc_toggle) < ------------------------------------------------------------------------------ @@ -188,8 +188,8 @@ Toggle the current window's location window or the current location window and do not move if toggled open. Uses |:lwindow| and |:lclose| under the hood. -Example: > - +Example: +> nmap (qf_loc_toggle_stay) < ------------------------------------------------------------------------------ @@ -200,8 +200,8 @@ Default: none ~ In a location/quickfix window, navigate to an older or newer list. -Example (in `after/ftplugin/qf.vim`): > - +Example (in `after/ftplugin/qf.vim`): +> nmap (qf_older) nmap (qf_newer) < @@ -214,8 +214,8 @@ Default: none ~ In a location/quickfix window, jump to the next group of lines corresponding to a file. -Example (in `after/ftplugin/qf.vim`): > - +Example (in `after/ftplugin/qf.vim`): +> nmap { (qf_previous_file) nmap } (qf_next_file) < @@ -233,8 +233,8 @@ Ack.vim-inspired mappings available only in location/quickfix windows: `O` ........ open entry and close the location/quickfix window `p` ........ open entry in a preview window -Add the line below to your vimrc to enable this feature: > - +Add the line below to your vimrc to enable this feature: +> let g:qf_mapping_ack_style = 1 < ------------------------------------------------------------------------------ @@ -244,8 +244,8 @@ Default: 1 ~ Open the quickfix window at the bottom of the screen. -Add the line below to your vimrc to disable this feature: > - +Add the line below to your vimrc to disable this feature: +> let g:qf_window_bottom = 0 < ------------------------------------------------------------------------------ @@ -255,8 +255,8 @@ Default: 1 ~ Open location list windows at the bottom of the screen. -Add the line below to your vimrc to disable this feature: > - +Add the line below to your vimrc to disable this feature: +> let g:qf_loclist_window_bottom = 0 < ------------------------------------------------------------------------------ @@ -267,8 +267,8 @@ Default: {} ~ It is possible to define what comes before and after the default information displayed in the |'statusline'|. -Example: > - +Example: +> let g:qf_statusline = {} let g:qf_statusline.before = '%<\ ' let g:qf_statusline.after = '\ %f%=%l\/%-6L\ \ \ \ \ ' @@ -280,8 +280,8 @@ Default: 1 ~ Open the quickfix window automatically if there are any errors. -Add the line below to your vimrc to disable this feature: > - +Add the line below to your vimrc to disable this feature: +> let g:qf_auto_open_quickfix = 0 < ------------------------------------------------------------------------------ @@ -291,8 +291,8 @@ Default: 1 ~ Open the location window automatically if there are any locations. -Add the line below to your vimrc to disable this feature: > - +Add the line below to your vimrc to disable this feature: +> let g:qf_auto_open_loclist = 0 < ------------------------------------------------------------------------------ @@ -304,8 +304,8 @@ Automatically adjust the height of location/quickfix windows to 10 lines (Vim's default) or to the number of items in the list if that number is inferior to 10. -Add the line below to your vimrc to disable this feature: > - +Add the line below to your vimrc to disable this feature: +> let g:qf_auto_resize = 0 < ------------------------------------------------------------------------------ @@ -352,7 +352,7 @@ Default: 1 ~ Save the view of the current window when toggling location/quickfix window. -Add the line below to your vimrc to disable this feature: > +Add the line below to your vimrc to disable this feature: > let g:qf_save_win_view = 0 < @@ -395,111 +395,72 @@ Add the line below to your vimrc to change the default value: let g:qf_shorten_path = 0 < ============================================================================== - 4. USAGE *qf-usage* + 4. Filtering *qf-usage* -The following commands are available when the location/quickfix window -is focused: +When working with a location/quickfix list, it might be useful to remove false +potives, for example, before further operation. vim-qf exposes three hopefully +intuitive commands to help in that scenario: |:Keep|, |:Reject|, and +|:Restore| when the location/quickfix window is focused: *:Keep* Keep some entries from the list. - Example: > + Example: + + `:Keep model` ...... Keep entries matching 'model' + `:Keep` ............ Keep entries with same filename as curent entry + `:.Keep` ........... Keep current entry + `:10,15Keep` ....... Keep entries 10..15 + `:'<,'>Keep` ....... Keep entries covered by visual selection - :Keep model Keep entries matching 'model' - :Keep Keep entries with same filename as curent entry - :.Keep Keep current entry - :10,15Keep Keep entries 10..15 - :'<,'>Keep Keep entries covered by visual selection -< With a pattern, filtering is done by default on the buffer name AND the text. This can be changed with the |g:qf_bufname_or_text| option. If a [range] was given, it is ignored. + With a [range], the lines covered by [range] are kept. If a pattern was + given, it is ignored. + With neither a pattern nor a [range], filtering is done: - on the buffer name if the cursor is on column 1, - on the word under the cursor if the cursor is on any other column. - With a [range], the lines covered by [range] are kept. If a pattern was - given, it is ignored. - *:Reject* Reject some entries from the list. - Example: > + Examples: + + `:Reject model` .... Reject entries matching 'model' + `:Reject` .......... Reject entries with same filename as curent entry + `:.Reject` ......... Reject current entry + `:10,15Reject` ..... Reject entries 10..15 + `:'<,'>Reject` ..... Reject entries covered by visual selection - :Reject model Reject entries matching 'model' - :Reject Reject entries with same filename as curent entry - :.Reject Reject current entry - :10,15Reject Reject entries 10..15 - :'<,'>Reject Reject entries covered by visual selection -< With a pattern, filtering is done by default on the buffer name AND the text. This can be changed with the |g:qf_bufname_or_text| option. If a [range] was given, it is ignored. + With a [range], the lines covered by [range] are rejected. If a pattern + was given, it is ignored. + With neither a pattern nor a [range], filtering is done: - on the buffer name if the cursor is on column 1, - on the word under the cursor if the cursor is on any other column. - With a [range], the lines covered by [range] are rejected. If a pattern - was given, it is ignored. - *:Restore* - Restore the list to its original state. - -*:SaveList* - - Save the current quickfix/location under the given name. If no name is - supplied the last saved list is used. - - Example: > - - :SaveList curlist -< -*:SaveListAdd* - - Like |:SaveList|, but adds to an existing named list. - - Example: > - - :SaveListAdd curlist -< -*:LoadList* - - Replace the current quickfix/location list with one or more saved named - lists. If no name is supplied, the last saved list is used. - - Example: > - - :LoadList curlist -< -*:LoadListAdd* - - Like |:LoadList|, but adds to an existing quickfix/location list. + Restore the list to its original state, before any |:Keep| or |:Reject|. - Example: > - - :LoadListAdd curlist -< -*:ListLists* - - List all currently saved lists. - - Example: > - - :ListLists - curlist - another_list + Example: +> + :helpgrep gd + :Keep usr_ + :Reject 26 + :Restore < -*:RemoveList* - - Remove given lists. With a bang all saved lists are removed. - NOTE: In most cases it is possible to only type a few characters to disembiguate commands. Assuming you don't already have custom commands with clashing names, you can shorten the commands above to: @@ -507,12 +468,6 @@ clashing names, you can shorten the commands above to: |:Keep| ....................................... :K |:Reject| ..................................... :Rej |:Restore| .................................... :Res - |:SaveList| ................................... :SaveList - |:SaveListAdd| ................................ :SaveListA - |:LoadList| ................................... :LoadList - |:LoadListAdd| ................................ :LoadListA - |:ListLists| .................................. :ListL - |:RemoveList| ................................. :Rem ============================================================================== 5. NAMED LISTS *qf-named-lists* @@ -555,7 +510,78 @@ Composing a list of files to attach a license to: > :cwindow :LoadList floss_files :cdo 0r /path/to/license + +The following commands are available when the location/quickfix window +is focused: + +*:SaveList* + + Save the current quickfix/location under the given name. If no name is + supplied the last saved list is used. + + Example: +> + :SaveList curlist +< +*:SaveListAdd* + + Like |:SaveList|, but adds to an existing named list. + + Example: +> + :SaveListAdd curlist +< +*:LoadList* + + Replace the current quickfix/location list with one or more saved named + lists. If no name is supplied, the last saved list is used. + + Example: +> + :LoadList curlist +< +*:LoadListAdd* + + Like |:LoadList|, but adds to an existing quickfix/location list. + + Example: +> + :LoadListAdd curlist < +*:ListLists* + + List all currently saved lists. + + Example: +> + :ListLists + curlist + another_list +< +*:RemoveList* + + Remove given lists. With a bang all saved lists are removed. + + Example: +> + :ListLists + curlist + another_list + :RemoveList another_list + :ListLists + curlist +< +NOTE: In most cases it is possible to only type a few characters to +disembiguate commands. Assuming you don't already have custom commands with +clashing names, you can shorten the commands above to: + + |:SaveList| ................................... :SaveList + |:SaveListAdd| ................................ :SaveListA + |:LoadList| ................................... :LoadList + |:LoadListAdd| ................................ :LoadListA + |:ListLists| .................................. :ListL + |:RemoveList| ................................. :Rem + ============================================================================== 6. ACKNOWLEGEMENTS *qf-acknowledgements* From a62b4973906437e423e578f6412e7250dbfac18d Mon Sep 17 00:00:00 2001 From: Romain Lafourcade Date: Thu, 6 May 2021 23:02:00 +0200 Subject: [PATCH 07/18] Move display formatting to its own file --- autoload/qf.vim | 65 ++-------------------------------------- autoload/qf/format.vim | 67 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+), 63 deletions(-) create mode 100644 autoload/qf/format.vim diff --git a/autoload/qf.vim b/autoload/qf.vim index dc4b8b7..0464cee 100644 --- a/autoload/qf.vim +++ b/autoload/qf.vim @@ -127,72 +127,11 @@ function! qf#OpenLocationWindow() endif endfunction +" Handles formatting of the text in the buffer function! qf#QuickfixTextFunc(options) let items = a:options["quickfix"] == 1 ? getqflist() : getloclist(a:options["winid"]) - return items->map({ key, val -> val->qf#FormatItem() }) -endfunction - -function! qf#FormatItem(item) - return [ - \ a:item->qf#FormatFilename(), - \ a:item->qf#FormatLocation(), - \ a:item->qf#FormatText(), - \ ]->join('|') -endfunction -function! qf#FormatFilename(item) - let filename = a:item["bufnr"]->bufname() - - if has('patch-8.2.1741') - return pathshorten(filename, g:->get("qf_shorten_path", 1)) - else - return pathshorten(filename) - endif -endfunction - -function! qf#FormatLocation(item) - return [ - \ a:item->get("lnum", 0)->qf#FormatLineNumber(), - \ a:item->get("col", 0)->qf#FormatColumn(), - \ a:item->get("type", '')->qf#FormatType(), - \ a:item->get("nr", 0)->qf#FormatErrorNumber(), - \ ]->join('') -endfunction - -function! qf#FormatText(item) - " return ' ' .. a:item->get("text", '') - return a:item["text"] -endfunction - -function! qf#FormatLineNumber(lnum) - return a:lnum != 0 ? a:lnum : '-' -endfunction - -function! qf#FormatColumn(col) - return a:col > 0 ? ' col ' .. a:col : '' -endfunction - -function! qf#FormatType(type) - return { - \ 'e': ' error', - \ 'i': ' info', - \ 'n': ' note', - \ 'w': ' warning' - \ }->get(a:type, '') -endfunction - -function! qf#FormatErrorNumber(nr) - if a:nr > 0 - if a:nr->string()->len() == 1 - return ' ' .. a:nr - elseif a:nr->string()->len() == 2 - return ' ' .. a:nr - else - return ' ' .. a:nr - endif - else - return '' - endif + return items->map({ key, val -> val->qf#format#FormatItem() }) endfunction let &cpo = s:save_cpo diff --git a/autoload/qf/format.vim b/autoload/qf/format.vim new file mode 100644 index 0000000..1ef04b4 --- /dev/null +++ b/autoload/qf/format.vim @@ -0,0 +1,67 @@ +" vim-qf - Tame the quickfix window +" Maintainer: romainl +" Version: 0.2.0 +" License: MIT +" Location: autoload/qf/format.vim +" Website: https://github.com/romainl/vim-qf + +let s:save_cpo = &cpo +set cpo&vim + +function! qf#format#FormatItem(item) + return [ + \ a:item->FormatFilename(), + \ a:item->FormatLocation(), + \ a:item->FormatText(), + \ ]->join('|') +endfunction + +function! s:FormatFilename(item) + let filename = a:item["bufnr"]->bufname() + + if has('patch-8.2.1741') + return pathshorten(filename, g:->get("qf_shorten_path", 1)) + else + return pathshorten(filename) + endif +endfunction + +function! s:FormatLocation(item) + return [ + \ a:item->get("lnum", 0)->FormatLineNumber(), + \ a:item->get("col", 0)->FormatColumn(), + \ a:item->get("type", '')->FormatType(), + \ a:item->get("nr", 0)->FormatErrorNumber(), + \ ]->join('') +endfunction + +function! s:FormatText(item) + return ' ' .. a:item->get("text", '') +endfunction + +function! s:FormatLineNumber(lnum) + return a:lnum != 0 ? a:lnum : '-' +endfunction + +function! s:FormatColumn(col) + return a:col > 0 ? ' col ' .. a:col : '' +endfunction + +function! s:FormatType(type) + return { + \ 'e': ' error', + \ 'i': ' info', + \ 'n': ' note', + \ 'w': ' warning' + \ }->get(a:type, '') +endfunction + +function! s:FormatErrorNumber(nr) + if a:nr > 0 + return printf("%4d", a:nr) + else + return '' + endif +endfunction + +let &cpo = s:save_cpo From cec5ab15f2d6cfbae112886b17fa798ac1dc9546 Mon Sep 17 00:00:00 2001 From: Romain Lafourcade Date: Thu, 6 May 2021 23:06:09 +0200 Subject: [PATCH 08/18] Formatting & normalisation of the coding style --- after/ftplugin/qf.vim | 133 +++++++++++++++++++++--------------------- autoload/qf.vim | 88 ++++++++++++++-------------- plugin/qf.vim | 75 +++++++++--------------- 3 files changed, 137 insertions(+), 159 deletions(-) diff --git a/after/ftplugin/qf.vim b/after/ftplugin/qf.vim index 7a480e2..99f983e 100644 --- a/after/ftplugin/qf.vim +++ b/after/ftplugin/qf.vim @@ -4,31 +4,20 @@ " License: MIT " Location: after/ftplugin/qf.vim " Website: https://github.com/romainl/vim-qf -" -" Use this command to get help on vim-qf: -" -" :help qf -" -" If this doesn't work and you installed vim-qf manually, use the following -" command to index vim-qf's documentation: -" -" :helptags ~/.vim/doc -" -" or read your runtimepath/plugin manager documentation. let s:save_cpo = &cpo set cpo&vim -" text wrapping is pretty much useless in the quickfix window +" Text wrapping is pretty much useless in the quickfix window " but some users may still want it execute get(g:, "qf_nowrap", 1) ? "setlocal nowrap" : "setlocal wrap" -" relative line numbers don't make much sense either +" Relative line numbers don't make much sense either " but absolute numbers definitely do setlocal norelativenumber setlocal number -" we don't want quickfix buffers to pop up when doing :bn or :bp +" We don't want quickfix buffers to pop up when doing :bn or :bp set nobuflisted if exists("b:undo_ftplugin") @@ -37,54 +26,59 @@ else let b:undo_ftplugin = "setl wrap< rnu< nu< bl<" endif -" are we in a location list or a quickfix list? -let b:qf_isLoc = get(get(getwininfo(win_getid()), 0, {}), 'loclist', 0) +" Are we in a location window or a quickfix window? +" 0 -> quickfix window +" 1 -> location window +let b:qf_isLoc = win_getid() + \ ->getwininfo() + \ ->get(0, {}) + \ ->get("loclist", 0) -" customize the statusline +" Customize the statusline if exists("g:qf_statusline") execute "setlocal statusline=" . g:qf_statusline.before . "%{qf#statusline#SetStatusline()}" . g:qf_statusline.after endif -" inspired by Ack.vim -if exists("g:qf_mapping_ack_style") - let qf_at_bottom = (b:qf_isLoc == 1 && get(g:, 'qf_loclist_window_bottom', 1)) - \ || (b:qf_isLoc == 0 && get(g:, 'qf_window_bottom', 1)) +" Mappings inspired by Ack.vim +if get(g:, "qf_mapping_ack_style", 0) + let qf_at_bottom = (get(b:, "qf_isLoc", 0) && get(g:, "qf_loclist_window_bottom", 1)) + \ || (!get(b:, "qf_isLoc", 0) && get(g:, "qf_window_bottom", 1)) - " open entry in a new vertical window. + " Open entry in a new vertical window if qf_at_bottom nnoremap v &splitright ? "\\\L\p\J\p" : "\\\H\p\J\p" else - " don't move quickfix to bottom if qf_loclist_window_bottom is 0 + " Don't move quickfix to bottom if qf_loclist_window_bottom is 0 nnoremap v &splitright ? "\\\L" : "\\\H" endif if qf_at_bottom && &splitbelow - " open entry in a new horizontal window and move quickfix to bottom + " Open entry in a new horizontal window and move quickfix to bottom nnoremap s pJp - " preview entry under the cursor and move quickfix to bottom + " Preview entry under the cursor and move quickfix to bottom nnoremap p :call qf#preview#PreviewFileUnderCursor()J else - " open entry in a new horizontal window + " Open entry in a new horizontal window nnoremap s - " preview entry under the cursor + " Preview entry under the cursor nnoremap p :call qf#preview#PreviewFileUnderCursor() endif - " open entry in a new tab. - nnoremap t T - - " open entry and come back - nnoremap o p - - " open entry and close the location/quickfix window. - if b:qf_isLoc == 1 + " Open entry and close the location/quickfix window + if get(b:, "qf_isLoc", 0) nnoremap O :lclose else nnoremap O :cclose endif + " Open entry in a new tab + nnoremap t T + + " Open entry and come back + nnoremap o p + let b:undo_ftplugin .= "| execute 'nunmap s'" \ . "| execute 'nunmap v'" \ . "| execute 'nunmap t'" @@ -93,70 +87,73 @@ if exists("g:qf_mapping_ack_style") \ . "| execute 'nunmap p'" endif -" filter the location/quickfix list -" (kept for backward compatibility, use :Keep and :Reject instead) -" usage: -" :Filter foo <-- same as :Keep foo -" :Filter! foo <-- same as :Reject foo -" :10,15Filter <-- same as :10,15Keep -" :10,15Filter! <-- same as :10,15Reject -command! -buffer -range -nargs=1 -bang Filter call qf#filter#FilterList(, expand("") == "!" ? 1 : 0, , , ) - -" keep entries matching the argument or range -" usage: +" Keep entries matching the argument or range +" Usage: " :Keep foo " :10,15Keep command! -buffer -range -nargs=? Keep call qf#filter#FilterList(, 0, , , ) -" reject entries matching the argument or range -" usage: +" Reject entries matching the argument or range +" Usage: " :Reject foo " :10,15Reject command! -buffer -range -nargs=? Reject call qf#filter#FilterList(, 1, , , ) -" restore the location/quickfix list -" usage: +" Restore the location/quickfix list +" Usage: " :Restore command! -buffer -bar Restore call qf#filter#RestoreList() -" save current location/quickfix list and associate it with a given name or the +" Save current location/quickfix list and associate it with a given name or the " last used name +" Usage: +" :SaveList foobar +" :SaveList command! -buffer -nargs=? -complete=customlist,qf#namedlist#CompleteList SaveList call qf#namedlist#SaveList(0, ) -" like SaveList, but add to a potentially existing named list +" Like SaveList, but add to a potentially existing named list +" Usage: +" :SaveListAdd foobar +" :SaveListAdd command! -buffer -nargs=? -complete=customlist,qf#namedlist#CompleteList SaveListAdd call qf#namedlist#SaveList(1, ) -" replace location/quickfix list with named lists +" Replace location/quickfix list with named lists +" Usage: +" :LoadList foobar command! -buffer -nargs=+ -complete=customlist,qf#namedlist#CompleteList LoadList call qf#namedlist#LoadList(0, ) -" like LoadList but append instead of replace +" Like LoadList but append instead of replace +" Usage: +" :LoadListAdd foobar command! -buffer -nargs=+ -complete=customlist,qf#namedlist#CompleteList LoadListAdd call qf#namedlist#LoadList(1, ) -" list currently saved lists +" List currently saved lists +" Usage: +" :ListLists command! -buffer ListLists call qf#namedlist#ListLists() -" remove given lists or all +" Remove given lists or all +" Usage: +" :RemoveList foobar +" :RemoveList! command! -buffer -nargs=* -bang -complete=customlist,qf#namedlist#CompleteList RemoveList call qf#namedlist#RemoveList(expand("") == "!" ? 1 : 0, ) -" quit Vim if the last window is a quickfix window -autocmd qf BufEnter nested if get(g:, 'qf_auto_quit', 1) | if winnr('$') < 2 | q | endif | endif -autocmd qf BufWinEnter nested if get(g:, 'qf_auto_quit', 1) | call qf#filter#ReuseTitle() | endif +" Quit Vim if the last window is a quickfix window +autocmd qf BufEnter nested if get(g:, "qf_auto_quit", 1) | if winnr('$') < 2 | q | endif | endif +autocmd qf BufWinEnter nested if get(g:, "qf_auto_quit", 1) | call qf#filter#ReuseTitle() | endif -" Move forward and backward in list history (in a quickfix or location window) +" Move forward and backward in list history (in a location/quickfix window) nnoremap (qf_older) :call qf#history#Older() nnoremap (qf_newer) :call qf#history#Newer() -" Jump to previous and next file grouping (in a quickfix or location window) +" Jump to previous and next file grouping (in a location/quickfix window) nnoremap (qf_previous_file) :call qf#filegroup#PreviousFile() nnoremap (qf_next_file) :call qf#filegroup#NextFile() -" decide where to open the location/quickfix window -" :help g:qf_loclist_window_bottom -" :help g:qf_window_bottom -if (b:qf_isLoc == 1 && get(g:, 'qf_loclist_window_bottom', 1)) - \ || (b:qf_isLoc == 0 && get(g:, 'qf_window_bottom', 1)) +" Decide where to open the location/quickfix window +if (get(b:, "qf_isLoc", 0) && get(g:, "qf_loclist_window_bottom", 1)) + \ || (!get(b:, "qf_isLoc", 0) && get(g:, "qf_window_bottom", 1)) wincmd J endif -let b:undo_ftplugin .= "| delcommand Filter" - \ . "| delcommand Keep" +let b:undo_ftplugin .= "| delcommand Keep" \ . "| delcommand Reject" \ . "| delcommand Restore" \ . "| delcommand SaveList" diff --git a/autoload/qf.vim b/autoload/qf.vim index 0464cee..f5025b5 100644 --- a/autoload/qf.vim +++ b/autoload/qf.vim @@ -4,23 +4,11 @@ " License: MIT " Location: autoload/qf.vim " Website: https://github.com/romainl/vim-qf -" -" Use this command to get help on vim-qf: -" -" :help qf -" -" If this doesn't work and you installed vim-qf manually, use the following -" command to index vim-qf's documentation: -" -" :helptags ~/.vim/doc -" -" or read your runtimepath/plugin manager documentation. let s:save_cpo = &cpo set cpo&vim -" helper function -" returns 1 if the window with the given number is a quickfix window +" Returns 1 if the window with the given number is a quickfix window " 0 if the window with the given number is not a quickfix window " TODO (Nelo-T. Wallus): make a:nbmr optional and return current window " by default @@ -32,98 +20,110 @@ function! qf#IsQfWindow(nmbr) return 0 endfunction -" helper function -" returns 1 if the window with the given number is a location window +" Returns 1 if the window with the given number is a location window " 0 if the window with the given number is not a location window function! qf#IsLocWindow(nmbr) return getbufvar(winbufnr(a:nmbr), "qf_isLoc") == 1 endfunction -" returns bool: Is quickfix window open? +" Returns bool: Is quickfix window open? function! qf#IsQfWindowOpen() abort - for winnum in range(1, winnr('$')) + for winnum in range(1, winnr("$")) if qf#IsQfWindow(winnum) return 1 endif endfor + return 0 endfunction -" returns bool: Is location window for window with given number open? +" Returns bool: Is location window for window with given number open? function! qf#IsLocWindowOpen(nmbr) abort let loclist = getloclist(a:nmbr) - for winnum in range(1, winnr('$')) + + for winnum in range(1, winnr("$")) if qf#IsLocWindow(winnum) && loclist ==# getloclist(winnum) return 1 endif endfor + return 0 endfunction -" returns current location list or quickfix list +" Returns items of the current location/quickfix list +" qf#GetListItems(0, 0) .... all items of the quickfix list +" qf#GetListItems(0, 5) .... item 5 of the quickfix list +" qf#GetListItems(1, 0) .... all items of the location list +" qf#GetListItems(1, 5) .... item 5 of the location list function! qf#GetListItems(loc, idx) - let what = { 'idx': a:->get('idx', 0), 'items': 1 } + let what = { "idx": get(a: "idx", 0), "items": 1 } - if get(a:, 'loc', 0) + if get(a:, "loc", 0) return getloclist(0, what)["items"] else return getqflist(what)["items"] endif endfunction -" helper -" returns the number of items in a loc/qf list +" Returns the number of items in a location/quickfix list +" qf#GetListSize(0) .... size of the quickfix list +" qf#GetListSize(1) .... size of the location list function! qf#GetListSize(loc) - let what = { 'size': 1 } + let what = { "size": 1 } - if get(a:, 'loc', 0) + if get(a:, "loc", 0) return getloclist(0, what)["size"] else return getqflist(what)["size"] endif endfunction -" sets location or qf list based in b:qf_isLoc to passed newlist +" Returns the maximum height of the location/quickfix window +function! qf#GetMaxHeight() + return get(g:, "qf_max_height", 10) < 1 ? 10 : get(g:, "qf_max_height", 10) +endfunction + +" Sets location or quickfix list based in b:qf_isLoc to passed newlist function! qf#SetList(newlist, ...) - " generate partial + " Generate partial let Func = get(b:, 'qf_isLoc', 0) \ ? function('setloclist', [0, a:newlist]) \ : function('setqflist', [a:newlist]) - " get user-defined maximum height - let max_height = get(g:, 'qf_max_height', 10) < 1 ? 10 : get(g:, 'qf_max_height', 10) + " Get user-defined maximum height + let max_height = qf#GetMaxHeight() - " call partial with optional arguments + " Call partial with optional arguments call call(Func, a:000) if a:newlist == [] return endif - if get(b:, 'qf_isLoc', 0) - execute get(g:, "qf_auto_resize", 1) ? 'lclose|' . min([ max_height, qf#GetListSize(1) ]) . 'lwindow' : 'lclose|lwindow' + if get(b:, "qf_isLoc", 0) + call qf#OpenLocationWindow() else - execute get(g:, "qf_auto_resize", 1) ? 'cclose|' . min([ max_height, qf#GetListSize(0)) . 'cwindow' : 'cclose|cwindow' + call qf#OpenQuickfixWindow() endif endfunction -" open the quickfix window if there are valid errors +" Open the quickfix window if there are valid errors function! qf#OpenQuickfixWindow() - if get(g:, 'qf_auto_open_quickfix', 1) - " get user-defined maximum height - let max_height = get(g:, 'qf_max_height', 10) < 1 ? 10 : get(g:, 'qf_max_height', 10) + if get(g:, "qf_auto_open_quickfix", 1) + " Get user-defined maximum height + let max_height = qf#GetMaxHeight() - execute get(g:, "qf_auto_resize", 1) ? 'cclose|' . min([ max_height, qf#GetListSize(0) ]) . 'cwindow' : 'cclose|cwindow' + execute get(g:, "qf_auto_resize", 1) ? "cclose|" . min([ max_height, qf#GetListSize(0) ]) . "cwindow" : "cclose|cwindow" endif endfunction -" open a location window if there are valid locations +" Open a location window if there are valid locations function! qf#OpenLocationWindow() - if get(g:, 'qf_auto_open_loclist', 1) - " get user-defined maximum height - let max_height = get(g:, 'qf_max_height', 10) < 1 ? 10 : get(g:, 'qf_max_height', 10) + if get(g:, "qf_auto_open_loclist", 1) + " Get user-defined maximum height + let max_height = qf#GetMaxHeight() - execute get(g:, "qf_auto_resize", 1) ? 'lclose|' . min([ max_height, qf#GetListSize(1) ]) . 'lwindow' : 'lclose|lwindow' + execute get(g:, "qf_auto_resize", 1) ? "lclose|" . min([ max_height, qf#GetListSize(1) ]) . "lwindow" : "lclose|lwindow" endif endfunction diff --git a/plugin/qf.vim b/plugin/qf.vim index 95cf36c..9c72acc 100644 --- a/plugin/qf.vim +++ b/plugin/qf.vim @@ -4,19 +4,8 @@ " License: MIT " Location: plugin/qf.vim " Website: https://github.com/romainl/vim-qf -" -" Use this command to get help on vim-qf: -" -" :help qf -" -" If this doesn't work and you installed vim-qf manually, use the following -" command to index vim-qf's documentation: -" -" :helptags ~/.vim/doc -" -" or read your runtimepath/plugin manager documentation. - -if exists("g:loaded_qf") || v:version < 703 || &compatible + +if exists("g:loaded_qf") || v:version < 802 || &compatible finish endif let g:loaded_qf = 1 @@ -24,83 +13,75 @@ let g:loaded_qf = 1 let s:save_cpo = &cpo set cpo&vim -" Kept for backward compatibility -nmap QfCprevious (qf_qf_previous) -nmap QfCnext (qf_qf_next) -nmap QfLprevious (qf_loc_previous) -nmap QfLnext (qf_loc_next) -nmap QfCtoggle (qf_qf_toggle) -nmap QfLtoggle (qf_loc_toggle) -nmap QfSwitch &filetype ==# 'qf' ? 'p' : 'b' - -" Go up and down quickfix list +" Go up and down the quickfix list nnoremap (qf_qf_previous) : call qf#wrap#WrapCommand('up', 'c') nnoremap (qf_qf_next) : call qf#wrap#WrapCommand('down', 'c') -" Go up and down location list +" Go up and down the location list nnoremap (qf_loc_previous) : call qf#wrap#WrapCommand('up', 'l') nnoremap (qf_loc_next) : call qf#wrap#WrapCommand('down', 'l') -" Toggle quickfix list +" Toggle the quickfix window nnoremap (qf_qf_toggle) : call qf#toggle#ToggleQfWindow(0) nnoremap (qf_qf_toggle_stay) : call qf#toggle#ToggleQfWindow(1) -" Toggle location list +" Toggle the location window nnoremap (qf_loc_toggle) : call qf#toggle#ToggleLocWindow(0) nnoremap (qf_loc_toggle_stay) : call qf#toggle#ToggleLocWindow(1) -" Jump to and from list +" Jump to and from a location/quickfix window nnoremap (qf_qf_switch) &filetype ==# 'qf' ? 'p' : 'b' " A list of commands used to trigger the QuickFixCmdPost event is documented in " `:help QuickFixCmdPre`. " NOTE: helgrep is excluded because it's a special case (see below). let s:qf_autocmd_triggers = [ - \ 'cbuffer', 'cgetbuffer', 'caddbuffer', - \ 'cexpr', 'cgetexpr', 'caddexpr', - \ 'cfile', 'cgetfile', 'caddfile', - \ 'grep', 'grepadd', - \ 'make', - \ 'vimgrep', 'vimgrepadd', - \ ]->join(',') + \ "cbuffer", "cgetbuffer", "caddbuffer", + \ "cexpr", "cgetexpr", "caddexpr", + \ "cfile", "cgetfile", "caddfile", + \ "grep", "grepadd", + \ "make", + \ "vimgrep", "vimgrepadd", + \ ]->join(",") let s:loc_autocmd_triggers = [ - \ 'lbuffer', 'lgetbuffer', 'laddbuffer', - \ 'lexpr', 'lgetexpr', 'laddexpr', - \ 'lfile', 'lgetfile', 'laddfile', - \ 'lgrep', 'grepadd', - \ 'lmake', - \ 'lvimgrep', 'lvimgrepadd', - \ ]->join(',') + \ "lbuffer", "lgetbuffer", "laddbuffer", + \ "lexpr", "lgetexpr", "laddexpr", + \ "lfile", "lgetfile", "laddfile", + \ "lgrep", "grepadd", + \ "lmake", + \ "lvimgrep", "lvimgrepadd", + \ ]->join(",") augroup qf autocmd! - " automatically open the location/quickfix window after :make, :grep, + " Automatically open the location/quickfix window after :make, :grep, " :lvimgrep and friends if there are valid locations/errors exec printf('autocmd QuickFixCmdPost %s nested call qf#OpenQuickfixWindow()', s:qf_autocmd_triggers) exec printf('autocmd QuickFixCmdPost %s nested call qf#OpenLocationWindow()', s:loc_autocmd_triggers) - " special case for :helpgrep and :lhelpgrep since the help window may not + " Special case for :helpgrep and :lhelpgrep since the help window may not " be opened yet when QuickFixCmdPost triggers if exists('*timer_start') autocmd QuickFixCmdPost helpgrep nested call timer_start(10, { -> execute('call qf#OpenQuickfixWindow()') }) autocmd QuickFixCmdPost lhelpgrep nested call timer_start(10, { -> execute('call qf#OpenLocationWindow()') }) else - " the window qf is not positioned correctly but at least it's there + " The window qf is not positioned correctly but at least it's there autocmd QuickFixCmdPost helpgrep nested call qf#OpenQuickfixWindow() " I can't make it work for :lhelpgrep endif - " spacial case for $ vim -q - autocmd VimEnter * nested if count(get(v:, 'argv', []), '-q') | call qf#OpenQuickfixWindow() | endif + " Special case for $ vim -q + autocmd VimEnter * nested if get(v:, 'argv', [])->count('-q') | call qf#OpenQuickfixWindow() | endif - " automatically close corresponding loclist when quitting a window + " Automatically close corresponding loclist when quitting a window if exists('##QuitPre') autocmd QuitPre * nested if &filetype != 'qf' | silent! lclose | endif endif augroup END +" Handle formatting if possible if exists('+quickfixtextfunc') && get(g:, "qf_shorten_path", 1) set quickfixtextfunc=qf#QuickfixTextFunc endif From 1a52e669f4ff744f680e31b49fe64b1bd13f7662 Mon Sep 17 00:00:00 2001 From: Romain Lafourcade Date: Thu, 6 May 2021 23:36:08 +0200 Subject: [PATCH 09/18] Make the diplay formatting closer to the default --- autoload/qf/format.vim | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/autoload/qf/format.vim b/autoload/qf/format.vim index 1ef04b4..e482261 100644 --- a/autoload/qf/format.vim +++ b/autoload/qf/format.vim @@ -40,7 +40,7 @@ function! s:FormatText(item) endfunction function! s:FormatLineNumber(lnum) - return a:lnum != 0 ? a:lnum : '-' + return a:lnum != 0 ? a:lnum : '' endfunction function! s:FormatColumn(col) @@ -58,7 +58,7 @@ endfunction function! s:FormatErrorNumber(nr) if a:nr > 0 - return printf("%4d", a:nr) + return ' ' .. printf("%3d", a:nr) else return '' endif From ac2c119225c63c7b2454353e24f50fc7a909486f Mon Sep 17 00:00:00 2001 From: Romain Lafourcade Date: Sat, 22 May 2021 00:02:25 +0200 Subject: [PATCH 10/18] Formatting and naming --- autoload/qf/format.vim | 34 +++++++++++++++------------------- plugin/qf.vim | 4 ++-- 2 files changed, 17 insertions(+), 21 deletions(-) diff --git a/autoload/qf/format.vim b/autoload/qf/format.vim index e482261..20476e2 100644 --- a/autoload/qf/format.vim +++ b/autoload/qf/format.vim @@ -11,57 +11,53 @@ set cpo&vim function! qf#format#FormatItem(item) return [ \ a:item->FormatFilename(), - \ a:item->FormatLocation(), + \ a:item->FormatPosition(), \ a:item->FormatText(), - \ ]->join('|') + \ ]->join("|") endfunction function! s:FormatFilename(item) let filename = a:item["bufnr"]->bufname() - if has('patch-8.2.1741') + if has("patch-8.2.1741") return pathshorten(filename, g:->get("qf_shorten_path", 1)) else return pathshorten(filename) endif endfunction -function! s:FormatLocation(item) +function! s:FormatPosition(item) return [ \ a:item->get("lnum", 0)->FormatLineNumber(), \ a:item->get("col", 0)->FormatColumn(), - \ a:item->get("type", '')->FormatType(), + \ a:item->get("type", "")->FormatType(), \ a:item->get("nr", 0)->FormatErrorNumber(), - \ ]->join('') + \ ]->join("") endfunction function! s:FormatText(item) - return ' ' .. a:item->get("text", '') + return " " .. a:item->get("text", "") endfunction function! s:FormatLineNumber(lnum) - return a:lnum != 0 ? a:lnum : '' + return a:lnum != 0 ? a:lnum : "" endfunction function! s:FormatColumn(col) - return a:col > 0 ? ' col ' .. a:col : '' + return a:col > 0 ? " col " .. a:col : "" endfunction function! s:FormatType(type) return { - \ 'e': ' error', - \ 'i': ' info', - \ 'n': ' note', - \ 'w': ' warning' - \ }->get(a:type, '') + \ "e": " error", + \ "i": " info", + \ "n": " note", + \ "w": " warning" + \ }->get(a:type, "") endfunction function! s:FormatErrorNumber(nr) - if a:nr > 0 - return ' ' .. printf("%3d", a:nr) - else - return '' - endif + return a:nr > 0 ? " " .. printf("%3d", a:nr) : "" endfunction let &cpo = s:save_cpo diff --git a/plugin/qf.vim b/plugin/qf.vim index 9c72acc..26c41cd 100644 --- a/plugin/qf.vim +++ b/plugin/qf.vim @@ -58,8 +58,8 @@ augroup qf " Automatically open the location/quickfix window after :make, :grep, " :lvimgrep and friends if there are valid locations/errors - exec printf('autocmd QuickFixCmdPost %s nested call qf#OpenQuickfixWindow()', s:qf_autocmd_triggers) - exec printf('autocmd QuickFixCmdPost %s nested call qf#OpenLocationWindow()', s:loc_autocmd_triggers) + execute "autocmd QuickFixCmdPost " .. s:qf_autocmd_triggers .. " nested call qf#OpenQuickfixWindow()" + execute "autocmd QuickFixCmdPost " .. s:loc_autocmd_triggers .. " nested call qf#OpenLocationWindow()" " Special case for :helpgrep and :lhelpgrep since the help window may not " be opened yet when QuickFixCmdPost triggers From d2ad511593e000a156ee0ce1828bf13950a91039 Mon Sep 17 00:00:00 2001 From: Romain Lafourcade Date: Wed, 26 May 2021 16:41:56 +0200 Subject: [PATCH 11/18] Fix typo --- README.md | 2 +- doc/qf.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 51c7ec5..34f0058 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ Many plugins interact with the quickfix/location list/window in ways that are mo - (optional) open the location/quickfix window automatically after `:make`, `:grep`, `:lvimgrep` and friends if there are valid locations/errors -- (optional) automatically set the height of location/quickfix windows to the number of list items if less than Vim's default height (10) or the user's prefered height +- (optional) automatically set the height of location/quickfix windows to the number of list items if less than Vim's default height (10) or the user's preferred height ### Local features (available only in location/quickfix windows) diff --git a/doc/qf.txt b/doc/qf.txt index c3965ed..7e6e3b7 100644 --- a/doc/qf.txt +++ b/doc/qf.txt @@ -35,7 +35,7 @@ These "global" features are available from any window: |:grep|, |:lvimgrep| and friends if there are valid locations/errors - (optional) automatically set the height of location/quickfix windows to the number of list items if less than Vim's default height (10) or - the user's prefered height + the user's preferred height These "local" features are only available in location/quickfix windows: From 74917ac469d47ba9d9484655c1d9dfc1db5bf078 Mon Sep 17 00:00:00 2001 From: Romain Lafourcade Date: Wed, 26 May 2021 16:46:30 +0200 Subject: [PATCH 12/18] Removed 7.x intructions. Changed some wording. --- README.md | 22 ++-------------------- 1 file changed, 2 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index 34f0058..896a1d3 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ ### Anti-features -Many plugins interact with the quickfix/location list/window in ways that are more or less incompatible with vim-qf. I have put considerable effort in making most vim-qf features optional so it should be possible to disable individual features in case of conflict but well… you never know. +Many plugins interact with the quickfix/location list/window in ways that are more or less incompatible with vim-qf. I have put considerable effort into making most vim-qf features optional so it should be possible to disable individual features in case of conflict but well… you never know. **If one of your plugins somehow already manages the quickfix/location list/window, then you should probably look elsewhere.** @@ -68,27 +68,9 @@ If you are using Vim 8.0 or above, move this directory to: See `:help package`. -### Method 3 - -If you are using Vim 7.4 or below, move the files in this directory to their standard location: - - # Unix-like systems - ~/.vim/after/ftplugin/qf.vim - ~/.vim/autoload/qf.vim - ~/.vim/autoload/qf/*.vim - ~/.vim/doc/qf.txt - ~/.vim/plugin/qf.vim - - # Windows - %userprofile%\vimfiles\after\ftplugin\qf.vim - %userprofile%\vimfiles\autoload\qf.vim - %userprofile%\vimfiles\autoload\qf\*.vim - %userprofile%\vimfiles\doc\qf.txt - %userprofile%\vimfiles\plugin\qf.vim - ## Documentation -You can use this command to get help on vim-qf: +The full documentation is available through this command: :help vim-qf From 391fc22932ee7d317bd6bb3c9e522ad0a3a4d03d Mon Sep 17 00:00:00 2001 From: Romain Lafourcade Date: Fri, 28 May 2021 12:55:25 +0200 Subject: [PATCH 13/18] Make utility functions more resilient. Upgrade toggle.vim. --- autoload/qf.vim | 89 ++++++++++++++++++++++-------------------- autoload/qf/toggle.vim | 23 ++--------- 2 files changed, 49 insertions(+), 63 deletions(-) diff --git a/autoload/qf.vim b/autoload/qf.vim index f5025b5..8e88e94 100644 --- a/autoload/qf.vim +++ b/autoload/qf.vim @@ -8,22 +8,28 @@ let s:save_cpo = &cpo set cpo&vim +function! s:GetWinInfo(nr) + let win_id = a:nr != 0 ? win_getid(a:nr) : win_getid() + + return win_id->getwininfo()->get(0, {}) +endfunction + " Returns 1 if the window with the given number is a quickfix window " 0 if the window with the given number is not a quickfix window -" TODO (Nelo-T. Wallus): make a:nbmr optional and return current window -" by default -function! qf#IsQfWindow(nmbr) - if getwinvar(a:nmbr, "&filetype") == "qf" - return qf#IsLocWindow(a:nmbr) ? 0 : 1 - endif +" Uses current window if no number is given +function! qf#IsQfWindow(...) + let info = get(a:, 1, 0)->GetWinInfo() - return 0 + return info->get("quickfix", 0) == 1 && info->get("loclist", 0) == 0 endfunction " Returns 1 if the window with the given number is a location window " 0 if the window with the given number is not a location window -function! qf#IsLocWindow(nmbr) - return getbufvar(winbufnr(a:nmbr), "qf_isLoc") == 1 +" Uses current window if no number is given +function! qf#IsLocWindow(...) + let info = get(a:, 1, 0)->GetWinInfo() + + return info->get("loclist", 0) == 1 endfunction " Returns bool: Is quickfix window open? @@ -41,11 +47,13 @@ endfunction function! qf#IsLocWindowOpen(nmbr) abort let loclist = getloclist(a:nmbr) - for winnum in range(1, winnr("$")) - if qf#IsLocWindow(winnum) && loclist ==# getloclist(winnum) - return 1 - endif - endfor + if loclist->len() > 0 + for winnum in range(1, winnr("$")) + if qf#IsLocWindow(winnum) && loclist ==# getloclist(winnum) + return 1 + endif + endfor + endif return 0 endfunction @@ -55,26 +63,22 @@ endfunction " qf#GetListItems(0, 5) .... item 5 of the quickfix list " qf#GetListItems(1, 0) .... all items of the location list " qf#GetListItems(1, 5) .... item 5 of the location list -function! qf#GetListItems(loc, idx) - let what = { "idx": get(a: "idx", 0), "items": 1 } - - if get(a:, "loc", 0) - return getloclist(0, what)["items"] +function! qf#GetListItems(loc = 0, idx = 0) + if a:loc == 1 + return getloclist(0, { "idx": a:idx, "items": 1 })["items"] else - return getqflist(what)["items"] + return getqflist({ "idx": a:idx, "items": 1 })["items"] endif endfunction " Returns the number of items in a location/quickfix list " qf#GetListSize(0) .... size of the quickfix list " qf#GetListSize(1) .... size of the location list -function! qf#GetListSize(loc) - let what = { "size": 1 } - - if get(a:, "loc", 0) - return getloclist(0, what)["size"] +function! qf#GetListSize(loc = 0) + if a:loc == 1 + return getloclist(0, { "size": 1 })->get("size", 99999) else - return getqflist(what)["size"] + return getqflist({ "size": 1 })->get("size", 99999) endif endfunction @@ -90,9 +94,6 @@ function! qf#SetList(newlist, ...) \ ? function('setloclist', [0, a:newlist]) \ : function('setqflist', [a:newlist]) - " Get user-defined maximum height - let max_height = qf#GetMaxHeight() - " Call partial with optional arguments call call(Func, a:000) @@ -100,38 +101,40 @@ function! qf#SetList(newlist, ...) return endif - if get(b:, "qf_isLoc", 0) - call qf#OpenLocationWindow() - else - call qf#OpenQuickfixWindow() - endif + call get(b:, "qf_isLoc", 0)->qf#OpenWindow() endfunction " Open the quickfix window if there are valid errors function! qf#OpenQuickfixWindow() if get(g:, "qf_auto_open_quickfix", 1) - " Get user-defined maximum height - let max_height = qf#GetMaxHeight() - - execute get(g:, "qf_auto_resize", 1) ? "cclose|" . min([ max_height, qf#GetListSize(0) ]) . "cwindow" : "cclose|cwindow" + call qf#OpenWindow(0) endif endfunction " Open a location window if there are valid locations function! qf#OpenLocationWindow() if get(g:, "qf_auto_open_loclist", 1) - " Get user-defined maximum height - let max_height = qf#GetMaxHeight() + call qf#OpenWindow(1) + endif +endfunction + +" Refresh the location/quickfix window +function! qf#OpenWindow(loc) + let prefix = get(a:, "loc", 0) ? "l" : "c" + let list_size = qf#GetListSize(a:loc) - execute get(g:, "qf_auto_resize", 1) ? "lclose|" . min([ max_height, qf#GetListSize(1) ]) . "lwindow" : "lclose|lwindow" + if list_size > 0 + execute get(g:, "qf_auto_resize", 1) + \ ? prefix .. "close|" .. min([ qf#GetMaxHeight(), list_size ]) .. prefix .. "window" + \ : prefix .. "close|" .. prefix .. "window" endif endfunction " Handles formatting of the text in the buffer function! qf#QuickfixTextFunc(options) - let items = a:options["quickfix"] == 1 ? getqflist() : getloclist(a:options["winid"]) + let items = qf#GetListItems(!a:options["quickfix"], 0) - return items->map({ key, val -> val->qf#format#FormatItem() }) + return items->map({ key, val -> qf#format#FormatItem(val) }) endfunction let &cpo = s:save_cpo diff --git a/autoload/qf/toggle.vim b/autoload/qf/toggle.vim index cf732bc..68ad618 100644 --- a/autoload/qf/toggle.vim +++ b/autoload/qf/toggle.vim @@ -4,17 +4,6 @@ " License: MIT " Location: autoload/toggle.vim " Website: https://github.com/romainl/vim-qf -" -" Use this command to get help on vim-qf: -" -" :help qf -" -" If this doesn't work and you installed vim-qf manually, use the following -" command to index vim-qf's documentation: -" -" :helptags ~/.vim/doc -" -" or read your runtimepath/plugin manager documentation. let s:save_cpo = &cpo set cpo&vim @@ -28,9 +17,6 @@ function! qf#toggle#ToggleQfWindow(stay) abort let winview = {} endif - " get user-defined maximum height - let max_height = get(g:, 'qf_max_height', 10) < 1 ? 10 : get(g:, 'qf_max_height', 10) - " if one of the windows is a quickfix window close it and return if qf#IsQfWindowOpen() cclose @@ -38,7 +24,7 @@ function! qf#toggle#ToggleQfWindow(stay) abort call winrestview(winview) endif else - execute get(g:, 'qf_auto_resize', 1) ? min([ max_height, qf#GetListSize() ]) . 'cwindow' : max_height . 'cwindow' + call qf#OpenQuickfixWindow() if qf#IsQfWindowOpen() wincmd p if !empty(winview) @@ -55,22 +41,19 @@ endfunction " or whatever location window has the focus. function! qf#toggle#ToggleLocWindow(stay) abort " save the view if the current window is not a location window - if get(g:, 'qf_save_win_view', 1) && !qf#IsLocWindow(winnr()) + if get(g:, 'qf_save_win_view', 1) && qf#IsLocWindow(winnr()) let winview = winsaveview() else let winview = {} endif - " get user-defined maximum height - let max_height = get(g:, 'qf_max_height', 10) < 1 ? 10 : get(g:, 'qf_max_height', 10) - if qf#IsLocWindowOpen(0) lclose if !empty(winview) call winrestview(winview) endif else - execute get(g:, 'qf_auto_resize', 1) ? min([ max_height, qf#GetListSize() ]) . 'lwindow' : max_height . 'lwindow' + call qf#OpenLocationWindow() if qf#IsLocWindowOpen(0) wincmd p if !empty(winview) From 5d51106c0548023614e9c888c74f807162d855c6 Mon Sep 17 00:00:00 2001 From: Romain Lafourcade Date: Fri, 28 May 2021 14:50:28 +0200 Subject: [PATCH 14/18] Rework filter.vim --- autoload/qf.vim | 11 ++ autoload/qf/filter.vim | 313 +++++++++++++++++------------------------ 2 files changed, 144 insertions(+), 180 deletions(-) diff --git a/autoload/qf.vim b/autoload/qf.vim index 8e88e94..f7e464d 100644 --- a/autoload/qf.vim +++ b/autoload/qf.vim @@ -82,6 +82,17 @@ function! qf#GetListSize(loc = 0) endif endfunction +" Returns the title of a location/quickfix list +" qf#GetListTitle(0) .... title of the quickfix list +" qf#GetListTitle(1) .... title of the location list +function! qf#GetListTitle(loc = 0) + if a:loc == 1 + return getloclist(0, { "title": 1 })->get("title", "") + else + return getqflist({ "title": 1 })->get("title", "") + endif +endfunction + " Returns the maximum height of the location/quickfix window function! qf#GetMaxHeight() return get(g:, "qf_max_height", 10) < 1 ? 10 : get(g:, "qf_max_height", 10) diff --git a/autoload/qf/filter.vim b/autoload/qf/filter.vim index 31eff1e..70ed5bf 100644 --- a/autoload/qf/filter.vim +++ b/autoload/qf/filter.vim @@ -4,122 +4,81 @@ " License: MIT " Location: autoload/filter.vim " Website: https://github.com/romainl/vim-qf -" -" Use this command to get help on vim-qf: -" -" :help qf -" -" If this doesn't work and you installed vim-qf manually, use the following -" command to index vim-qf's documentation: -" -" :helptags ~/.vim/doc -" -" or read your runtimepath/plugin manager documentation. let s:save_cpo = &cpo set cpo&vim " deletes every original list function! s:ResetLists() - if exists("b:qf_isLoc") - if b:qf_isLoc == 1 - call setwinvar(winnr("#"), "qf_location_lists", []) - call setwinvar(winnr("#"), "qf_location_titles", []) - else - let g:qf_quickfix_lists = [] - let g:qf_quickfix_titles = [] - endif + if qf#IsLocWindow() + call winnr("#")->setwinvar("qf_location_lists", []) + call winnr("#")->setwinvar("qf_location_titles", []) + endif + + if qf#IsQfWindow() + let g:qf_quickfix_lists = [] + let g:qf_quickfix_titles = [] endif endfunction -function! s:SetList(pat, range, reject, strategy) +function! s:FilteredList(list, pat, range, reject, strategy) " decide what regexp operator to use - let operator = a:reject == 0 ? '=~' : '!~' - " get user-defined maximum height - let max_height = get(g:, 'qf_max_height', 10) < 1 ? 10 : get(g:, 'qf_max_height', 10) - - if exists("b:qf_isLoc") - if b:qf_isLoc == 1 - " bufname && text - if a:strategy == 0 - call setloclist(0, filter(getloclist(0), "(bufname(v:val['bufnr']) . v:val['text'] " . operator . " a:pat)"), "r") - endif + let operator = a:reject == 0 ? '=~' : '!~' - " only bufname - if a:strategy == 1 - call setloclist(0, filter(getloclist(0), "bufname(v:val['bufnr']) " . operator . " a:pat"), "r") - endif - - " only text - if a:strategy == 2 - call setloclist(0, filter(getloclist(0), "v:val['text'] " . operator . " a:pat"), "r") - endif + " create an empty list + let new_list = [] - " range - if a:strategy == 3 - let current_list = getloclist(0) - if a:reject - " remove range from list - call remove(current_list, a:range[0], a:range[1]) - call setloclist(0, current_list, "r") - else - " take range from list - call setloclist(0, remove(current_list, a:range[0], a:range[1]), "r") - endif - endif + " bufname && text + if a:strategy == 0 + let new_list = a:list->filter("(bufname(v:val['bufnr']) . v:val['text'] " . operator . " a:pat)") + endif - execute get(g:, "qf_auto_resize", 1) ? 'lclose|' . min([ max_height, len(getloclist(0)) ]) . 'lwindow' : 'lclose|lwindow' - else - " bufname && text - if a:strategy == 0 - call setqflist(filter(getqflist(), "(bufname(v:val['bufnr']) . v:val['text'] " . operator . " a:pat)"), "r") - endif + " only bufname + if a:strategy == 1 + let new_list = a:list->filter("bufname(v:val['bufnr']) " . operator . " a:pat") + endif - " only bufname - if a:strategy == 1 - call setqflist(filter(getqflist(), "bufname(v:val['bufnr']) " . operator . " a:pat"), "r") - endif + " only text + if a:strategy == 2 + let new_list = a:list->filter("v:val['text'] " . operator . " a:pat") + endif - " only text - if a:strategy == 2 - call setqflist(filter(getqflist(), "v:val['text'] " . operator . " a:pat"), "r") - endif + " range + if a:strategy == 3 + if a:reject + let current_list = a:list - " range - if a:strategy == 3 - let current_list = getqflist() - if a:reject - " remove range from list - call remove(current_list, a:range[0], a:range[1]) - call setqflist(current_list, "r") - else - " take range from list - call setqflist(remove(current_list, a:range[0], a:range[1]), "r") - endif - endif + " remove range from list + call current_list->remove(a:range[0], a:range[1]) - execute get(g:, "qf_auto_resize", 1) ? 'cclose|' . min([ max_height, len(getqflist()) ]) . 'cwindow' : 'cclose|cwindow' + let new_list = current_list + else + " take range from list + let new_list = a:list->remove(a:range[0], a:range[1]) endif endif + + return new_list endfunction function! s:AddList() - if exists("b:qf_isLoc") - if b:qf_isLoc == 1 - let locations = getwinvar(winnr("#"), "qf_location_lists") + if qf#IsLocWindow() + let locations = winnr("#")->getwinvar("qf_location_lists") - if len(locations) > 0 - call add(locations, getloclist(0)) - call setwinvar(winnr("#"), "qf_location_lists", locations) - else - call setwinvar(winnr("#"), "qf_location_lists", [getloclist(0)]) - endif + if len(locations) > 0 + call locations->add(qf#GetListItems(1)) + + call winnr("#")->setwinvar("qf_location_lists", locations) else - if exists("g:qf_quickfix_lists") - let g:qf_quickfix_lists = add(g:qf_quickfix_lists, getqflist()) - else - let g:qf_quickfix_lists = [getqflist()] - endif + call winnr("#")->setwinvar("qf_location_lists", [qf#GetListItems(1)]) + endif + endif + + if qf#IsQfWindow() + if exists("g:qf_quickfix_lists") + let g:qf_quickfix_lists = add(g:qf_quickfix_lists, getqflist()) + else + let g:qf_quickfix_lists = [getqflist()] endif endif endfunction @@ -137,34 +96,34 @@ endfunction " :grep foo sample.txt [reject: entry 13] function! s:SetTitle(pat, range, reject) " did we use :Keep or :Reject? - let action = a:reject == 0 ? 'keep' : 'reject' + let action = a:reject == 0 ? "keep" : "reject" " describe the filter that was applied if a:pat != '' let filter = "'" . a:pat . "'" else if a:range[0] == a:range[1] - let filter = 'entry ' . (a:range[0] + 1) + let filter = "entry " . (a:range[0] + 1) else - let filter = 'entries ' . (a:range[0] + 1) . '..' . (a:range[1] + 1) + let filter = "entries " . (a:range[0] + 1) . ".." . (a:range[1] + 1) endif endif let str = " [" . action . ": " . filter . "]" - if exists("b:qf_isLoc") - if b:qf_isLoc == 1 - call s:SetTitleValue(getwinvar(winnr("#"), "qf_location_titles")[0] . str) - else - if exists("g:qf_quickfix_titles") - if len(g:qf_quickfix_titles) > 0 - call s:SetTitleValue(g:qf_quickfix_titles[0] . str) - else - call s:SetTitleValue(w:quickfix_title . str) - endif + if qf#IsLocWindow() + call s:SetTitleValue(winnr("#")->getwinvar("qf_location_titles")[0] .. str) + endif + + if qf#IsQfWindow() + if exists("g:qf_quickfix_titles") + if len(g:qf_quickfix_titles) > 0 + call s:SetTitleValue(g:qf_quickfix_titles[0] .. str) else - call s:SetTitleValue(w:quickfix_title . str) + call s:SetTitleValue(w:quickfix_title .. str) endif + else + call s:SetTitleValue(w:quickfix_title .. str) endif endif endfunction @@ -175,35 +134,32 @@ endfunction function! s:SetTitleValue(title) let w:quickfix_title = a:title " Update the quickfix/location list title if this Vim supports it - if has('patch-7.4.2200') - if b:qf_isLoc == 1 - noautocmd call setloclist(0, [], 'a', {'title': a:title}) - else - noautocmd call setqflist([], 'a', {'title': a:title}) - endif + if qf#IsLocWindow() + noautocmd call setloclist(0, [], "a", {"title": a:title}) + endif + + if qf#IsQfWindow() + noautocmd call setqflist([], "a", {"title": a:title}) endif endfunction " store the current title function! s:AddTitle(title) - if exists("b:qf_isLoc") - if b:qf_isLoc == 1 - let titles = getwinvar(winnr("#"), "qf_location_titles") + if qf#IsLocWindow() + let titles = winnr("#")->getwinvar("qf_location_titles") - if len(titles) > 0 - call add(titles, a:title) - call setwinvar(winnr("#"), "qf_location_titles", titles) - else - call setwinvar(winnr("#"), "qf_location_titles", [a:title]) - endif + if len(titles) > 0 + call titles->add(a:title) + + call winnr("#")->setwinvar("qf_location_titles", titles) else - if exists("g:qf_quickfix_titles") - let g:qf_quickfix_titles = add(g:qf_quickfix_titles, a:title) - else - let g:qf_quickfix_titles = [a:title] - endif + call winnr("#")->setwinvar("qf_location_titles", [a:title]) endif endif + + if qf#IsQfWindow() + let g:qf_quickfix_titles = get(g:, "qf_quickfix_titles", [])->add(a:title) + endif endfunction function! s:GetSelection() @@ -211,30 +167,32 @@ function! s:GetSelection() normal! gv"vy let raw_search = getreg("v") call setreg("v", old_reg) - return substitute(escape(raw_search, '\/.*$^~[]'), "\n", '\\n', "g") + return raw_search + \ ->escape('\/.*$^~[]') + \ ->substitute("\n", '\\n', "g") endfunction " filter the current list function! qf#filter#FilterList(pat, reject, lnum1, lnum2, cnt) - let strategy = get(g:, 'qf_bufname_or_text', 0) - let pat = '' + let strategy = get(g:, "qf_bufname_or_text", 0) + let pat = "" let range = [] - if a:pat != '' + if a:pat != "" let pat = a:pat else if a:cnt == -1 " no range was given " :Reject - if col('.') == 1 - if get(g:, 'qf_shorten_path', 1) - let pat = split(split(getline('.'), '|')[0], '/')[-1] + if col(".") == 1 + if get(g:, "qf_shorten_path", 1) + let pat = split(split(getline("."), "|")[0], "/")[-1] else - let pat = split(getline('.'), '|')[0] + let pat = split(getline("."), "|")[0] endif let strategy = 1 else - let pat = expand('') + let pat = expand("") let strategy = 2 endif else @@ -247,44 +205,55 @@ function! qf#filter#FilterList(pat, reject, lnum1, lnum2, cnt) endif endif - if exists("b:qf_isLoc") + if qf#IsLocWindow() || qf#IsQfWindow() call s:AddList() - call s:AddTitle(get(w:, 'quickfix_title', ' ')) + call s:AddTitle(get(w:, "quickfix_title", " ")) - call s:SetList(pat, range, a:reject, strategy) + call qf#GetListItems(qf#IsLocWindow(), 0) + \ ->s:FilteredList(pat, range, a:reject, strategy) + \ ->s:ReplaceList(qf#IsLocWindow()) call s:SetTitle(pat, range, a:reject) - call s:AddTitle(get(w:, 'quickfix_title', ' ')) + call s:AddTitle(get(w:, "quickfix_title", " ")) endif endfunction +function! s:ReplaceList(new_list, loc) + if a:loc == 1 + call setloclist(0, a:new_list, "r") + else + call setqflist(a:new_list, "r") + endif + + call qf#OpenWindow(a:loc) +endfunction + " restore the original list function! qf#filter#RestoreList() - " get user-defined maximum height - let max_height = get(g:, 'qf_max_height', 10) < 1 ? 10 : get(g:, 'qf_max_height', 10) + if qf#IsLocWindow() + let lists = winnr("#")->getwinvar("qf_location_lists") - if exists("b:qf_isLoc") - if b:qf_isLoc == 1 - let lists = getwinvar(winnr("#"), "qf_location_lists") + if len(lists) > 0 + call setloclist(0, winnr("#")->getwinvar("qf_location_lists")[0], "r") - if len(lists) > 0 - call setloclist(0, getwinvar(winnr("#"), "qf_location_lists")[0], "r") - execute get(g:, "qf_auto_resize", 1) ? 'lclose|' . min([ max_height, len(getloclist(0)) ]) . 'lwindow' : 'lwindow' + call qf#OpenWindow(1) - call s:SetTitleValue(getwinvar(winnr("#"), "qf_location_titles")[0]) - else - echo "No filter applied. Nothing to restore." - endif + call s:SetTitleValue(winnr("#")->getwinvar("qf_location_titles")[0]) else - if exists("g:qf_quickfix_lists") - if len(g:qf_quickfix_lists) > 0 - call setqflist(g:qf_quickfix_lists[0], "r") - execute get(g:, "qf_auto_resize", 1) ? 'cclose|' . min([ max_height, len(getqflist()) ]) . 'cwindow' : 'cwindow' + echo "No filter applied. Nothing to restore." + endif + endif - call s:SetTitleValue(g:qf_quickfix_titles[0]) - else - echo "No filter applied. Nothing to restore." - endif + if qf#IsQfWindow() + if exists("g:qf_quickfix_lists") + if len(g:qf_quickfix_lists) > 0 + call setqflist(g:qf_quickfix_lists[0], "r") + + call qf#OpenWindow(0) + + call s:SetTitleValue(g:qf_quickfix_titles[0]) + else + echo "No filter applied. Nothing to restore." endif endif endif @@ -294,28 +263,12 @@ endfunction " replace the current title function! qf#filter#ReuseTitle() - if exists("b:qf_isLoc") - if b:qf_isLoc == 1 - if has('patch-7.4.2200') - let w:quickfix_title = getloclist(0, {'title': 0}).title - else - let titles = getwinvar(winnr("#"), "qf_location_titles") + if qf#IsLocWindow() + let w:quickfix_title = qf#GetListTitle(1) + endif - if len(titles) > 0 - let w:quickfix_title = getwinvar(winnr("#"), "qf_location_titles")[0] - endif - endif - else - if has('patch-7.4.2200') - let w:quickfix_title = getqflist({'title': 0}).title - else - if exists("g:qf_quickfix_titles") - if len(g:qf_quickfix_titles) > 0 - let w:quickfix_title = g:qf_quickfix_titles[0] - endif - endif - endif - endif + if qf#IsQfWindow() + let w:quickfix_title = qf#GetListTitle() endif endfunction From db53f013c566f910037f9ba3169a3abd3488056b Mon Sep 17 00:00:00 2001 From: Romain Lafourcade Date: Fri, 28 May 2021 14:54:27 +0200 Subject: [PATCH 15/18] Syntax --- autoload/qf/filter.vim | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/autoload/qf/filter.vim b/autoload/qf/filter.vim index 70ed5bf..841bc07 100644 --- a/autoload/qf/filter.vim +++ b/autoload/qf/filter.vim @@ -30,17 +30,17 @@ function! s:FilteredList(list, pat, range, reject, strategy) " bufname && text if a:strategy == 0 - let new_list = a:list->filter("(bufname(v:val['bufnr']) . v:val['text'] " . operator . " a:pat)") + let new_list = a:list->filter("(bufname(v:val['bufnr']) .. v:val['text'] " .. operator .. " a:pat)") endif " only bufname if a:strategy == 1 - let new_list = a:list->filter("bufname(v:val['bufnr']) " . operator . " a:pat") + let new_list = a:list->filter("bufname(v:val['bufnr']) " .. operator .. " a:pat") endif " only text if a:strategy == 2 - let new_list = a:list->filter("v:val['text'] " . operator . " a:pat") + let new_list = a:list->filter("v:val['text'] " .. operator .. " a:pat") endif " range @@ -76,9 +76,9 @@ function! s:AddList() if qf#IsQfWindow() if exists("g:qf_quickfix_lists") - let g:qf_quickfix_lists = add(g:qf_quickfix_lists, getqflist()) + let g:qf_quickfix_lists = add(g:qf_quickfix_lists, qf#GetListItems()) else - let g:qf_quickfix_lists = [getqflist()] + let g:qf_quickfix_lists = [qf#GetListItems()] endif endif endfunction @@ -100,16 +100,16 @@ function! s:SetTitle(pat, range, reject) " describe the filter that was applied if a:pat != '' - let filter = "'" . a:pat . "'" + let filter = "'" .. a:pat .. "'" else if a:range[0] == a:range[1] - let filter = "entry " . (a:range[0] + 1) + let filter = "entry " .. (a:range[0] + 1) else - let filter = "entries " . (a:range[0] + 1) . ".." . (a:range[1] + 1) + let filter = "entries " .. (a:range[0] + 1) .. ".." .. (a:range[1] + 1) endif endif - let str = " [" . action . ": " . filter . "]" + let str = " [" .. action .. ": " .. filter .. "]" if qf#IsLocWindow() call s:SetTitleValue(winnr("#")->getwinvar("qf_location_titles")[0] .. str) From faf2e110a5f2122f1a672c7c28f63800679c34a0 Mon Sep 17 00:00:00 2001 From: Romain Lafourcade Date: Fri, 28 May 2021 15:06:32 +0200 Subject: [PATCH 16/18] Use empty() instead of len() to check if a list is empty --- autoload/qf.vim | 2 +- autoload/qf/filter.vim | 10 +++++----- autoload/qf/statusline.vim | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/autoload/qf.vim b/autoload/qf.vim index f7e464d..a52405e 100644 --- a/autoload/qf.vim +++ b/autoload/qf.vim @@ -47,7 +47,7 @@ endfunction function! qf#IsLocWindowOpen(nmbr) abort let loclist = getloclist(a:nmbr) - if loclist->len() > 0 + if !loclist->empty() for winnum in range(1, winnr("$")) if qf#IsLocWindow(winnum) && loclist ==# getloclist(winnum) return 1 diff --git a/autoload/qf/filter.vim b/autoload/qf/filter.vim index 841bc07..ecdb891 100644 --- a/autoload/qf/filter.vim +++ b/autoload/qf/filter.vim @@ -65,7 +65,7 @@ function! s:AddList() if qf#IsLocWindow() let locations = winnr("#")->getwinvar("qf_location_lists") - if len(locations) > 0 + if !locations->empty() call locations->add(qf#GetListItems(1)) call winnr("#")->setwinvar("qf_location_lists", locations) @@ -117,7 +117,7 @@ function! s:SetTitle(pat, range, reject) if qf#IsQfWindow() if exists("g:qf_quickfix_titles") - if len(g:qf_quickfix_titles) > 0 + if !g:qf_quickfix_titles->empty() call s:SetTitleValue(g:qf_quickfix_titles[0] .. str) else call s:SetTitleValue(w:quickfix_title .. str) @@ -148,7 +148,7 @@ function! s:AddTitle(title) if qf#IsLocWindow() let titles = winnr("#")->getwinvar("qf_location_titles") - if len(titles) > 0 + if !titles->empty() call titles->add(a:title) call winnr("#")->setwinvar("qf_location_titles", titles) @@ -233,7 +233,7 @@ function! qf#filter#RestoreList() if qf#IsLocWindow() let lists = winnr("#")->getwinvar("qf_location_lists") - if len(lists) > 0 + if !lists->empty() call setloclist(0, winnr("#")->getwinvar("qf_location_lists")[0], "r") call qf#OpenWindow(1) @@ -246,7 +246,7 @@ function! qf#filter#RestoreList() if qf#IsQfWindow() if exists("g:qf_quickfix_lists") - if len(g:qf_quickfix_lists) > 0 + if !g:qf_quickfix_lists->empty() call setqflist(g:qf_quickfix_lists[0], "r") call qf#OpenWindow(0) diff --git a/autoload/qf/statusline.vim b/autoload/qf/statusline.vim index bd925f3..3caeba6 100644 --- a/autoload/qf/statusline.vim +++ b/autoload/qf/statusline.vim @@ -30,7 +30,7 @@ function! qf#statusline#SetStatusline() let titles = get(g:, 'qf_quickfix_titles', []) endif - if len(titles) > 0 + if !titles->empty() return titles[-1] endif From e99733edb87ea19aded8c0f6a8a763cca4ba6010 Mon Sep 17 00:00:00 2001 From: Romain Lafourcade Date: Tue, 8 Jun 2021 08:22:56 +0200 Subject: [PATCH 17/18] Fix doc/tags --- doc/tags | 6 ------ 1 file changed, 6 deletions(-) diff --git a/doc/tags b/doc/tags index ee5a502..521dce6 100644 --- a/doc/tags +++ b/doc/tags @@ -11,8 +11,6 @@ 'g:qf_shorten_path' qf.txt /*'g:qf_shorten_path'* 'g:qf_statusline' qf.txt /*'g:qf_statusline'* 'g:qf_window_bottom' qf.txt /*'g:qf_window_bottom'* -:Dofile qf.txt /*:Dofile* -:Doline qf.txt /*:Doline* :Keep qf.txt /*:Keep* :ListLists qf.txt /*:ListLists* :LoadList qf.txt /*:LoadList* @@ -35,10 +33,6 @@ (qf_qf_switch) qf.txt /*(qf_qf_switch)* (qf_qf_toggle) qf.txt /*(qf_qf_toggle)* (qf_qf_toggle_stay) qf.txt /*(qf_qf_toggle_stay)* -QfHistoryNewer qf.txt /*QfHistoryNewer* -QfHistoryOlder qf.txt /*QfHistoryOlder* -QfNextFile qf.txt /*QfNextFile* -QfPreviousFile qf.txt /*QfPreviousFile* qf qf.txt /*qf* qf-acknowledgements qf.txt /*qf-acknowledgements* qf-configuration qf.txt /*qf-configuration* From 8c927fc609c7c814c86baf72e259fc1e403dd62b Mon Sep 17 00:00:00 2001 From: Romain Lafourcade Date: Mon, 25 Oct 2021 07:49:58 +0200 Subject: [PATCH 18/18] default behaviour --- autoload/qf.vim | 2 ++ 1 file changed, 2 insertions(+) diff --git a/autoload/qf.vim b/autoload/qf.vim index a52405e..572ccce 100644 --- a/autoload/qf.vim +++ b/autoload/qf.vim @@ -138,6 +138,8 @@ function! qf#OpenWindow(loc) execute get(g:, "qf_auto_resize", 1) \ ? prefix .. "close|" .. min([ qf#GetMaxHeight(), list_size ]) .. prefix .. "window" \ : prefix .. "close|" .. prefix .. "window" + else + execute prefix .. "close" endif endfunction