Skip to content

feature request: Add events to allow integrations #310

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

Closed
1 task done
wojciech-kulik opened this issue Feb 11, 2024 · 12 comments
Closed
1 task done

feature request: Add events to allow integrations #310

wojciech-kulik opened this issue Feb 11, 2024 · 12 comments
Labels
enhancement New feature or request P0 Highest priority, will receive attention

Comments

@wojciech-kulik
Copy link

Did you check existing requests?

  • I have searched the existing issues

Describe the feature

It would be great to be able to subscribe to CRUD events (add/delete/rename) for files and folders. It would allow for integration with other plugins.

Provide background

I'm working on a plugin (xcodebuild.nvim) that allows you to manage project files, each change in file structure must update project file. Currently, I provide simple functions to work with files, but for users it would be much more convenient to use their file manager. I'm already working on integration with nvim-tree, because they expose events. However, as far as I was able to check there is no such thing in Oil.

What is the significance of this feature?

strongly desired

Additional details

No response

@wojciech-kulik wojciech-kulik added the enhancement New feature or request label Feb 11, 2024
@wojciech-kulik
Copy link
Author

Here are events provided by nvim-tree, just for the reference:

- Event.WillRenameNode
                • Note: A node can either be a file or a directory.
                handler parameters: ~
                  {old_name}     `{string}` Absolute path to the old node location.
                  {new_name}     `{string}` Absolute path to the new node location.

- Event.NodeRenamed
                • Note: A node can either be a file or a directory.
                handler parameters: ~
                  {old_name}     `{string}` Absolute path to the old node location.
                  {new_name}     `{string}` Absolute path to the new node location.

- Event.FileCreated
                handler parameters: ~
                  {fname}        `{string}` Absolute path to the created file

- Event.WillCreateFile
                handler parameters: ~
                  {fname}        `{string}` Absolute path to the file to be
                  created

- Event.FileRemoved
                handler parameters: ~
                  {fname}        `{string}` Absolute path to the removed file.

- Event.WillRemoveFile
                handler parameters: ~
                  {fname}        `{string}` Absolute path to the file to be
                  removed

- Event.FolderCreated
                handler parameters: ~
                  {folder_name}  `{string}` Absolute path to the created folder.

- Event.FolderRemoved
                handler parameters: ~
                  {folder_name}  `{string}` Absolute path to the removed folder.

@rchatham
Copy link

+1 to this! @wojciech-kulik really appreciate all your work to support mac/ios dev in nvim so far. Found this because I prefer using oil and was curious on how to integrate it with your current work, turns out you are already working on it 😄

@wojciech-kulik
Copy link
Author

wojciech-kulik commented Feb 21, 2024

@rchatham haha, nice to meet you here, the internet is a small place 😂

@stevearc stevearc added the P0 Highest priority, will receive attention label Feb 21, 2024
@wSedlacek
Copy link

Having events would help me too.
I have noticed that often times after I delete a file from disk with oil.nvim I still end up with the buffer open.
I would love a solution for removing buffers when files are deleted from disk.
Events could let me setup autocmds to do that.

@stevearc
Copy link
Owner

Okay, I've added two User autocmds that you can subscribe to: OilActionsPre and OilActionsPost. These both include the raw actions that oil will/did process in the data. Note that since oil supports trash and ssh, these actions are not just simple file paths, but fully-specified urls like oil:///path/to/file. You can split this into the url_scheme + url_path easily with this logic, which you can either copy or call directly:

---@param url string
---@return nil|string
---@return nil|string
M.parse_url = function(url)
return url:match("^(.*://)(.*)$")
end

The full definition of the shapes of actions can be found in these type definitions:

---@alias oil.Action oil.CreateAction|oil.DeleteAction|oil.MoveAction|oil.CopyAction|oil.ChangeAction
---@class (exact) oil.CreateAction
---@field type "create"
---@field url string
---@field entry_type oil.EntryType
---@field link nil|string
---@class (exact) oil.DeleteAction
---@field type "delete"
---@field url string
---@field entry_type oil.EntryType
---@class (exact) oil.MoveAction
---@field type "move"
---@field entry_type oil.EntryType
---@field src_url string
---@field dest_url string
---@class (exact) oil.CopyAction
---@field type "copy"
---@field entry_type oil.EntryType
---@field src_url string
---@field dest_url string
---@class (exact) oil.ChangeAction
---@field type "change"
---@field entry_type oil.EntryType
---@field url string
---@field column string
---@field value any

