mirror of
https://github.com/neovim/neovim.git
synced 2025-12-16 03:15:39 +00:00
Address PR comments
This commit is contained in:
@@ -1,8 +1,10 @@
|
||||
local function highlight_formatted(line, linenr)
|
||||
local buf_hls = {}
|
||||
|
||||
local function highlight_line(line, linenr)
|
||||
local chars = {}
|
||||
local prev_char = ''
|
||||
local overstrike, escape = false, false
|
||||
local hls = {} -- Store highlight groups as { attr, start, end }
|
||||
local hls = {} -- Store highlight groups as { attr, start, final }
|
||||
local NONE, BOLD, UNDERLINE, ITALIC = 0, 1, 2, 3
|
||||
local hl_groups = {[BOLD]="manBold", [UNDERLINE]="manUnderline", [ITALIC]="manItalic"}
|
||||
local attr = NONE
|
||||
@@ -10,40 +12,40 @@ local function highlight_formatted(line, linenr)
|
||||
|
||||
local function end_attr_hl(attr)
|
||||
for i, hl in ipairs(hls) do
|
||||
if hl[1] == attr and hl[3] == -1 then
|
||||
hl[3] = byte
|
||||
if hl.attr == attr and hl.final == -1 then
|
||||
hl.final = byte
|
||||
hls[i] = hl
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function add_attr_hl(code)
|
||||
local on = true
|
||||
local continue_hl = true
|
||||
if code == 0 then
|
||||
attr = NONE
|
||||
on = false
|
||||
continue_hl = false
|
||||
elseif code == 1 then
|
||||
attr = BOLD
|
||||
elseif code == 21 or code == 22 then
|
||||
elseif code == 22 then
|
||||
attr = BOLD
|
||||
on = false
|
||||
continue_hl = false
|
||||
elseif code == 3 then
|
||||
attr = ITALIC
|
||||
elseif code == 23 then
|
||||
attr = ITALIC
|
||||
on = false
|
||||
continue_hl = false
|
||||
elseif code == 4 then
|
||||
attr = UNDERLINE
|
||||
elseif code == 24 then
|
||||
attr = UNDERLINE
|
||||
on = false
|
||||
continue_hl = false
|
||||
else
|
||||
attr = NONE
|
||||
return
|
||||
end
|
||||
|
||||
if on then
|
||||
hls[#hls + 1] = {attr, byte, -1}
|
||||
if continue_hl then
|
||||
hls[#hls + 1] = {attr=attr, start=byte, final=-1}
|
||||
else
|
||||
if attr == NONE then
|
||||
for a, _ in pairs(hl_groups) do
|
||||
@@ -55,12 +57,15 @@ local function highlight_formatted(line, linenr)
|
||||
end
|
||||
end
|
||||
|
||||
-- Break input into UTF8 characters
|
||||
-- Break input into UTF8 code points. ASCII code points (from 0x00 to 0x7f)
|
||||
-- can be represented in one byte. Any code point above that is represented by
|
||||
-- a leading byte (0xc0 and above) and continuation bytes (0x80 to 0xbf, or
|
||||
-- decimal 128 to 191).
|
||||
for char in line:gmatch("[^\128-\191][\128-\191]*") do
|
||||
if overstrike then
|
||||
local last_hl = hls[#hls]
|
||||
if char == prev_char then
|
||||
if char == '_' and attr == UNDERLINE and last_hl and last_hl[3] == byte then
|
||||
if char == '_' and attr == UNDERLINE and last_hl and last_hl.final == byte then
|
||||
-- This underscore is in the middle of an underlined word
|
||||
attr = UNDERLINE
|
||||
else
|
||||
@@ -72,21 +77,21 @@ local function highlight_formatted(line, linenr)
|
||||
elseif prev_char == '+' and char == 'o' then
|
||||
-- bullet (overstrike text '+^Ho')
|
||||
attr = BOLD
|
||||
char = [[·]]
|
||||
elseif prev_char == [[·]] and char == 'o' then
|
||||
char = '·'
|
||||
elseif prev_char == '·' and char == 'o' then
|
||||
-- bullet (additional handling for '+^H+^Ho^Ho')
|
||||
attr = BOLD
|
||||
char = [[·]]
|
||||
char = '·'
|
||||
else
|
||||
-- use plain char
|
||||
attr = NONE
|
||||
end
|
||||
|
||||
-- Grow the previous highlight group if possible
|
||||
if last_hl and last_hl[1] == attr and last_hl[3] == byte then
|
||||
last_hl[3] = byte + #char
|
||||
if last_hl and last_hl.attr == attr and last_hl.final == byte then
|
||||
last_hl.final = byte + #char
|
||||
else
|
||||
hls[#hls + 1] = {attr, byte, byte + #char}
|
||||
hls[#hls + 1] = {attr=attr, start=byte, final=byte + #char}
|
||||
end
|
||||
|
||||
overstrike = false
|
||||
@@ -96,15 +101,19 @@ local function highlight_formatted(line, linenr)
|
||||
elseif escape then
|
||||
-- Use prev_char to store the escape sequence
|
||||
prev_char = prev_char .. char
|
||||
local sgr = prev_char:match("^%[([\020-\063]*)m$")
|
||||
-- We only want to match against SGR sequences, which consist of ESC
|
||||
-- followed by '[', then a series of parameter and intermediate bytes in
|
||||
-- the range 0x20 - 0x3f, then 'm'. (See ECMA-48, sections 5.4 & 8.3.117)
|
||||
local sgr = prev_char:match("^%[([\032-\063]*)m$")
|
||||
if sgr then
|
||||
local match = ''
|
||||
while sgr and #sgr > 0 do
|
||||
-- Match against SGR parameters, which may be separated by ';'
|
||||
match, sgr = sgr:match("^(%d*);?(.*)")
|
||||
add_attr_hl(match + 0) -- coerce to number
|
||||
end
|
||||
escape = false
|
||||
elseif not prev_char:match("^%[[\020-\063]*$") then
|
||||
elseif not prev_char:match("^%[[\032-\063]*$") then
|
||||
-- Stop looking if this isn't a partial CSI sequence
|
||||
escape = false
|
||||
end
|
||||
@@ -122,20 +131,38 @@ local function highlight_formatted(line, linenr)
|
||||
end
|
||||
end
|
||||
|
||||
for i, hl in ipairs(hls) do
|
||||
if hl[1] ~= NONE then
|
||||
vim.api.nvim_buf_add_highlight(
|
||||
for _, hl in ipairs(hls) do
|
||||
if hl.attr ~= NONE then
|
||||
buf_hls[#buf_hls + 1] = {
|
||||
0,
|
||||
-1,
|
||||
hl_groups[hl[1]],
|
||||
hl_groups[hl.attr],
|
||||
linenr - 1,
|
||||
hl[2],
|
||||
hl[3]
|
||||
)
|
||||
hl.start,
|
||||
hl.final
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
return table.concat(chars, '')
|
||||
end
|
||||
|
||||
return { highlight_formatted = highlight_formatted }
|
||||
local function highlight_man_page()
|
||||
local mod = vim.api.nvim_eval("&modifiable")
|
||||
vim.api.nvim_command("set modifiable")
|
||||
|
||||
local lines = vim.api.nvim_buf_get_lines(0, 0, -1, false)
|
||||
for i, line in ipairs(lines) do
|
||||
lines[i] = highlight_line(line, i)
|
||||
end
|
||||
vim.api.nvim_buf_set_lines(0, 0, -1, false, lines)
|
||||
|
||||
for _, args in ipairs(buf_hls) do
|
||||
vim.api.nvim_buf_add_highlight(unpack(args))
|
||||
end
|
||||
buf_hls = {}
|
||||
|
||||
vim.api.nvim_command("let &modifiable = "..mod)
|
||||
end
|
||||
|
||||
return { highlight_man_page = highlight_man_page }
|
||||
|
||||
Reference in New Issue
Block a user