Skip to content

Commit

Permalink
feat(diff): run xdiff on a separate thread
Browse files Browse the repository at this point in the history
  • Loading branch information
lewis6991 committed Apr 11, 2022
1 parent 4a68d2a commit 18bffca
Show file tree
Hide file tree
Showing 14 changed files with 191 additions and 74 deletions.
1 change: 1 addition & 0 deletions gitsigns.nvim-scm-1.rockspec
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ build = {
['gitsigns.debounce'] = 'lua/gitsigns/debounce.lua',
['gitsigns.debug'] = 'lua/gitsigns/debug.lua',
['gitsigns.diffthis'] = 'lua/gitsigns/diffthis.lua',
['gitsigns.diff'] = 'lua/gitsigns/diff.lua',
['gitsigns.diff_ext'] = 'lua/gitsigns/diff_ext.lua',
['gitsigns.diff_int'] = 'lua/gitsigns/diff_int.lua',
['gitsigns.diff_int.xdl_diff_ffi'] = 'lua/gitsigns/diff_int/xdl_diff_ffi.lua',
Expand Down
12 changes: 1 addition & 11 deletions lua/gitsigns/actions.lua

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions lua/gitsigns/async.lua

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 9 additions & 0 deletions lua/gitsigns/config.lua

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 13 additions & 0 deletions lua/gitsigns/diff.lua

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

70 changes: 56 additions & 14 deletions lua/gitsigns/diff_int.lua

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 2 additions & 11 deletions lua/gitsigns/manager.lua

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 1 addition & 11 deletions teal/gitsigns/actions.tl
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ local util = require('gitsigns.util')
local manager = require('gitsigns.manager')
local git = require('gitsigns.git')
local warn = require('gitsigns.message').warn
local run_diff = require('gitsigns.diff')

local gs_cache = require('gitsigns.cache')
local cache = gs_cache.cache
Expand Down Expand Up @@ -602,17 +603,6 @@ M.get_hunks = function(bufnr: integer): {Hunk_Public}
return ret
end

local function run_diff(a: {string}, b: {string}): {Hunk}
local diff_opts = config.diff_opts
local f: function({string}, {string}, string, boolean): {Hunk}
if config.diff_opts.internal then
f = require('gitsigns.diff_int').run_diff
else
f = require('gitsigns.diff_ext').run_diff
end
return f(a, b, diff_opts.algorithm, diff_opts.indent_heuristic)
end

local function get_blame_hunk(repo: git.Repo, info: git.BlameInfo): Hunk, integer, integer
local a = {}
-- If no previous so sha of blame added the file
Expand Down
5 changes: 5 additions & 0 deletions teal/gitsigns/async.tl
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,19 @@ local type fun2 = function <A1,A2> (A1,A2)
local type fun2_2 = function <A1,A2,R1,R2> (A1,A2) : R1,R2
local type fun3 = function <A1,A2,A3> (A1,A2,A3)
local type fun4 = function <A1,A2,A3,A4> (A1,A2,A3,A4)
local type fun4_1 = function <A1,A2,A3,A4,R1> (A1,A2,A3,A4): R1

local record Async
-- Order by highest number of return types

void: function (fun0 ): fun0
void: function<A1> (fun1<A1> ): fun1<A1>
void: function<A1,A2>(fun2<A1,A2>): fun2<A1,A2>
void: function<A1,A2,A3,A4,R1>(fun4_1<A1,A2,A3,A4,R1>): fun4_1<A1,A2,A3,A4,R1>
void: function<A1,A2,A3,A4>(fun4<A1,A2,A3,A4>): fun4<A1,A2,A3,A4>

wrap: function<A1,A2,R1,R2>(function(A1,A2, function(R1,R2)), integer): fun2_2 <A1,A2,R1,R2>
wrap: function<A1,A2,A3,A4,R1>(function(A1,A2,A3,A4,function(R1)), integer): fun4_1<A1,A2,A3,A4,R1>
wrap: function<A1,A2,A3> (function(A1,A2,A3,function()) , integer): fun3 <A1,A2,A3>

scheduler: function()
Expand Down
9 changes: 9 additions & 0 deletions teal/gitsigns/config.tl
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ local record M
word_diff: boolean
_refresh_staged_on_update: boolean
_blame_cache: boolean
_threaded_diff: boolean

_git_version: string
_verbose: boolean
Expand Down Expand Up @@ -629,6 +630,14 @@ M.schema = {
]]
},

