Skip to content

Commit 6c60d17

Browse files
committed
refactor: tally
1 parent af7925c commit 6c60d17

File tree

2 files changed

+104
-138
lines changed

2 files changed

+104
-138
lines changed

lua/qf.lua

+73-101
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ local util = require("qf.util")
6969

7070
local fix_list = util.fix_list
7171
local list_items = util.list_items
72+
local valid_list_items = util.valid_list_items
7273
local get_height = util.get_height
7374

7475
local post_commands = {
@@ -158,12 +159,8 @@ function qf.reopen(list)
158159

159160
list = fix_list(list)
160161

161-
local new = api.nvim_get_current_win()
162-
163-
-- api.nvim_set_current_win(prev)
164-
165162
if util.get_list_win(list) == 0 then
166-
-- return
163+
return
167164
end
168165

169166
print("Reopening window: " .. list)
@@ -272,7 +269,7 @@ function qf.open(list, stay, silent, weak)
272269
list = fix_list(list)
273270

274271
local opts = qf.config[list]
275-
local num_items = #list_items(list)
272+
local num_items = get_list(list, { size = 1 }).size
276273

277274
local other
278275
if list == "c" then
@@ -319,7 +316,7 @@ function qf.open(list, stay, silent, weak)
319316
end
320317

321318
--- Close `list`
322-
--- @param list List
319+
--- @param list string
323320
---@tag qf.close() Qclose LClose VClose
324321
function qf.close(list)
325322
list = fix_list(list)
@@ -374,69 +371,56 @@ local is_valid = util.is_valid
374371

375372
-- Returns the list entry currently previous to the cursor
376373
local function follow_prev(list, items, bufnr, line, col)
377-
local last_valid = 1
378374
local found_buf = false
379375
for i = 1, #items do
380376
local j = #items - i + 1
381377
local item = items[j]
382378

383-
local valid = is_valid(item)
384-
if valid then
385-
-- We overshot the current buffer
386-
if found_buf and item.bufnr ~= bufnr then
387-
return j
388-
elseif item.bufnr == bufnr then
389-
found_buf = true
390-
-- If the current entry is past cursor, of the entry of the cursor has been
391-
-- passed
392-
item.col = math.min(item.col, linelen(item.bufnr, item.lnum))
393-
if item.lnum < line or (item.lnum == line and (item.col > 0 and col and item.col < col)) then
394-
return j
395-
end
379+
-- We overshot the current buffer
380+
if found_buf or item.bufnr == bufnr then
381+
found_buf = true
382+
-- If the current entry is past cursor, of the entry of the cursor has been
383+
-- passed
384+
item.col = math.min(item.col, linelen(item.bufnr, item.lnum))
385+
if
386+
item.bufnr ~= bufnr
387+
or item.lnum < line
388+
or (item.lnum == line and (item.col > 0 and col and item.col < col))
389+
then
390+
return item.idx
396391
end
397392
end
398393
end
399394

400-
local cur = util.get_list(list, { idx = 0 }).idx
401-
if cur > 1 then
402-
return cur - 1
403-
else
404-
return #items
405-
end
395+
return get_list(list, { size = 1 }).size
406396
end
407397

408398
-- Returns the first entry after the cursor in buf or the first entry in the
409399
-- buffer
410400
local function follow_next(list, items, bufnr, line, col)
411401
local found_buf = false
412-
for i, item in ipairs(items) do
413-
local valid = is_valid(item)
414-
if valid then
415-
-- We overshot the current buffer
416-
if found_buf and item.bufnr ~= bufnr then
417-
return i
418-
elseif item.bufnr == bufnr then
419-
found_buf = true
420-
-- If the current entry is past cursor, of the entry of the cursor has been
421-
-- passed
422-
item.col = math.min(item.col, linelen(item.bufnr, item.lnum))
423-
if item.lnum > line or (item.lnum == line and (item.col > 0 and col and item.col > col)) then
424-
return i
425-
end
402+
for _, item in ipairs(items) do
403+
-- We overshot the current buffer
404+
if found_buf or item.bufnr == bufnr then
405+
found_buf = true
406+
-- If the current entry is past cursor, of the entry of the cursor has been
407+
-- passed
408+
item.col = math.min(item.col, linelen(item.bufnr, item.lnum))
409+
if
410+
item.bufnr ~= bufnr
411+
or item.lnum > line
412+
or (item.lnum == line and (item.col > 0 and col and item.col > col))
413+
then
414+
return item.idx
426415
end
427416
end
428417
end
429418

430-
local cur = util.get_list(list, { idx = 0 }).idx
431-
if cur < #items then
432-
return cur + 1
433-
else
434-
return 1
435-
end
419+
return 1
436420
end
437421

438422
-- Returns the list entry closest to the cursor vertically
439-
local function follow_nearest(list, items, bufnr, line, col)
423+
local function follow_nearest(_, items, bufnr, line, col)
440424
local i = 1
441425
local min = nil
442426
local min_i = nil
@@ -560,49 +544,6 @@ function qf.prev(list, wrap, verbose)
560544
end
561545
end
562546

563-
local function prev_valid(items, idx)
564-
while idx and idx > 1 do
565-
idx = idx - 1
566-
if is_valid(items[idx]) then
567-
return idx
568-
end
569-
end
570-
571-
return idx
572-
end
573-
574-
local function prev_valid_wrap(items, start)
575-
for i = 1, #items do
576-
local idx = (#items + start - i - 1) % #items + 1
577-
if is_valid(items[idx]) then
578-
return idx
579-
end
580-
end
581-
return 1
582-
end
583-
584-
local function next_valid_wrap(items, start)
585-
for i = 1, #items do
586-
local idx = (i + start - 1) % #items + 1
587-
if is_valid(items[idx]) then
588-
return idx
589-
end
590-
end
591-
return 1
592-
end
593-
594-
local function next_valid(items, idx)
595-
while idx and idx <= #items - 1 do
596-
idx = idx + 1
597-
if is_valid(items[idx]) then
598-
return idx
599-
end
600-
end
601-
602-
vim.notify("No more items", vim.log.levels.ERROR)
603-
return nil
604-
end
605-
606547
--- Wrapping version of [lc]above
607548
--- Will switch buffer
608549
---@tag qf.above() Qabove Labove Vabove
@@ -613,7 +554,7 @@ function qf.above(list, wrap, verbose)
613554

614555
list = fix_list(list)
615556

616-
local items = list_items(list, true)
557+
local items = valid_list_items(list)
617558

618559
if not check_empty(list, #items, verbose) then
619560
return
@@ -642,7 +583,7 @@ function qf.below(list, wrap, verbose)
642583
end
643584
list = fix_list(list)
644585

645-
local items = list_items(list, true)
586+
local items = valid_list_items(list)
646587

647588
if not check_empty(list, #items, verbose) then
648589
return
@@ -726,7 +667,7 @@ end
726667
---@field winid number|nil
727668
---@field title string|nil
728669
---@field tally boolean|nil
729-
---@field open boolean
670+
---@field open boolean|nil if not specified, open if there are errors
730671

731672
--- Set location or quickfix list items
732673
--- If a compiler is given, the items will be parsed from it
@@ -776,8 +717,9 @@ function qf.set(list, opts)
776717
vim.cmd("compiler " .. old_c)
777718
end
778719

720+
local tally = util.tally(list)
779721
if opts.tally then
780-
qf.tally(list, opts.title or "")
722+
qf.tally(list, opts.title or "", tally)
781723
end
782724

783725
qf.config[list].last_line = nil
@@ -786,22 +728,52 @@ function qf.set(list, opts)
786728
api.nvim_set_current_dir(old_cwd)
787729
end
788730

789-
if opts.open ~= false then
731+
if opts.open == true or (opts.open == nil and tally[1] > 0) then
790732
qf.open(list, true, true)
791733
end
792734
end
793735

794736
--- Suffix the chosen list with a summary of the classified number of entries
795-
function qf.tally(list, title)
737+
---@param list string
738+
---@param title string|nil
739+
---@param tally integer[]|nil
740+
function qf.tally(list, title, tally)
796741
list = fix_list(list)
797742

743+
local info = get_list(list, { title = 1, id = 0 })
744+
798745
if title == nil then
799-
title = get_list(list, { title = 1 }).title
746+
title = info.title
800747
end
801748

802-
local s = title:match("[^%-]*") .. util.tally(list)
749+
tally = tally or util.tally(list)
803750

804-
set_list(list, {}, "r", { title = s })
751+
local d = require("qf").config.signs
752+
d = {
753+
d.E,
754+
d.W,
755+
d.I,
756+
d.N,
757+
d.T,
758+
}
759+
760+
local total_count = 0
761+
local t = {}
762+
for i, v in ipairs(tally) do
763+
if v > 0 then
764+
total_count = total_count + 1
765+
local severity = d[i]
766+
t[#t + 1] = "%#" .. severity.hl .. "#" .. severity.sign .. " " .. v
767+
end
768+
end
769+
770+
local tally_str = " - " .. table.concat(t, " ") .. "%#Normal#"
771+
772+
if total_count > 0 then
773+
local s = title:match("[^%-]*%s?") .. tally_str
774+
775+
set_list(list, {}, "r", { title = s })
776+
end
805777
end
806778

807779
function qf.filter_text(list, pat)
@@ -880,7 +852,7 @@ function qf.setup_autocmds(config)
880852
for k, list in pairs({ c = config.c, l = config.l }) do
881853
if list.auto_follow then
882854
au(list.follow_slow and "CursorHold" or "CursorMoved", function()
883-
follow(k, list.auto_follow, true)
855+
follow(k, list.auto_follow, 16)
884856
end)
885857
end
886858

lua/qf/util.lua

+31-37
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ function M.fix_list(list)
1919
end
2020
end
2121
api.nvim_err_writeln("Invalid list type: " .. list)
22-
return nil
22+
return "c"
2323
end
2424

2525
-- Returns true if the current item is valid by having valid == 1 and a valid bufnr and line number
@@ -72,67 +72,61 @@ function M.list_items(list, all)
7272
end
7373
end
7474

75+
function M.valid_list_items(list)
76+
local items = M.get_list(list).items
77+
local t = {}
78+
79+
for i, v in ipairs(items) do
80+
if is_valid(v) then
81+
v.idx = i
82+
t[#t + 1] = v
83+
end
84+
end
85+
86+
return t
87+
end
88+
7589
function M.get_height(list, config)
7690
local opts = config[list]
7791

7892
if opts.auto_resize == false then
7993
return opts.max_height
8094
end
8195

82-
local size = 0
83-
if list == "c" then
84-
size = fn.getqflist({ size = 1 }).size
85-
else
86-
size = fn.getloclist(".", { size = 1 }).size
87-
end
96+
local size = M.get_list(list, { size = 1 }).size
8897

8998
return math.max(math.min(size, opts.max_height), opts.min_height)
9099
end
91100

101+
---comment
102+
---@param list any
103+
---@return integer[]
92104
function M.tally(list)
93-
local d = require("qf").config.signs
94-
d = {
95-
d.E,
96-
d.W,
97-
d.I,
98-
d.N,
99-
d.T,
100-
}
101105
-- Tally
102-
local E = 0
103-
local W = 0
104-
local I = 0
105-
local N = 0
106-
local T = 0
106+
local error = 0
107+
local warn = 0
108+
local information = 0
109+
local hint = 0
110+
local text = 0
107111

108112
local sevs = {}
109113

110-
for _, v in ipairs(M.list_items(list)) do
114+
for _, v in ipairs(M.list_items(list, false)) do
111115
sevs[v.type] = (sevs[v.type] or 0) + 1
112116
if v.type == "E" then
113-
E = E + 1
117+
error = error + 1
114118
elseif v.type == "W" then
115-
W = W + 1
119+
warn = warn + 1
116120
elseif v.type == "I" then
117-
I = I + 1
121+
information = information + 1
118122
elseif v.type == "N" then
119-
N = N + 1
123+
hint = hint + 1
120124
else
121-
T = T + 1
122-
end
123-
end
124-
125-
local tally = { E, W, I, N, T }
126-
local t = {}
127-
for i, v in ipairs(tally) do
128-
if v > 0 then
129-
local severity = d[i]
130-
t[#t + 1] = "%#" .. severity.hl .. "#" .. severity.sign .. " " .. v
125+
text = text + 1
131126
end
132127
end
133128

134-
-- return table.concat(t, " | ")
135-
return " - " .. table.concat(t, " ") .. "%#Normal#"
129+
return { error, warn, information, hint, text }
136130
end
137131

138132
return M

0 commit comments

Comments
 (0)