Skip to content

feat(icons): filetype detection via shebang#618

Open
nobe4 wants to merge 12 commits intostevearc:masterfrom
nobe4:shebang-detection
Open

feat(icons): filetype detection via shebang#618
nobe4 wants to merge 12 commits intostevearc:masterfrom
nobe4:shebang-detection

Conversation

@nobe4
Copy link

@nobe4 nobe4 commented Apr 13, 2025

This PR adds a step in the columns making: read the first line of the file and use that to compute a "fallback" filetype in case the filename alone cannot be used to determine the filetype.

This is then passed to the IconProvider which uses it if the icon is nil, or default.

This works well in initial tests, but vim.fn.readfile(name, '', 1) only read files in the current folder, I need to understand how I can make that work when changing folders. However, once this is done, I think this will provide some nice additional icons.

Looking forward to getting a review/suggestions :)

@github-actions github-actions bot requested a review from stevearc April 13, 2025 19:20
Copy link
Owner

@stevearc stevearc left a comment

Choose a reason for hiding this comment

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

I mentioned this in the issue, but performance is a concern here. Passing a max lines of 1 to readfile is helpful, but this will still slow us down in large directories because we'll have to open a lot of files. Could we maybe put this behind a config option so the default behavior is still fast?

lua/oil/util.lua Outdated
Comment on lines +935 to +937
if icon == nil or is_default then
icon, hl = mini_icons.get("filetype", ft or "")
end
Copy link
Owner

Choose a reason for hiding this comment

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

Probably should only do this when ft is non-nil, right?

Copy link
Owner

Choose a reason for hiding this comment

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

Actually, I think for both devicons and MiniIcons it makes sense to use the filetype first if it's provided, as that implementation should both be faster and more correct, and only use the original logic if the filetype is nil.

Copy link
Author

@nobe4 nobe4 Jun 2, 2025

Choose a reason for hiding this comment

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

I have pushed some commits to address this, thanks for the suggestion!

nobe4 added 4 commits June 2, 2025 08:57
As @stevearc mentioned, it would be better to use the ft directly if the
function gets it, and fallback to the original logic otherwise.

cc stevearc#618 (comment)
Upon looking at devicons' code, it seems that passing `ft` even when nil
will result in the same execution, and doing otherwise won't create any
performance improvements.
As @stevearc suggested, it would be better to keep the default behavior
for performance reasons. Adding a config option to enable the ft
detection ensures this.

cc stevearc#618 (review)

local ft = ""
if field_type == "file" then
local firstline = vim.fn.readfile(name, '', 1)
Copy link
Author

Choose a reason for hiding this comment

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

@stevearc, I have searched, and failed to find how to get absolute filepaths, or the current directory in the context of this function. Do you know how I can get it?

Copy link
Owner

Choose a reason for hiding this comment

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

The render function takes a bufnr as the third argument

---@field render fun(entry: oil.InternalEntry, conf: nil|table, bufnr: integer): nil|oil.TextChunk

You could parse the buffer name to get the parent dir like we do here
local bufname = vim.api.nvim_buf_get_name(bufnr)
local _, path = util.parse_url(bufname)

Copy link
Author

Choose a reason for hiding this comment

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

Awesome! Thanks for this!

Done in e2ad451

@github-actions github-actions bot requested a review from stevearc June 2, 2025 07:27
nobe4 added 2 commits June 2, 2025 09:35
The ft is compared against `nil` in the rest of the code, so don't set
it up to an empty string if missing.
`get_icon` favor the filename instead of the `ft`, so we need to use
`get_icon_by_filetype` to explicitly make the ft a priority.

This commits leaves the normal logic as a fallback if the icon is not
found with the filetype.
Comment on lines +103 to +105
-- Read the first line of the file and use vim's matching ft.
-- Can slow down the execution considerably for large projects.
use_vim_ft = false,
Copy link
Owner

Choose a reason for hiding this comment

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

Could we instead make this an option for the icon column, like we do for add_padding? You can just access it on the conf table like conf.use_slow_filetype_detection and then add an entry to this file to generate the documentation for it.

Copy link
Author

Choose a reason for hiding this comment

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

Done in 2aa7176

@github-actions github-actions bot requested a review from stevearc June 4, 2025 08:50
barrettruth added a commit to barrettruth/canola.nvim that referenced this pull request Feb 21, 2026
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#618
barrettruth added a commit to barrettruth/canola.nvim that referenced this pull request Mar 15, 2026
Problem: Issue stevearc#617 (filetype-based icon detection) was still listed as
`open` in the upstream tracker despite being addressed by PR stevearc#618.

Solution: Update status to `fixed — cherry-picked (stevearc#618)`. Verified
with manual testing that `use_slow_filetype_detection` correctly detects
shebangs in extensionless files.
barrettruth added a commit to barrettruth/canola.nvim that referenced this pull request Mar 15, 2026
#123)