_threaded_diff = {
type = 'boolean',
default = false,
description = [[
Run diffs on a separate thread
]]
},

debug_mode = {
type = 'boolean',
default = false,
Expand Down
13 changes: 13 additions & 0 deletions teal/gitsigns/diff.tl
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
local config = require('gitsigns.config').config
local Hunk = require('gitsigns.hunks').Hunk

return function(a: {string}, b: {string}): {Hunk}
local diff_opts = config.diff_opts
local f: function({string}, {string}, string, boolean): {Hunk}
if diff_opts.internal then
f = require('gitsigns.diff_int').run_diff
else
f = require('gitsigns.diff_ext').run_diff
end
return f(a, b, diff_opts.algorithm, diff_opts.indent_heuristic)
end
72 changes: 57 additions & 15 deletions teal/gitsigns/diff_int.tl
Original file line number Diff line number Diff line change
@@ -1,28 +1,70 @@
local create_hunk = require("gitsigns.hunks").create_hunk
local Hunk = require('gitsigns.hunks').Hunk
local config = require('gitsigns.config').config
local async = require('gitsigns.async')

local M = {}
local record M
run_diff: function({string}, {string}, string, boolean): {Hunk}
run_word_diff: function({string}, {string}): {Region}, {Region}
end

local type DiffFun = function({string}, {string}, string, boolean): {DiffResult}
local type DiffResult = {integer, integer, integer, integer}

local run_diff_xdl: function({string}, {string}, diff_algo: string, indent_heuristic: boolean): {DiffResult}
local run_diff_xdl = function(
fa: {string}, fb: {string},
algorithm: string, indent_heuristic: boolean
): {DiffResult}

local a = vim.tbl_isempty(fa) and '' or table.concat(fa, '\n')..'\n'
local b = vim.tbl_isempty(fb) and '' or table.concat(fb, '\n')..'\n'

return vim.diff(a, b, {
result_type = 'indices',
algorithm = algorithm,
indent_heuristic = indent_heuristic
})
end

local run_diff_xdl_async = async.wrap(function(
fa: {string}, fb: {string},
algorithm: string, indent_heuristic: boolean,
callback: function({DiffResult})
)

if vim.diff then
run_diff_xdl = function(fa: {string}, fb: {string}, algorithm: string, indent_heuristic: boolean): {DiffResult}
local a = vim.tbl_isempty(fa) and '' or table.concat(fa, '\n')..'\n'
local b = vim.tbl_isempty(fb) and '' or table.concat(fb, '\n')..'\n'
return vim.diff(a, b, {
local a = vim.tbl_isempty(fa) and '' or table.concat(fa, '\n')..'\n'
local b = vim.tbl_isempty(fb) and '' or table.concat(fb, '\n')..'\n'

vim.loop.new_work(function(
a0: string, b0: string,
algorithm0: string, indent_heuristic0: boolean
): string
return vim.mpack.encode(vim.diff(a0, b0, {
result_type = 'indices',
algorithm = algorithm,
indent_heuristic = indent_heuristic
})
end
else
algorithm = algorithm0,
indent_heuristic = indent_heuristic0
}))
end, function(r: string)
callback(vim.mpack.decode(r) as {DiffResult})
end):queue(a, b, algorithm, indent_heuristic)
end, 5)

if not vim.diff then
run_diff_xdl = require('gitsigns.diff_int.xdl_diff_ffi')
end

function M.run_diff(fa: {string}, fb: {string}, diff_algo: string, indent_heuristic: boolean): {Hunk}
local results = run_diff_xdl(fa, fb, diff_algo, indent_heuristic)
M.run_diff = async.void(function(
fa: {string}, fb: {string},
diff_algo: string, indent_heuristic: boolean
): {Hunk}
local run_diff0: DiffFun
if config._threaded_diff and vim.is_thread then
run_diff0 = run_diff_xdl_async
else
run_diff0 = run_diff_xdl
end

local results = run_diff0(fa, fb, diff_algo, indent_heuristic)

local hunks: {Hunk} = {}

Expand All @@ -43,7 +85,7 @@ function M.run_diff(fa: {string}, fb: {string}, diff_algo: string, indent_heuris
end

return hunks
end
end)

local type Region = {integer, string, integer, integer}

Expand Down
Loading

0 comments on commit 18bffca

Please sign in to comment.