Skip to content

Commit

Permalink
feat(lib): add 'ringbuf' (#18)
Browse files Browse the repository at this point in the history
feat(lib): add 'buf_options' (#18)

feat(lib): add 'win_options' (#18)
  • Loading branch information
linrongbin16 authored Dec 12, 2023
1 parent 5838476 commit 2124d6e
Show file tree
Hide file tree
Showing 8 changed files with 622 additions and 1 deletion.
63 changes: 62 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,15 @@ The commons lua library for Neovim plugin project.
- [Embed Source Code](#embed-source-code)
- [Usage](#usage)
- [Modules](#modules)
- [commons.buf_options](#commonsbuf_options)
- [commons.fileios](#commonsfileios)
- [commons.jsons](#commonsjsons)
- [commons.numbers](#commonsnumbers)
- [commons.ringbuf](#commonsringbuf)
- [commons.strings](#commonsstrings)
- [commons.termcolors](#commonstermcolors)
- [commons.uv](#commonsuv)
- [commons.win_options](#commonswin_options)
- [Development](#development)
- [Contribute](#contribute)

Expand Down Expand Up @@ -134,6 +137,13 @@ local jsons = require("your.plugin.commons.jsons")

## Modules

### [commons.buf_options](/lua/commons/buf_options.lua)

Compatible Neovim buffer relate APIs.

- `get_buf_option(bufnr:integer, name:string):any`: get `bufnr` buffer option.
- `set_buf_option(bufnr:integer, name:string, value:any):any`: set `bufnr` buffer option value.

### [commons.fileios](/lua/commons/fileios.lua)

File (sync/async) IO operations.
Expand All @@ -159,16 +169,60 @@ Use [actboy168/json.lua](https://github.com/actboy168/json.lua) for Neovim <

### [commons.numbers](/lua/commons/numbers.lua)

Numbers utilities.

- `INT32_MIN`/`INT32_MAX`: 32 bit integer max/min value.
- `eq(a:number?, b:number?):boolean`/`ne(a:number?, b:number?):boolean`: Whether `a` and `b` are equal or not.
- `lt(a:number?, b:number?):boolean`/`le(a:number?, b:number?):boolean`: Whether `a` is less than (or less equal to) `b` or not.
- `gt(a:number?, b:number?):boolean`/`ge(a:number?, b:number?):boolean`: Whether `a` is greater than (or greater equal to) `b` or not.
- `bound(value:number?, left:number?, right:numbers?):number`: Returns the bounded `value` by the max value `right` and min value `left`, e.g. when `value < left` returns `left`, when `value > right` returns `right`.
- `auto_incremental_id():integer`: Returns auto-incremental ID, start from `1`.

### [commons.ringbuf](/lua/commons/ringbuf.lua)

Drop-in replacement **Ring Buffer** data structure with iterator support.

- `RingBuffer`:

- `new(maxsize:integer):RingBuffer`: Create new ring buffer data structure with fixed list size.
- `push(item:any):integer`: Push new `item` into ring buffer. Returns new added item index.
- `pop():any`: Pop out latest added `item` from ring buffer. Returns the latest added item.
- `peek():any`: Get latest added `item` without remove it from ring buffer. Returns the latest added item.
- `clear():any`: Clear whole ring buffer. Returns the previous items count.
- `iterator():_RingBufferIterator`: Returns iterator (from oldest to latest).
- `riterator():_RingBufferRIterator`: Returns reverse iterator (from latest to oldest).

- `_RingBufferIterator`:

- `has_next():boolean`: Whether has next item in ring buffer.
- `next():any`: Returns next item in ring buffer, returns `nil` if there's no more items. For example:

```lua
local ringbuf = require("commons.ringbuf").RingBuffer:new()
local iter = ringbuf:iterator()
while iter:has_next() do
local item = iter:next()
-- consume item
end
```

- `_RingBufferRIterator`:

- `has_next():boolean`: Whether has next item in ring buffer.
- `next():any`: Returns next item in ring buffer, returns `nil` if there's no more items. For example:

```lua
local ringbuf = require("commons.ringbuf").RingBuffer:new()
local riter = ringbuf:riterator()
while iter:has_next() do
local item = iter:next()
-- consume item
end
```

### [commons.strings](/lua/commons/strings.lua)

String manipulation utilities.
String utilities.

- `empty(s:string?):boolean`/`not_empty(s:string?):boolean`: Whether string `s` is empty or not.
- `blank(s:string?):boolean`/`not_blank(s:string?):boolean`: Whether (trimed) string `s` is blank or not.
Expand Down Expand Up @@ -231,6 +285,13 @@ And some other APIs:

Use [vim.loop](https://github.com/neovim/neovim/blob/a9fbba81d5d4562a2d2b2cbb41d73f1de83d3102/runtime/doc/deprecated.txt?plain=1#L166) for Neovim &lt; 0.10, [vim.uv](https://github.com/neovim/neovim/blob/a9fbba81d5d4562a2d2b2cbb41d73f1de83d3102/runtime/doc/news.txt?plain=1#L345) for Neovim &ge; 0.10.

### [commons.win_options](/lua/commons/win_options.lua)

Compatible Neovim window relate APIs.

- `get_win_option(winnr:integer, name:string):any`: get `winnr` window option.
- `set_win_option(winnr:integer, name:string, value:any):any`: set `winnr` window option value.

## Development

Setup the plugin development with:
Expand Down
28 changes: 28 additions & 0 deletions lua/commons/buf_options.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
-- Compatible Neovim buffer related API

local M = {}

--- @param bufnr integer
--- @param name string
--- @return any
M.get_buf_option = function(bufnr, name)
if vim.fn.has("nvim-0.8") > 0 then
return vim.api.nvim_get_option_value(name, { buf = bufnr })
else
return vim.api.nvim_buf_get_option(bufnr, name)
end
end

--- @param bufnr integer
--- @param name string
--- @param value any
--- @return any
M.set_buf_option = function(bufnr, name, value)
if vim.fn.has("nvim-0.8") > 0 then
return vim.api.nvim_set_option_value(name, value, { buf = bufnr })
else
return vim.api.nvim_buf_set_option(bufnr, name, value)
end
end

return M
Empty file added lua/commons/fork.lua
Empty file.
229 changes: 229 additions & 0 deletions lua/commons/ringbuf.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,229 @@
-- Drop-in replacement 'RingBuffer' data structure

local M = {}

--- @class commons.RingBuffer
--- @field pos integer
--- @field queue any[]
--- @field size integer
--- @field maxsize integer
local RingBuffer = {}

--- @param maxsize integer?
--- @return commons.RingBuffer
function RingBuffer:new(maxsize)
assert(type(maxsize) == "number" and maxsize > 0)
local o = {
pos = 0,
queue = {},
size = 0,
maxsize = maxsize,
}
setmetatable(o, self)
self.__index = self
return o
end

--- @param idx integer
--- @return integer
function RingBuffer:_inc(idx)
if idx == self.maxsize then
return 1
else
return idx + 1
end
end

--- @param idx integer
--- @return integer
function RingBuffer:_dec(idx)
if idx == 1 then
return self.maxsize
else
return idx - 1
end
end

--- @param item any
--- @return integer
function RingBuffer:push(item)
assert(self.size >= 0 and self.size <= self.maxsize)

if self.size < self.maxsize then
table.insert(self.queue, item)
self.pos = self:_inc(self.pos)
self.size = self.size + 1
else
self.pos = self:_inc(self.pos)
self.queue[self.pos] = item
end
return self.pos
end

--- @return any?
function RingBuffer:pop()
if self.size <= 0 then
return nil
end

local old = self.queue[self.pos]
self.queue[self.pos] = nil
self.size = self.size - 1
self.pos = self:_dec(self.pos)
return old
end

--- @return any?
function RingBuffer:peek()
if self.size <= 0 then
return nil
end
return self.queue[self.pos]
end

--- @return integer
function RingBuffer:clear()
local old = self.size
self.pos = 0
self.queue = {}
self.size = 0
return old
end

-- RingBufferIterator {

-- usage:
--
-- ```lua
-- local it = ringbuf:iterator()
-- local item = nil
-- repeat
-- item = it:next()
-- if item then
-- -- consume item data
-- end
-- until item
-- ```
--
--- @class commons._RingBufferIterator
--- @field ringbuf commons.RingBuffer
--- @field index integer
--- @field initial_index integer
local _RingBufferIterator = {}

--- @param ringbuf commons.RingBuffer
--- @param index integer
--- @return commons._RingBufferIterator
function _RingBufferIterator:new(ringbuf, index)
assert(type(ringbuf) == "table")

local o = {
ringbuf = ringbuf,
index = index,
initial_index = index,
}
setmetatable(o, self)
self.__index = self
return o
end

--- @return boolean
function _RingBufferIterator:has_next()
if self.ringbuf.size == 0 then
return false
end
if self.index <= 0 or self.index > self.ringbuf.size then
return false
end
if
self.index ~= self.initial_index
and self.ringbuf:_inc(self.index) == self.initial_index
then
return false
end

return true
end

--- @return any?
function _RingBufferIterator:next()
assert(self:has_next())
assert(self.index >= 1 and self.index <= self.ringbuf.maxsize)
local item = self.ringbuf.queue[self.index]
self.index = self.ringbuf:_inc(self.index)
return item
end

-- RingBufferIterator }

-- RingBufferRIterator {

--- @class commons._RingBufferRIterator
--- @field ringbuf commons.RingBuffer
--- @field index integer
--- @field initial_index integer
local _RingBufferRIterator = {}

--- @param ringbuf commons.RingBuffer
--- @param index integer
--- @return commons._RingBufferRIterator
function _RingBufferRIterator:new(ringbuf, index)
assert(type(ringbuf) == "table")

local o = {
ringbuf = ringbuf,
index = index,
initial_index = index,
}
setmetatable(o, self)
self.__index = self
return o
end

--- @return boolean
function _RingBufferRIterator:has_next()
if self.ringbuf.size == 0 then
return false
end
if self.index <= 0 or self.index > self.ringbuf.size then
return false
end
if
self.index ~= self.initial_index
and self.ringbuf:_dec(self.index) == self.initial_index
then
return false
end

return true
end

--- @return any?
function _RingBufferRIterator:next()
assert(self:has_next())
assert(self.index >= 1 and self.index <= self.ringbuf.maxsize)

local item = self.ringbuf.queue[self.index]
self.index = self.ringbuf:_dec(self.index)
return item
end

-- RingBufferRIterator }

--- @return commons._RingBufferIterator
function RingBuffer:iterator()
if self.size < self.maxsize then
return _RingBufferIterator:new(self, 0)
else
return _RingBufferIterator:new(self, self:_inc(self.pos))
end
end

--- @return commons._RingBufferRIterator
function RingBuffer:riterator()
return _RingBufferRIterator:new(self, self.pos)
end

M.RingBuffer = RingBuffer

return M
28 changes: 28 additions & 0 deletions lua/commons/win_options.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
-- Compatible Neovim window related API

local M = {}

--- @param winnr integer
--- @param name string
--- @return any
M.get_win_option = function(winnr, name)
if vim.fn.has("nvim-0.8") > 0 then
return vim.api.nvim_get_option_value(name, { win = winnr })
else
return vim.api.nvim_win_get_option(winnr, name)
end
end

--- @param winnr integer
--- @param name string
--- @param value any
--- @return any
M.set_win_option = function(winnr, name, value)
if vim.fn.has("nvim-0.8") > 0 then
return vim.api.nvim_set_option_value(name, value, { win = winnr })
else
return vim.api.nvim_win_set_option(winnr, name, value)
end
end

return M
Loading

0 comments on commit 2124d6e

Please sign in to comment.