Problem: Issue stevearc#617 (filetype-based icon detection) was still listed as
`open` in the upstream tracker despite being addressed by PR stevearc#618.

Solution: Update status to `fixed — cherry-picked (stevearc#618)`. Verified
with manual testing that `use_slow_filetype_detection` correctly detects
shebangs in extensionless files.
barrettruth added a commit to barrettruth/canola.nvim that referenced this pull request Mar 15, 2026
* docs(upstream): mark stevearc#617 fixed via cherry-picked stevearc#618

Problem: Issue stevearc#617 (filetype-based icon detection) was still listed as
`open` in the upstream tracker despite being addressed by PR stevearc#618.

Solution: Update status to `fixed — cherry-picked (stevearc#618)`. Verified
with manual testing that `use_slow_filetype_detection` correctly detects
shebangs in extensionless files.

* docs(upstream): mark stevearc#675 as duplicate of #117

Problem: Issue stevearc#675 (move file into folder by renaming) was listed as
`open` despite being a duplicate of #117, the primary tracking issue
for move-by-rename (46 upvotes). Upstream already closed stevearc#675 as such.

Solution: Update status to `duplicate of #117`.
barrettruth added a commit to barrettruth/canola.nvim that referenced this pull request Mar 15, 2026
* docs(upstream): mark stevearc#617 fixed via cherry-picked stevearc#618

Problem: Issue stevearc#617 (filetype-based icon detection) was still listed as
`open` in the upstream tracker despite being addressed by PR stevearc#618.

Solution: Update status to `fixed — cherry-picked (stevearc#618)`. Verified
with manual testing that `use_slow_filetype_detection` correctly detects
shebangs in extensionless files.

* docs(upstream): mark stevearc#675 as duplicate of #117

Problem: Issue stevearc#675 (move file into folder by renaming) was listed as
`open` despite being a duplicate of #117, the primary tracking issue
for move-by-rename (46 upvotes). Upstream already closed stevearc#675 as such.

Solution: Update status to `duplicate of #117`.

* docs(upstream): mark stevearc#707 as duplicate of #117

Problem: Issue stevearc#707 (move file/dir into new dir by renaming) was listed
as `open` despite being identical to #117. The associated draft PR stevearc#708
is already tracked separately in the PRs table.

Solution: Update status to `duplicate of #117`.
barrettruth added a commit to barrettruth/canola.nvim that referenced this pull request Mar 15, 2026
* docs(upstream): mark stevearc#617 fixed via cherry-picked stevearc#618

Problem: Issue stevearc#617 (filetype-based icon detection) was still listed as
`open` in the upstream tracker despite being addressed by PR stevearc#618.

Solution: Update status to `fixed — cherry-picked (stevearc#618)`. Verified
with manual testing that `use_slow_filetype_detection` correctly detects
shebangs in extensionless files.

* docs(upstream): mark stevearc#675 as duplicate of #117

Problem: Issue stevearc#675 (move file into folder by renaming) was listed as
`open` despite being a duplicate of #117, the primary tracking issue
for move-by-rename (46 upvotes). Upstream already closed stevearc#675 as such.

Solution: Update status to `duplicate of #117`.

* docs(upstream): mark stevearc#707 as duplicate of #117

Problem: Issue stevearc#707 (move file/dir into new dir by renaming) was listed
as `open` despite being identical to #117. The associated draft PR stevearc#708
is already tracked separately in the PRs table.

Solution: Update status to `duplicate of #117`.

* docs(upstream): consolidate owner/group issues into #126

