Skip to content
Open
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
62 changes: 16 additions & 46 deletions lua/tirenvi/core/attr.lua
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
local CONST = require("tirenvi.constants")
local Cell = require("tirenvi.core.cell")
local log = require("tirenvi.util.log")

Expand Down Expand Up @@ -48,28 +47,6 @@ local function new_from_columns(columns)
return { columns = columns }
end

---@param records Record_grid[]
---@return Attr
local function new_merged_attr(records)
local attr = M.grid.new()
for _, record in ipairs(records) do
merge(attr, M.grid.new_from_record(record))
end
return attr
end

---@self Attr
---@param source Attr
local function extend(self, source)
if #self.columns == 0 then
self.columns = source.columns
else
for index, column in ipairs(self.columns) do
column.width = column.width or source.columns[index].width
end
end
end

-----------------------------------------------------------------------
-- Public API
-----------------------------------------------------------------------
Expand Down Expand Up @@ -119,41 +96,34 @@ end
---@return Attr
function M.grid.new(record)
if record then
return M.grid.new_from_record(record)
return M.grid.new_from_record(record.row)
else
return new_from_columns({})
end
end

---@param record Record_grid
---@param cells Cell[]
---@return Attr
function M.grid.new_from_record(record)
return new_from_columns(get_columns(record.row))
function M.grid.new_from_record(cells)
return new_from_columns(get_columns(cells))
end

---@self Attr
---@param records Record_grid[]
function M.grid:extend(records)
extend(self, new_merged_attr(records))
---@return Attr
function M.grid.new_merged_attr(records)
local attr = M.grid.new()
for _, record in ipairs(records) do
merge(attr, M.grid.new_from_record(record.row))
end
return attr
end

---@self Attr
---@return boolean
function M.grid:has_all()
if not self or self.kind ~= CONST.KIND.ATTR_GRID then
return false
end
local cols = self.columns
if not cols or #cols == 0 then
return false
end
for index = 1, #cols do
local col = cols[index]
if not col or not col.width or not col.align then
return false
end
end
return true
---@param icol integer
---@param width integer
function M.grid:set_width(icol, width)
self.columns[icol] = self.columns[icol] or {}
self.columns[icol].width = math.max(width, 1)
end

return M
172 changes: 108 additions & 64 deletions lua/tirenvi/core/block.lua
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
local CONST = require("tirenvi.constants")
local Record = require("tirenvi.core.record")
local Cell = require("tirenvi.core.cell")
local config = require("tirenvi.config")
local Attr = require("tirenvi.core.attr")
local util = require("tirenvi.util.util")
Expand All @@ -12,20 +11,32 @@ M.grid = {}

-- constants / defaults

---@param map {[string]: string}
---@return {[string]: string}
local function prepare_replace_map(map)
local out = {}
for key, value in pairs(map) do
out[vim.pesc(key)] = value
end
return out
end

local ESCAPE_MAP = prepare_replace_map({
["\n"] = config.marks.lf,
["\t"] = config.marks.tab,
})

local UNESCAPE_MAP = prepare_replace_map({
[config.marks.lf] = "\n",
[config.marks.tab] = "\t",
})

-----------------------------------------------------------------------
-- Private helpers
-----------------------------------------------------------------------

local function nop(...) end

---@self Block_grid
local function reset_master_attr(self)
if Attr.grid.has_all(self.attr) then
return
end
Attr.grid.extend(self.attr, self.records)
end

---@self Block
---@param kind Block_kind
local function initialize(self, kind)
Expand All @@ -45,16 +56,25 @@ local function serialize_records(self)
end

---@param self Block_grid
local function split_lf(self)
local function wrap_lf(self)
local records = {}
for _, record in ipairs(self.records) do
util.extend(records, Record.grid.wrap_lf(record))
end
self.records = records
end

---@param self Block_grid
local function wrap_width(self)
local records = {}
for _, record in ipairs(self.records) do
util.extend(records, Record.grid.split_lf(record))
util.extend(records, Record.grid.wrap_width(record, self.attr.columns))
end
self.records = records
end

---@param self Block_grid
local function fill_padding(self)
local function apply_column_widths(self)
for _, record in ipairs(self.records) do
Record.grid.fill_padding(record, self.attr.columns)
end
Expand All @@ -68,23 +88,62 @@ local function remove_padding(self)
end

