Skip to content

Commit

Permalink
fix: fix rendering glitches due to interaction with vim-dirvish
Browse files Browse the repository at this point in the history
This isn't a bug in vim-dirvish, but there is something about the way it
operates that triggers this undesired behavior in Command-T. The repro
isn't 100% reliable but it almost is:

1. Create a tmux split in order to have a narrow window to test inside.
2. Open vim-dirvish with `nvim .`.
3. Split the buffer vertically to make it even thinner (strictly
   speaking, you don't have to do this, but it makes it more likely to
   reproduce).
4. Open Command-T; see that the match listing is acting as though it
   were scrolled to the right (ie. you can't see the text on the left,
   or you can only see the tail end of it).

Now, what vim-dirvish is doing is having potentially very long absolute
paths in its buffer that are very wide, and hiding the bit that
corresponds to the current working directory using Vim's "conceal"
feature. So, you only see relative paths (relative to the current
working directory), but each line in the buffer may be much longer.

So, given a `'textwidth'` of, say, 80, it's easily possibly for you to
have lines longer than that, even if they don't look that long. This
becomes more obvious if you set `'colorcolumn'` to "+0,+1" etc; you
might have a path that looks like "README.md" in the visible spectrum,
but the line is actually prefixed by something way longer, and you can
see the colorcolumn columns not in column 80 (assuming `'textwidth'` is
80) like you would expect, but in something way farther to the left,
like "column" 15 or 20.

If you jump the cursor all the way to the start of the line (with `^`)
then you see the colorcolumn highlighting move to the right, and
Command-T works without the rendering glitch. If you jump to the end
(with `$`), the colorcolumn highlighting moves back to the left and the
bug returns.

I tried various settings of `'sidescroll'` and `'sidescrolloff'` but the
only way I could get the problem to go away was to turn `'wrap'` _on_,
and then trim my lines to avoid the unwanted wrapping. Moving the cursor
to column 0 with `nvim_win_set_cursor` does not solve this problem, even
thought he docs say it will scroll the window if necessary (note: we
were already doing this).

I tried to repro this without vim-dirvish, and didn't succeed. For
example I got a big Markdown file with long lines and tried various
values of all the settings without reproducing the bug. I turned off
various bells and whistles. I updated vim-dirvish. In the end, I don't
have a smoking gun, but I have a correlation. It's a mystery how the
state of the vim-dirvish window could/would affect an independent buffer
(the match listing); that does feel like a bug, in Neovim most likely.
But it seem so edge-casey and speculative that I don't think I can even
formulate a bug report.
  • Loading branch information
wincent committed Aug 28, 2022
1 parent 2be25b7 commit ca959c9
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 30 deletions.
3 changes: 0 additions & 3 deletions doc/command-t.txt
Original file line number Diff line number Diff line change
Expand Up @@ -240,9 +240,6 @@ KNOWN ISSUES *command-t-known-issues*
to force a re-scan. 6.x does not implement any such caching (which means
that results are always fresh, but on large directories the re-scanning may
introduce a noticeable delay).
- Sometimes the results in the match listing are scrolled to the right,
causing the left edge to be cut off; I would love to fix this but haven't
identified a cause yet.
- The documentation for 6.x (ie. this document) is still a work in progress.


Expand Down
7 changes: 6 additions & 1 deletion ftplugin/CommandTMatchListing.lua
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,9 @@ vim.bo.textwidth = 0
vim.wo.concealcursor = ''
vim.wo.conceallevel = 0
vim.wo.winhighlight = 'IncSearch:Normal,Search:Normal'
vim.wo.wrap = false

-- Would like this to be false, but that produces rendering glitches in
-- conjunction with vim-dirvish, so instead we turn wrapping on but trim our
-- match listing text so that it is never wide enough to actually cause
-- wrapping.
vim.wo.wrap = true
60 changes: 34 additions & 26 deletions lua/wincent/commandt/private/match_listing.lua
Original file line number Diff line number Diff line change
Expand Up @@ -43,19 +43,45 @@ function MatchListing:close()
end
end

local format_line = function(line, width, selected)
local prefix = selected and '> ' or ' '

-- Right pad so that selection highlighting is shown across full width.
if width < 104 then
if #line > 99 then
-- No padding needed.
line = prefix .. line
else
line = prefix .. string.format('%-' .. (width - #prefix) .. 's', line)
end
else
-- Avoid: "invalid option" caused by format argument > 99.
line = prefix .. string.format('%-99s', line)
local diff = width - line:len()
if diff > 0 then
line = line .. string.rep(' ', diff)
end
end

-- Trim right to make sure we never wrap.
return line:sub(1, width)
end

function MatchListing:select(selected)
assert(type(selected) == 'number')
assert(selected > 0)
assert(selected <= #self._lines)
assert(selected <= #self._results)
if self._window then
local selection = ' ' .. self._lines[self._selected]:sub(3)
self._window:replace_line(selection, self._selected)
local width = self._window:width() or vim.o.columns -- BUG: width may be cached/stale

local previous_selection = format_line(self._results[self._selected], width, false)
self._window:replace_line(previous_selection, self._selected)
self._window:unhighlight_line(self._selected)

self._selected = selected
selection = '> ' .. self._lines[self._selected]:sub(3)
self._window:replace_line(selection, selected)
self._window:highlight_line(selected)
local new_selection = format_line(self._results[self._selected], width, true)
self._window:replace_line(new_selection, self._selected)
self._window:highlight_line(self._selected)
end
end

Expand Down Expand Up @@ -112,26 +138,8 @@ function MatchListing:update(results, options)
local width = self._window:width() or vim.o.columns
self._lines = {}
for i, result in ipairs(results) do
local prefix = i == self._selected and '> ' or ' '
local line = nil

-- Right pad so that selection highlighting is shown across full width.
if width < 104 then
if #result > 99 then
-- No padding needed.
line = prefix .. result
else
line = prefix .. string.format('%-' .. (width - #prefix) .. 's', result)
end
else
-- Avoid: "invalid option" caused by format argument > 99.
line = prefix .. string.format('%-99s', result)
local diff = width - line:len()
if diff > 0 then
line = line .. string.rep(' ', diff)
end
end

local selected = i == self._selected
local line = format_line(result, width, selected)
table.insert(self._lines, line)
end
self._window:unhighlight()
Expand Down

0 comments on commit ca959c9

Please sign in to comment.