Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: bookmark filter shows marked directory children #2719

Merged
merged 10 commits into from
Mar 30, 2024

Conversation

remvn
Copy link
Contributor

@remvn remvn commented Mar 20, 2024

Currently, bookmark filter doesn't include the children of marked directory
image

This PR fixes it
image

For now, this assume x is a directory by adding trailing slash approach is working fine. However, It would be better if I we knew the filetype of path and mark in the first place to skip some unnecessary checks (requiring changes from should_filter function). What do you think? Is it worth the change?

@remvn remvn marked this pull request as ready for review March 20, 2024 11:08
@alex-courtis
Copy link
Member

However, It would be better if I we knew the filetype of path and mark in the first place to skip some unnecessary checks (requiring changes from should_filter function). What do you think? Is it worth the change?

Yes. That would be a lot faster and cleaner, which is desirable as this is a critical path function. We definitely don't want to make alny filesystem calls.

The node contains that information however we don't always have a node when calling this method, hence it is called with absolute path only.

Looking at the call sites we could add a uv.uv_fs_t parameter to should_filter(path, status). They appear to have it available one way or another.

@remvn
Copy link
Contributor Author

remvn commented Mar 24, 2024

I'm not sure what uv.uv_fs_t does (Is it used to do filesystem call to get the information?) but I think a new filetype argument as string should be good

@alex-courtis
Copy link
Member

alex-courtis commented Mar 24, 2024

I'm not sure what uv.uv_fs_t does (Is it used to do filesystem call to get the information?)

That's it. It is returned by libuv filesystem calls https://github.com/luvit/luv/blob/master/docs.md#uvfs_statpath-callback and has a field .type which is a string. Example nvim-tree usage:

if source_stats.type == "file" then

It's retained by the node

---@field fs_stat uv.uv_fs_t

Node has a string type as well, however that's to identify the class of the node and cannot be used for our purposes.

All of the filter call sites have access to uv.uv_fs_t: from the node itself or the result of a stat e.g.

stat, _ = vim.loop.fs_stat(path)

@remvn
Copy link
Contributor Author

remvn commented Mar 25, 2024

I think uv.uv_fs_t is not a table that carry information of the file but rather something to deal with async operation

see: https://github.com/luvit/luv/blob/master/docs.md#uvfs_statpath-callback

uv.fs_stat(path, [callback])
this fs_stat function actually has 2 different versions: sync and async

Currently, only one should_filter call site doesn't have uv.fs_stat.result:

---@param type_ string|nil
---@param cwd string
---@return any
local function get_type_from(type_, cwd)
return type_ or (vim.loop.fs_stat(cwd) or {}).type
end
---@param handle uv.uv_fs_t
---@param cwd string
---@param node Node
---@param git_status table
local function populate_children(handle, cwd, node, git_status)
local node_ignored = explorer_node.is_git_ignored(node)
local nodes_by_path = utils.bool_record(node.nodes, "absolute_path")
local filter_status = filters.prepare(git_status)
while true do
local name, t = vim.loop.fs_scandir_next(handle)
if not name then
break
end
local abs = utils.path_join { cwd, name }
local profile = log.profile_start("explore populate_children %s", abs)
t = get_type_from(t, abs)
if not filters.should_filter(abs, filter_status) and not nodes_by_path[abs] and Watcher.is_fs_event_capable(abs) then
local child = nil
if t == "directory" and vim.loop.fs_access(abs, "R") then

vim.loop.fs_scandir_next(handle) only provide name and type

Which means we will have to call vim.loop.fs_stat for every files in the loop

My current approach only uses type which available at all the places. There's really nothing useful in uv.fs_stat.result for filter purposes other than type

I believe it's ready to merge if there's nothing else to concern.

@alex-courtis
Copy link
Member

I think uv.uv_fs_t is not a table that carry information of the file but rather something to deal with async operation

Right you are, that's a handle. The fs_stat field in node.lua is incorrect. It should indeed be a uv.fs_stat.result.

Many thanks for taking the time to identify this one.

@alex-courtis
Copy link
Member

It looks like we can add uv.fs_stat.result as a param to filter rather than type. This is desirable so that we can in future filter on other criteria in that result set such as mtime.

RE explore.lua that is a problem. get_type_from doesn't usually (never?) execute the fs_stat. I agree that we should not blow out that loop by executing it. Node construction, however, does execute fs_stat.
Remediation:

  • Remove get_type_from
  • Replace get_type_from with an fs_stat
  • Pass the stat to filter
  • Pass the stat to the node constructor
    The above needs to be done one way or the other in the name of efficiency.

@alex-courtis
Copy link
Member

If you'd like to take on the above task I would be most grateful, however I understand that this is outside the scope of this change.

If you choose not to we can merge this now and I'll raise an issue.

@@ -79,9 +79,18 @@ local function bookmark(path, bookmarks)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the interests of efficiency let's return early in the first line if bookmarks is empty or nil.

That will avoid the first utils.path_add_trailing

@alex-courtis
Copy link
Member

FYI nvim 0.10 will be providing full luadoc api coverage including uv, lsp etc.

That would have made this PR much easier...

@remvn
Copy link
Contributor Author

remvn commented Mar 26, 2024

FYI nvim 0.10 will be providing full luadoc api coverage including uv, lsp etc.

That would have made this PR much easier...

Did you mean we will have type and intellisense for vim api functions?

@remvn
Copy link
Contributor Author

remvn commented Mar 26, 2024

Quick summary for few changes I have made:

  • Node.fs_stat field are replaced with the correct type
  • add fs_stat parameter to Node constructor
  • Node constructor and should_filter function in explore.lua now will use the same fs_stat which is called once for every file in the loop.
  • reload.lua: removed fs_stat_cached helper function, refactor some statement to make it consistent and cleaner

@alex-courtis
Copy link
Member

Did you mean we will have type and intellisense for vim api functions?

Yes. I'm quite excited. It's anything vim.

@@ -139,17 +156,18 @@ function M.prepare(git_status)
end

for _, node in pairs(marks.get_marks()) do
status.bookmarks[node.absolute_path] = true
status.bookmarks[node.absolute_path] = node.type
Copy link
Member

@alex-courtis alex-courtis Mar 30, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nicely efficient.

Future PR: create a proper class for the return. It will be done when we apply all the 0.10 annotations and the enum is present.

@@ -6,6 +6,14 @@ local M = {}
---@return table
local function get_formatted_lines(node)
local stats = node.fs_stat
if stats == nil then
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Many thanks!

Copy link
Member

@alex-courtis alex-courtis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just fantastic - thank you for going the extra mile with these great improvements to the codebase.

@alex-courtis alex-courtis changed the title fix: bookmark filter should include marked directory's children fix: bookmark filter shows bookmarked directory children Mar 30, 2024
@alex-courtis alex-courtis changed the title fix: bookmark filter shows bookmarked directory children fix: bookmark filter shows marked directory children Mar 30, 2024
@alex-courtis alex-courtis merged commit 2d97059 into nvim-tree:master Mar 30, 2024
7 checks passed
@alex-courtis
Copy link
Member

Did you mean we will have type and intellisense for vim api functions?

#2731

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants