Neovim sign gutter, designed to be mostly VCS agnostic
at experimental_diffthis 104 lines 3.1 kB view raw
1local M = {} 2 3local diff = require "vcsigns.diff" 4local high = require "vcsigns.high" 5local repo = require "vcsigns.repo" 6local sign = require "vcsigns.sign" 7local state = require "vcsigns.state" 8local util = require "vcsigns.util" 9local ignore = require "vclib.ignore" 10 11--- Cheap update assuming the old file contents are still fresh. 12---@param bufnr integer The buffer number. 13function M.shallow_update(bufnr) 14 local buffer_lines = vim.api.nvim_buf_get_lines(bufnr, 0, -1, false) 15 local s = state.get(bufnr) 16 local old_lines = s.diff.old_lines 17 18 if not old_lines then 19 util.verbose "No old contents available, skipping diff." 20 return 21 end 22 23 local path = vim.fn.fnamemodify(vim.api.nvim_buf_get_name(bufnr), ":f") 24 if 25 vim.g.vcsigns_respect_gitignore 26 and #old_lines == 0 27 and ignore.is_ignored(path) 28 then 29 -- Rough proxy for checking if file is ignored and not tracked. 30 util.verbose "File ignored and had no previous contents, skipping diff." 31 return 32 end 33 34 local hunks = diff.compute_diff(old_lines, buffer_lines) 35 s.diff.hunks = hunks 36 sign.add_signs(bufnr, hunks) 37 38 if vim.b[bufnr].vcsigns_show_hunk_diffs then 39 high.highlight_hunks(bufnr, hunks) 40 else 41 high.highlight_hunks(bufnr, {}) 42 end 43end 44 45---@param bufnr integer The buffer number. 46---@param vcs Vcs The VCS object for the buffer. 47---@param cb fun(bufnr: integer) Callback to call after the old file contents are refreshed. 48local function _refresh_old_file_contents(bufnr, vcs, cb) 49 local start_time = vim.uv.now() ---@diagnostic disable-line: undefined-field 50 51 repo.show_file(bufnr, vcs, function(old_lines) 52 if not old_lines then 53 -- Some kind of failure, skip the diff. 54 return 55 end 56 local s = state.get(bufnr) 57 local last = s.diff.last_update 58 if start_time <= last then 59 util.verbose "Skipping updating old file, we already have a newer update." 60 return 61 end 62 s.diff.old_lines = old_lines 63 s.diff.last_update = start_time 64 s.diff.hunks_changedtick = vim.b[bufnr].changedtick 65 cb(bufnr) 66 end) 67end 68 69---@param bufnr integer The buffer number. 70---@return Vcs|nil The VCS object if ready, nil otherwise. 71local function _get_vcs_if_ready(bufnr) 72 local vcs_state = state.get(bufnr).vcs 73 local detecting = vcs_state.detecting 74 if detecting == nil then 75 util.verbose "Buffer not initialized yet." 76 end 77 if detecting then 78 util.verbose "Busy detecting, skipping." 79 return 80 end 81 return vcs_state.vcs 82end 83 84--- Expensive update including vcs querying for file contents. 85---@param bufnr integer The buffer number. 86function M.deep_update(bufnr, clear_ignore_cache) 87 if clear_ignore_cache then 88 ignore.clear_ignored_cache() 89 end 90 if vim.bo[bufnr].buftype ~= "" then 91 -- Not a normal file buffer, don't do anything. 92 util.verbose "Not a normal file buffer, skipping." 93 return 94 end 95 local vcs = _get_vcs_if_ready(bufnr) 96 if not vcs then 97 util.verbose "No VCS detected for buffer, skipping." 98 return 99 end 100 101 _refresh_old_file_contents(bufnr, vcs, M.shallow_update) 102end 103 104return M