Skip to content

Commit 9e541b8

Browse files
committed
fix: try a little bit harder to handle multi-cell glyphs
I previously said I thought this would be too expensive, but it's not _that_ bad, so something like this is close to what we'd need.
1 parent a21bce9 commit 9e541b8

File tree

1 file changed

+27
-14
lines changed

1 file changed

+27
-14
lines changed

lua/wincent/commandt/private/match_listing.lua

Lines changed: 27 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -60,13 +60,33 @@ function MatchListing:icon_getter()
6060
end
6161
end
6262

63+
local function str_prefix(str, length)
64+
local trim = 0
65+
while vim.fn.strwidth(str) > length do
66+
-- For typical strings, we'll do one `sub()`. For the degenerate case with
67+
-- many multi-cell glyphs, we'll loop as many times as needed.
68+
trim = trim + 1
69+
str = sub(str, 1, length - trim)
70+
end
71+
return str
72+
end
73+
74+
local function str_suffix(str, length)
75+
local trim = 0
76+
while vim.fn.strwidth(str) > length do
77+
-- For typical strings, we'll do one `sub()`. For the degenerate case with
78+
-- many multi-cell glyphs, we'll loop as many times as needed.
79+
trim = trim + 1
80+
str = sub(str, -(length - trim))
81+
end
82+
return str
83+
end
84+
6385
local format_line = function(line, width, selected, truncate, get_icon)
6486
local prefix = selected and '> ' or ' '
6587

6688
local icon = get_icon and get_icon(line)
67-
local icon_length = 0
6889
if icon then
69-
icon_length = vim.fn.strwidth(icon .. ' ')
7090
prefix = prefix .. icon .. ' '
7191
end
7292

@@ -83,15 +103,15 @@ local format_line = function(line, width, selected, truncate, get_icon)
83103

84104
if vim.fn.strwidth(prefix .. line) <= width then
85105
-- Line fits without trimming.
86-
elseif vim.fn.strwidth(line) < (5 + icon_length) then
106+
elseif vim.fn.strwidth(prefix .. line) < 5 then
87107
-- Line is so short that adding an ellipsis is not practical.
88108
elseif truncate == true or truncate == 'true' or truncate == 'middle' then
89109
local half = math.floor((width - 2) / 2)
90-
local left = sub(line, 1, half - 3 + width % 2)
91-
local right = sub(line, 3 - half)
110+
local left = str_prefix(line, half - 2 + width % 2)
111+
local right = str_suffix(line, half - 2)
92112
line = left .. '' .. right
93113
elseif truncate == 'beginning' then
94-
line = '' .. sub(line, -width + vim.fn.strwidth(prefix) + 1)
114+
line = '' .. str_suffix(line, width - vim.fn.strwidth(prefix))
95115
elseif truncate == false or truncate == 'false' or truncate == 'end' then
96116
-- Fall through; truncation will happen before the final `return`.
97117
end
@@ -108,14 +128,7 @@ local format_line = function(line, width, selected, truncate, get_icon)
108128
end
109129

110130
-- Trim to make sure we never wrap.
111-
local trim = 0
112-
while vim.fn.strwidth(line) > width do
113-
-- For typical strings, we'll do one `sub()`. For the degenerate case with
114-
-- many multi-cell glyphs, we'll loop as many times as needed.
115-
trim = trim + 1
116-
line = sub(line, 1, width - trim)
117-
end
118-
return line
131+
return str_prefix(line, width)
119132
end
120133

121134
function MatchListing:select(selected)

0 commit comments

Comments
 (0)