nvim/.config/nvim/lua/plugins/coding/formatter.lua

-- nvim/.config/nvim/lua/plugins/coding/formatter.lua
-- conform.nvim — replaced null-ls for formatting.

return {
  "stevearc/conform.nvim",
  event = { "BufWritePre" },
  cmd = { "ConformInfo" },
  keys = {
    {
      "<leader>cf",
      function() require("conform").format({ async = true, lsp_fallback = true }) end,
      mode = { "n", "v" },
      desc = "format buffer",
    },
  },
  opts = {
    format_on_save = function(bufnr)
      if vim.g.disable_autoformat or vim.b[bufnr].disable_autoformat then return end
      return { timeout_ms = 1500, lsp_fallback = true }
    end,
    notify_on_error = true,
    formatters_by_ft = {
      lua        = { "stylua" },
      go         = { "goimports", "gofumpt" },
      rust       = { "rustfmt" },
      python     = { "ruff_fix", "ruff_format" },
      sh         = { "shfmt" },
      bash       = { "shfmt" },
      zsh        = { "shfmt" },
      javascript = { "prettierd", "prettier", stop_after_first = true },
      typescript = { "prettierd", "prettier", stop_after_first = true },
      json       = { "prettierd", "prettier", stop_after_first = true },
      jsonc      = { "prettierd", "prettier", stop_after_first = true },
      yaml       = { "prettierd", "prettier", stop_after_first = true },
      markdown   = { "prettierd", "prettier", stop_after_first = true },
      toml       = { "taplo" },
    },
    formatters = {
      shfmt = { prepend_args = { "-i", "2", "-ci", "-bn" } },
      stylua = { prepend_args = { "--indent-type", "Spaces", "--indent-width", "2" } },
    },
  },
  init = function()
    vim.api.nvim_create_user_command("FormatDisable", function(args)
      if args.bang then vim.b.disable_autoformat = true else vim.g.disable_autoformat = true end
    end, { bang = true })
    vim.api.nvim_create_user_command("FormatEnable", function()
      vim.b.disable_autoformat = false
      vim.g.disable_autoformat = false
    end, {})
  end,
}