mirror of
https://github.com/neovim/neovim.git
synced 2025-12-11 17:12:40 +00:00
ui: add tests for hlstate extension
This commit is contained in:
287
test/functional/ui/hlstate_spec.lua
Normal file
287
test/functional/ui/hlstate_spec.lua
Normal file
@@ -0,0 +1,287 @@
|
|||||||
|
local helpers = require('test.functional.helpers')(after_each)
|
||||||
|
local Screen = require('test.functional.ui.screen')
|
||||||
|
|
||||||
|
local clear, insert = helpers.clear, helpers.insert
|
||||||
|
local command = helpers.command
|
||||||
|
local meths = helpers.meths
|
||||||
|
local iswin = helpers.iswin
|
||||||
|
local nvim_dir = helpers.nvim_dir
|
||||||
|
local thelpers = require('test.functional.terminal.helpers')
|
||||||
|
|
||||||
|
describe('ext_hlstate detailed highlights', function()
|
||||||
|
local screen
|
||||||
|
|
||||||
|
before_each(function()
|
||||||
|
clear()
|
||||||
|
command('syntax on')
|
||||||
|
screen = Screen.new(40, 8)
|
||||||
|
screen:attach({ext_hlstate=true})
|
||||||
|
end)
|
||||||
|
|
||||||
|
after_each(function()
|
||||||
|
screen:detach()
|
||||||
|
end)
|
||||||
|
|
||||||
|
|
||||||
|
it('work with combined UI and syntax highlights', function()
|
||||||
|
insert([[
|
||||||
|
these are some lines
|
||||||
|
with colorful text]])
|
||||||
|
meths.buf_add_highlight(0, -1, "String", 0 , 10, 14)
|
||||||
|
meths.buf_add_highlight(0, -1, "Statement", 1 , 5, -1)
|
||||||
|
command("/th co")
|
||||||
|
|
||||||
|
screen:expect([[
|
||||||
|
these are {1:some} lines |
|
||||||
|
^wi{2:th }{4:co}{3:lorful text} |
|
||||||
|
{5:~ }|
|
||||||
|
{5:~ }|
|
||||||
|
{5:~ }|
|
||||||
|
{5:~ }|
|
||||||
|
{5:~ }|
|
||||||
|
{6:search hit BOTTOM, continuing at TOP} |
|
||||||
|
]], {
|
||||||
|
[1] = {{foreground = Screen.colors.Magenta},
|
||||||
|
{{hi_name = "Constant", kind = "syntax"}}},
|
||||||
|
[2] = {{background = Screen.colors.Yellow},
|
||||||
|
{{hi_name = "Search", ui_name = "Search", kind = "ui"}}},
|
||||||
|
[3] = {{bold = true, foreground = Screen.colors.Brown},
|
||||||
|
{{hi_name = "Statement", kind = "syntax"}}},
|
||||||
|
[4] = {{bold = true, background = Screen.colors.Yellow, foreground = Screen.colors.Brown}, {3, 2}},
|
||||||
|
[5] = {{bold = true, foreground = Screen.colors.Blue1},
|
||||||
|
{{hi_name = "NonText", ui_name = "EndOfBuffer", kind = "ui"}}},
|
||||||
|
[6] = {{foreground = Screen.colors.Red},
|
||||||
|
{{hi_name = "WarningMsg", ui_name = "WarningMsg", kind = "ui"}}},
|
||||||
|
})
|
||||||
|
end)
|
||||||
|
|
||||||
|
it('work with cleared UI highlights', function()
|
||||||
|
screen:set_default_attr_ids({
|
||||||
|
[1] = {{}, {{hi_name = "VertSplit", ui_name = "VertSplit", kind = "ui"}}},
|
||||||
|
[2] = {{bold = true, foreground = Screen.colors.Blue1},
|
||||||
|
{{hi_name = "NonText", ui_name = "EndOfBuffer", kind = "ui"}}},
|
||||||
|
[3] = {{bold = true, reverse = true},
|
||||||
|
{{hi_name = "StatusLine", ui_name = "StatusLine", kind = "ui"}}} ,
|
||||||
|
[4] = {{reverse = true},
|
||||||
|
{{hi_name = "StatusLineNC", ui_name = "StatusLineNC" , kind = "ui"}}},
|
||||||
|
[5] = {{}, {{hi_name = "StatusLine", ui_name = "StatusLine", kind = "ui"}}},
|
||||||
|
[6] = {{}, {{hi_name = "StatusLineNC", ui_name = "StatusLineNC", kind = "ui"}}},
|
||||||
|
})
|
||||||
|
command("hi clear VertSplit")
|
||||||
|
command("vsplit")
|
||||||
|
|
||||||
|
screen:expect([[
|
||||||
|
^ {1:│} |
|
||||||
|
{2:~ }{1:│}{2:~ }|
|
||||||
|
{2:~ }{1:│}{2:~ }|
|
||||||
|
{2:~ }{1:│}{2:~ }|
|
||||||
|
{2:~ }{1:│}{2:~ }|
|
||||||
|
{2:~ }{1:│}{2:~ }|
|
||||||
|
{3:[No Name] }{4:[No Name] }|
|
||||||
|
|
|
||||||
|
]])
|
||||||
|
|
||||||
|
command("hi clear StatusLine | hi clear StatuslineNC")
|
||||||
|
screen:expect([[
|
||||||
|
^ {1:│} |
|
||||||
|
{2:~ }{1:│}{2:~ }|
|
||||||
|
{2:~ }{1:│}{2:~ }|
|
||||||
|
{2:~ }{1:│}{2:~ }|
|
||||||
|
{2:~ }{1:│}{2:~ }|
|
||||||
|
{2:~ }{1:│}{2:~ }|
|
||||||
|
{5:[No Name] }{6:[No Name] }|
|
||||||
|
|
|
||||||
|
]])
|
||||||
|
|
||||||
|
-- redrawing is done even if visible highlights didn't change
|
||||||
|
command("wincmd w")
|
||||||
|
screen:expect([[
|
||||||
|
{1:│}^ |
|
||||||
|
{2:~ }{1:│}{2:~ }|
|
||||||
|
{2:~ }{1:│}{2:~ }|
|
||||||
|
{2:~ }{1:│}{2:~ }|
|
||||||
|
{2:~ }{1:│}{2:~ }|
|
||||||
|
{2:~ }{1:│}{2:~ }|
|
||||||
|
{6:[No Name] }{5:[No Name] }|
|
||||||
|
|
|
||||||
|
]])
|
||||||
|
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("work with window-local highlights", function()
|
||||||
|
screen:set_default_attr_ids({
|
||||||
|
[1] = {{foreground = Screen.colors.Brown}, {{hi_name = "LineNr", ui_name = "LineNr", kind = "ui"}}},
|
||||||
|
[2] = {{bold = true, foreground = Screen.colors.Blue1}, {{hi_name = "NonText", ui_name = "EndOfBuffer", kind = "ui"}}},
|
||||||
|
[3] = {{bold = true, reverse = true}, {{hi_name = "StatusLine", ui_name = "StatusLine", kind = "ui"}}},
|
||||||
|
[4] = {{reverse = true}, {{hi_name = "StatusLineNC", ui_name = "StatusLineNC", kind = "ui"}}},
|
||||||
|
[5] = {{background = Screen.colors.Red, foreground = Screen.colors.Grey100}, {{hi_name = "ErrorMsg", ui_name = "LineNr", kind = "ui"}}},
|
||||||
|
[6] = {{bold = true, reverse = true}, {{hi_name = "MsgSeparator", ui_name = "Normal", kind = "ui"}}},
|
||||||
|
[7] = {{foreground = Screen.colors.Brown, bold = true, reverse = true}, {6, 1}},
|
||||||
|
[8] = {{foreground = Screen.colors.Blue1, bold = true, reverse = true}, {6, 2}},
|
||||||
|
[9] = {{bold = true, foreground = Screen.colors.Brown}, {{hi_name = "Statement", ui_name = "NormalNC", kind = "ui"}}},
|
||||||
|
[10] = {{bold = true, foreground = Screen.colors.Brown}, {9, 1}},
|
||||||
|
[11] = {{bold = true, foreground = Screen.colors.Blue1}, {9, 2}}
|
||||||
|
})
|
||||||
|
|
||||||
|
command("set number")
|
||||||
|
command("split")
|
||||||
|
-- NormalNC is not applied if not set, to avoid spurious redraws
|
||||||
|
screen:expect([[
|
||||||
|
{1: 1 }^ |
|
||||||
|
{2:~ }|
|
||||||
|
{2:~ }|
|
||||||
|
{3:[No Name] }|
|
||||||
|
{1: 1 } |
|
||||||
|
{2:~ }|
|
||||||
|
{4:[No Name] }|
|
||||||
|
|
|
||||||
|
]])
|
||||||
|
|
||||||
|
command("set winhl=LineNr:ErrorMsg")
|
||||||
|
screen:expect([[
|
||||||
|
{5: 1 }^ |
|
||||||
|
{2:~ }|
|
||||||
|
{2:~ }|
|
||||||
|
{3:[No Name] }|
|
||||||
|
{1: 1 } |
|
||||||
|
{2:~ }|
|
||||||
|
{4:[No Name] }|
|
||||||
|
|
|
||||||
|
]])
|
||||||
|
|
||||||
|
command("set winhl=Normal:MsgSeparator,NormalNC:Statement")
|
||||||
|
screen:expect([[
|
||||||
|
{7: 1 }{6:^ }|
|
||||||
|
{8:~ }|
|
||||||
|
{8:~ }|
|
||||||
|
{3:[No Name] }|
|
||||||
|
{1: 1 } |
|
||||||
|
{2:~ }|
|
||||||
|
{4:[No Name] }|
|
||||||
|
|
|
||||||
|
]])
|
||||||
|
|
||||||
|
command("wincmd w")
|
||||||
|
screen:expect([[
|
||||||
|
{10: 1 }{9: }|
|
||||||
|
{11:~ }|
|
||||||
|
{11:~ }|
|
||||||
|
{4:[No Name] }|
|
||||||
|
{1: 1 }^ |
|
||||||
|
{2:~ }|
|
||||||
|
{3:[No Name] }|
|
||||||
|
|
|
||||||
|
]])
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("work with :terminal", function()
|
||||||
|
screen:set_default_attr_ids({
|
||||||
|
[1] = {{}, {{hi_name = "TermCursorNC", ui_name = "TermCursorNC", kind = "ui"}}},
|
||||||
|
[2] = {{special = Screen.colors.Grey0, foreground = 52479}, {{kind = "term"}}},
|
||||||
|
[3] = {{special = Screen.colors.Grey0, bold = true, foreground = 52479}, {{kind = "term"}}},
|
||||||
|
[4] = {{special = Screen.colors.Grey0, foreground = 52479}, {2, 1}},
|
||||||
|
[5] = {{special = Screen.colors.Grey0, foreground = 4259839}, {{kind = "term"}}},
|
||||||
|
[6] = {{special = Screen.colors.Grey0, foreground = 4259839}, {5, 1}},
|
||||||
|
})
|
||||||
|
command('enew | call termopen(["'..nvim_dir..'/tty-test"])')
|
||||||
|
screen:expect([[
|
||||||
|
^tty ready |
|
||||||
|
{1: } |
|
||||||
|
|
|
||||||
|
|
|
||||||
|
|
|
||||||
|
|
|
||||||
|
|
|
||||||
|
|
|
||||||
|
]])
|
||||||
|
|
||||||
|
thelpers.feed_data('x ')
|
||||||
|
thelpers.set_fg(45)
|
||||||
|
thelpers.feed_data('y ')
|
||||||
|
thelpers.set_bold()
|
||||||
|
thelpers.feed_data('z\n')
|
||||||
|
-- TODO(bfredl): check if this distinction makes sense
|
||||||
|
if iswin() then
|
||||||
|
screen:expect([[
|
||||||
|
^tty ready |
|
||||||
|
x {5:y z} |
|
||||||
|
{1: } |
|
||||||
|
|
|
||||||
|
|
|
||||||
|
|
|
||||||
|
|
|
||||||
|
|
|
||||||
|
]])
|
||||||
|
else
|
||||||
|
screen:expect([[
|
||||||
|
^tty ready |
|
||||||
|
x {2:y }{3:z} |
|
||||||
|
{1: } |
|
||||||
|
|
|
||||||
|
|
|
||||||
|
|
|
||||||
|
|
|
||||||
|
|
|
||||||
|
]])
|
||||||
|
end
|
||||||
|
|
||||||
|
thelpers.feed_termcode("[A")
|
||||||
|
thelpers.feed_termcode("[2C")
|
||||||
|
if iswin() then
|
||||||
|
screen:expect([[
|
||||||
|
^tty ready |
|
||||||
|
x {6:y}{5: z} |
|
||||||
|
|
|
||||||
|
|
|
||||||
|
|
|
||||||
|
|
|
||||||
|
|
|
||||||
|
|
|
||||||
|
]])
|
||||||
|
else
|
||||||
|
screen:expect([[
|
||||||
|
^tty ready |
|
||||||
|
x {4:y}{2: }{3:z} |
|
||||||
|
|
|
||||||
|
|
|
||||||
|
|
|
||||||
|
|
|
||||||
|
|
|
||||||
|
|
|
||||||
|
]])
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("can use independent cterm and rgb colors", function()
|
||||||
|
-- tell test module to save all attributes (doesn't change nvim options)
|
||||||
|
screen:set_hlstate_cterm(true)
|
||||||
|
|
||||||
|
screen:set_default_attr_ids({
|
||||||
|
[1] = {{bold = true, foreground = Screen.colors.Blue1}, {foreground = 12}, {{hi_name = "NonText", ui_name = "EndOfBuffer", kind = "ui"}}},
|
||||||
|
[2] = {{reverse = true, foreground = Screen.colors.Red}, {foreground = 10, italic=true}, {{hi_name = "NonText", ui_name = "EndOfBuffer", kind = "ui"}}},
|
||||||
|
})
|
||||||
|
screen:expect([[
|
||||||
|
^ |
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
{1:~ }|
|
||||||
|
|
|
||||||
|
]])
|
||||||
|
|
||||||
|
command("hi NonText guifg=Red gui=reverse ctermfg=Green cterm=italic")
|
||||||
|
screen:expect([[
|
||||||
|
^ |
|
||||||
|
{2:~ }|
|
||||||
|
{2:~ }|
|
||||||
|
{2:~ }|
|
||||||
|
{2:~ }|
|
||||||
|
{2:~ }|
|
||||||
|
{2:~ }|
|
||||||
|
|
|
||||||
|
]])
|
||||||
|
|
||||||
|
end)
|
||||||
|
end)
|
||||||
@@ -142,8 +142,10 @@ function Screen.new(width, height)
|
|||||||
_default_attr_ignore = nil,
|
_default_attr_ignore = nil,
|
||||||
_mouse_enabled = true,
|
_mouse_enabled = true,
|
||||||
_attrs = {},
|
_attrs = {},
|
||||||
|
_hl_info = {},
|
||||||
_attr_table = {[0]={{},{}}},
|
_attr_table = {[0]={{},{}}},
|
||||||
_clear_attrs = {},
|
_clear_attrs = {},
|
||||||
|
_new_attrs = false,
|
||||||
_cursor = {
|
_cursor = {
|
||||||
row = 1, col = 1
|
row = 1, col = 1
|
||||||
},
|
},
|
||||||
@@ -161,6 +163,10 @@ function Screen:set_default_attr_ignore(attr_ignore)
|
|||||||
self._default_attr_ignore = attr_ignore
|
self._default_attr_ignore = attr_ignore
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function Screen:set_hlstate_cterm(val)
|
||||||
|
self._hlstate_cterm = val
|
||||||
|
end
|
||||||
|
|
||||||
function Screen:attach(options)
|
function Screen:attach(options)
|
||||||
if options == nil then
|
if options == nil then
|
||||||
options = {rgb=true}
|
options = {rgb=true}
|
||||||
@@ -218,6 +224,11 @@ function Screen:expect(expected, attr_ids, attr_ignore, condition, any)
|
|||||||
end
|
end
|
||||||
local ids = attr_ids or self._default_attr_ids
|
local ids = attr_ids or self._default_attr_ids
|
||||||
local ignore = attr_ignore or self._default_attr_ignore
|
local ignore = attr_ignore or self._default_attr_ignore
|
||||||
|
local id_to_index
|
||||||
|
if self._options.ext_hlstate then
|
||||||
|
id_to_index = self:hlstate_check_attrs(ids or {})
|
||||||
|
end
|
||||||
|
self._new_attrs = false
|
||||||
self:wait(function()
|
self:wait(function()
|
||||||
if condition ~= nil then
|
if condition ~= nil then
|
||||||
local status, res = pcall(condition)
|
local status, res = pcall(condition)
|
||||||
@@ -231,9 +242,14 @@ function Screen:expect(expected, attr_ids, attr_ignore, condition, any)
|
|||||||
.. ') differs from configured height(' .. self._height .. ') of Screen.')
|
.. ') differs from configured height(' .. self._height .. ') of Screen.')
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if self._options.ext_hlstate and self._new_attrs then
|
||||||
|
id_to_index = self:hlstate_check_attrs(ids or {})
|
||||||
|
end
|
||||||
|
|
||||||
|
local info = self._options.ext_hlstate and id_to_index or ids
|
||||||
local actual_rows = {}
|
local actual_rows = {}
|
||||||
for i = 1, self._height do
|
for i = 1, self._height do
|
||||||
actual_rows[i] = self:_row_repr(self._rows[i], ids, ignore)
|
actual_rows[i] = self:_row_repr(self._rows[i], info, ignore)
|
||||||
end
|
end
|
||||||
|
|
||||||
if expected == nil then
|
if expected == nil then
|
||||||
@@ -347,7 +363,7 @@ function Screen:_handle_resize(width, height)
|
|||||||
for _ = 1, height do
|
for _ = 1, height do
|
||||||
local cols = {}
|
local cols = {}
|
||||||
for _ = 1, width do
|
for _ = 1, width do
|
||||||
table.insert(cols, {text = ' ', attrs = self._clear_attrs})
|
table.insert(cols, {text = ' ', attrs = self._clear_attrs, hl_id = 0})
|
||||||
end
|
end
|
||||||
table.insert(rows, cols)
|
table.insert(rows, cols)
|
||||||
end
|
end
|
||||||
@@ -449,6 +465,7 @@ function Screen:_handle_scroll(count)
|
|||||||
for j = left, right do
|
for j = left, right do
|
||||||
target[j].text = source[j].text
|
target[j].text = source[j].text
|
||||||
target[j].attrs = source[j].attrs
|
target[j].attrs = source[j].attrs
|
||||||
|
target[j].hl_id = source[j].hl_id
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -468,6 +485,7 @@ end
|
|||||||
|
|
||||||
function Screen:_handle_hl_attr_define(id, rgb_attrs, cterm_attrs, info)
|
function Screen:_handle_hl_attr_define(id, rgb_attrs, cterm_attrs, info)
|
||||||
self._attr_table[id] = {rgb_attrs, cterm_attrs}
|
self._attr_table[id] = {rgb_attrs, cterm_attrs}
|
||||||
|
self._hl_info[id] = info
|
||||||
self._new_attrs = true
|
self._new_attrs = true
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -487,6 +505,7 @@ function Screen:_handle_put(str)
|
|||||||
local cell = self._rows[self._cursor.row][self._cursor.col]
|
local cell = self._rows[self._cursor.row][self._cursor.col]
|
||||||
cell.text = str
|
cell.text = str
|
||||||
cell.attrs = self._attrs
|
cell.attrs = self._attrs
|
||||||
|
cell.hl_id = -1
|
||||||
self._cursor.col = self._cursor.col + 1
|
self._cursor.col = self._cursor.col + 1
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -495,14 +514,17 @@ function Screen:_handle_grid_line(grid, row, col, items)
|
|||||||
local line = self._rows[row+1]
|
local line = self._rows[row+1]
|
||||||
local colpos = col+1
|
local colpos = col+1
|
||||||
local hl = self._clear_attrs
|
local hl = self._clear_attrs
|
||||||
|
local hl_id = 0
|
||||||
for _,item in ipairs(items) do
|
for _,item in ipairs(items) do
|
||||||
local text, hlid, count = unpack(item)
|
local text, hl_id_cell, count = unpack(item)
|
||||||
if hlid ~= nil then
|
if hl_id_cell ~= nil then
|
||||||
hl = self._attr_table[hlid]
|
hl_id = hl_id_cell
|
||||||
|
hl = self._attr_table[hl_id]
|
||||||
end
|
end
|
||||||
for _ = 1, (count or 1) do
|
for _ = 1, (count or 1) do
|
||||||
local cell = line[colpos]
|
local cell = line[colpos]
|
||||||
cell.text = text
|
cell.text = text
|
||||||
|
cell.hl_id = hl_id
|
||||||
cell.attrs = hl
|
cell.attrs = hl
|
||||||
colpos = colpos+1
|
colpos = colpos+1
|
||||||
end
|
end
|
||||||
@@ -641,18 +663,28 @@ function Screen:print_snapshot(attrs, ignore)
|
|||||||
if ignore == nil then
|
if ignore == nil then
|
||||||
ignore = self._default_attr_ignore
|
ignore = self._default_attr_ignore
|
||||||
end
|
end
|
||||||
|
local id_to_index = {}
|
||||||
if attrs == nil then
|
if attrs == nil then
|
||||||
attrs = {}
|
attrs = {}
|
||||||
if self._default_attr_ids ~= nil then
|
if self._default_attr_ids ~= nil then
|
||||||
for i, a in pairs(self._default_attr_ids) do
|
for i, a in pairs(self._default_attr_ids) do
|
||||||
attrs[i] = a
|
attrs[i] = a
|
||||||
end
|
end
|
||||||
|
if self._options.ext_hlstate then
|
||||||
|
id_to_index = self:hlstate_check_attrs(attrs)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if ignore ~= true then
|
if ignore ~= true then
|
||||||
for i = 1, self._height do
|
for i = 1, self._height do
|
||||||
local row = self._rows[i]
|
local row = self._rows[i]
|
||||||
for j = 1, self._width do
|
for j = 1, self._width do
|
||||||
|
if self._options.ext_hlstate then
|
||||||
|
local hl_id = row[j].hl_id
|
||||||
|
if hl_id ~= 0 then
|
||||||
|
self:_insert_hl_id(attrs, id_to_index, hl_id)
|
||||||
|
end
|
||||||
|
else
|
||||||
local attr = row[j].attrs
|
local attr = row[j].attrs
|
||||||
if self:_attr_index(attrs, attr) == nil and self:_attr_index(ignore, attr) == nil then
|
if self:_attr_index(attrs, attr) == nil and self:_attr_index(ignore, attr) == nil then
|
||||||
if not self:_equal_attrs(attr, {}) then
|
if not self:_equal_attrs(attr, {}) then
|
||||||
@@ -663,10 +695,12 @@ function Screen:print_snapshot(attrs, ignore)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
local rv = {}
|
local rv = {}
|
||||||
|
local info = self._options.ext_hlstate and id_to_index or attrs
|
||||||
for i = 1, self._height do
|
for i = 1, self._height do
|
||||||
table.insert(rv, " "..self:_row_repr(self._rows[i],attrs, ignore).."|")
|
table.insert(rv, " "..self:_row_repr(self._rows[i], info, ignore).."|")
|
||||||
end
|
end
|
||||||
local attrstrs = {}
|
local attrstrs = {}
|
||||||
local alldefault = true
|
local alldefault = true
|
||||||
@@ -674,7 +708,12 @@ function Screen:print_snapshot(attrs, ignore)
|
|||||||
if self._default_attr_ids == nil or self._default_attr_ids[i] ~= a then
|
if self._default_attr_ids == nil or self._default_attr_ids[i] ~= a then
|
||||||
alldefault = false
|
alldefault = false
|
||||||
end
|
end
|
||||||
local dict = "{"..self:_pprint_attrs(a).."}"
|
local dict
|
||||||
|
if self._options.ext_hlstate then
|
||||||
|
dict = self:_pprint_hlstate(a)
|
||||||
|
else
|
||||||
|
dict = "{"..self:_pprint_attrs(a).."}"
|
||||||
|
end
|
||||||
table.insert(attrstrs, "["..tostring(i).."] = "..dict)
|
table.insert(attrstrs, "["..tostring(i).."] = "..dict)
|
||||||
end
|
end
|
||||||
local attrstr = "{"..table.concat(attrstrs, ", ").."}"
|
local attrstr = "{"..table.concat(attrstrs, ", ").."}"
|
||||||
@@ -688,6 +727,117 @@ function Screen:print_snapshot(attrs, ignore)
|
|||||||
io.stdout:flush()
|
io.stdout:flush()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function Screen:_insert_hl_id(attrs, id_to_index, hl_id)
|
||||||
|
if id_to_index[hl_id] ~= nil then
|
||||||
|
return id_to_index[hl_id]
|
||||||
|
end
|
||||||
|
local raw_info = self._hl_info[hl_id]
|
||||||
|
local info = {}
|
||||||
|
if #raw_info > 1 then
|
||||||
|
for i, item in ipairs(raw_info) do
|
||||||
|
info[i] = self:_insert_hl_id(attrs, id_to_index, item.id)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
info[1] = {}
|
||||||
|
for k, v in pairs(raw_info[1]) do
|
||||||
|
if k ~= "id" then
|
||||||
|
info[1][k] = v
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local entry = self._attr_table[hl_id]
|
||||||
|
local attrval
|
||||||
|
if self._hlstate_cterm then
|
||||||
|
attrval = {entry[1], entry[2], info} -- unpack() doesn't work
|
||||||
|
else
|
||||||
|
attrval = {entry[1], info}
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
table.insert(attrs, attrval)
|
||||||
|
id_to_index[hl_id] = #attrs
|
||||||
|
return #attrs
|
||||||
|
end
|
||||||
|
|
||||||
|
function Screen:hlstate_check_attrs(attrs)
|
||||||
|
local id_to_index = {}
|
||||||
|
for i = 1,#self._attr_table do
|
||||||
|
local iinfo = self._hl_info[i]
|
||||||
|
local matchinfo = {}
|
||||||
|
if #iinfo > 1 then
|
||||||
|
for k,item in ipairs(iinfo) do
|
||||||
|
matchinfo[k] = id_to_index[item.id]
|
||||||
|
end
|
||||||
|
else
|
||||||
|
matchinfo = iinfo
|
||||||
|
end
|
||||||
|
for k,v in pairs(attrs) do
|
||||||
|
local attr, info, attr_rgb, attr_cterm
|
||||||
|
if self._hlstate_cterm then
|
||||||
|
attr_rgb, attr_cterm, info = unpack(v)
|
||||||
|
attr = {attr_rgb, attr_cterm}
|
||||||
|
else
|
||||||
|
attr, info = unpack(v)
|
||||||
|
end
|
||||||
|
if self:_equal_attr_def(attr, self._attr_table[i]) then
|
||||||
|
if #info == #matchinfo then
|
||||||
|
local match = false
|
||||||
|
if #info == 1 then
|
||||||
|
if self:_equal_info(info[1],matchinfo[1]) then
|
||||||
|
match = true
|
||||||
|
end
|
||||||
|
else
|
||||||
|
match = true
|
||||||
|
for j = 1,#info do
|
||||||
|
if info[j] ~= matchinfo[j] then
|
||||||
|
match = false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if match then
|
||||||
|
id_to_index[i] = k
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return id_to_index
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function Screen:_pprint_hlstate(item)
|
||||||
|
--print(require('inspect')(item))
|
||||||
|
local attrdict = "{"..self:_pprint_attrs(item[1]).."}, "
|
||||||
|
local attrdict2, hlinfo
|
||||||
|
if self._hlstate_cterm then
|
||||||
|
attrdict2 = "{"..self:_pprint_attrs(item[2]).."}, "
|
||||||
|
hlinfo = item[3]
|
||||||
|
else
|
||||||
|
attrdict2 = ""
|
||||||
|
hlinfo = item[2]
|
||||||
|
end
|
||||||
|
local descdict = "{"..self:_pprint_hlinfo(hlinfo).."}"
|
||||||
|
return "{"..attrdict..attrdict2..descdict.."}"
|
||||||
|
end
|
||||||
|
|
||||||
|
function Screen:_pprint_hlinfo(states)
|
||||||
|
if #states == 1 then
|
||||||
|
local items = {}
|
||||||
|
for f, v in pairs(states[1]) do
|
||||||
|
local desc = tostring(v)
|
||||||
|
if type(v) == type("") then
|
||||||
|
desc = '"'..desc..'"'
|
||||||
|
end
|
||||||
|
table.insert(items, f.." = "..desc)
|
||||||
|
end
|
||||||
|
return "{"..table.concat(items, ", ").."}"
|
||||||
|
else
|
||||||
|
return table.concat(states, ", ")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
function Screen:_pprint_attrs(attrs)
|
function Screen:_pprint_attrs(attrs)
|
||||||
local items = {}
|
local items = {}
|
||||||
for f, v in pairs(attrs) do
|
for f, v in pairs(attrs) do
|
||||||
@@ -711,11 +861,18 @@ local function backward_find_meaningful(tbl, from) -- luacheck: no unused
|
|||||||
return from
|
return from
|
||||||
end
|
end
|
||||||
|
|
||||||
function Screen:_get_attr_id(attr_ids, ignore, attrs)
|
function Screen:_get_attr_id(attr_ids, ignore, attrs, hl_id)
|
||||||
if not attr_ids then
|
if not attr_ids then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if self._options.ext_hlstate then
|
||||||
|
local id = attr_ids[hl_id]
|
||||||
|
if id ~= nil or hl_id == 0 then
|
||||||
|
return id
|
||||||
|
end
|
||||||
|
return "UNEXPECTED "..self:_pprint_attrs(self._attr_table[hl_id][1])
|
||||||
|
else
|
||||||
for id, a in pairs(attr_ids) do
|
for id, a in pairs(attr_ids) do
|
||||||
if self:_equal_attrs(a, attrs) then
|
if self:_equal_attrs(a, attrs) then
|
||||||
return id
|
return id
|
||||||
@@ -728,16 +885,29 @@ function Screen:_get_attr_id(attr_ids, ignore, attrs)
|
|||||||
end
|
end
|
||||||
return "UNEXPECTED "..self:_pprint_attrs(attrs)
|
return "UNEXPECTED "..self:_pprint_attrs(attrs)
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function Screen:_equal_attr_def(a, b)
|
||||||
|
if self._hlstate_cterm then
|
||||||
|
return self:_equal_attrs(a[1],b[1]) and self:_equal_attrs(a[2],b[2])
|
||||||
|
else
|
||||||
|
return self:_equal_attrs(a,b[1])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
function Screen:_equal_attrs(a, b)
|
function Screen:_equal_attrs(a, b)
|
||||||
return a.bold == b.bold and a.standout == b.standout and
|
return a.bold == b.bold and a.standout == b.standout and
|
||||||
a.underline == b.underline and a.undercurl == b.undercurl and
|
a.underline == b.underline and a.undercurl == b.undercurl and
|
||||||
a.italic == b.italic and a.reverse == b.reverse and
|
a.italic == b.italic and a.reverse == b.reverse and
|
||||||
a.foreground == b.foreground and
|
a.foreground == b.foreground and a.background == b.background and
|
||||||
a.background == b.background and
|
|
||||||
a.special == b.special
|
a.special == b.special
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function Screen:_equal_info(a, b)
|
||||||
|
return a.kind == b.kind and a.hi_name == b.hi_name and
|
||||||
|
a.ui_name == b.ui_name
|
||||||
|
end
|
||||||
|
|
||||||
function Screen:_attr_index(attrs, attr)
|
function Screen:_attr_index(attrs, attr)
|
||||||
if not attrs then
|
if not attrs then
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
Reference in New Issue
Block a user