diff --git a/runtime/doc/deprecated.txt b/runtime/doc/deprecated.txt index 99300750c3..f235698cda 100644 --- 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 index a148b20c4a..95e9e07bc5 100644 --- 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. @@ -647,74 +647,6 @@ vim.hl.range({bufnr}, {ns}, {higroup}, {start}, {finish}, {opts}) manually. nil is returned if timeout is not specified -============================================================================== -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* @@ -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 index 3b078cf2cd..d2fc64d860 100644 --- 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 index 29643c3bed..9db0004143 100644 --- 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 index d8bd2d96d2..ed8f9f258b 100644 --- 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 deleted file mode 100644 index 4803ed4775..0000000000 --- a/runtime/lua/vim/_meta/diff.lua +++ /dev/null @@ -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 index 25126d738d..8d8c49d327 100644 --- 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 local itoa = {} ---@type table diff --git a/src/gen/gen_vimdoc.lua b/src/gen/gen_vimdoc.lua index f932fadb53..3ffca47d40 100755 --- 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 index 2fc9367ead..0340a22a34 100644 --- 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 index 3eccfba47c..c8272e4aaa 100644 --- 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 index e4ff2b8068..8653377760 100644 --- 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 index 269dbde10a..3ffe16e4d9 100644 --- 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)]])) - - eq( - [[bad argument #3 to 'diff' (expected table)]], - pcall_err(exec_lua, [[vim.diff('a', 'b', true)]]) + t.matches( + [[bad argument %#1 to '_?diff' %(expected string%)]], + pcall_err(exec_lua, [[vim.text.diff(1, 2)]]) ) - eq([[invalid key: bad_key]], pcall_err(exec_lua, [[vim.diff('a', 'b', { bad_key = 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.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)