aboutsummaryrefslogtreecommitdiff
path: root/runtime/lua/editorconfig.lua
diff options
context:
space:
mode:
authorLewis Russell <lewis6991@gmail.com>2026-09-28 14:19:41 +0100
committerLewis Russell <lewis6991@gmail.com>2026-09-28 14:43:14 +0100
commit33b148752008aef20b460ebd61d71a3cd850a0da (patch)
tree1289bd0c10438fce1130051cd40b35c5dba2a2ca /runtime/lua/editorconfig.lua
parentd51a6e2d55486b8ac3e352dc48f290884577dad9 (diff)
downloadrneovim-33b148752008aef20b460ebd61d71a3cd850a0da.tar.gz
rneovim-33b148752008aef20b460ebd61d71a3cd850a0da.tar.bz2
rneovim-33b148752008aef20b460ebd61d71a3cd850a0da.zip
fix(editorconfig): handle root separately from properties
Problem: A child root=false masks a parent root=true during merging. Solution: Return the search boundary separately from string properties. Exclude root from property callbacks and b:editorconfig. AI-assisted
Diffstat (limited to 'runtime/lua/editorconfig.lua')
-rw-r--r--runtime/lua/editorconfig.lua25
1 files changed, 15 insertions, 10 deletions
diff --git a/runtime/lua/editorconfig.lua b/runtime/lua/editorconfig.lua
index 9941a7ccdc..9ac54096e2 100644
--- a/runtime/lua/editorconfig.lua
+++ b/runtime/lua/editorconfig.lua
@@ -59,7 +59,7 @@
local nvim_on = require('vim._core.util').nvim_on
---- @type table<string,fun(bufnr: integer, val: string, opts: table)>
+--- @type table<string,fun(bufnr: integer, val: string, opts: table<string,string>)>
local properties = {}
--- Modified version of the builtin assert that does not include error position information
@@ -82,8 +82,9 @@ end
--- If "true", then stop searching for `.editorconfig` files in parent
--- directories. This property must be at the top-level of the
--- `.editorconfig` file (i.e. it must not be within a glob section).
+--- It only controls the search and is excluded from property callbacks and [b:editorconfig].
function properties.root()
- -- Unused
+ -- Documentation only. The parser handles root separately.
end
--- One of `"utf-8"`, `"utf-8-bom"`, `"latin1"`, `"utf-16be"`, or `"utf-16le"`.
@@ -267,13 +268,16 @@ end
--- Parse options from an `.editorconfig` file
--- @param filepath string File path of the file to apply EditorConfig settings to
--- @param dir string Current directory
---- @return table<string,string|boolean> Table of options to apply to the given file
+--- @return table<string,string> options to apply to the given file
+--- @return boolean is_root Whether to stop searching parent directories
local function parse(filepath, dir)
local pat --- @type vim.regex?
- local opts = {} --- @type table<string,string|boolean>
+ local opts = {} --- @type table<string,string>
+ local is_root = false
local f = io.open(dir .. '/.editorconfig')
if f then
for line in f:lines() do
+ --- @cast line string
local glob, key, val = parse_line(line)
if glob then
glob = glob:find('/') and (dir .. '/' .. glob:gsub('^/', '')) or ('**/' .. glob)
@@ -287,7 +291,7 @@ local function parse(filepath, dir)
elseif key ~= nil and val ~= nil then
if key == 'root' then
assert(val == 'true' or val == 'false', 'root must be either "true" or "false"')
- opts.root = val == 'true'
+ is_root = val == 'true'
elseif pat and pat:match_str(filepath) then
opts[key] = val
end
@@ -295,7 +299,7 @@ local function parse(filepath, dir)
end
f:close()
end
- return opts
+ return opts, is_root
end
local M = {}
@@ -317,20 +321,21 @@ function M.config(buf)
return
end
- local opts = {} --- @type table<string,string|boolean>
+ local opts = {} --- @type table<string,string>
for parent in vim.fs.parents(path) do
- for k, v in pairs(parse(path, parent)) do
+ local parent_opts, is_root = parse(path, parent)
+ for k, v in pairs(parent_opts) do
if opts[k] == nil then
opts[k] = v
end
end
- if opts.root then
+ if is_root then
break
end
end
- local applied = {} --- @type table<string,string|boolean>
+ local applied = {} --- @type table<string,string>
for opt, val in pairs(opts) do
if val ~= 'unset' then
local func = M.properties[opt]