Skip to content

fix: error when entering new file whose name matches one of the patterns case insensitively #27

@Futarimiti

Description

@Futarimiti

Hi, another issue found when testing.

Minimum reproducible example:

-- config
require('esqueleto').setup { patterns = { 'main.py' } }

Then, with nvim, create and edit file Main.py (or whatever filename as long as it insensitively matches 'main.py' e.g. MAIN.py, mAIn.PY...), will trigger the following error:

Error detected while processing BufWinEnter Autocommands for "main.py":
Error executing lua callback: ...l/share/nvim/lazy/esqueleto.nvim/lua/esqueleto/utils.lua:18: attempt to concatenate local 'pattern' (a
 nil value)
stack traceback:
        ...l/share/nvim/lazy/esqueleto.nvim/lua/esqueleto/utils.lua:18: in function 'gettemplates'
        ...l/share/nvim/lazy/esqueleto.nvim/lua/esqueleto/utils.lua:86: in function 'inserttemplate'
        ...share/nvim/lazy/esqueleto.nvim/lua/esqueleto/autocmd.lua:21: in function <...share/nvim/lazy/esqueleto.nvim/lua/esqueleto/au
tocmd.lua:18>

And after some debugging, I believe here's the reason:

  1. Patterns provided by users are directly passed as autocmd patterns:

      vim.api.nvim_create_autocmd(
        { "BufWinEnter", "BufReadPost", "FileType" },
        {
          group = group,
          desc = "esqueleto.nvim :: Insert template",
          pattern = opts.patterns,  -- { 'main.py' }
          callback = function()
            local filepath = vim.fn.expand("%")
            local emptyfile = vim.fn.getfsize(filepath) < 4
            if emptyfile then utils.inserttemplate(opts) end
          end
        }
      )

    Though not directly documented in the manual, it seems that autocmd patterns are indeed case-insensitive,
    therefore Main.py matches the main.py and the callback is executed.

  2. Then, within inserttemplate:

    M.inserttemplate = function(opts)
      ...
      -- Identify if pattern matches user configuration
      local pattern = nil
      if not _G.esqueleto_inserted[filepath] then
        -- match either filename or extension. Filename has priority
        if vim.tbl_contains(opts.patterns, filename) then
          pattern = filename
        elseif vim.tbl_contains(opts.patterns, filetype) then
          pattern = filetype
        end
    
        -- Get templates for selected pattern
        local templates = M.gettemplates(pattern, opts.directories)
        ...
      end
    end

    Where vim.tbl_contains, which is case-sensitive, is used to get that pattern. Of course, opts.patterns does not contain Main.py, and pattern, without nil-checks, will be passed to gettemplates to be concatenated with filepaths.

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions