mirror of
https://github.com/neovim/neovim.git
synced 2026-02-18 01:18:34 +00:00
feat(lua): add ringbuffer (#22894)
https://en.wikipedia.org/wiki/Circular_buffer
This commit is contained in:
committed by
GitHub
parent
38b0bb3c93
commit
7c661207cc
@@ -881,4 +881,98 @@ function vim.defaulttable(create)
|
||||
})
|
||||
end
|
||||
|
||||
do
|
||||
---@class vim.Ringbuf<T>
|
||||
---@field private _items table[]
|
||||
---@field private _idx_read integer
|
||||
---@field private _idx_write integer
|
||||
---@field private _size integer
|
||||
local Ringbuf = {}
|
||||
|
||||
--- Clear all items
|
||||
function Ringbuf.clear(self)
|
||||
self._items = {}
|
||||
self._idx_read = 0
|
||||
self._idx_write = 0
|
||||
end
|
||||
|
||||
--- Adds an item, overriding the oldest item if the buffer is full.
|
||||
---@generic T
|
||||
---@param item T
|
||||
function Ringbuf.push(self, item)
|
||||
self._items[self._idx_write] = item
|
||||
self._idx_write = (self._idx_write + 1) % self._size
|
||||
if self._idx_write == self._idx_read then
|
||||
self._idx_read = (self._idx_read + 1) % self._size
|
||||
end
|
||||
end
|
||||
|
||||
--- Removes and returns the first unread item
|
||||
---@generic T
|
||||
---@return T?
|
||||
function Ringbuf.pop(self)
|
||||
local idx_read = self._idx_read
|
||||
if idx_read == self._idx_write then
|
||||
return nil
|
||||
end
|
||||
local item = self._items[idx_read]
|
||||
self._items[idx_read] = nil
|
||||
self._idx_read = (idx_read + 1) % self._size
|
||||
return item
|
||||
end
|
||||
|
||||
--- Returns the first unread item without removing it
|
||||
---@generic T
|
||||
---@return T?
|
||||
function Ringbuf.peek(self)
|
||||
if self._idx_read == self._idx_write then
|
||||
return nil
|
||||
end
|
||||
return self._items[self._idx_read]
|
||||
end
|
||||
|
||||
--- Create a ring buffer limited to a maximal number of items.
|
||||
--- Once the buffer is full, adding a new entry overrides the oldest entry.
|
||||
---
|
||||
--- <pre>
|
||||
--- local ringbuf = vim.ringbuf(4)
|
||||
--- ringbuf:push("a")
|
||||
--- ringbuf:push("b")
|
||||
--- ringbuf:push("c")
|
||||
--- ringbuf:push("d")
|
||||
--- ringbuf:push("e") -- overrides "a"
|
||||
--- print(ringbuf:pop()) -- returns "b"
|
||||
--- print(ringbuf:pop()) -- returns "c"
|
||||
---
|
||||
--- -- Can be used as iterator. Pops remaining items:
|
||||
--- for val in ringbuf do
|
||||
--- print(val)
|
||||
--- end
|
||||
--- </pre>
|
||||
---
|
||||
--- Returns a Ringbuf instance with the following methods:
|
||||
---
|
||||
--- - |Ringbuf:push()|
|
||||
--- - |Ringbuf:pop()|
|
||||
--- - |Ringbuf:peek()|
|
||||
--- - |Ringbuf:clear()|
|
||||
---
|
||||
---@param size integer
|
||||
---@return vim.Ringbuf ringbuf (table)
|
||||
function vim.ringbuf(size)
|
||||
local ringbuf = {
|
||||
_items = {},
|
||||
_size = size + 1,
|
||||
_idx_read = 0,
|
||||
_idx_write = 0,
|
||||
}
|
||||
return setmetatable(ringbuf, {
|
||||
__index = Ringbuf,
|
||||
__call = function(self)
|
||||
return self:pop()
|
||||
end,
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
return vim
|
||||
|
||||
Reference in New Issue
Block a user