And here's a simple example of subscribing to the events:

vim.api.nvim_create_autocmd("User", {
  pattern = "OilActionsPre",
  callback = function(args) vim.print(args) end,
})
vim.api.nvim_create_autocmd("User", {
  pattern = "OilActionsPost",
  callback = function(args)
    -- If err is non-null, we encountered an error while processing the actions
    if args.data.err then
      vim.print("ERROR", args.data.err)
    else
      vim.print(args)
    end
  end,
})

@wSedlacek
Copy link

wSedlacek commented Mar 18, 2024

A practical example. Deleting a file with oil will close the buf open with that file (if any)

---@param url string
---@return nil|string
---@return nil|string
local parse_url = function(url)
  return url:match "^.*://(.*)$"
end

vim.api.nvim_create_autocmd("User", {
  pattern = "OilActionsPost",
  callback = function(args)
    if args.data.err == nil then
      for _, action in ipairs(args.data.actions) do
        if action.type == "delete" then
          local path = parse_url(action.url)
          local bufnr = vim.fn.bufnr(path)
          if bufnr == -1 then
            return
          end

          vim.t.bufs = vim.tbl_filter(function(b)
            return b ~= bufnr
          end, vim.t.bufs)
          vim.cmd("bdelete " .. bufnr)
        end
      end
    end
  end,
})
Screen.Recording.2024-03-17.at.23.50.58.mov

❤️ Thank you for making this possible @stevearc

@wojciech-kulik
Copy link
Author

Thank you @stevearc!

@wojciech-kulik
Copy link
Author

wojciech-kulik commented Mar 18, 2024

@stevearc I get this error when I try moving a file from one folder to another:
image

I figured out that it happens because I use a binding that calls :wa

@wojciech-kulik
Copy link
Author

I started performing multiple operations (one by one) and after moving folder back and forth I got this issue:
image

@stevearc
Copy link
Owner

@wojciech-kulik please file this as a new issue with complete reproduction steps

wojciech-kulik added a commit to wojciech-kulik/xcodebuild.nvim that referenced this issue Mar 19, 2024
@wojciech-kulik
Copy link
Author

wojciech-kulik commented Mar 19, 2024

I updated @wSedlacek version to:

-- close deleted files via oil.nvim
vim.api.nvim_create_autocmd("User", {
  pattern = "OilActionsPost",
  callback = function(args)
    local parse_url = function(url)
      return url:match("^.*://(.*)$")
    end

    if args.data.err then
      return
    end

    for _, action in ipairs(args.data.actions) do
      if action.type == "delete" and action.entry_type == "file" then
        local path = parse_url(action.url)
        local bufnr = vim.fn.bufnr(path)
        if bufnr == -1 then
          return
        end

        vim.cmd("bw " .. bufnr)
      end
    end
  end,
})

However, it looks like I can't delete any buffer when floating oil is visible. Even if I manually run :bw BUFNR it doesn't work. Only if I close oil.

Any ideas why it is happening?


Ok, I figured it out, I can't wipe out a buffer that is the last one visible. So the fix is to just navigate first to the previous one:

vim.cmd("bp | bw " .. bufnr)

@wojciech-kulik
Copy link
Author

I improved the version above:

-- close deleted files via oil.nvim
vim.api.nvim_create_autocmd("User", {
  pattern = "OilActionsPost",
  callback = function(args)
    local parse_url = function(url)
      return url:match("^.*://(.*)$")
    end

    if args.data.err then
      return
    end

    for _, action in ipairs(args.data.actions) do
      if action.type == "delete" and action.entry_type == "file" then
        local path = parse_url(action.url)
        local bufnr = vim.fn.bufnr(path)
        if bufnr == -1 then
          return
        end

        local winnr = vim.fn.win_findbuf(bufnr)[1]
        if not winnr then
          return
        end

        vim.fn.win_execute(winnr, "bfirst | bw " .. bufnr)
      end
    end
  end,
})

as we are still in Oil, we need to use vim.fn.win_execute

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request P0 Highest priority, will receive attention
Projects
None yet
Development

No branches or pull requests

4 participants