diff --git a/README.md b/README.md index c60db66..bff7f71 100644 --- a/README.md +++ b/README.md @@ -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 } @@ -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 }) -- ... @@ -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' " ... diff --git a/lua/cokeline/buffers.lua b/lua/cokeline/buffers.lua index a22c44c..a6748b4 100644 --- a/lua/cokeline/buffers.lua +++ b/lua/cokeline/buffers.lua @@ -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 @@ -49,29 +50,27 @@ local M = {} local Buffer = {} Buffer.__index = Buffer ----@param buffers Buffer[] ----@return Buffer[] +---@param buffers Iter +---@return Iter 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 @@ -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 @@ -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 + 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 + 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 @@ -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 diff --git a/lua/cokeline/components.lua b/lua/cokeline/components.lua index 6bbadc3..9cefed7 100644 --- a/lua/cokeline/components.lua +++ b/lua/cokeline/components.lua @@ -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 @@ -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 @@ -177,10 +175,7 @@ end ---@param direction '"left"' | '"right"' | nil ---@return Component[] 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 @@ -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, diff --git a/lua/cokeline/hover.lua b/lua/cokeline/hover.lua index cce906f..2ff6837 100644 --- a/lua/cokeline/hover.lua +++ b/lua/cokeline/hover.lua @@ -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() @@ -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) diff --git a/lua/cokeline/init.lua b/lua/cokeline/init.lua index 60dabfd..a351acd 100644 --- a/lua/cokeline/init.lua +++ b/lua/cokeline/init.lua @@ -55,6 +55,13 @@ _G.cokeline = { --@param preferences table|nil ---@param preferences Component 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) diff --git a/lua/cokeline/rendering.lua b/lua/cokeline/rendering.lua index 43b8573..2d6bd6d 100644 --- a/lua/cokeline/rendering.lua +++ b/lua/cokeline/rendering.lua @@ -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 @@ -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 diff --git a/lua/cokeline/utils.lua b/lua/cokeline/utils.lua index 8d4fd76..2def0d8 100644 --- a/lua/cokeline/utils.lua +++ b/lua/cokeline/utils.lua @@ -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, }