@@ -28,8 +28,11 @@ for i = 0, 23 do
28
28
end
29
29
30
30
--- Parses xterm color codes and converts them to RGB hex format.
31
- -- This function matches both #xNN format (decimal, 0-255) and ANSI escape sequences \e[38;5;NNNm
32
- -- for xterm 256-color palette. It returns the corresponding RGB hex string from the xterm color palette.
31
+ -- This function matches following color codes:
32
+ -- 1. #xNN format (decimal, 0-255).
33
+ -- 2. ANSI escape sequences \e[38;5;NNNm for xterm 256-color palette.
34
+ -- 3. ANSI escape sequences \e[X;Ym for xterm 16-color palette.
35
+ -- It returns the corresponding RGB hex string from the xterm color palette.
33
36
--- @param line string : The line of text to parse for xterm color codes
34
37
--- @param i number : The starting index within the line where parsing should begin
35
38
--- @return number | nil : The end index of the parsed xterm color code within the line , or ` nil` if parsing failed
@@ -40,8 +43,8 @@ function M.parser(line, i)
40
43
if hash_x == " #x" then
41
44
local num = line :sub (i + 2 ):match (" ^(%d?%d?%d)" )
42
45
if num then
43
- local idx = tonumber (num )
44
- if idx and idx >= 0 and idx <= 255 then
46
+ local idx = tonumber (num ) or - 1
47
+ if idx >= 0 and idx <= 255 then
45
48
local next_char = line :sub (i + 2 + # num , i + 2 + # num )
46
49
if next_char == " " or not next_char :match (" %w" ) then
47
50
return 2 + # num , xterm_palette [idx + 1 ]
@@ -50,16 +53,16 @@ function M.parser(line, i)
50
53
end
51
54
end
52
55
-- \e[38;5;NNNm (decimal, 0-255), support both literal '\e' and actual escape char
53
- local ansi_patterns = {
56
+ local ansi_256_patterns = {
54
57
" ^\\ e%[38;5;(%d?%d?%d)m" , -- literal '\e'
55
58
" ^\27 %[38;5;(%d?%d?%d)m" , -- ASCII 27
56
59
" ^\x1b %[38;5;(%d?%d?%d)m" , -- hex escape
57
60
}
58
- for _ , esc_pat in ipairs (ansi_patterns ) do
61
+ for _ , esc_pat in ipairs (ansi_256_patterns ) do
59
62
local esc_match = line :sub (i ):match (esc_pat )
60
63
if esc_match then
61
- local idx = tonumber (esc_match )
62
- if idx and idx >= 0 and idx <= 255 then
64
+ local idx = tonumber (esc_match ) or - 1
65
+ if idx >= 0 and idx <= 255 then
63
66
-- Use string.find to get the end index of the match
64
67
local _ , end_idx = line :sub (i ):find (esc_pat )
65
68
if end_idx then
@@ -70,7 +73,26 @@ function M.parser(line, i)
70
73
end
71
74
end
72
75
end
76
+ -- \e[X;Ym for xterm 16-color palette, support foreground colors (30-37) with brightness (0-1)
77
+ -- TODO: Support background colors and other patterns
78
+ local ansi_16_patterns = {
79
+ " ^\\ e%[(%d+);(%d+)m" , -- literal '\e'
80
+ " ^\27 %[(%d+);(%d+)m" , -- ASCII 27
81
+ " ^\x1b %[(%d+);(%d+)m" , -- hex escape
82
+ }
83
+ for _ , esc_pat in ipairs (ansi_16_patterns ) do
84
+ local match_x , match_y = line :sub (i ):match (esc_pat )
85
+ if match_x and match_y then
86
+ local x , y = tonumber (match_x ) or - 1 , tonumber (match_y ) or - 1
87
+ -- Color and brightness positions are interchangeable
88
+ local color , brightness = math.max (x , y ), math.min (x , y )
89
+ if color >= 30 and color <= 37 and brightness >= 0 and brightness <= 1 then
90
+ color = color - 30
91
+ return 5 + # match_x + # match_y , xterm_palette [color + 1 + brightness * 8 ]
92
+ end
93
+ end
94
+ end
73
95
return nil
74
96
end
75
97
76
- return M
98
+ return M
0 commit comments