mfussenegger / nvim-lint

An asynchronous linter plugin for Neovim complementary to the built-in Language Server Protocol support.
GNU General Public License v3.0
1.76k stars 191 forks source link

fix(stylelint): Shell escape file names/paths #613

Open ChristinWhite opened 4 days ago

ChristinWhite commented 4 days ago

Problem

Currently, stylelint fails to lint files when there are spaces in the file path. This causes issues for users with spaces in their directory or file names, preventing proper linting of their CSS files.

Solution

This PR wraps file paths with vim.fn.shellescape() to properly handle edge cases where file paths contain spaces or other characters that require quoting or escaping.

Changes

Testing

Tested with file paths containing spaces:

Impact

This change ensures that stylelint works correctly regardless of file path structure.

ChristinWhite commented 4 hours ago

I did not test this on Windows but I ran into this on macOS. As soon as there is space anywhere current filename or path the linter would fail. Once I figured out how to construct and log the command I noticed that spaces weren't being escaped nor was the path quoted, when I added the shell-escape stylelint has been linting flawlessly for me with and without spaces.

That said, I would have expected macOS to handle it the same way Linux does, they're generally pretty similar at the shell level.

I am fairly new to Neovim and haven't done a ton of CLI-based linting so I could be making a mistake. How can I be most helpful in solving this issue?

Environment details:

macOS: 14.5 (23F79) wezterm 20240203-110809-5046fc22 zsh 5.9 (arm-apple-darwin23.0.0) NVIM v0.10.0 Build type: Release LuaJIT 2.1.1716656478

Configuration:

local linters = {
  stylelint = {
    args = {
      -- Use a default configuration file if one doesn't exist in the project or a parent.
      "--config",
      function()
        local config = vim.fs.find(".stylelint.config.yaml", {
          upward = true,
          stop = vim.fs.dirname(vim.uv.os_homedir()),
          path = vim.fs.dirname(vim.api.nvim_buf_get_name(0)),
        })
        if #config > 0 then
          print("found")
          return config[1]
        else
          print("default")
          local default_config = xdg_config .. "/stylelint/stylelint.config.yaml"

          return default_config
        end
      end,
    },
  },

  -- Other linter configs...
}

local filetypes = {
  css = { "stylelint" },

  -- Other filetypes...
}

function M.config()
  local lint = require("lint")

  for linter, config in pairs(linters) do
    lint.linters[linter].args = vim.list_extend(lint.linters[linter].args or {}, config.args)
  end

  lint.linters_by_ft = filetypes or {}

  local lint_augroup = vim.api.nvim_create_augroup("lint", { clear = true })
  vim.api.nvim_create_autocmd({ "BufEnter", "BufWritePost", "InsertLeave", "TextChanged" }, {
    group = lint_augroup,
    callback = function()
      require("lint").try_lint()
    end,
  })
end