---@self Block_grid
local function concat_record(self)
local function unwrap(self)
local records = {}
---@type Record_grid
local new_record = nil
local cont = false
local cont_prev = false
for _, record in ipairs(self.records) do
if not cont then
if not cont_prev then
new_record = Record.grid.new(record.row)
records[#records + 1] = new_record
else
Record.grid.concat(new_record, record)
end
cont = record._has_continuation
cont_prev = record._has_continuation
new_record._has_continuation = cont_prev
end
self.records = records
end

--- Normalize all rows in a grid block to have the same number of columns.
---@self Block_grid
local function apply_column_count(self, ncol)
for _, record in ipairs(self.records) do
Record.apply_column_count(record, ncol)
end
end

local function derive_column_count(self)
local ncol = 0
for _, record in ipairs(self.records) do
ncol = math.max(ncol, #record.row)
end
return ncol
end

---@self Block
local function ensure_table_attr(self)
if #self.attr.columns == 0 then
self.attr = Attr.grid.new_merged_attr(self.records)
end
end

---@self Block
---@self Block_grid
---@param replace {[string]:string}
local function apply_replacements(self, replace)
for _, record in ipairs(self.records) do
assert(record.kind == CONST.KIND.GRID, "unexpected record kind")
for icol, cell in ipairs(record.row) do
for key, val in pairs(replace) do
cell = cell:gsub(key, val)
end
record.row[icol] = cell
end
end
end

-----------------------------------------------------------------------
-- Public API
-----------------------------------------------------------------------
Expand Down Expand Up @@ -128,13 +187,6 @@ function M.plain:serialize()
return serialize_records(self)
end

M.plain.normalize = nop
M.plain.to_vim = nop
M.plain.apply_replacements = nop
M.plain.from_vim = nop
M.plain.set_attr = nop
M.plain.set_attr_from_vi = nop

---@self Block_plain
---@return Block_grid
function M.plain:to_grid()
Expand All @@ -147,70 +199,62 @@ function M.plain:to_grid()
return block
end

M.plain.set_attr = nop
M.plain.from_flat = nop
M.plain.to_flat = nop
M.plain.from_vim = nop
M.plain.to_vim = nop

---@self Block_grid
---@return Ndjson[]
function M.grid:serialize()
return serialize_records(self)
end

--- Normalize all rows in a grid block to have the same number of columns.
---@self Block_grid
function M.grid:normalize()
reset_master_attr(self)
local ncol = #self.attr.columns
for _, record in ipairs(self.records) do
Record.normalize_and_resize(record, ncol)
---@return Block_grid
function M.grid:to_grid()
return self
end

---@self Block
---@param attr Attr|nil
function M.grid:set_attr(attr)
if not attr or Attr.is_plain(attr) then
return
end
self.attr = attr
end

--- Normalize all rows in a grid block to have the same number of columns.
---@self Block_grid
function M.grid:to_vim()
split_lf(self)
fill_padding(self)
function M.grid:from_flat()
local ncol = derive_column_count(self)
apply_column_count(self, ncol)
apply_replacements(self, ESCAPE_MAP)
end

---@self Block_grid
---@param replace {[string]:string}
function M.grid:apply_replacements(replace)
for _, record in ipairs(self.records) do
assert(record.kind == CONST.KIND.GRID, "unexpected record kind")
for icol, cell in ipairs(record.row) do
for key, val in pairs(replace) do
cell = cell:gsub(key, val)
end
record.row[icol] = cell
end
end
function M.grid:to_flat()
apply_replacements(self, UNESCAPE_MAP)
end

---@self Block_grid
function M.grid:from_vim()
ensure_table_attr(self)
remove_padding(self)
concat_record(self)
apply_column_count(self, #self.attr.columns)
unwrap(self)
end

--- Normalize all rows in a grid block to have the same number of columns.
---@self Block_grid
---@return Block_grid
function M.grid:to_grid()
return self
end

---@self Block
---@param attr Attr|nil
function M.grid:set_attr(attr)
if not attr or Attr.is_plain(attr) then
return
end
self.attr = attr
end

---@self Block
function M.grid:set_attr_from_vi()
if #self.records == 0 then
return
end
self.attr = Attr.grid.new_from_record(self.records[1])
function M.grid:to_vim()
wrap_lf(self)
ensure_table_attr(self)
apply_column_count(self, #self.attr.columns)
wrap_width(self)
apply_column_widths(self)
end

return M
Loading
Loading