Commit graph

558 commits

Author SHA1 Message Date
50f1ade92c
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.
2026-02-21 23:26:39 -05:00
364b787578
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.
2026-02-21 23:25:42 -05:00
Barrett Ruth
0f8b084e4a
Docs/centralize helpdoc (#18)
* 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

* doc: minor phrasing "improvements"

* fix(doc): restore Q/A format in FAQ and close lua block
2026-02-21 23:10:59 -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
3b930636e3
docs: centralize documentation into helpdoc (#15)
* docs: centralize documentation into helpdoc

Problem: documentation was spread across four files (README.md,
doc/oil.txt, doc/api.md, doc/recipes.md) with duplication and gaps.
User events were undocumented, and adapter docs only lived in the
README.

Solution: expand doc/oil.txt with five new sections (introduction,
requirements, adapters, recipes, events) from existing content. Trim
README to a landing page pointing to :help oil. Delete doc/api.md
and doc/recipes.md since their content now lives in the helpdoc.

Closes: barrettruth/oil.nvim#6

* build: remove docgen pipeline

Problem: the Python docgen pipeline (scripts/generate.py,
scripts/main.py, nvim_doc_tools) was designed for upstream's doc
layout and is incompatible with the centralized helpdoc structure.
It overwrites doc/oil.txt entirely and expects sections in README.md
that no longer exist.

Solution: delete the pipeline scripts (generate.py, main.py,
requirements.txt), remove the update_docs CI job, and clean up the
Makefile and .gitignore references. Linting and typechecking remain
unchanged.
2026-02-21 22:15:53 -05:00
Barrett Ruth
1712b6feb3
docs: upstream tracking in README + daily PR mirror (#13)
* docs: replace changelog with upstream divergence table in README

Problem: fork changes were not documented anywhere user-facing. The
auto-generated CHANGELOG.md tracked upstream releases, not fork
divergence.

Solution: delete CHANGELOG.md and add a collapsed <details> block to
README.md with two tables — cherry-picked PRs (by number, with commit
hashes) and triaged upstream issues (by number, with status and
resolution). This gives users a single place to see what the fork
offers over upstream.

* ci: add daily upstream PR mirror workflow

Problem: new upstream PRs required manual monitoring of
stevearc/oil.nvim to discover.

Solution: add a GitHub Actions workflow that runs daily at 08:00 UTC
and creates issues in the fork for any upstream PRs opened in the last
24 hours. Skips dependabot PRs and deduplicates by title prefix.
Issues are labeled upstream/pr for easy filtering.
2026-02-21 15:53:53 -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
034dce7f78
ci: request review from fork owner instead of upstream maintainer 2026-02-21 02:20:07 -05:00
bb128e96af
ci: replace docgen push with staleness check
Problem: the docgen workflow pushed directly to main, which is blocked
by repository rulesets. No token-based push from GitHub Actions can
bypass ruleset rules on personal repos.

Solution: replace the push step with a git diff --exit-code check that
fails if generated docs are out of date. Docs must now be committed by
the developer via make doc. Also regenerates docs to reflect batch 4
changes (close_float, OilFileIcon, OilExecutableHidden, recipe link).
2026-02-20 21:16:17 -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
60aed7d595
ci: use PUSH_TOKEN for docgen push to bypass branch rules
Problem: the docgen workflow pushes to main using GITHUB_TOKEN, which
authenticates as github-actions[bot]. The bot cannot bypass repository
rulesets on personal repos, so the push is rejected by required PR,
status check, and signature rules.

Solution: prefer a PUSH_TOKEN secret (a PAT authenticated as the repo
admin, who has bypass permissions) with fallback to GITHUB_TOKEN so
the workflow does not break before the secret is created.
2026-02-20 20:35:07 -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
38db6cf8ea
docs(recipes): add recipe to disable hidden file dimming
Problem: hidden files are dimmed via OilHidden -> Comment, and there is
no clean way to make them look identical to visible entries. Clearing
OilHidden alone causes all hidden types to lose their type-specific
coloring.

Solution: add a recipe that iterates _get_highlights() and relinks
each Oil*Hidden group to its non-hidden base. The Lua pattern
"^(Oil.+)Hidden$" naturally skips OilHidden itself and automatically
covers any future entry types.

Resolves: stevearc/oil.nvim#578
2026-02-20 20:26:08 -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
Github Actions
950d3d1ad2 [docgen] Update docs
skip-checks: true
2026-02-20 21:33:22 +00:00
42af6caf0a ci: rename default branch from master to main
Problem: the fork used master as the default branch name.

Solution: rename to main and update all CI workflow triggers,
ref checks, and the pre-push hook fallback.
2026-02-20 16:32:53 -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
dcb3a08776 docs: add recipe for custom file extension column
Problem: there was no example showing how to register and sort by a
custom column.

Solution: add a recipe demonstrating an "extension" column with
natural-order sorting.

Cherry-picked from: stevearc/oil.nvim#697
2026-02-20 16:16:49 -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
582d9fc815 docs: add malewicz1337/oil-git.nvim to third-party extensions
Problem: the async fork of oil-git.nvim with directory highlighting
was not listed in the README.

Solution: add it to the third-party extensions list, disambiguating
both oil-git.nvim entries by author name.

Cherry-picked from: stevearc/oil.nvim#717
2026-02-20 16:15:47 -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
Github Actions
f55b25e493 [docgen] Update docs
skip-checks: true
2026-01-17 05:01:19 +00:00
zeta-squared
7a09f0b000
fix: add open_float params to toggle_float (#716)
* feat: `toggle_float` now takes the same params as `open_float`

* docs: update `toggle_float` docs for `opts` and `cb` params

* fix: ensure cb is always called

---------

Co-authored-by: Steven Arcangeli <506791+stevearc@users.noreply.github.com>
2026-01-16 21:01:02 -08:00
malewicz1337
6b59a6cf62
feat: add support for column text alignment (#711)
* feat: add support for column text alignment

* refactor(util): replace rpad with pad_align

* refactor(columns): whitespace handling in parse_col

* refactor: small changes

* doc: add align option to doc generation

* refactor: replace lpad with pad_align

---------

Co-authored-by: Steven Arcangeli <stevearc@stevearc.com>
2026-01-13 21:28:16 -08:00
Daniel Kongsgaard
fbbb2a9872
doc: fix s3 column descriptions (#715) 2026-01-12 11:26:43 -08:00
Sebastian Oberhoff
d278dc40f9
fix: propagate errors in recursive_delete and recursive_copy (#712)
The `complete` callback checks `err` instead of `err2`, but `err` is
always nil inside the `elseif entries` branch. This silently ignores
child operation errors, causing misleading "directory not empty" failures.
2026-01-11 13:55:32 -08:00
Github Actions
43227c5a1c [docgen] Update docs
skip-checks: true
2026-01-11 21:53:37 +00:00
Ross
24055701b7
feat: add horizontal scrolling actions (#709)
* feat: add horizontal scrolling actions

* refactor(actions): remove unnecessary use of `nvim_replace_termcodes`

* lint: apply stylua

---------

Co-authored-by: Steven Arcangeli <506791+stevearc@users.noreply.github.com>
2026-01-11 13:53:17 -08:00
Steven Arcangeli
81b8a91735 cleanup: remove deprecated trash_command 2026-01-01 00:22:58 -05:00
jake-stewart
78ed0cf7d9
fix: multicursor when opened with --preview (#701) 2025-12-31 12:50:39 -08:00
Dominic Della Valle
963c8d2c55
fix: handle empty LSP glob patterns (#702)
* fix: handle empty LSP glob patterns

* fix: use non-greedy pattern matching

* lint: fix shadowed variable

---------

Co-authored-by: Steven Arcangeli <506791+stevearc@users.noreply.github.com>
2025-12-29 12:27:20 -08:00
Muhammad Imaduddin
634049414b
fix: open files under cwd with relative name (#693) 2025-12-29 10:15:58 -08:00
phanium
bbfa7cba85
fix: args.count of 0 is not used as size (#695) 2025-12-27 13:27:37 -08:00
jake-stewart
756dec855b
feat: support multicursor.nvim (#696)
* support multicursor.nvim

* lint: apply stylua

---------

Co-authored-by: Steven Arcangeli <stevearc@stevearc.com>
2025-12-21 12:26:10 -08:00
Steven Arcangeli
09a4e4f460 ci: fix type error 2025-12-21 15:14:45 -05:00