Commit graph

441 commits

Author SHA1 Message Date
Barrett Ruth
c7b905137c
fix: make parent action a no-op at filesystem root (#109)
Problem: at the filesystem root (`/`), `actions.parent` triggers a
full `vim.cmd.edit()` and async re-render cycle even though the parent
of `/` is `/`.

Solution: in `canola.open()`, return early when `parent_url` equals
the current buffer name.

Closes #108.
2026-03-09 18:05:04 -04:00
Barrett Ruth
39374ee99b
fix(select): redraw screen after buffer switch (#106)
* fix(select): redraw screen after buffer switch

Problem: `select` opens files inside a `vim.schedule_wrap` callback
from `normalize_url`. Scheduled `FileType` autocmds (e.g. treesitter
parsing) queue onto the same batch, blocking the screen update. The
oil buffer stays visible until the heavy work finishes.

Solution: call `vim.cmd.redraw()` after the buffer switch to flush
the screen before any queued scheduled callbacks run. Matches the
behavior of plain `:e`.

* docs(upstream): mark #699 fixed (#106)
2026-03-09 17:40:19 -04:00
Barrett Ruth
425a53d2fa
fix(view): constrain cursor in insert mode (#93)
Problem: `constrain_cursor` only fired on `CursorMoved` and
`ModeChanged`, so arrow key navigation in insert mode could move
the cursor into the concealed ID prefix area.

Solution: add `CursorMovedI` to the autocmd event list. The
`constrain_cursor()` function is already mode-agnostic.
2026-03-08 16:02:09 -04:00
Barrett Ruth
94db584f81
feat: add toggle() API for regular windows (#88)
* feat: add `toggle()` API for regular windows

Problem: `toggle_float()` and `toggle_split()` exist but there is no
`toggle()` for regular windows, forcing users to write their own
filetype-checking wrapper.

Solution: add `M.toggle()` that delegates to `close()` or `open()`
based on whether the current buffer is a canola buffer. Includes
vimdoc entry.

* docs(upstream): mark #621 fixed
2026-03-08 15:33:45 -04:00
Barrett Ruth
fc43684bbd
fix(columns): hide misleading directory sizes (#87)
* fix(columns): hide misleading directory sizes in size column

Problem: the size column shows the filesystem inode size (typically
4096 = 4.1k) for directories, which is misleading — users expect no
size for directories.

Solution: add an early return for directory entries in the size render
function of the files, SSH, and S3 adapters.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* docs(upstream): mark #486 fixed

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 15:31:43 -04:00
Barrett Ruth
4a8d57a269
feat: add max_file_size preview limit and show_hidden_when_empty (#85)
* feat(preview): add `max_file_size` config to skip large file previews

Problem: previewing large files (e.g. 500 MB logs, binaries) loads them
into a buffer and can freeze or OOM Neovim. `disable_preview` only
receives the filename, so users cannot gate on file size.

Solution: add `preview_win.max_file_size` (number, MB, default 10). In
`open_preview`, check `entry.meta.stat.size` and fall back to
`vim.uv.fs_stat` when the cached stat is absent. If the file exceeds
the limit and a preview window is already open, render "File too large
to preview" in it; if not, emit a WARN notify and return early. The
cursor-moved auto-update path only fires when a window already exists,
so no flag threading is needed to distinguish explicit from implicit.

Based on: stevearc/oil.nvim#213

* feat(view): add `show_hidden_when_empty` for hidden-only directories

Problem: with `show_hidden = false`, a directory containing only
dotfiles renders as just `..`, giving no indication that entries exist.

Solution: add `view_options.show_hidden_when_empty` (boolean, default
false). After the main filter loop in `render_buffer`, if the option is
set and `#line_table <= 1`, iterate `entry_list` again and render any
entry not matched by `is_always_hidden`, using `is_hidden = true` so
they render with the dimmed hidden style.

Based on: stevearc/oil.nvim#473

* docs(upstream): fix formatting

* docs(upstream): update #213 and #473 with PR and commit links
2026-03-07 16:52:57 -05:00
Barrett Ruth
a9a06b8f3b
feat: add auto_save_on_select_new_entry config option (#84)
Problem: users who want hands-off behaviour had no way to skip the
`prompt_save_on_select_new_entry` confirmation dialog — enabling the
prompt meant always being asked, with no silent auto-save path.

Solution: add `auto_save_on_select_new_entry` (default `false`) which,
when true, calls `M.save()` and proceeds immediately instead of showing
the confirm dialog. Includes type annotations, vimdoc, and upstream
tracker update for stevearc/oil.nvim#393.
2026-03-07 16:08:34 -05:00
Barrett Ruth
082573d779
feat: add open_split/toggle_split API and upstream triage batch (#83)
* docs(upstream): triage batch — #739 cherry-pick, 10 issue updates

* feat: add `open_split` and `toggle_split` API

Problem: canola had no way to open a browser in a normal split window;
only floating windows were supported via `open_float`/`toggle_float`.
`M.close` also crashed with E444 when called from the last window.

Solution: port stevearc/oil.nvim#728 — add `open_split(dir, opts, cb)`
and `toggle_split(dir, opts, cb)` mirroring the float API. Use
`is_canola_win`/`canola_original_win` window vars (not the upstream
`is_oil_win` names). Wrap `nvim_win_close` in `pcall` with `enew()`
fallback to handle the last-window E444 case.

Based on: stevearc/oil.nvim#728

* docs: add vimdoc for `open_split`/`toggle_split` and macOS trash recipe

Cherry-picked from: stevearc/oil.nvim#739

* docs(upstream): fix prettier formatting
2026-03-07 15:45:23 -05:00
Barrett Ruth
01f10e1d79
refactor: drop nvim 0.8/0.9 compat shims from init.lua (#79) 2026-03-06 16:36:37 -05:00
Barrett Ruth
0f386bb69c
fix: show float title when border is nil (#78)
* fix: show float title when border is nil

Problem: the float title was only shown via the native `nvim_win_set_config`
path, which requires a border to render. The guard `config.float.border ~=
'none'` did not account for `nil`, which is the default — so users with no
explicit `border` config never saw the path title in the floating window.

Solution: require both `~= nil` and `~= 'none'` before using the native
title. In all other cases (border nil, 'none', or nvim < 0.9), fall back to
`util.add_title_to_win`, which renders a child floating window for the title.

Based on: stevearc/oil.nvim#683

* refactor: drop nvim-0.9 version checks in float title logic
2026-03-06 16:29:47 -05:00
Barrett Ruth
ba49f76e91
feat: add skip_confirm_for_delete option (#77)
feat: add \`skip_confirm_for_delete\` option

Problem: there was no way to suppress the confirmation popup when the
only pending operations are deletes. \`skip_confirm_for_simple_edits\`
explicitly excludes deletes, so users who delete frequently had no opt-out.

Solution: add \`skip_confirm_for_delete = false\` config option. When true,
\`confirmation.show()\` skips the popup if every pending action is a delete.

Based on: stevearc/oil.nvim#392
2026-03-06 16:29:12 -05:00
Barrett Ruth
7a46246062
fix: escape on save prompt cancels select (#76)
Problem: when `prompt_save_on_select_new_entry` is enabled and the user
presses Escape on the "Save changes?" confirm dialog, `vim.fn.confirm`
returns 0, but the select continued as if the user had chosen "No".

Solution: add an explicit `choice == 0` branch that returns immediately,
aborting the select without saving or opening any files.
2026-03-06 16:28:57 -05:00
Barrett Ruth
a74747e1f5
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
2026-03-06 15:54:01 -05:00
Barrett Ruth
1ee6c6b259
feat: add cleanup_buffers_on_delete option (#73)
Problem: When files are deleted via canola, any open Neovim buffers
for those files remain alive, polluting the jumplist with stale
entries.

Solution: Add an opt-in `cleanup_buffers_on_delete` config option
(default `false`). When enabled, `finish()` in `mutator/init.lua`
iterates completed delete actions and wipes matching buffers via
`nvim_buf_delete` before `CanolaActionsPost` fires. Only local
filesystem deletes are handled (guarded by the `files` adapter
check).
2026-03-06 15:19:32 -05:00
Barrett Ruth
69d85b8de1
feat(view): position cursor at name column on new empty lines (#72)
Problem: pressing `o`/`O` in a canola buffer placed the cursor at
column 0, requiring manual navigation past concealed ID prefixes and
column text (icons, permissions) to reach the name column.

Solution: add `show_insert_guide()` which temporarily sets
`virtualedit=all` on empty lines and positions the cursor at the
name column. Computes the correct virtual column by measuring the
visible column prefix width via `nvim_strwidth`, adjusting for
`conceallevel` (0=full ID width, 1=replacement char, 2/3=hidden).
Restores `virtualedit` on `TextChangedI` or `InsertLeave`.
2026-03-06 14:40:10 -05:00
Barrett Ruth
41f375ee9e
fix: restore buflisted on jumplist buffer re-entry (#71)
* fix: restore `buflisted` on jumplist buffer re-entry

Problem: Neovim's jumplist machinery re-enters canola buffers via an
internal `:edit`-equivalent path, which unconditionally sets
`buflisted = true`. The existing workaround in `open()` and
`open_float()` only covers canola-initiated navigation, leaving
`<C-o>` and `<C-i>` unhandled.

Solution: Apply the same `buf_options.buflisted` guard in the
`BufEnter` autocmd, directly after `set_win_options()`. This fires
on every buffer entry — including all jumplist paths — and mirrors
the pattern already used at the two `:edit` callsites.

* docs: mark upstream #302 as fixed in tracker
2026-03-06 11:55:37 -05:00
c3de0004d1
ci: format 2026-03-05 14:53:30 -05:00
Barrett Ruth
0d3088f57e
refactor: rename oil to canola across entire codebase (#70)
Problem: the codebase still used the upstream \`oil\` naming everywhere —
URL schemes, the \`:Oil\` command, highlight groups, user events, module
paths, filetypes, buffer/window variables, LuaCATS type annotations,
vimdoc help tags, syntax groups, and internal identifiers.

Solution: mechanical rename of every reference. URL schemes now use
\`canola://\` (plus \`canola-ssh://\`, \`canola-s3://\`, \`canola-sss://\`,
\`canola-trash://\`, \`canola-test://\`). The \`:Canola\` command replaces
\`:Oil\`. All highlight groups, user events, augroups, namespaces,
filetypes, require paths, type annotations, help tags, and identifiers
follow suit. The \`upstream\` remote to \`stevearc/oil.nvim\` has been
removed and the \`vim.g.oil\` deprecation shim dropped.
2026-03-05 14:50:10 -05:00
63fb912d52
fix(icons): use nonicons hl groups 2026-03-02 20:21:47 -05:00
05234a67ba
fix: use guard clause 2026-03-02 19:26:02 -05:00
262bf8710e
fix: ensure nvim-web-devicoins exists 2026-03-02 19:25:08 -05:00
b87c665ccb
fix(icon): use fill directory by default 2026-02-23 17:20:44 -05:00
60bfbe05da fix: preserve devicons highlight groups in nonicons icon provider
Problem: when the nonicons direct API was detected, all icons were
returned with the generic 'OilFileIcon' highlight group, losing
per-filetype colors from nvim-web-devicons.

Solution: resolve highlight groups from devicons when available so
nonicons glyphs retain their per-filetype colors.
2026-02-23 15:16:25 -05:00
Barrett Ruth
d1f7c691b5
feat(icons): add direct nonicons.nvim icon provider (#31)
Problem: nonicons.nvim exposes a public get_icon/get_icon_by_filetype
API, but oil.nvim can only use nonicons glyphs indirectly through the
devicons monkey-patch. This couples oil to devicons even when nonicons
is available standalone.

Solution: add a nonicons provider in get_icon_provider() between
mini.icons and devicons. Feature-gated on nonicons.get_icon existing
so old nonicons versions fall through to devicons. Uses OilDirIcon
and OilFileIcon highlight groups.
2026-02-22 21:31:09 -05:00
b0f44d3af6
fix: remove nonicons custom impl
Some checks failed
luarocks / quality (push) Has been cancelled
luarocks / publish (push) Has been cancelled
2026-02-22 21:03:56 -05:00
Barrett Ruth
07ae3a8dc3
feat(icons): add nonicons.nvim icon provider support (#30)
* feat(icons): add nonicons.nvim icon provider support

Problem: oil.nvim only recognizes mini.icons and nvim-web-devicons as
icon providers. nonicons.nvim works when paired with devicons (via its
apply() monkey-patch), but has no standalone support.

Solution: add a nonicons.nvim fallback in get_icon_provider(), placed
after devicons so the patched devicons path is preferred when both are
installed. The standalone path handles directories via
nonicons.get('file-directory'), files via filetype/extension lookup with
a generic file icon fallback.

* fix(doc): improve readme phrasing
2026-02-22 20:58:22 -05:00
Barrett Ruth
86f553cd0a
build: replace luacheck with selene, add nix devshell and pre-commit (#20)
* build: replace luacheck with selene

Problem: luacheck is unmaintained (last release 2018) and required
suppressing four warning classes to avoid false positives. It also
lacks first-class vim/neovim awareness.

Solution: switch to selene with std='vim' for vim-aware linting.
Replace the luacheck CI job with selene, update the Makefile lint
target, and delete .luacheckrc.

* build: add nix devshell and pre-commit hooks

Problem: oil.nvim had no reproducible dev environment. The .envrc
set up a Python venv for the now-removed docgen pipeline, and there
were no pre-commit hooks for local formatting checks.

Solution: add flake.nix with stylua, selene, and prettier in the
devshell. Replace the stale Python .envrc with 'use flake'. Add
.pre-commit-config.yaml with stylua and prettier hooks matching
other plugins in the repo collection.

* fix: format with stylua

* build(selene): configure lints and add inline suppressions

Problem: selene fails on 5 errors and 3 warnings from upstream code
patterns that are intentional (mixed tables in config API, unused
callback parameters, identical if branches for readability).

Solution: globally allow mixed_table and unused_variable (high volume,
inherent to the codebase design). Add inline selene:allow directives
for the 8 remaining issues: if_same_then_else (4), mismatched_arg_count
(1), empty_if (2), global_usage (1). Remove .envrc from tracking.

* build: switch typecheck action to mrcjkb/lua-typecheck-action

Problem: oil.nvim used stevearc/nvim-typecheck-action, which required
cloning the action repo locally for the Makefile lint target. All
other plugins in the collection use mrcjkb/lua-typecheck-action.

Solution: swap to mrcjkb/lua-typecheck-action@v0 for consistency.
Remove the nvim-typecheck-action git clone from the Makefile and
.gitignore. Drop LuaLS from the local lint target since it requires
a full language server install — CI handles it.
2026-02-21 23:52:27 -05:00
Barrett Ruth
856716e6dc
feat: support vim.g.oil configuration + remove release-please (#17)
* feat: support vim.g.oil declarative configuration

Problem: oil.nvim requires an imperative require("oil").setup(opts)
call to initialize. The Neovim ecosystem is moving toward vim.g.plugin
as a declarative config source that works without explicit setup calls.

Solution: fall back to vim.g.oil in config.setup() when no opts are
passed, and add plugin/oil.lua to auto-initialize when vim.g.oil is
set. Explicit setup(opts) calls still take precedence. Update docs
and add tests for the new resolution order.

Closes: barrettruth/oil.nvim#1

* build: remove release-please pipeline

Problem: the release-please action creates automated releases that
are not needed for this fork's workflow.

Solution: remove the release job from tests.yml and the
release-please branch exclusion from the review request workflow.

* fix(doc): improve readme phrasing

* doc: minor phrasing "improvements"

* ci: add luarocks release on tag push

Problem: there is no automated way to publish oil.nvim to luarocks
when a new version is tagged.

Solution: add a luarocks workflow that triggers on v* tag pushes,
runs the test suite via workflow_call, then publishes via
luarocks-tag-release. Add workflow_call trigger to tests.yml so it
can be reused.
2026-02-21 22:38:38 -05:00
Barrett Ruth
fe16993262
fix(preview): prevent preview from re-initializing modified oil buffers (#12)
Problem: when the preview window opens a directory that already has a
loaded oil buffer with unsaved edits, open_preview() unconditionally
calls load_oil_buffer() on it. This re-initializes the buffer via
view.initialize() -> render_buffer_async(), which re-fetches the
directory listing from disk and replaces all buffer lines, destroying
the user's pending edits. The mutation parser then can't see the
deleted entry in the source buffer, so it produces a COPY action
instead of a MOVE.

Solution: guard the load_oil_buffer() call in open_preview() with a
check for vim.b[filebufnr].oil_ready. Buffers that are already
initialized and rendered are not re-loaded, preserving any unsaved
modifications the user has made.

Closes: stevearc/oil.nvim#632
2026-02-21 02:43:59 -05:00
Barrett Ruth
70861e5896
fix: hijack all directory buffers at setup, not just current (#11)
Problem: when neovim is opened with multiple directory arguments
(e.g. nvim dir1/ dir2/), only the first directory gets handled by oil.
The BufAdd autocmd that renames directory buffers to oil:// URLs is
registered inside setup(), but neovim creates all argument buffers
before setup() runs. The initial hijack block only processes
nvim_get_current_buf(), so additional directory buffers are never
renamed and remain as plain empty buffers.

Solution: iterate all existing buffers at setup time instead of only
the current one. Each directory buffer gets renamed to an oil:// URL
so that BufReadCmd fires when the user switches to it.

Closes: stevearc/oil.nvim#670
2026-02-21 02:22:49 -05:00
Barrett Ruth
01b860ed5c
fix: set buftype before BufEnter fires on oil buffers (#10)
Problem: oil sets buftype='acwrite' inside view.initialize(), which runs
in an async finish() callback after adapter.normalize_url(). BufEnter
fires before finish() completes, so user autocmds that check buftype on
oil buffers see an empty string instead of 'acwrite'.

Solution: set buftype='acwrite' early in load_oil_buffer() alongside the
existing early filetype='oil' assignment, before the async gap. The
redundant set in view.initialize() is harmless (idempotent).

Closes: stevearc/oil.nvim#710
2026-02-21 02:22:38 -05:00
181e735c3b
fix: move opts cast after second tbl_deep_extend in render_buffer_async
Problem: the ---@cast opts -nil was placed after the first opts guard
but LuaLS loses narrowing at the second tbl_deep_extend on line 928,
causing a persistent need-check-nil warning at opts.refetch.

Solution: remove the redundant first opts = opts or {} guard (the
tbl_deep_extend already handles nil) and place the cast after the
second tbl_deep_extend where opts is actually used.
2026-02-20 20:51:39 -05:00
6dcd9c0d8f
fix: add missing cast for opts in render_buffer_async
Problem: LuaLS still warns at opts.refetch access because it does not
track narrowing through opts = opts or {}.

Solution: add ---@cast opts -nil after the guard, matching the same
pattern used in util.render_text.
2026-02-20 20:49:18 -05:00
642f745038
fix: resolve pre-existing LuaLS typecheck warnings
Problem: CI typecheck fails with 13 warnings — 11 need-check-nil in
util.render_text (opts param annotated nil|table but guaranteed non-nil
after tbl_deep_extend), 1 undefined-doc-param in view.render_buffer_async
(annotation says "callback" but param is "caller_callback"), and 1
need-check-nil on opts in the same function.

Solution: add ---@cast opts -nil after the tbl_deep_extend call, fix
the param name in the doc annotation, and add opts = opts or {} guard.
2026-02-20 20:34:59 -05:00
209d631cb9
fix(ci): format 2026-02-20 20:27:55 -05:00
f6bcdda988
feat(actions): add close_float to close only floating oil windows
Problem: users who bind <Esc> to close oil in floating windows also
accidentally close oil in split or fullscreen windows. There is no
action that closes only a floating oil window and is a no-op otherwise.

Solution: add a close_float action that checks vim.w.is_oil_win (the
same window-local variable oil.close already uses to identify its own
floating windows) before delegating to oil.close.

Resolves: stevearc/oil.nvim#645
2026-02-20 20:26:08 -05:00
ce64ae18de
feat: add OilFileIcon highlight group for fallback file icons
Problem: when nvim-web-devicons returns no highlight for an unrecognized
file extension, the icon gets nil for its highlight group. Directories
have OilDirIcon as a targetable fallback, but files have nothing.

Solution: define OilFileIcon (linked to nil, matching OilFile) and use
it as the fallback in the devicons provider when get_icon returns a nil
highlight. The mini.icons provider already returns highlights for all
files so only the devicons path needs this.

Resolves: stevearc/oil.nvim#690
2026-02-20 20:26:08 -05:00
85ed9b8a72
fix: add missing OilExecutableHidden highlight group
Problem: the rendering code constructs "OilExecutable" .. "Hidden" for
hidden executables, but that group was never defined. Hidden executables
silently lose all highlighting instead of being dimmed like every other
hidden entry type.

Solution: add OilExecutableHidden linked to OilHidden, consistent with
OilFileHidden, OilDirHidden, and all other hidden variants.

Based on: stevearc/oil.nvim#698
2026-02-20 20:26:08 -05:00
9110a1a499
fix(view): strip newlines from symlink target display text
Problem: when a symlink target path contains a newline character, the
rendered line passed to nvim_buf_set_lines includes that newline,
causing the error "'replacement string' item contains newlines".

Solution: apply the same gsub("\n", "") sanitization to meta.link in
get_link_text that is already used for entry names at line 791.

Resolves: stevearc/oil.nvim#673
2026-02-20 20:26:08 -05:00
ca834cf703
fix(view): suppress W10 warning when nvim is launched with -R
Problem: when Neovim is started with -R (read-only), all buffers get
readonly=true. Oil's render_buffer toggles modifiable to write directory
listings, which triggers "W10: Warning: Changing a readonly file" on
every directory navigation.

Solution: clear readonly on oil buffers during initialization. Oil
buffers are buftype=acwrite — readonly has no meaning for them since
writes go through BufWriteCmd, not the filesystem.

Resolves: stevearc/oil.nvim#642
2026-02-20 20:26:07 -05:00
c6b4a7a07b
feat: add configurable file and directory creation permissions
Problem: files were always created with mode 0644 and directories
with 0755, hardcoded in fs.touch and uv.fs_mkdir. Users who need
different defaults (e.g. 0600 for security) had no config option.

Solution: add new_file_mode (default 420 = 0644) and new_dir_mode
(default 493 = 0755) config options, passed through to fs.touch and
uv.fs_mkdir in the files and mac trash adapters. The fs.touch
signature accepts an optional mode parameter with backwards
compatibility (detects function argument to support old callers).
Local cache directories (SSH, S3) continue using standard system
permissions rather than the user-configured mode.

Based on: stevearc/oil.nvim#537
2026-02-20 20:26:07 -05:00
ded17258cd
feat(icon): add opt-in filetype detection via file contents
Problem: files without standard extensions (e.g. scripts with
shebangs, Makefile, Dockerfile) got incorrect or default icons since
icon providers match by filename or extension only.

Solution: add use_slow_filetype_detection option to the icon column
config. When enabled, reads the first 16 lines of each file and
passes them to vim.filetype.match for content-based detection. The
detected filetype is forwarded to mini.icons or nvim-web-devicons as
a trailing parameter, preserving backwards compatibility with
existing icon provider implementations.

Based on: stevearc/oil.nvim#618
2026-02-20 20:26:07 -05:00
41556ec87f
feat: add highlight for executable files
Problem: executable files were visually indistinguishable from regular
files in oil buffers.

Solution: add OilExecutable highlight group (linked to DiagnosticOk)
that detects executables via Unix permission bits (S_IXUSR|S_IXGRP|
S_IXOTH) and Windows executable extensions (.exe, .bat, .cmd, .com,
.ps1). Applied to both regular files and symlink targets.

Based on: stevearc/oil.nvim#698
Closes stevearc/oil.nvim#679
2026-02-20 20:26:07 -05:00
4ab4765a84 feat: pass entry to is_hidden_file and is_always_hidden callbacks
Problem: the is_hidden_file and is_always_hidden config callbacks
only received (name, bufnr), making it impossible to filter by entry
type, permissions, or other metadata without reimplementing entry
lookup.

Solution: pass the full oil.Entry as a third argument to both
callbacks. Existing configs that only accept (name, bufnr) are
unaffected since Lua silently ignores extra arguments. The internal
should_display function signature changes from (name, bufnr) to
(bufnr, entry) to reflect its new contract.

Cherry-picked from: stevearc/oil.nvim#644
2026-02-20 16:29:08 -05:00
16f3d7bfa9 fix: cancel visual/operator-pending mode instead of closing buffer
Problem: when close() is triggered from visual or operator-pending
mode (e.g. pressing q after d in an oil buffer), the buffer closes
instead of canceling the pending operation. This happens because
keymaps without an explicit mode default to "" which covers normal,
visual, select, and operator-pending modes.

Solution: check the current mode at the top of close() and send
<Esc> to cancel the mode instead of proceeding with the close. The
check covers all visual modes (v, V, CTRL-V), select modes (s, S,
CTRL-S), and operator-pending submodes (no, nov, noV, noCTRL-V).

Based on: stevearc/oil.nvim#495
2026-02-20 16:28:26 -05:00
29239d56fb feat: emit OilReadPost user event after each buffer render
Problem: third-party plugins like oil-git-status.nvim had no way to
know when an oil buffer was re-rendered after a filesystem change,
causing their decorations to be cleared with no signal to refresh.

Solution: emit a User OilReadPost autocmd after every successful
render_buffer_async call. Also document all oil user events
(OilEnter, OilReadPost, OilMutationComplete) in oil.txt since none
were previously documented.

Cherry-picked from: stevearc/oil.nvim#723
2026-02-20 16:27:09 -05:00
2228f80196 refactor: only create BufAdd autocmd when default_file_explorer is true
Problem: the BufAdd autocmd that hijacks directory buffers was always
created, even when default_file_explorer was false. The guard inside
maybe_hijack_directory_buffer made it a no-op, but the autocmd still
fired on every BufAdd event.

Solution: wrap the BufAdd autocmd creation and initial buffer hijack
in a config.default_file_explorer conditional. The guard inside
maybe_hijack_directory_buffer is kept as defense-in-depth.

Based on: stevearc/oil.nvim#720
2026-02-20 16:26:24 -05:00
723145c9fb fix: normalize keymap keys before merging user config
Problem: user keymap overrides like <c-t> failed to replace the
default <C-t> because the keys were compared as raw strings during
merge, leaving both entries in the table.

Solution: use nvim_replace_termcodes to compare keymap keys by their
internal representation, removing any default entry that normalizes
to the same key as the user-provided one before inserting it.

Closes #692
Cherry-picked from: stevearc/oil.nvim#725
2026-02-20 16:26:03 -05:00
eed6697ce2 docs: clarify get_current_dir nil return and add telescope recipe
Problem: get_current_dir returns nil in several cases that were not
documented, causing confusion when used in keymaps that open pickers
like Telescope (#682). Also, posix_to_os_path could crash on Windows
when no drive letter is found.

Solution: expand get_current_dir docs to explain nil return cases, add
a Telescope recipe with nil guards, and add a defensive nil check in
posix_to_os_path.

Cherry-picked from: stevearc/oil.nvim#727
2026-02-20 16:16:02 -05:00
b92ecb04ee fix(trash): update freedesktop trash specification url
Problem: the old URL specifications.freedesktop.org/trash-spec/1.0/ is
dead and redirects or 404s.

Solution: update to the current URL trash/1.0/ in docs, source, and
the generation script.

Cherry-picked from: stevearc/oil.nvim#722
2026-02-20 16:15:27 -05:00