mirror of
https://github.com/Refactorio/RedMew.git
synced 2025-11-23 22:35:38 +02:00
158 lines
4.6 KiB
Lua
158 lines
4.6 KiB
Lua
---@class History
|
|
--- A class that manages a history buffer with undo/redo capabilities.
|
|
local History = {}
|
|
History.__index = History
|
|
|
|
script.register_metatable('RedMew_HistoryClass', History)
|
|
|
|
local DEFAULT_SIZE = 100
|
|
local math_min = math.min
|
|
local math_max = math.max
|
|
local insert = table.insert
|
|
local remove = table.remove
|
|
|
|
--- Creates a new History instance.
|
|
---@param size number? Optional maximum size of the history buffer. Defaults to 100 if not provided or invalid.
|
|
---@return History
|
|
function History.new(size)
|
|
return setmetatable({
|
|
buffer = {}, -- Table storing the history elements
|
|
index = 0, -- Current position in the history buffer
|
|
max_size = (size and size > 0 or DEFAULT_SIZE) -- Max number of items to store
|
|
}, History)
|
|
end
|
|
|
|
--- Keeps only the elements within the specified range [left, right].
|
|
---@param self History The history object.
|
|
---@param left number The starting index of the range (1-based).
|
|
---@param right number The ending index of the range (1-based).
|
|
local function range(self, left, right)
|
|
local result = {}
|
|
local len = #self.buffer
|
|
|
|
left = math_max(1, left)
|
|
right = math_min(right, len)
|
|
|
|
for i = left, right do
|
|
insert(result, self.buffer[i])
|
|
end
|
|
|
|
self.buffer = result
|
|
|
|
if self.index > #self.buffer then
|
|
self.index = #self.buffer
|
|
end
|
|
end
|
|
|
|
--- Returns the current size of the history buffer.
|
|
---@param self History The history object.
|
|
---@return number
|
|
function History:size()
|
|
return #self.buffer
|
|
end
|
|
|
|
--- ADD a new element to the history buffer.
|
|
--- If the current position is not at the end, discards all "redo" states.
|
|
--- Ensures the buffer does not exceed max_size by trimming oldest entries.
|
|
---@param self History The history object.
|
|
---@param element any The element to add. Nil elements are ignored.
|
|
function History:add(element)
|
|
if element == nil then
|
|
return
|
|
end
|
|
|
|
if self.index ~= #self.buffer then
|
|
range(self, 1, self.index)
|
|
end
|
|
|
|
insert(self.buffer, element)
|
|
self.index = #self.buffer
|
|
|
|
if #self.buffer > self.max_size then
|
|
range(self, 1 + #self.buffer - self.max_size, #self.buffer)
|
|
end
|
|
end
|
|
|
|
--- REMOVE the element at the specified index.
|
|
---@param self History The history object.
|
|
---@param index number? Optional index to remove; defaults to current index.
|
|
function History:remove(index)
|
|
if index == nil then
|
|
index = self.index
|
|
end
|
|
if not self.buffer[index] then
|
|
return
|
|
end
|
|
-- Adjust index if removing current or previous
|
|
if self.index >= index then
|
|
self.index = self.index - 1
|
|
end
|
|
remove(self.buffer, index)
|
|
end
|
|
|
|
--- GET the element at the specified index.
|
|
--- If no index is provided, returns the current element.
|
|
---@param self History The history object.
|
|
---@param index number? Optional index to retrieve; defaults to current index.
|
|
---@return any
|
|
function History:get(index)
|
|
if index == nil then
|
|
index = self.index
|
|
end
|
|
return self.buffer[index]
|
|
end
|
|
|
|
--- GET the current position index in the history buffer.
|
|
---@param self History The history object.
|
|
---@return number The current index.
|
|
function History:get_index()
|
|
return self.index
|
|
end
|
|
|
|
--- GET the previous element in the history without changing the current index.
|
|
---@param self History The history object.
|
|
---@return any|nil The previous element or nil if none exists.
|
|
function History:peek_previous()
|
|
return self.buffer[self.index - 1]
|
|
end
|
|
|
|
--- GET the next element in the history without changing the current index.
|
|
---@param self History The history object.
|
|
---@return any|nil The next element or nil if none exists.
|
|
function History:peek_next()
|
|
return self.buffer[self.index + 1]
|
|
end
|
|
|
|
--- MOVE to the previous history element, if possible.
|
|
--- Updates the current index and returns the element.
|
|
---@param self History The history object.
|
|
---@return any|nil The previous element, or nil if at the beginning.
|
|
function History:previous()
|
|
if not self.buffer[self.index - 1] then
|
|
return nil
|
|
end
|
|
self.index = self.index - 1
|
|
return self.buffer[self.index]
|
|
end
|
|
|
|
--- MOVE to the next history element, if possible.
|
|
--- Updates the current index and returns the element.
|
|
---@param self History The history object.
|
|
---@return any|nil The next element, or nil if at the latest.
|
|
function History:next()
|
|
if not self.buffer[self.index + 1] then
|
|
return nil
|
|
end
|
|
self.index = self.index + 1
|
|
return self.buffer[self.index]
|
|
end
|
|
|
|
--- CLEAR the entire history buffer and resets the current index.
|
|
---@param self History The history object.
|
|
function History:clear()
|
|
self.buffer = {}
|
|
self.index = 0
|
|
end
|
|
|
|
return History
|