fix: "invalid 'line'" when hidden_display is set and tree is empty - #3354
Conversation
"The PR description and comments must be written by the contributor, with no AI assistance beyond grammar or English translations." In the future, please write the PR description yourself. You are welcome to use AI to assist, however the PR itself should be human written. Keep it brief, concise and to the point. The above wall of text is difficult to read. |
In your future PRs, especially for more complex changes, it's recommended to install the tools so that you do not need to wait for CI. |
alex-courtis
left a comment
There was a problem hiding this comment.
The fix works as per the test case, as well as hidden_display "all" and function.
Please remove the unnecessary comment.
| -- The count hangs under the last line that was drawn. The root has no | ||
| -- such line when every one of its children is filtered out: line 0 is | ||
| -- the empty line the buffer is left with, and is where the count goes | ||
| -- instead of line -1, which nvim_buf_set_extmark rejects. |
There was a problem hiding this comment.
Please remove this comment; referencing a fixed bug has no value to future maintainers.
There was a problem hiding this comment.
Lines 343 to 346 were dropped. Thank you for the polite review.
There was a problem hiding this comment.
I don't know if you prefer a blank line in there, between locals and anything else. Please let me know what your preference is. Dropping 343 to 346 left a blank line, which I removed to get this to a 1 line diff.
There was a problem hiding this comment.
I don't know if you prefer a blank line in there, between locals and anything else. Please let me know what your preference is. Dropping 343 to 346 left a blank line, which I removed to get this to a 1 line diff.
Looks good, matches the surrounding code style.
7e5466b to
4fcd086
Compare
4fcd086 to
801fdda
Compare
alex-courtis
left a comment
There was a problem hiding this comment.
Many thanks for your contribution!
renderer.hidden_displayraises whenever a directory is left with no visible rows and the root row is not drawn.Reproduction, with
renderer.root_folder_label = falseandrenderer.hidden_display = "simple":Open the tree and press
H. The only entry is a dotfile, so hiding dotfiles empties the tree:Builder:add_hidden_count_stringhangs the count under the last line that was drawn,#self.lines - 1. For the root, that line is its last child. With every child filtered out there are no lines at all, so the index is-1andRenderer:_drawhands it tonvim_buf_set_extmark. The defaultroot_folder_labelhides the whole thing, because the root row is then a line of its own and#self.linesis never 0; setting it tofalseis what makes the case reachable. Only the root can reach zero lines, since a nested open directory is always preceded by its own row.Two things follow from the raise, which is why it is worth more than the error text.
_drawhas already callednvim_buf_set_linesby the time it raises, so the rows are gone from the buffer but the window is never redrawn: the tree stays painted with entries that are no longer there. And when the draw comes from the filesystem watcher, the raise happens insideutils.debounce, which setsexecuting = truebefore the callback and clears it after, so the flag stays set and every later event for that directory reschedules forever. That directory stops refreshing for the rest of the session. I found this by deleting the last visible file from the tree and being left looking at a tree that still listed a file that was no longer on disk.Solution
nvim_buf_set_lines(bufnr, 0, -1, false, {})leaves the buffer holding one empty line, so line 0 always exists. Clamping the index to it puts the count under that empty line, where it renders on its own:I considered skipping the count when there are no lines instead. That hides the information at the one moment it matters most: a tree that is empty with nothing to say why reads as a broken tree, which is the case
hidden_displayexists for.Testing
A minimal config pointed at this branch, run against both values of
root_folder_label, before and after the change. Onlyfalseraises, and only before it:The extmark output above is from the same config after the change, so the count is drawn and not merely not raising.
Also run against my own config, which sets
root_folder_label = falseand passes a function forhidden_display. Seven cases, driven over a socket on a real editor with a pty: an empty directory, a directory of dotfiles with dotfiles hidden, a directory of git-ignored files with those hidden, a directory holding only.git,Htaking the last row, deleting the last visible file, and a control with rows in it. Five of them fail onmasterand all seven pass with this change.scripts/doc-comments.shpasses. luacheck, CodeFormat and luals are not installed on this machine, somake lint,make styleandmake checkwere not run; CI will be the first to run them.AI usage
Per CONTRIBUTING.md, disclosed in full.
Claude (Anthropic's Claude Code) was used. It wrote the one-line change, the comment above it, and this description, and it ran the tests above on my machine at my direction. Nothing in the diff was written by hand. I have read the change and the reasoning behind it and I am accountable for it.
No AI review tools are enabled on this pull request.