NeogitOrg / neogit

An interactive and powerful Git interface for Neovim, inspired by Magit
MIT License
4.02k stars 236 forks source link

Neogit status diffs are not correctly indented #1193

Closed Tinku10 closed 7 months ago

Tinku10 commented 8 months ago

Description

It seems like Neogit is adjusting the indentation of the displayed diffs to 1 unit, no matter the default indentation level of the code base.

Neovim version

NVIM v0.9.4 Build type: Release LuaJIT 2.1.1700008891

Operating system and version

macOS 13.1

Steps to reproduce

Expected behavior

The indentations should align.

Actual behavior

The indentations are different making it seem like the about to be committed code has been misaligned.

I am using Go in a codebase and it turns out that gofmt enforces tabs over spaces. But there seems to be a difference in the interpretation of the tab width between Neovim and Neogit. From the image below you can see that the alignment does not look right in the Neogit Status panel.

If the code is manually aligned with spaces, this does not raise this inconsistency. But almost everyone would use gofmt for Go formatting making this a nuisance.

image image

Minimal config

-- NOTE: See the end of this file if you are reporting an issue, etc. Ignore all the "scary" functions up top, those are
-- used for setup and other operations.
local M = {}

local base_root_path = vim.fn.fnamemodify(debug.getinfo(1, "S").source:sub(2), ":p:h") .. "/.min"
function M.root(path)
  return base_root_path .. "/" .. (path or "")
end

function M.load_plugin(plugin_name, plugin_url)
  local package_root = M.root("plugins/")
  local install_destination = package_root .. plugin_name
  vim.opt.runtimepath:append(install_destination)

  if not vim.loop.fs_stat(package_root) then
    vim.fn.mkdir(package_root, "p")
  end

  if not vim.loop.fs_stat(install_destination) then
    print(string.format("> Downloading plugin '%s' to '%s'", plugin_name, install_destination))
    vim.fn.system({
      "git",
      "clone",
      "--depth=1",
      plugin_url,
      install_destination,
    })
    if vim.v.shell_error > 0 then
      error(string.format("> Failed to clone plugin: '%s' in '%s'!", plugin_name, install_destination),
        vim.log.levels.ERROR)
    end
  end
end

---@alias PluginName string The plugin name, will be used as part of the git clone destination
---@alias PluginUrl string The git url at which a plugin is located, can be a path. See https://git-scm.com/book/en/v2/Git-on-the-Server-The-Protocols for details
---@alias MinPlugins table<PluginName, PluginUrl>

---Do the initial setup. Downloads plugins, ensures the minimal init does not pollute the filesystem by keeping
---everything self contained to the CWD of the minimal init file. Run prior to running tests, reproducing issues, etc.
---@param plugins? table<PluginName, PluginUrl>
function M.setup(plugins)
  vim.opt.packpath = {}                      -- Empty the package path so we use only the plugins specified
  vim.opt.runtimepath:append(M.root(".min")) -- Ensure the runtime detects the root min dir

  -- Install required plugins
  if plugins ~= nil then
    for plugin_name, plugin_url in pairs(plugins) do
      M.load_plugin(plugin_name, plugin_url)
    end
  end

  vim.env.XDG_CONFIG_HOME = M.root("xdg/config")
  vim.env.XDG_DATA_HOME = M.root("xdg/data")
  vim.env.XDG_STATE_HOME = M.root("xdg/state")
  vim.env.XDG_CACHE_HOME = M.root("xdg/cache")

  -- NOTE: Cleanup the xdg cache on exit so new runs of the minimal init doesn't share any previous state, e.g. shada
  vim.api.nvim_create_autocmd("VimLeave", {
    callback = function()
      vim.fn.system({
        "rm",
        "-r",
        "-f",
        M.root("xdg")
      })
    end
  })
end

-- NOTE: If you have additional plugins you need to install to reproduce your issue, include them in the plugins
-- table within the setup call below.
M.setup({
  plenary = "https://github.com/nvim-lua/plenary.nvim.git",
  telescope = "https://github.com/nvim-telescope/telescope.nvim",
  diffview = "https://github.com/sindrets/diffview.nvim",
  neogit = "https://github.com/NeogitOrg/neogit"
})
-- WARN: Do all plugin setup, test runs, reproductions, etc. AFTER calling setup with a list of plugins!
-- Basically, do all that stuff AFTER this line.
require("neogit").setup({}) -- For instance, setup Neogit
CKolkey commented 7 months ago

Ahh, wild, this has to do with how the git cli prints things. Those diffs are rendered pretty much straight from the CLI output - we parse that and show it. So, tabstop/shifwidth/friends wouldn't really have a big impact as it's not a buffer in the traditional sense. I think the easiest thing to do here is to just replace tabs when we render the diff. Lemme see how that works.

CKolkey commented 7 months ago

Ok, I don't think there's much I can do about this and be "right" in all cases. Vim is rendering the tabs according to tabstops value, and I'm just not sure what I could do to "force" it to be right. I was able to reproduce this where I had a buffer that had a mix of indentations, both tabs and spaces. Even though they did line up in the buffer, in neogit they didn't. Off by one. Which makes sense: In neogit, there's a + at the beginning of the line, which I think the tabs would quietly ignore, while the spaces would not.

If you have any clever ideas, I'm open to it, but otherwise I think there's not anything to do here.