Skip to content

Commit 26fd5ba

Browse files
committed
refactor(messages): Changed how :hi <group> message is shown
feat(messages): Linked highlight groups now also show their active definition when checked via `:hi`.
1 parent 3d523c6 commit 26fd5ba

2 files changed

Lines changed: 227 additions & 59 deletions

File tree

lua/ui/spec.lua

Lines changed: 167 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,110 @@
11
local spec = {};
22
local utils = require("ui.utils");
33

4+
--- Creates message text from highlight group properties.
5+
---@param props table
6+
---@return string[]
7+
---@return ( ui.message.hl_fragment[] )[]
8+
local function hl_prop_txt (props)
9+
---|fS
10+
11+
local lines, exts = {}, {};
12+
13+
local function new_property (name, value, hl)
14+
table.insert(lines, string.format(" %s: %s", name, value));
15+
table.insert(exts, {});
16+
17+
table.insert(exts[#exts], { 2, 2 + #name, "@property" });
18+
table.insert(exts[#exts], { 2 + #name, 2 + #name + 1, "@punctuation" });
19+
20+
table.insert(exts[#exts], { 2 + #name + 2, 2 + #name + 2 + #value, hl or "@string.special" });
21+
end
22+
23+
table.insert(lines, string.format("Name: %s", props.group_name));
24+
table.insert(exts, {});
25+
26+
table.insert(exts[#exts], { 0, 5, "@property" });
27+
table.insert(exts[#exts], { 6, 6 + #props.group_name, "@string" });
28+
29+
if props.value then
30+
if props.value.link then
31+
new_property("link", tostring(props.value.link), tostring(props.value.link));
32+
end
33+
34+
if vim.islist(props.value.cterm) then
35+
table.insert(lines, " cterm:");
36+
table.insert(exts, {});
37+
38+
table.insert(exts[#exts], { 2, 7, "@property" });
39+
table.insert(exts[#exts], { 7, 8, "@punctuation" });
40+
41+
for _, item in ipairs(props.value.cterm) do
42+
table.insert(lines, string.format(" • %s", tostring(item)));
43+
table.insert(exts, {});
44+
45+
table.insert(exts[#exts], { 4, 4 + #"", "@punctuation" });
46+
table.insert(exts[#exts], { #"", #lines[#lines], "@constant" })
47+
end
48+
end
49+
50+
if props.value.start then
51+
new_property("start", tostring(props.value.start), "@string.special");
52+
end
53+
54+
if props.value.stop then
55+
new_property("stop", tostring(props.value.stop), "@string.special");
56+
end
57+
58+
if props.value.ctermfg then
59+
new_property("ctermfg", tostring(props.value.ctermfg), "@number");
60+
end
61+
62+
if props.value.ctermbg then
63+
new_property("ctermbg", tostring(props.value.ctermbg), "@number");
64+
end
65+
66+
if vim.islist(props.value.gui) then
67+
table.insert(lines, "gui:");
68+
table.insert(exts, {});
69+
70+
table.insert(exts[#exts], { 0, 3, "@property" });
71+
table.insert(exts[#exts], { 3, 4, "@punctuation" });
72+
73+
for _, item in ipairs(props.value.gui) do
74+
table.insert(lines, string.format(" • %s", tostring(item)));
75+
table.insert(exts, {});
76+
77+
table.insert(exts[#exts], { 2, 2 + #"", "@punctuation" });
78+
table.insert(exts[#exts], { #"", #lines[#lines], "@constant" })
79+
end
80+
end
81+
82+
if props.value.font then
83+
new_property("font", props.value.font, "@string");
84+
end
85+
86+
if props.value.guifg then
87+
new_property("guifg", props.value.guifg, "@constant");
88+
end
89+
90+
if props.value.guibg then
91+
new_property("guibg", props.value.guibg, "@constant");
92+
end
93+
94+
if props.value.guisp then
95+
new_property("guisp", props.value.guisp, "@constant");
96+
end
97+
98+
if props.value.blend then
99+
new_property("blend", props.value.blend, "@number");
100+
end
101+
end
102+
103+
return lines, exts;
104+
105+
---|fE
106+
end
107+
4108
--- Checks if a message is a list message.
5109
---@param lines string[]
6110
---@return boolean
@@ -1064,42 +1168,65 @@ spec.default = {
10641168
---|fS
10651169

10661170
condition = function (_, lines)
1067-
return #lines == 2 and string.match(lines[2], "^.- +xxx links to .-") ~= nil;
1171+
local is_hl, data = utils.is_hl_line(lines[2] or "")
1172+
return lines[1] == "" and is_hl and data.value.link;
10681173
end,
10691174

10701175
modifier = function (_, lines)
1071-
local group_name, link = string.match(lines[2], "^(.-) +xxx links to (.-)$");
1072-
group_name = string.gsub(group_name, "[^a-zA-Z0-9_.@-]", "");
1176+
local _, data = utils.is_hl_line(lines[2] or "")
10731177

1074-
return {
1075-
lines = {
1076-
"abcABC 123",
1077-
string.format("Group: %s", group_name),
1078-
string.format(" Link: %s", link)
1178+
local definition = vim.api.nvim_exec2("hi " .. data.value.link, { output = true }).output;
1179+
local _, def_data = utils.is_hl_line(definition);
1180+
1181+
local d_lines, d_exts = hl_prop_txt(def_data);
1182+
1183+
-- Remove the group name part.
1184+
table.remove(d_lines, 1);
1185+
table.remove(d_exts, 1);
1186+
1187+
local o_lines, o_exts = {
1188+
"abcABC 123",
1189+
"Name: " .. data.group_name,
1190+
" link: " .. data.value.link,
1191+
"",
1192+
"Raw definition:"
1193+
}, {
1194+
{
1195+
{ 0, 10, data.group_name }
10791196
},
1080-
extmarks = {
1081-
{
1082-
{ 0, 10, group_name }
1083-
},
1084-
{
1085-
{ 0, 7, "DiagnosticInfo" },
1086-
{ 7, 7 + #group_name, "@label" }
1087-
},
1088-
{
1089-
{ 2, 7, "@property" },
1090-
{ 8, 8 + #link, "@constant" },
1091-
}
1092-
}
1093-
}
1197+
{
1198+
{ 0, 4, "@property" },
1199+
{ 4, 5, "@punctuation" },
1200+
{ 6, 6 + #data.group_name, "@string" },
1201+
},
1202+
{
1203+
{ 0, 6, "@property" },
1204+
{ 6, 7, "@punctuation" },
1205+
{ 8, 8 + #data.value.link, "@constant" },
1206+
},
1207+
{},
1208+
{
1209+
{ 0, #"Raw definition", "DiagnosticHint" },
1210+
{ #"Raw definition", #"Raw definition" + 1, "@punctuation" },
1211+
},
1212+
};
1213+
1214+
o_lines = vim.list_extend(o_lines, d_lines);
1215+
o_exts = vim.list_extend(o_exts, d_exts);
1216+
1217+
return {
1218+
lines = o_lines,
1219+
extmarks = o_exts
1220+
};
10941221
end,
10951222
decorations = {
10961223
icon = {
1097-
{ "▍ ", "UIMessagePaletteSign" }
1224+
{ "▍ ", "UIMessagePalette" }
10981225
},
10991226
padding = {
1100-
{ "", "UIMessagePaletteSign" }
1227+
{ "", "UIMessagePalette" }
11011228
},
1102-
}
1229+
},
11031230

11041231
---|fE
11051232
},
@@ -1108,41 +1235,28 @@ spec.default = {
11081235
---|fS
11091236

11101237
condition = function (_, lines)
1111-
return #lines == 2 and string.match(lines[2], "^.- xxx links to .-") == nil and string.match(lines[2], "^.- +xxx") ~= nil;
1238+
local is_hl, data = utils.is_hl_line(lines[2] or "")
1239+
return lines[1] == "" and is_hl and data.value.link == nil;
11121240
end,
11131241

11141242
modifier = function (_, lines)
1115-
local group_name, properties = string.match(lines[2], "^(%S+)%s+xxx%s(.-)$");
1116-
group_name = string.gsub(group_name, "[^a-zA-Z0-9_.@-]", "");
1243+
local _, data = utils.is_hl_line(lines[2] or "")
1244+
local d_lines, d_exts = hl_prop_txt(data);
11171245

1118-
local _lines = {
1246+
local o_lines, o_exts = {
11191247
"abcABC 123",
1120-
string.format("Group: %s", group_name),
1121-
};
1122-
local _extmarks = {
1248+
}, {
11231249
{
1124-
{ 0, #_lines[1], group_name }
1125-
},
1126-
{
1127-
{ 0, 7, "DiagnosticInfo" },
1128-
{ 7, 7 + #group_name, "@label" }
1250+
{ 0, 10, data.group_name }
11291251
},
11301252
};
11311253

1132-
for _, property in ipairs(vim.split(properties, " ")) do
1133-
local name, value = string.match(property, "^(.-)=(.+)$");
1134-
1135-
table.insert(_lines, string.format(" %s: %s", name, value));
1136-
table.insert(_extmarks, {
1137-
{ 2, 2 + #name, "@property" },
1138-
{ 2 + #name, 2 + #name + 1, "Comment" },
1139-
{ 2 + #name + 2, 2 + #name + 2 + #value, "@constant" },
1140-
})
1141-
end
1254+
o_lines = vim.list_extend(o_lines, d_lines);
1255+
o_exts = vim.list_extend(o_exts, d_exts);
11421256

11431257
return {
1144-
lines = _lines,
1145-
extmarks = _extmarks
1258+
lines = o_lines,
1259+
extmarks = o_exts
11461260
};
11471261
end,
11481262

@@ -1417,16 +1531,10 @@ spec.default = {
14171531
hi = {
14181532
---|fS
14191533

1420-
condition = function ()
1421-
local last_cmd = vim.fn.histget("cmd", -1);
1422-
1423-
for _, patt in ipairs({ "^hi%s*$", "^highlight%s*$" }) do
1424-
if string.match(last_cmd, patt) then
1425-
return true;
1426-
end
1427-
end
1428-
1429-
return false;
1534+
condition = function (_, lines)
1535+
local is_hl = utils.is_hl_line(lines[2] or "");
1536+
require("ui.log").print(is_hl, "Blah");
1537+
return lines[1] == "" and is_hl;
14301538
end,
14311539

14321540
modifier = function (_, lines, exts)

lua/ui/utils.lua

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -591,4 +591,64 @@ utils.trim_lines = function (lines)
591591
---|fE
592592
end
593593

594+
--- Checks if a line is in the format of `:hi`.
595+
---@param line string
596+
---@return boolean
597+
---@return table
598+
utils.is_hl_line = function (line)
599+
---|fS
600+
601+
local data = {
602+
group_name = nil,
603+
value = {},
604+
};
605+
606+
if string.match(line, "([a-zA-Z0-9_.@-]+) +xxx links to ([a-zA-Z0-9_.@-]+)$") then
607+
-- @constant xxx links to Constant
608+
local group, link = string.match(line, "([a-zA-Z0-9_.@-]+) +xxx links to ([a-zA-Z0-9_.@-]+)$");
609+
610+
data.group_name = group;
611+
data.value.link = link;
612+
elseif string.match(line, "([a-zA-Z0-9_.@-]+) +xxx (.+)$") then
613+
-- Cursor xxx guifg=#1e1e2e guibg=#f5e0dc
614+
local group, properties = string.match(line, "([a-zA-Z0-9_.@-]+) +xxx (.+)$");
615+
616+
data.group_name = group;
617+
618+
data.value.ctermfg = string.match(properties, "ctermfg=(%S+)");
619+
data.value.ctermbg = string.match(properties, "ctermbg=(%S+)");
620+
621+
data.value.start = string.match(properties, "start=(%S+)");
622+
data.value.stop = string.match(properties, "stop=(%S+)");
623+
624+
data.value.font = string.match(properties, "font=(%S+)");
625+
626+
data.value.guifg = string.match(properties, "guifg=(%S+)");
627+
data.value.guibg = string.match(properties, "guibg=(%S+)");
628+
data.value.guisp = string.match(properties, "guisp=(%S+)");
629+
630+
data.value.blend = string.match(properties, "blend=(%d+)");
631+
632+
if string.match(properties, "cterm=(%S+)") then
633+
data.value.cterm = vim.split(
634+
string.match(properties, "cterm=(%S+)"),
635+
",",
636+
{ trimempty = true }
637+
);
638+
end
639+
640+
if string.match(properties, "gui=(%S+)") then
641+
data.value.gui = vim.split(
642+
string.match(properties, "gui=(%S+)"),
643+
",",
644+
{ trimempty = true }
645+
);
646+
end
647+
end
648+
649+
return data.group_name ~= nil, data;
650+
651+
---|fE
652+
end
653+
594654
return utils;

0 commit comments

Comments
 (0)