Problem: Three upstream issues (stevearc#436, stevearc#599, stevearc#684) all request the same
feature — owner/group columns in the directory listing.

Solution: Create canonical tracking issue #126
and mark all three as `consolidated into #126`.
barrettruth added a commit to barrettruth/canola.nvim that referenced this pull request Mar 15, 2026
* docs(upstream): mark stevearc#617 fixed via cherry-picked stevearc#618

Problem: Issue stevearc#617 (filetype-based icon detection) was still listed as
`open` in the upstream tracker despite being addressed by PR stevearc#618.

Solution: Update status to `fixed — cherry-picked (stevearc#618)`. Verified
with manual testing that `use_slow_filetype_detection` correctly detects
shebangs in extensionless files.

* docs(upstream): mark stevearc#675 as duplicate of #117

Problem: Issue stevearc#675 (move file into folder by renaming) was listed as
`open` despite being a duplicate of #117, the primary tracking issue
for move-by-rename (46 upvotes). Upstream already closed stevearc#675 as such.

Solution: Update status to `duplicate of #117`.

* docs(upstream): mark stevearc#707 as duplicate of #117

Problem: Issue stevearc#707 (move file/dir into new dir by renaming) was listed
as `open` despite being identical to #117. The associated draft PR stevearc#708
is already tracked separately in the PRs table.

Solution: Update status to `duplicate of #117`.

* docs(upstream): consolidate owner/group issues into #126

Problem: Three upstream issues (stevearc#436, stevearc#599, stevearc#684) all request the same
feature — owner/group columns in the directory listing.

Solution: Create canonical tracking issue #126
and mark all three as `consolidated into #126`.

* docs(upstream): mark stevearc#570 not actionable

Problem: Issue stevearc#570 (`c0`/`d0` deletes concealed entry ID prefix,
causing rename to be parsed as delete+create) was listed as `open`.

Solution: Mark as `not actionable — blocked on Neovim extmark API`.
Neovim provides no mechanism to protect concealed extmark text from
operator-pending motions. The intended rename workflow uses `cw`/`ciw`
within the constrained cursor region.
barrettruth added a commit to barrettruth/canola.nvim that referenced this pull request Mar 17, 2026
#123)

Problem: Issue stevearc#617 (filetype-based icon detection) was still listed as
`open` in the upstream tracker despite being addressed by PR stevearc#618.

Solution: Update status to `fixed — cherry-picked (stevearc#618)`. Verified
with manual testing that `use_slow_filetype_detection` correctly detects
shebangs in extensionless files.
barrettruth added a commit to barrettruth/canola.nvim that referenced this pull request Mar 17, 2026
* docs(upstream): mark stevearc#617 fixed via cherry-picked stevearc#618

Problem: Issue stevearc#617 (filetype-based icon detection) was still listed as
`open` in the upstream tracker despite being addressed by PR stevearc#618.

Solution: Update status to `fixed — cherry-picked (stevearc#618)`. Verified
with manual testing that `use_slow_filetype_detection` correctly detects
shebangs in extensionless files.

* docs(upstream): mark stevearc#675 as duplicate of #117

Problem: Issue stevearc#675 (move file into folder by renaming) was listed as
`open` despite being a duplicate of #117, the primary tracking issue
for move-by-rename (46 upvotes). Upstream already closed stevearc#675 as such.

Solution: Update status to `duplicate of #117`.
barrettruth added a commit to barrettruth/canola.nvim that referenced this pull request Mar 17, 2026
* docs(upstream): mark stevearc#617 fixed via cherry-picked stevearc#618

Problem: Issue stevearc#617 (filetype-based icon detection) was still listed as
`open` in the upstream tracker despite being addressed by PR stevearc#618.

Solution: Update status to `fixed — cherry-picked (stevearc#618)`. Verified
with manual testing that `use_slow_filetype_detection` correctly detects
shebangs in extensionless files.

* docs(upstream): mark stevearc#675 as duplicate of #117

Problem: Issue stevearc#675 (move file into folder by renaming) was listed as
`open` despite being a duplicate of #117, the primary tracking issue
for move-by-rename (46 upvotes). Upstream already closed stevearc#675 as such.

Solution: Update status to `duplicate of #117`.

* docs(upstream): mark stevearc#707 as duplicate of #117

Problem: Issue stevearc#707 (move file/dir into new dir by renaming) was listed
as `open` despite being identical to #117. The associated draft PR stevearc#708
is already tracked separately in the PRs table.

Solution: Update status to `duplicate of #117`.
barrettruth added a commit to barrettruth/canola.nvim that referenced this pull request Mar 17, 2026
* docs(upstream): mark stevearc#617 fixed via cherry-picked stevearc#618

Problem: Issue stevearc#617 (filetype-based icon detection) was still listed as
`open` in the upstream tracker despite being addressed by PR stevearc#618.

Solution: Update status to `fixed — cherry-picked (stevearc#618)`. Verified
with manual testing that `use_slow_filetype_detection` correctly detects
shebangs in extensionless files.

* docs(upstream): mark stevearc#675 as duplicate of #117

Problem: Issue stevearc#675 (move file into folder by renaming) was listed as
`open` despite being a duplicate of #117, the primary tracking issue
for move-by-rename (46 upvotes). Upstream already closed stevearc#675 as such.

Solution: Update status to `duplicate of #117`.

* docs(upstream): mark stevearc#707 as duplicate of #117

Problem: Issue stevearc#707 (move file/dir into new dir by renaming) was listed
as `open` despite being identical to #117. The associated draft PR stevearc#708
is already tracked separately in the PRs table.

Solution: Update status to `duplicate of #117`.

* docs(upstream): consolidate owner/group issues into #126

Problem: Three upstream issues (stevearc#436, stevearc#599, stevearc#684) all request the same
feature — owner/group columns in the directory listing.

Solution: Create canonical tracking issue #126
and mark all three as `consolidated into #126`.
barrettruth added a commit to barrettruth/canola.nvim that referenced this pull request Mar 17, 2026
* docs(upstream): mark stevearc#617 fixed via cherry-picked stevearc#618

Problem: Issue stevearc#617 (filetype-based icon detection) was still listed as
`open` in the upstream tracker despite being addressed by PR stevearc#618.

Solution: Update status to `fixed — cherry-picked (stevearc#618)`. Verified
with manual testing that `use_slow_filetype_detection` correctly detects
shebangs in extensionless files.

* docs(upstream): mark stevearc#675 as duplicate of #117

Problem: Issue stevearc#675 (move file into folder by renaming) was listed as
`open` despite being a duplicate of #117, the primary tracking issue
for move-by-rename (46 upvotes). Upstream already closed stevearc#675 as such.

Solution: Update status to `duplicate of #117`.

* docs(upstream): mark stevearc#707 as duplicate of #117

Problem: Issue stevearc#707 (move file/dir into new dir by renaming) was listed
as `open` despite being identical to #117. The associated draft PR stevearc#708
is already tracked separately in the PRs table.

Solution: Update status to `duplicate of #117`.

* docs(upstream): consolidate owner/group issues into #126

Problem: Three upstream issues (stevearc#436, stevearc#599, stevearc#684) all request the same
feature — owner/group columns in the directory listing.

Solution: Create canonical tracking issue #126
and mark all three as `consolidated into #126`.

* docs(upstream): mark stevearc#570 not actionable

Problem: Issue stevearc#570 (`c0`/`d0` deletes concealed entry ID prefix,
causing rename to be parsed as delete+create) was listed as `open`.

Solution: Mark as `not actionable — blocked on Neovim extmark API`.
Neovim provides no mechanism to protect concealed extmark text from
operator-pending motions. The intended rename workflow uses `cw`/`ciw`
within the constrained cursor region.
barrettruth added a commit to barrettruth/canola.nvim that referenced this pull request Mar 17, 2026
* docs(upstream): mark stevearc#617 fixed via cherry-picked stevearc#618

Problem: Issue stevearc#617 (filetype-based icon detection) was still listed as
`open` in the upstream tracker despite being addressed by PR stevearc#618.

Solution: Update status to `fixed — cherry-picked (stevearc#618)`. Verified
with manual testing that `use_slow_filetype_detection` correctly detects
shebangs in extensionless files.

* docs(upstream): mark stevearc#675 as duplicate of #117

Problem: Issue stevearc#675 (move file into folder by renaming) was listed as
`open` despite being a duplicate of #117, the primary tracking issue
for move-by-rename (46 upvotes). Upstream already closed stevearc#675 as such.

Solution: Update status to `duplicate of #117`.
barrettruth added a commit to barrettruth/canola.nvim that referenced this pull request Mar 17, 2026
* docs(upstream): mark stevearc#617 fixed via cherry-picked stevearc#618

Problem: Issue stevearc#617 (filetype-based icon detection) was still listed as
`open` in the upstream tracker despite being addressed by PR stevearc#618.

Solution: Update status to `fixed — cherry-picked (stevearc#618)`. Verified
with manual testing that `use_slow_filetype_detection` correctly detects
shebangs in extensionless files.

* docs(upstream): mark stevearc#675 as duplicate of #117

Problem: Issue stevearc#675 (move file into folder by renaming) was listed as
`open` despite being a duplicate of #117, the primary tracking issue
for move-by-rename (46 upvotes). Upstream already closed stevearc#675 as such.

Solution: Update status to `duplicate of #117`.
barrettruth added a commit to barrettruth/canola.nvim that referenced this pull request Mar 17, 2026
* docs(upstream): mark stevearc#675 as duplicate of #117 (#124)

* docs(upstream): mark stevearc#617 fixed via cherry-picked stevearc#618

Problem: Issue stevearc#617 (filetype-based icon detection) was still listed as
`open` in the upstream tracker despite being addressed by PR stevearc#618.

Solution: Update status to `fixed — cherry-picked (stevearc#618)`. Verified
with manual testing that `use_slow_filetype_detection` correctly detects
shebangs in extensionless files.

* docs(upstream): mark stevearc#675 as duplicate of #117

Problem: Issue stevearc#675 (move file into folder by renaming) was listed as
`open` despite being a duplicate of #117, the primary tracking issue
for move-by-rename (46 upvotes). Upstream already closed stevearc#675 as such.

Solution: Update status to `duplicate of #117`.

* fix(float): support `close = false` for floating oil windows

Problem: `select` with `close = false` was broken for floating oil
windows. The float auto-close autocmd would always close the window
when focus left, and there was no mechanism to preserve it.

Solution: Add `oil_keep_open` window flag set when `close = false` is
used on a float. The auto-close autocmd checks this flag before closing.
On file select, focus returns to the original window behind the float
so the file opens there, then focus restores to the float.

* docs(upstream): mark stevearc#399 as fixed (#159)
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