commit f3a54e7ccfcfa2752eccd7585e2c4b94a4c8c433
parent 430be9d01df443b096ab2c22f943589fb9086025
Author: Justin M. Keyes <justinkz@gmail.com>
Date: Sat, 12 Jul 2025 18:36:07 -0400
refactor(lua): rename vim.diff => vim.text.diff #34864
Problem:
`vim.diff()` was introduced before we had the `vim.text` module, where
it obviously belongs.
Solution:
Move it.
Diffstat:
12 files changed, 176 insertions(+), 173 deletions(-)
diff --git a/runtime/doc/deprecated.txt b/runtime/doc/deprecated.txt
@@ -38,7 +38,7 @@ LSP
LUA
-• todo
+• *vim.diff()* Renamed to |vim.text.diff()|
VIMSCRIPT
diff --git a/runtime/doc/lua.txt b/runtime/doc/lua.txt
@@ -581,7 +581,7 @@ A subset of the `vim.*` stdlib is available in threads, including:
- `vim.mpack` and `vim.json` (useful for serializing messages between threads)
- `require` in threads can use Lua packages from the global |package.path|
- `print()` and `vim.inspect`
-- `vim.diff`
+- `vim.text.diff`
- Most utility functions in `vim.*` that work with pure Lua values, like
`vim.split`, `vim.tbl_*`, `vim.list_*`, etc.
- `vim.is_thread()` returns true from a non-main thread.
@@ -648,74 +648,6 @@ vim.hl.range({bufnr}, {ns}, {higroup}, {start}, {finish}, {opts})
==============================================================================
-VIM.DIFF *vim.diff*
-
-vim.diff({a}, {b}, {opts}) *vim.diff()*
- Run diff on strings {a} and {b}. Any indices returned by this function,
- either directly or via callback arguments, are 1-based.
-
- Examples: >lua
- vim.diff('a\n', 'b\nc\n')
- -- =>
- -- @@ -1 +1,2 @@
- -- -a
- -- +b
- -- +c
-
- vim.diff('a\n', 'b\nc\n', {result_type = 'indices'})
- -- =>
- -- {
- -- {1, 1, 1, 2}
- -- }
-<
-
- Parameters: ~
- • {a} (`string`) First string to compare
- • {b} (`string`) Second string to compare
- • {opts} (`table?`) Optional parameters:
- • {on_hunk}?
- (`fun(start_a: integer, count_a: integer, start_b: integer, count_b: integer): integer?`)
- Invoked for each hunk in the diff. Return a negative number
- to cancel the callback for any remaining hunks. Arguments:
- • `start_a` (`integer`): Start line of hunk in {a}.
- • `count_a` (`integer`): Hunk size in {a}.
- • `start_b` (`integer`): Start line of hunk in {b}.
- • `count_b` (`integer`): Hunk size in {b}.
- • {result_type}? (`'unified'|'indices'`, default: `'unified'`)
- Form of the returned diff:
- • `unified`: String in unified format.
- • `indices`: Array of hunk locations. Note: This option is
- ignored if `on_hunk` is used.
- • {linematch}? (`boolean|integer`) Run linematch on the
- resulting hunks from xdiff. When integer, only hunks upto
- this size in lines are run through linematch. Requires
- `result_type = indices`, ignored otherwise.
- • {algorithm}? (`'myers'|'minimal'|'patience'|'histogram'`,
- default: `'myers'`) Diff algorithm to use. Values:
- • `myers`: the default algorithm
- • `minimal`: spend extra time to generate the smallest
- possible diff
- • `patience`: patience diff algorithm
- • `histogram`: histogram diff algorithm
- • {ctxlen}? (`integer`) Context length
- • {interhunkctxlen}? (`integer`) Inter hunk context length
- • {ignore_whitespace}? (`boolean`) Ignore whitespace
- • {ignore_whitespace_change}? (`boolean`) Ignore whitespace
- change
- • {ignore_whitespace_change_at_eol}? (`boolean`) Ignore
- whitespace change at end-of-line.
- • {ignore_cr_at_eol}? (`boolean`) Ignore carriage return at
- end-of-line
- • {ignore_blank_lines}? (`boolean`) Ignore blank lines
- • {indent_heuristic}? (`boolean`) Use the indent heuristic for
- the internal diff library.
-
- Return: ~
- (`string|integer[][]?`) See {opts.result_type}. `nil` if
- {opts.on_hunk} is given.
-
-
-==============================================================================
VIM.MPACK *vim.mpack*
This module provides encoding and decoding of Lua objects to and from
@@ -4959,6 +4891,70 @@ vim.snippet.stop() *vim.snippet.stop()*
==============================================================================
Lua module: vim.text *vim.text*
+vim.text.diff({a}, {b}, {opts}) *vim.text.diff()*
+ Run diff on strings {a} and {b}. Any indices returned by this function,
+ either directly or via callback arguments, are 1-based.
+
+ Examples: >lua
+ vim.text.diff('a\n', 'b\nc\n')
+ -- =>
+ -- @@ -1 +1,2 @@
+ -- -a
+ -- +b
+ -- +c
+
+ vim.text.diff('a\n', 'b\nc\n', {result_type = 'indices'})
+ -- =>
+ -- {
+ -- {1, 1, 1, 2}
+ -- }
+<
+
+ Parameters: ~
+ • {a} (`string`) First string to compare
+ • {b} (`string`) Second string to compare
+ • {opts} (`table?`) Optional parameters:
+ • {on_hunk}?
+ (`fun(start_a: integer, count_a: integer, start_b: integer, count_b: integer): integer?`)
+ Invoked for each hunk in the diff. Return a negative number
+ to cancel the callback for any remaining hunks. Arguments:
+ • `start_a` (`integer`): Start line of hunk in {a}.
+ • `count_a` (`integer`): Hunk size in {a}.
+ • `start_b` (`integer`): Start line of hunk in {b}.
+ • `count_b` (`integer`): Hunk size in {b}.
+ • {result_type}? (`'unified'|'indices'`, default: `'unified'`)
+ Form of the returned diff:
+ • `unified`: String in unified format.
+ • `indices`: Array of hunk locations. Note: This option is
+ ignored if `on_hunk` is used.
+ • {linematch}? (`boolean|integer`) Run linematch on the
+ resulting hunks from xdiff. When integer, only hunks upto
+ this size in lines are run through linematch. Requires
+ `result_type = indices`, ignored otherwise.
+ • {algorithm}? (`'myers'|'minimal'|'patience'|'histogram'`,
+ default: `'myers'`) Diff algorithm to use. Values:
+ • `myers`: the default algorithm
+ • `minimal`: spend extra time to generate the smallest
+ possible diff
+ • `patience`: patience diff algorithm
+ • `histogram`: histogram diff algorithm
+ • {ctxlen}? (`integer`) Context length
+ • {interhunkctxlen}? (`integer`) Inter hunk context length
+ • {ignore_whitespace}? (`boolean`) Ignore whitespace
+ • {ignore_whitespace_change}? (`boolean`) Ignore whitespace
+ change
+ • {ignore_whitespace_change_at_eol}? (`boolean`) Ignore
+ whitespace change at end-of-line.
+ • {ignore_cr_at_eol}? (`boolean`) Ignore carriage return at
+ end-of-line
+ • {ignore_blank_lines}? (`boolean`) Ignore blank lines
+ • {indent_heuristic}? (`boolean`) Use the indent heuristic for
+ the internal diff library.
+
+ Return: ~
+ (`string|integer[][]?`) See {opts.result_type}. `nil` if
+ {opts.on_hunk} is given.
+
vim.text.hexdecode({enc}) *vim.text.hexdecode()*
Hex decode a string.
diff --git a/runtime/doc/news-0.9.txt b/runtime/doc/news-0.9.txt
@@ -140,7 +140,7 @@ The following new APIs or features were added.
• 'diffopt' now includes a `linematch` option to enable a second-stage diff on
individual hunks to provide much more accurate diffs. This option is also
- available to |vim.diff()|
+ available to |vim.text.diff()|
See https://github.com/neovim/neovim/pull/14537.
diff --git a/runtime/doc/news.txt b/runtime/doc/news.txt
@@ -87,7 +87,7 @@ LSP
LUA
-• todo
+• Renamed `vim.diff` to `vim.text.diff`.
OPTIONS
diff --git a/runtime/lua/vim/_editor.lua b/runtime/lua/vim/_editor.lua
@@ -1314,9 +1314,12 @@ end
require('vim._options')
--- Remove at Nvim 1.0
+--- Remove at Nvim 1.0
---@deprecated
vim.loop = vim.uv
+--- Renamed to `vim.text.diff`, remove at Nvim 1.0
+---@deprecated
+vim.diff = vim._diff ---@type fun(a: string, b: string, opts?: vim.text.diff.Opts): string|integer[][]?
-- Deprecated. Remove at Nvim 2.0
vim.highlight = vim._defer_deprecated_module('vim.highlight', 'vim.hl')
diff --git a/runtime/lua/vim/_meta/diff.lua b/runtime/lua/vim/_meta/diff.lua
@@ -1,71 +0,0 @@
----@meta
-
---- Optional parameters:
---- @class vim.diff.Opts
---- @inlinedoc
----
---- Invoked for each hunk in the diff. Return a negative number
---- to cancel the callback for any remaining hunks.
---- Arguments:
---- - `start_a` (`integer`): Start line of hunk in {a}.
---- - `count_a` (`integer`): Hunk size in {a}.
---- - `start_b` (`integer`): Start line of hunk in {b}.
---- - `count_b` (`integer`): Hunk size in {b}.
---- @field on_hunk? fun(start_a: integer, count_a: integer, start_b: integer, count_b: integer): integer?
----
---- Form of the returned diff:
---- - `unified`: String in unified format.
---- - `indices`: Array of hunk locations.
---- Note: This option is ignored if `on_hunk` is used.
---- (default: `'unified'`)
---- @field result_type? 'unified'|'indices'
----
---- Run linematch on the resulting hunks from xdiff. When integer, only hunks
---- upto this size in lines are run through linematch.
---- Requires `result_type = indices`, ignored otherwise.
---- @field linematch? boolean|integer
----
---- Diff algorithm to use. Values:
---- - `myers`: the default algorithm
---- - `minimal`: spend extra time to generate the smallest possible diff
---- - `patience`: patience diff algorithm
---- - `histogram`: histogram diff algorithm
---- (default: `'myers'`)
---- @field algorithm? 'myers'|'minimal'|'patience'|'histogram'
---- @field ctxlen? integer Context length
---- @field interhunkctxlen? integer Inter hunk context length
---- @field ignore_whitespace? boolean Ignore whitespace
---- @field ignore_whitespace_change? boolean Ignore whitespace change
---- @field ignore_whitespace_change_at_eol? boolean Ignore whitespace change at end-of-line.
---- @field ignore_cr_at_eol? boolean Ignore carriage return at end-of-line
---- @field ignore_blank_lines? boolean Ignore blank lines
---- @field indent_heuristic? boolean Use the indent heuristic for the internal diff library.
-
--- luacheck: no unused args
-
---- Run diff on strings {a} and {b}. Any indices returned by this function,
---- either directly or via callback arguments, are 1-based.
----
---- Examples:
----
---- ```lua
---- vim.diff('a\n', 'b\nc\n')
---- -- =>
---- -- @@ -1 +1,2 @@
---- -- -a
---- -- +b
---- -- +c
----
---- vim.diff('a\n', 'b\nc\n', {result_type = 'indices'})
---- -- =>
---- -- {
---- -- {1, 1, 1, 2}
---- -- }
---- ```
----
----@param a string First string to compare
----@param b string Second string to compare
----@param opts? vim.diff.Opts
----@return string|integer[][]?
---- See {opts.result_type}. `nil` if {opts.on_hunk} is given.
-function vim.diff(a, b, opts) end
diff --git a/runtime/lua/vim/text.lua b/runtime/lua/vim/text.lua
@@ -2,6 +2,80 @@
local M = {}
+--- Optional parameters:
+--- @class vim.text.diff.Opts
+--- @inlinedoc
+---
+--- Invoked for each hunk in the diff. Return a negative number
+--- to cancel the callback for any remaining hunks.
+--- Arguments:
+--- - `start_a` (`integer`): Start line of hunk in {a}.
+--- - `count_a` (`integer`): Hunk size in {a}.
+--- - `start_b` (`integer`): Start line of hunk in {b}.
+--- - `count_b` (`integer`): Hunk size in {b}.
+--- @field on_hunk? fun(start_a: integer, count_a: integer, start_b: integer, count_b: integer): integer?
+---
+--- Form of the returned diff:
+--- - `unified`: String in unified format.
+--- - `indices`: Array of hunk locations.
+--- Note: This option is ignored if `on_hunk` is used.
+--- (default: `'unified'`)
+--- @field result_type? 'unified'|'indices'
+---
+--- Run linematch on the resulting hunks from xdiff. When integer, only hunks
+--- upto this size in lines are run through linematch.
+--- Requires `result_type = indices`, ignored otherwise.
+--- @field linematch? boolean|integer
+---
+--- Diff algorithm to use. Values:
+--- - `myers`: the default algorithm
+--- - `minimal`: spend extra time to generate the smallest possible diff
+--- - `patience`: patience diff algorithm
+--- - `histogram`: histogram diff algorithm
+--- (default: `'myers'`)
+--- @field algorithm? 'myers'|'minimal'|'patience'|'histogram'
+--- @field ctxlen? integer Context length
+--- @field interhunkctxlen? integer Inter hunk context length
+--- @field ignore_whitespace? boolean Ignore whitespace
+--- @field ignore_whitespace_change? boolean Ignore whitespace change
+--- @field ignore_whitespace_change_at_eol? boolean Ignore whitespace change at end-of-line.
+--- @field ignore_cr_at_eol? boolean Ignore carriage return at end-of-line
+--- @field ignore_blank_lines? boolean Ignore blank lines
+--- @field indent_heuristic? boolean Use the indent heuristic for the internal diff library.
+
+-- luacheck: no unused args
+
+--- Run diff on strings {a} and {b}. Any indices returned by this function,
+--- either directly or via callback arguments, are 1-based.
+---
+--- Examples:
+---
+--- ```lua
+--- vim.text.diff('a\n', 'b\nc\n')
+--- -- =>
+--- -- @@ -1 +1,2 @@
+--- -- -a
+--- -- +b
+--- -- +c
+---
+--- vim.text.diff('a\n', 'b\nc\n', {result_type = 'indices'})
+--- -- =>
+--- -- {
+--- -- {1, 1, 1, 2}
+--- -- }
+--- ```
+---
+---@diagnostic disable-next-line: undefined-doc-param
+---@param a string First string to compare
+---@diagnostic disable-next-line: undefined-doc-param
+---@param b string Second string to compare
+---@diagnostic disable-next-line: undefined-doc-param
+---@param opts? vim.text.diff.Opts
+---@return string|integer[][]? # See {opts.result_type}. `nil` if {opts.on_hunk} is given.
+function M.diff(...)
+ return vim._diff(...)
+end
+
local alphabet = '0123456789ABCDEF'
local atoi = {} ---@type table<string, integer>
local itoa = {} ---@type table<integer, string>
diff --git a/src/gen/gen_vimdoc.lua b/src/gen/gen_vimdoc.lua
@@ -133,7 +133,6 @@ local config = {
filename = 'lua.txt',
section_order = {
'hl.lua',
- 'diff.lua',
'mpack.lua',
'json.lua',
'base64.lua',
@@ -185,7 +184,6 @@ local config = {
'runtime/lua/vim/text.lua',
'runtime/lua/vim/glob.lua',
'runtime/lua/vim/_meta/builtin.lua',
- 'runtime/lua/vim/_meta/diff.lua',
'runtime/lua/vim/_meta/mpack.lua',
'runtime/lua/vim/_meta/json.lua',
'runtime/lua/vim/_meta/base64.lua',
@@ -230,7 +228,6 @@ local config = {
'mpack',
'json',
'base64',
- 'diff',
'spell',
'regex',
'lpeg',
diff --git a/src/nvim/lua/stdlib.c b/src/nvim/lua/stdlib.c
@@ -761,9 +761,9 @@ void nlua_state_add_stdlib(lua_State *const lstate, bool is_thread)
lua_setfield(lstate, -2, "lpeg");
lua_pop(lstate, 4);
- // vim.diff
+ // vim.text.diff
lua_pushcfunction(lstate, &nlua_xdl_diff);
- lua_setfield(lstate, -2, "diff");
+ lua_setfield(lstate, -2, "_diff");
// vim.json
lua_cjson_new(lstate);
diff --git a/src/nvim/lua/xdiff.c b/src/nvim/lua/xdiff.c
@@ -164,9 +164,7 @@ static int call_on_hunk_cb(int start_a, int count_a, int start_b, int count_b, v
lua_pushinteger(lstate, count_b);
if (lua_pcall(lstate, 4, 1, 0) != 0) {
- api_set_error(err, kErrorTypeException,
- "error running function on_hunk: %s",
- lua_tostring(lstate, -1));
+ api_set_error(err, kErrorTypeException, "on_hunk: %s", lua_tostring(lstate, -1));
return -1;
}
diff --git a/test/functional/lua/thread_spec.lua b/test/functional/lua/thread_spec.lua
@@ -217,7 +217,7 @@ describe('thread', function()
it('diff', function()
exec_lua [[
local entry = function(async)
- async:send(vim.diff('Hello\n', 'Helli\n'))
+ async:send(vim.text.diff('Hello\n', 'Helli\n'))
end
local on_async = function(ret)
vim.rpcnotify(1, 'result', ret)
@@ -372,7 +372,7 @@ describe('threadpool', function()
it('work', function()
exec_lua [[
local work_fn = function()
- return vim.diff('Hello\n', 'Helli\n')
+ return vim.text.diff('Hello\n', 'Helli\n')
end
local after_work_fn = function(ret)
vim.rpcnotify(1, 'result', ret)
diff --git a/test/functional/lua/xdiff_spec.lua b/test/functional/lua/xdiff_spec.lua
@@ -27,7 +27,7 @@ describe('xdiff bindings', function()
'',
}, '\n'),
exec_lua(function()
- return vim.diff(a1, b1)
+ return vim.text.diff(a1, b1)
end)
)
@@ -43,7 +43,7 @@ describe('xdiff bindings', function()
'',
}, '\n'),
exec_lua(function()
- return vim.diff(a2, b2)
+ return vim.text.diff(a2, b2)
end)
)
end)
@@ -53,7 +53,7 @@ describe('xdiff bindings', function()
{ { 1, 1, 1, 1 } },
exec_lua(function()
local exp = {} --- @type table[]
- assert(vim.diff(a1, b1, {
+ assert(vim.text.diff(a1, b1, {
on_hunk = function(...)
exp[#exp + 1] = { ... }
end,
@@ -66,7 +66,7 @@ describe('xdiff bindings', function()
{ { 1, 1, 1, 1 }, { 3, 1, 3, 2 } },
exec_lua(function()
local exp = {} --- @type table[]
- assert(vim.diff(a2, b2, {
+ assert(vim.text.diff(a2, b2, {
on_hunk = function(...)
exp[#exp + 1] = { ... }
end,
@@ -80,7 +80,7 @@ describe('xdiff bindings', function()
{ { 1, 1, 1, 1 }, { 3, 1, 3, 2 } },
exec_lua(function()
local exp = {} --- @type table[]
- assert(vim.diff(a2, b2, {
+ assert(vim.text.diff(a2, b2, {
on_hunk = function(...)
exp[#exp + 1] = { ... }
end,
@@ -92,10 +92,10 @@ describe('xdiff bindings', function()
end)
it('with error callback', function()
- eq(
- [[.../xdiff_spec.lua:0: error running function on_hunk: .../xdiff_spec.lua:0: ERROR1]],
+ t.matches(
+ [[on_hunk: %.%.%./xdiff_spec%.lua%:0%: ERROR1]],
pcall_err(exec_lua, function()
- vim.diff(a1, b1, {
+ vim.text.diff(a1, b1, {
on_hunk = function()
error('ERROR1')
end,
@@ -108,14 +108,14 @@ describe('xdiff bindings', function()
eq(
{ { 1, 1, 1, 1 } },
exec_lua(function()
- return vim.diff(a1, b1, { result_type = 'indices' })
+ return vim.text.diff(a1, b1, { result_type = 'indices' })
end)
)
eq(
{ { 1, 1, 1, 1 }, { 3, 1, 3, 2 } },
exec_lua(function()
- return vim.diff(a2, b2, { result_type = 'indices' })
+ return vim.text.diff(a2, b2, { result_type = 'indices' })
end)
)
end)
@@ -160,7 +160,7 @@ describe('xdiff bindings', function()
'',
}, '\n'),
exec_lua(function()
- return vim.diff(a, b, {
+ return vim.text.diff(a, b, {
algorithm = 'patience',
})
end)
@@ -169,20 +169,26 @@ describe('xdiff bindings', function()
end)
it('can handle bad args', function()
- eq([[Expected at least 2 arguments]], pcall_err(exec_lua, [[vim.diff('a')]]))
+ eq([[Expected at least 2 arguments]], pcall_err(exec_lua, [[vim.text.diff('a')]]))
- eq([[bad argument #1 to 'diff' (expected string)]], pcall_err(exec_lua, [[vim.diff(1, 2)]]))
+ t.matches(
+ [[bad argument %#1 to '_?diff' %(expected string%)]],
+ pcall_err(exec_lua, [[vim.text.diff(1, 2)]])
+ )
- eq(
- [[bad argument #3 to 'diff' (expected table)]],
- pcall_err(exec_lua, [[vim.diff('a', 'b', true)]])
+ t.matches(
+ [[bad argument %#3 to '_?diff' %(expected table%)]],
+ pcall_err(exec_lua, [[vim.text.diff('a', 'b', true)]])
)
- eq([[invalid key: bad_key]], pcall_err(exec_lua, [[vim.diff('a', 'b', { bad_key = true })]]))
+ eq(
+ [[invalid key: bad_key]],
+ pcall_err(exec_lua, [[vim.text.diff('a', 'b', { bad_key = true })]])
+ )
eq(
[[on_hunk is not a function]],
- pcall_err(exec_lua, [[vim.diff('a', 'b', { on_hunk = true })]])
+ pcall_err(exec_lua, [[vim.text.diff('a', 'b', { on_hunk = true })]])
)
end)
@@ -190,7 +196,7 @@ describe('xdiff bindings', function()
eq(
{ { 0, 0, 1, 1 }, { 1, 0, 3, 2 } },
exec_lua(function()
- return vim.diff('\n', '\0\n\n\nb', { linematch = true, result_type = 'indices' })
+ return vim.text.diff('\n', '\0\n\n\nb', { linematch = true, result_type = 'indices' })
end)
)
end)