Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

perf: use stream-based iterators where possible #135

Merged
merged 1 commit into from
Jul 2, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 8 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -425,7 +425,8 @@ plugin and a patched font (see [Nerd Fonts](https://www.nerdfonts.com/)).
{
"willothy/nvim-cokeline",
dependencies = {
"kyazdani42/nvim-web-devicons",
"nvim-lua/plenary.nvim", -- Required for v0.4.0+
"kyazdani42/nvim-web-devicons", -- If you want devicons
},
config = true
}
Expand All @@ -440,9 +441,12 @@ require('packer').startup(function()
-- ...
use({
'willothy/nvim-cokeline',
requires = 'kyazdani42/nvim-web-devicons', -- If you want devicons
requires = {
"nvim-lua/plenary.nvim", -- Required for v0.4.0+
"kyazdani42/nvim-web-devicons", -- If you want devicons
},
config = function()
require('cokeline').setup()
require("cokeline").setup()
end
})
-- ...
Expand All @@ -457,6 +461,7 @@ If your config is still written in Vimscript and you use
```vim
call plug#begin('~/.config/nvim/plugged')
" ...
Plug 'nvim-lua/plenary.nvim' " Required for v0.4.0+
Plug 'kyazdani42/nvim-web-devicons' " If you want devicons
Plug 'willothy/nvim-cokeline'
" ...
Expand Down
137 changes: 67 additions & 70 deletions lua/cokeline/buffers.lua
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,11 @@ local cmd = vim.cmd
local diagnostic = vim.diagnostic or vim.lsp.diagnostic
local fn = vim.fn
local split = vim.split
local filter = vim.tbl_filter
local map = vim.tbl_map

local util = require("cokeline.utils")
local it = require("plenary.iterators")
local iter = it.iter
local enumerate = util.enumerate

---@type bufnr
local current_valid_index
Expand Down Expand Up @@ -49,29 +50,27 @@ local M = {}
local Buffer = {}
Buffer.__index = Buffer

---@param buffers Buffer[]
---@return Buffer[]
---@param buffers Iter<Buffer>
---@return Iter<Buffer>
local compute_unique_prefixes = function(buffers)
local is_windows = fn.has("win32") == 1

-- FIXME: it appears in windows sometimes directories are separated by '/'
-- instead of '\\'??
if is_windows then
buffers = map(function(buffer)
buffer.path = buffer.path:gsub("/", "\\")
return buffer
end, buffers)
end

local path_separator = not is_windows and "/" or "\\"

local paths = map(function(buffer)
return fn.reverse(split(buffer.path, path_separator))
end, buffers)

local prefixes = map(function()
return {}
end, buffers)
local prefixes = {}
local paths = {}
buffers = buffers
:map(function(buffer)
prefixes[#prefixes + 1] = {}
paths[#paths + 1] = fn.reverse(
split(
is_windows and buffer.path:gsub("/", "\\") or buffer.path,
path_separator
)
)
return buffer
end)
:tolist()

for i = 1, #paths do
for j = i + 1, #paths do
Expand All @@ -88,15 +87,14 @@ local compute_unique_prefixes = function(buffers)
end
end

for i, buffer in ipairs(buffers) do
return enumerate(iter(buffers)):map(function(i, buffer)
buffer.unique_prefix = concat({
#prefixes[i] == #paths[i] and path_separator or "",
fn.join(fn.reverse(prefixes[i]), path_separator),
#prefixes[i] > 0 and path_separator or "",
})
end

return buffers
return i, buffer
end)
end

---@param filename string
Expand Down Expand Up @@ -397,45 +395,38 @@ function M.get_valid_buffers()
_G.cokeline.buf_order = {}
end

local buffers
local info = fn.getbufinfo({ buflisted = 1 })
if vim.iter then
buffers = vim
.iter(info)
:map(Buffer.new)
:filter(function(buffer)
return buffer.filetype ~= "netrw"
end)
:filter(
type(_G.cokeline.config.buffers.filter_valid) == "function"
and _G.cokeline.config.buffers.filter_valid
or function()
return true
end
)
:totable()
else
buffers = map(Buffer.new, info)
buffers = filter(function(buffer)
return buffer.filetype ~= "netrw"
end, buffers)

if _G.cokeline.config.buffers.filter_valid then
buffers = filter(_G.cokeline.config.buffers.filter_valid, buffers)
end
---@type Iter<Buffer>
local buffers = iter(info):map(Buffer.new):filter(function(buffer)
return buffer.filetype ~= "netrw"
end)

if _G.cokeline.config.buffers.filter_valid then
---@type Iter<Buffer>
buffers = buffers:filter(_G.cokeline.config.buffers.filter_valid)
end

---@type Buffer[]
buffers = compute_unique_prefixes(buffers)

if current_valid_index == nil then
_G.cokeline.buf_order = {}
for i, buffer in ipairs(buffers) do
buffer._valid_index = i
_G.cokeline.buf_order[buffer.number] = buffer._valid_index
if buffer.is_focused then
current_valid_index = i
end
end
buffers = buffers
:map(function(i, buffer)
buffer._valid_index = i
_G.cokeline.buf_order[buffer.number] = buffer._valid_index
if buffer.is_focused then
current_valid_index = i
end
return buffer
end)
:tolist()
else
buffers = buffers
:map(function(_, buf)
return buf
end)
:tolist()
end

if _G.cokeline.config.buffers.new_buffers_position == "last" then
Expand Down Expand Up @@ -465,29 +456,35 @@ end
function M.get_visible()
_G.cokeline.valid_buffers = M.get_valid_buffers()
_G.cokeline.valid_lookup = {}
for _, buffer in ipairs(_G.cokeline.valid_buffers) do

local bufs = iter(_G.cokeline.valid_buffers):map(function(buffer)
_G.cokeline.valid_lookup[buffer.number] = buffer
return buffer
end)

if _G.cokeline.config.buffers.filter_visible then
bufs = bufs:filter(_G.cokeline.config.buffers.filter_visible)
end

bufs = enumerate(bufs):map(function(i, buf)
buf.index = i
return buf
end)

if not _G.cokeline.config.pick.use_filename then
bufs = bufs:map(function(buf)
buf.pick_letter = get_pick_letter(buf.filename, buf.number)
return buf
end)
end

_G.cokeline.visible_buffers = not _G.cokeline.config.buffers.filter_visible
and _G.cokeline.valid_buffers
or filter(
_G.cokeline.config.buffers.filter_visible,
_G.cokeline.valid_buffers
)
_G.cokeline.visible_buffers = bufs:tolist()

if #_G.cokeline.visible_buffers > 0 then
_G.cokeline.visible_buffers[1].is_first = true
_G.cokeline.visible_buffers[#_G.cokeline.visible_buffers].is_last = true
end

for i, buffer in ipairs(_G.cokeline.visible_buffers) do
buffer.index = i
if not _G.cokeline.config.pick.use_filename then
buffer.pick_letter = get_pick_letter(buffer.filename, buffer.number)
end
end

return _G.cokeline.visible_buffers
end

Expand Down
26 changes: 11 additions & 15 deletions lua/cokeline/components.lua
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
local Hlgroup = require("cokeline/hlgroups").Hlgroup

local rep = string.rep
local concat = table.concat
local insert = table.insert
local remove = table.remove

local fold = require("cokeline.utils").fold
local iter = require("plenary.iterators").iter
local fn = vim.fn
local map = vim.tbl_map

---@generic Cx
---@class Component<Cx>
Expand Down Expand Up @@ -162,11 +162,9 @@ end
---@param components Component[]
---@return number
local width_of_components = function(components)
local width = 0
for _, component in pairs(components) do
width = width + component.width
end
return width
return fold(iter(components), 0, function(a, c)
return a + c.width
end)
end

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

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

return concat(map(function(component)
return embed(component)
end, components))
end
local concat = function(a, b)
return a .. b
end

return fold(iter(components):map(embed), "", concat)
end

return {
Component = Component,
Expand Down
24 changes: 14 additions & 10 deletions lua/cokeline/hover.lua
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ local version = vim.version()
local buffers = require("cokeline.buffers")
local tabs = require("cokeline.tabs")
local rendering = require("cokeline.rendering")
local iter = require("plenary.iterators").iter
local fold = require("cokeline.utils").fold
local last_position = nil

function M.hovered()
Expand Down Expand Up @@ -183,17 +185,19 @@ local function on_hover(current)
end

local function width(bufs, buf)
return vim
.iter(bufs)
:filter(function(v)
return v.bufnr == buf
end)
:map(function(v)
return v.width
end)
:fold(0, function(acc, v)
return fold(
iter(bufs)
:filter(function(v)
return v.bufnr == buf
end)
:map(function(v)
return v.width
end),
0,
function(acc, v)
return acc + v
end)
end
)
end

local function start_pos(bufs, buf)
Expand Down
7 changes: 7 additions & 0 deletions lua/cokeline/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,13 @@ _G.cokeline = {
--@param preferences table|nil
---@param preferences Component<TabPage>
local setup = function(preferences)
local ok, _ = pcall(require, "plenary")
if not ok then
vim.api.nvim_err_writeln(
"nvim-cokeline: plenary.nvim is required to use this plugin as of v0.4.0"
)
return
end
_G.cokeline.config = config.get(preferences or {})
if _G.cokeline.config.history.enabled then
history.setup(_G.cokeline.config.history.size)
Expand Down
6 changes: 3 additions & 3 deletions lua/cokeline/rendering.lua
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@ local sidebar = require("cokeline/sidebar")
local rhs = require("cokeline/rhs")
local tabs = require("cokeline.tabs")
local RenderContext = require("cokeline/context")
local iter = require("plenary.iterators").iter

local insert = table.insert
local sort = table.sort
local unpack = unpack or table.unpack

local extend = vim.list_extend
local filter = vim.tbl_filter
local o = vim.o

---@type index
Expand All @@ -19,9 +19,9 @@ local current_index
---@param previous_buffer_index index
---@return Buffer
local find_current_buffer = function(buffers, previous_buffer_index)
local focused_buffer = filter(function(buffer)
local focused_buffer = iter(buffers):find(function(buffer)
return buffer.is_focused
end, buffers)[1]
end)

return focused_buffer or buffers[previous_buffer_index] or buffers[#buffers]
end
Expand Down
17 changes: 17 additions & 0 deletions lua/cokeline/utils.lua
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,24 @@ local function buf_delete(bufnr, focus, wipeout)
end
end

local fold = function(iterable, acc, f)
iterable:for_each(function(v)
acc = f(acc, v)
end)
return acc
end

local enumerate = function(iterable)
local i = 0
return iterable:map(function(...)
i = i + 1
return i, ...
end)
end

return {
get_hex = get_hex,
buf_delete = buf_delete,
fold = fold,
enumerate = enumerate,
}