feat: emit CanolaFileCreated autocmd on file creation (#75)

* feat: emit \`CanolaFileCreated\` autocmd on file creation

Problem: no way to hook into individual file creation to populate
initial contents, without a plugin-specific config callback.

Solution: fire \`User CanolaFileCreated\` with \`data.path\` after each
successful \`fs.touch\` in the files adapter. Users listen with
\`nvim_create_autocmd\` and write to the path however they like.

* build: gitignore `doc/upstream.html`

* docs(upstream): mark #721 fixed, triage #735

* docs(upstream): simplify #735 note
This commit is contained in:
Barrett Ruth 2026-03-06 15:54:01 -05:00 committed by GitHub
parent c7a55fd787
commit a74747e1f5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 41 additions and 13 deletions

1
.gitignore vendored
View file

@ -1,4 +1,5 @@
doc/tags
doc/upstream.html
*.log
.*cache*
CLAUDE.md

View file

@ -1135,6 +1135,22 @@ CanolaMutationComplete *CanolaMutationComp
additional data fields. Use this event for post-mutation side effects such
as refreshing external status indicators.
CanolaFileCreated *CanolaFileCreated*
Fired after a new file is successfully created on the local filesystem.
The `args.data.path` field contains the absolute path of the created file.
Use this event to populate initial file contents, run formatters, or
perform any other setup on newly created files. >lua
vim.api.nvim_create_autocmd("User", {
pattern = "CanolaFileCreated",
callback = function(args)
local path = args.data.path
if path:match("%.sh$") then
vim.fn.writefile({ "#!/usr/bin/env bash" }, path)
end
end,
})
<
--------------------------------------------------------------------------------
TRASH *canola-trash*

View file

@ -37,21 +37,20 @@ Bugs fixed in this fork that remain open upstream.
## Open upstream PRs
| PR | Description | Status |
| ----------------------------------------------------- | ------------------------------------------- | ------------------------------------------------------------------------------------ |
| [#488](https://github.com/stevearc/oil.nvim/pull/488) | Parent directory in a split | not actionable — empty PR |
| [#493](https://github.com/stevearc/oil.nvim/pull/493) | UNC paths on Windows | not actionable — superseded by [#686](https://github.com/stevearc/oil.nvim/pull/686) |
| [#591](https://github.com/stevearc/oil.nvim/pull/591) | release-please changelog | not applicable |
| [#667](https://github.com/stevearc/oil.nvim/pull/667) | Virtual text columns + headers | deferred — WIP, conflicting |
| [#686](https://github.com/stevearc/oil.nvim/pull/686) | Windows path conversion fix | not actionable — Windows-only |
| [#708](https://github.com/stevearc/oil.nvim/pull/708) | Move file into new dir by renaming | deferred — needs rewrite |
| [#721](https://github.com/stevearc/oil.nvim/pull/721) | `create_hook` to populate file contents | deferred — fixing via autocmd event on file create |
| [#728](https://github.com/stevearc/oil.nvim/pull/728) | `open_split` for opening oil in a split | tracked — [#2](https://github.com/barrettruth/canola.nvim/issues/2) |
| [#735](https://github.com/stevearc/oil.nvim/pull/735) | gX opens external program with selection | not actionable — hardcoded Linux-only program list, no config surface, author-acknowledged incomplete |
| PR | Description | Status |
| ----------------------------------------------------- | ------------------------------------------- | ----------------------------------------------------------------------------------------------- |
| [#488](https://github.com/stevearc/oil.nvim/pull/488) | Parent directory in a split | not actionable — empty PR |
| [#493](https://github.com/stevearc/oil.nvim/pull/493) | UNC paths on Windows | not actionable — superseded by [#686](https://github.com/stevearc/oil.nvim/pull/686) |
| [#591](https://github.com/stevearc/oil.nvim/pull/591) | release-please changelog | not applicable |
| [#667](https://github.com/stevearc/oil.nvim/pull/667) | Virtual text columns + headers | deferred — WIP, conflicting |
| [#686](https://github.com/stevearc/oil.nvim/pull/686) | Windows path conversion fix | not actionable — Windows-only |
| [#708](https://github.com/stevearc/oil.nvim/pull/708) | Move file into new dir by renaming | deferred — needs rewrite |
| [#721](https://github.com/stevearc/oil.nvim/pull/721) | `create_hook` to populate file contents | fixed — `CanolaFileCreated` autocmd — [#75](https://github.com/barrettruth/canola.nvim/pull/75) |
| [#728](https://github.com/stevearc/oil.nvim/pull/728) | `open_split` for opening oil in a split | tracked — [#2](https://github.com/barrettruth/canola.nvim/issues/2) |
| [#735](https://github.com/stevearc/oil.nvim/pull/735) | gX opens external program with a selection. | not actionable — wrong abstraction layer |
## Upstream issues
| Issue | Status | Notes |
| ------------------------------------------------------- | -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| [#85](https://github.com/stevearc/oil.nvim/issues/85) | open | Git status column (P2) |

View file

@ -600,7 +600,19 @@ M.perform_action = function(action, cb)
---@diagnostic disable-next-line: param-type-mismatch
uv.fs_symlink(target, path, flags, cb)
else
fs.touch(path, config.new_file_mode, cb)
fs.touch(
path,
config.new_file_mode,
vim.schedule_wrap(function(err)
if not err then
vim.api.nvim_exec_autocmds(
'User',
{ pattern = 'CanolaFileCreated', modeline = false, data = { path = path } }
)
end
cb(err)
end)
)
end
elseif action.type == 'delete' then
local _, path = util.parse_url(action.url)