Skip to content

Commit 8b877a9

Browse files
committed
perf!: use stream-based iterators where possible
build: added plenary.nvim as a required dependency refactor: add missing dependency notice
1 parent c76d23b commit 8b877a9

File tree

7 files changed

+127
-101
lines changed

7 files changed

+127
-101
lines changed

README.md

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -425,7 +425,8 @@ plugin and a patched font (see [Nerd Fonts](https://www.nerdfonts.com/)).
425425
{
426426
"willothy/nvim-cokeline",
427427
dependencies = {
428-
"kyazdani42/nvim-web-devicons",
428+
"nvim-lua/plenary.nvim", -- Required for v0.4.0+
429+
"kyazdani42/nvim-web-devicons", -- If you want devicons
429430
},
430431
config = true
431432
}
@@ -440,9 +441,12 @@ require('packer').startup(function()
440441
-- ...
441442
use({
442443
'willothy/nvim-cokeline',
443-
requires = 'kyazdani42/nvim-web-devicons', -- If you want devicons
444+
requires = {
445+
"nvim-lua/plenary.nvim", -- Required for v0.4.0+
446+
"kyazdani42/nvim-web-devicons", -- If you want devicons
447+
},
444448
config = function()
445-
require('cokeline').setup()
449+
require("cokeline").setup()
446450
end
447451
})
448452
-- ...
@@ -457,6 +461,7 @@ If your config is still written in Vimscript and you use
457461
```vim
458462
call plug#begin('~/.config/nvim/plugged')
459463
" ...
464+
Plug 'nvim-lua/plenary.nvim' " Required for v0.4.0+
460465
Plug 'kyazdani42/nvim-web-devicons' " If you want devicons
461466
Plug 'willothy/nvim-cokeline'
462467
" ...

lua/cokeline/buffers.lua

Lines changed: 67 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,11 @@ local cmd = vim.cmd
88
local diagnostic = vim.diagnostic or vim.lsp.diagnostic
99
local fn = vim.fn
1010
local split = vim.split
11-
local filter = vim.tbl_filter
12-
local map = vim.tbl_map
1311

1412
local util = require("cokeline.utils")
13+
local it = require("plenary.iterators")
14+
local iter = it.iter
15+
local enumerate = util.enumerate
1516

1617
---@type bufnr
1718
local current_valid_index
@@ -49,29 +50,27 @@ local M = {}
4950
local Buffer = {}
5051
Buffer.__index = Buffer
5152

52-
---@param buffers Buffer[]
53-
---@return Buffer[]
53+
---@param buffers Iter<Buffer>
54+
---@return Iter<Buffer>
5455
local compute_unique_prefixes = function(buffers)
5556
local is_windows = fn.has("win32") == 1
5657

57-
-- FIXME: it appears in windows sometimes directories are separated by '/'
58-
-- instead of '\\'??
59-
if is_windows then
60-
buffers = map(function(buffer)
61-
buffer.path = buffer.path:gsub("/", "\\")
62-
return buffer
63-
end, buffers)
64-
end
65-
6658
local path_separator = not is_windows and "/" or "\\"
6759

68-
local paths = map(function(buffer)
69-
return fn.reverse(split(buffer.path, path_separator))
70-
end, buffers)
71-
72-
local prefixes = map(function()
73-
return {}
74-
end, buffers)
60+
local prefixes = {}
61+
local paths = {}
62+
buffers = buffers
63+
:map(function(buffer)
64+
prefixes[#prefixes + 1] = {}
65+
paths[#paths + 1] = fn.reverse(
66+
split(
67+
is_windows and buffer.path:gsub("/", "\\") or buffer.path,
68+
path_separator
69+
)
70+
)
71+
return buffer
72+
end)
73+
:tolist()
7574

7675
for i = 1, #paths do
7776
for j = i + 1, #paths do
@@ -88,15 +87,14 @@ local compute_unique_prefixes = function(buffers)
8887
end
8988
end
9089

91-
for i, buffer in ipairs(buffers) do
90+
return enumerate(iter(buffers)):map(function(i, buffer)
9291
buffer.unique_prefix = concat({
9392
#prefixes[i] == #paths[i] and path_separator or "",
9493
fn.join(fn.reverse(prefixes[i]), path_separator),
9594
#prefixes[i] > 0 and path_separator or "",
9695
})
97-
end
98-
99-
return buffers
96+
return i, buffer
97+
end)
10098
end
10199

102100
---@param filename string
@@ -397,45 +395,38 @@ function M.get_valid_buffers()
397395
_G.cokeline.buf_order = {}
398396
end
399397

400-
local buffers
401398
local info = fn.getbufinfo({ buflisted = 1 })
402-
if vim.iter then
403-
buffers = vim
404-
.iter(info)
405-
:map(Buffer.new)
406-
:filter(function(buffer)
407-
return buffer.filetype ~= "netrw"
408-
end)
409-
:filter(
410-
type(_G.cokeline.config.buffers.filter_valid) == "function"
411-
and _G.cokeline.config.buffers.filter_valid
412-
or function()
413-
return true
414-
end
415-
)
416-
:totable()
417-
else
418-
buffers = map(Buffer.new, info)
419-
buffers = filter(function(buffer)
420-
return buffer.filetype ~= "netrw"
421-
end, buffers)
422-
423-
if _G.cokeline.config.buffers.filter_valid then
424-
buffers = filter(_G.cokeline.config.buffers.filter_valid, buffers)
425-
end
399+
---@type Iter<Buffer>
400+
local buffers = iter(info):map(Buffer.new):filter(function(buffer)
401+
return buffer.filetype ~= "netrw"
402+
end)
403+
404+
if _G.cokeline.config.buffers.filter_valid then
405+
---@type Iter<Buffer>
406+
buffers = buffers:filter(_G.cokeline.config.buffers.filter_valid)
426407
end
427408

409+
---@type Buffer[]
428410
buffers = compute_unique_prefixes(buffers)
429411

430412
if current_valid_index == nil then
431413
_G.cokeline.buf_order = {}
432-
for i, buffer in ipairs(buffers) do
433-
buffer._valid_index = i
434-
_G.cokeline.buf_order[buffer.number] = buffer._valid_index
435-
if buffer.is_focused then
436-
current_valid_index = i
437-
end
438-
end
414+
buffers = buffers
415+
:map(function(i, buffer)
416+
buffer._valid_index = i
417+
_G.cokeline.buf_order[buffer.number] = buffer._valid_index
418+
if buffer.is_focused then
419+
current_valid_index = i
420+
end
421+
return buffer
422+
end)
423+
:tolist()
424+
else
425+
buffers = buffers
426+
:map(function(_, buf)
427+
return buf
428+
end)
429+
:tolist()
439430
end
440431

441432
if _G.cokeline.config.buffers.new_buffers_position == "last" then
@@ -465,29 +456,35 @@ end
465456
function M.get_visible()
466457
_G.cokeline.valid_buffers = M.get_valid_buffers()
467458
_G.cokeline.valid_lookup = {}
468-
for _, buffer in ipairs(_G.cokeline.valid_buffers) do
459+
460+
local bufs = iter(_G.cokeline.valid_buffers):map(function(buffer)
469461
_G.cokeline.valid_lookup[buffer.number] = buffer
462+
return buffer
463+
end)
464+
465+
if _G.cokeline.config.buffers.filter_visible then
466+
bufs = bufs:filter(_G.cokeline.config.buffers.filter_visible)
467+
end
468+
469+
bufs = enumerate(bufs):map(function(i, buf)
470+
buf.index = i
471+
return buf
472+
end)
473+
474+
if not _G.cokeline.config.pick.use_filename then
475+
bufs = bufs:map(function(buf)
476+
buf.pick_letter = get_pick_letter(buf.filename, buf.number)
477+
return buf
478+
end)
470479
end
471480

472-
_G.cokeline.visible_buffers = not _G.cokeline.config.buffers.filter_visible
473-
and _G.cokeline.valid_buffers
474-
or filter(
475-
_G.cokeline.config.buffers.filter_visible,
476-
_G.cokeline.valid_buffers
477-
)
481+
_G.cokeline.visible_buffers = bufs:tolist()
478482

479483
if #_G.cokeline.visible_buffers > 0 then
480484
_G.cokeline.visible_buffers[1].is_first = true
481485
_G.cokeline.visible_buffers[#_G.cokeline.visible_buffers].is_last = true
482486
end
483487

484-
for i, buffer in ipairs(_G.cokeline.visible_buffers) do
485-
buffer.index = i
486-
if not _G.cokeline.config.pick.use_filename then
487-
buffer.pick_letter = get_pick_letter(buffer.filename, buffer.number)
488-
end
489-
end
490-
491488
return _G.cokeline.visible_buffers
492489
end
493490

lua/cokeline/components.lua

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
local Hlgroup = require("cokeline/hlgroups").Hlgroup
22

33
local rep = string.rep
4-
local concat = table.concat
54
local insert = table.insert
65
local remove = table.remove
76

7+
local fold = require("cokeline.utils").fold
8+
local iter = require("plenary.iterators").iter
89
local fn = vim.fn
9-
local map = vim.tbl_map
1010

1111
---@generic Cx
1212
---@class Component<Cx>
@@ -162,11 +162,9 @@ end
162162
---@param components Component[]
163163
---@return number
164164
local width_of_components = function(components)
165-
local width = 0
166-
for _, component in pairs(components) do
167-
width = width + component.width
168-
end
169-
return width
165+
return fold(iter(components), 0, function(a, c)
166+
return a + c.width
167+
end)
170168
end
171169

172170
-- Takes a list of components, returns a new list of components `to_width` wide
@@ -177,10 +175,7 @@ end
177175
---@param direction '"left"' | '"right"' | nil
178176
---@return Component<Cx>[]
179177
local shorten_components = function(components, to_width, direction)
180-
local current_width = 0
181-
for _, component in pairs(components) do
182-
current_width = current_width + component.width
183-
end
178+
local current_width = width_of_components(components)
184179

185180
-- `extra` is the width of the extra characters that are appended when a
186181
-- component is shortened, an ellipses if we're shortening within a buffer
@@ -256,11 +251,12 @@ local render_components = function(components)
256251
end
257252
end
258253

259-
return concat(map(function(component)
260-
return embed(component)
261-
end, components))
262-
end
254+
local concat = function(a, b)
255+
return a .. b
256+
end
263257

258+
return fold(iter(components):map(embed), "", concat)
259+
end
264260

265261
return {
266262
Component = Component,

lua/cokeline/hover.lua

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ local version = vim.version()
55
local buffers = require("cokeline.buffers")
66
local tabs = require("cokeline.tabs")
77
local rendering = require("cokeline.rendering")
8+
local iter = require("plenary.iterators").iter
9+
local fold = require("cokeline.utils").fold
810
local last_position = nil
911

1012
function M.hovered()
@@ -183,17 +185,19 @@ local function on_hover(current)
183185
end
184186

185187
local function width(bufs, buf)
186-
return vim
187-
.iter(bufs)
188-
:filter(function(v)
189-
return v.bufnr == buf
190-
end)
191-
:map(function(v)
192-
return v.width
193-
end)
194-
:fold(0, function(acc, v)
188+
return fold(
189+
iter(bufs)
190+
:filter(function(v)
191+
return v.bufnr == buf
192+
end)
193+
:map(function(v)
194+
return v.width
195+
end),
196+
0,
197+
function(acc, v)
195198
return acc + v
196-
end)
199+
end
200+
)
197201
end
198202

199203
local function start_pos(bufs, buf)

lua/cokeline/init.lua

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,13 @@ _G.cokeline = {
5555
--@param preferences table|nil
5656
---@param preferences Component<TabPage>
5757
local setup = function(preferences)
58+
local ok, _ = pcall(require, "plenary")
59+
if not ok then
60+
vim.api.nvim_err_writeln(
61+
"nvim-cokeline: plenary.nvim is required to use this plugin as of v0.4.0"
62+
)
63+
return
64+
end
5865
_G.cokeline.config = config.get(preferences or {})
5966
if _G.cokeline.config.history.enabled then
6067
history.setup(_G.cokeline.config.history.size)

lua/cokeline/rendering.lua

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,13 @@ local sidebar = require("cokeline/sidebar")
33
local rhs = require("cokeline/rhs")
44
local tabs = require("cokeline.tabs")
55
local RenderContext = require("cokeline/context")
6+
local iter = require("plenary.iterators").iter
67

78
local insert = table.insert
89
local sort = table.sort
910
local unpack = unpack or table.unpack
1011

1112
local extend = vim.list_extend
12-
local filter = vim.tbl_filter
1313
local o = vim.o
1414

1515
---@type index
@@ -19,9 +19,9 @@ local current_index
1919
---@param previous_buffer_index index
2020
---@return Buffer
2121
local find_current_buffer = function(buffers, previous_buffer_index)
22-
local focused_buffer = filter(function(buffer)
22+
local focused_buffer = iter(buffers):find(function(buffer)
2323
return buffer.is_focused
24-
end, buffers)[1]
24+
end)
2525

2626
return focused_buffer or buffers[previous_buffer_index] or buffers[#buffers]
2727
end

lua/cokeline/utils.lua

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,24 @@ local function buf_delete(bufnr, focus, wipeout)
120120
end
121121
end
122122

123+
local fold = function(iterable, acc, f)
124+
iterable:for_each(function(v)
125+
acc = f(acc, v)
126+
end)
127+
return acc
128+
end
129+
130+
local enumerate = function(iterable)
131+
local i = 0
132+
return iterable:map(function(...)
133+
i = i + 1
134+
return i, ...
135+
end)
136+
end
137+
123138
return {
124139
get_hex = get_hex,
125140
buf_delete = buf_delete,
141+
fold = fold,
142+
enumerate = enumerate,
126143
}

0 commit comments

Comments
 (0)