From 3f1d8238e88a3f55dd6e34e9023c9ab1aa44ffaf Mon Sep 17 00:00:00 2001 From: Matěj Cepl Date: Sat, 25 Mar 2023 13:36:20 +0100 Subject: Hide vis/vim complexity behind getline shim. --- ftplugin/diff_navigator.lua | 26 +++++++++----------------- ftplugin/hunk.lua | 42 +++++++++++++++++++++++++++++++++++++++--- ftplugin/hunk_spec.lua | 20 +++++++++++++++++--- 3 files changed, 65 insertions(+), 23 deletions(-) diff --git a/ftplugin/diff_navigator.lua b/ftplugin/diff_navigator.lua index c36cfab..d0789d9 100644 --- a/ftplugin/diff_navigator.lua +++ b/ftplugin/diff_navigator.lua @@ -42,14 +42,6 @@ vim.g.loaded_diff_navigator = 1 -- Utility functions --- from http://lua-users.org/wiki/SplitJoin -local split = function(self, sep) - local sep, fields = sep or ":", {} - local pattern = string.format("([^%s]+)", sep) - self:gsub(pattern, function(c) fields[#fields+1] = c end) - return fields -end - local function executable(cmd) -- calling /bin/sh -c even for users with default shells -- which are not POSIX compatible (squinting at fish) @@ -87,13 +79,13 @@ local hnk = require('hunk') -- Get hunk header from the hunk surrounding cursor function getCurrentHunkHeader() local lineno = 0 - if (vim.api.nvim_eval('getline(".") =~ "^+++ \\|^--- "') ~= 0) then + if (vim.api.nvim_eval(getline(".") .. ' =~ "^+++ \\|^--- "') ~= 0) then lineno = vim.fn.search('^@@[ +-\\,\\d]*@@.*$', 'ncW') else lineno = vim.fn.search('^@@[ +-\\,\\d]*@@.*$', 'bncW') end - return hnk.Header.parse(vim.fn.getline(lineno), lineno) + return hnk.Header.parse(lineno) end @@ -169,7 +161,7 @@ function DiffSplitHunk() -- -- Start line below header and stop one line above the current line local diff_lines = hnk.countLines(old_cur_header['line'] + 1, - cur_line_no - 1, vim.fn.getline) + cur_line_no - 1) local diff_old = diff_lines[1] local diff_new = diff_lines[2] @@ -231,7 +223,7 @@ function DiffDeleteHunk() -- we are in the middle of the file ... it's a bit more complicated else local count_lines = hnk.countLines(start_hunk_line + 1, - next_hunk_line - 1, vim.fn.getline) + next_hunk_line - 1) local added_lines = count_lines[2] - count_lines[1] vim.fn.setpos(".", {0, next_hunk_line, 1, 0}) vim.cmd("normal " .. start_hunk_line .. "," .. (next_hunk_line - 1) .. "d") @@ -244,16 +236,16 @@ function DiffDeleteHunk() local cur_header = hnk.parse(vim.fn.line(".")) local old_line = cur_header['newFirst'] local new_line = old_line - added_lines - vim.fn.setreg('x', vim.fn.substitute(vim.fn.getline("."), "+" .. old_line .. ",", + vim.fn.setreg('x', vim.fn.substitute(hnk.getline("."), "+" .. old_line .. ",", "+" .. new_line .. ",", "")) vim.cmd('normal ^d$"xp') -- check the next hunk - local next_hunk_line = vim.fn.search('\\_^@@[ +-\\,\\d]*@@\\_.*\\_$', 'nW') - local start_of_next_file_line = vim.fn.search('^--- .*$', 'ncW') + next_hunk_line = vim.fn.search('\\_^@@[ +-\\,\\d]*@@\\_.*\\_$', 'nW') + start_of_next_file_line = vim.fn.search('^--- .*$', 'ncW') if (start_of_next_file_line < next_hunk_line) then - local next_hunk_line = start_of_next_file_line - local last_hunk_in_file = 1 + next_hunk_line = start_of_next_file_line + last_hunk_in_file = 1 end vim.fn.setpos(".", {0, next_hunk_line, 1, 0}) end diff --git a/ftplugin/hunk.lua b/ftplugin/hunk.lua index db8ac06..d450cb6 100644 --- a/ftplugin/hunk.lua +++ b/ftplugin/hunk.lua @@ -11,8 +11,18 @@ local M = {} -- Header object M.Header = {} -function M.Header:parse(inline, lineNo) +function M.Header:parse(lineNo) + local inline local pat = "@@%s+%-(%d+),(%d+)%s+%+(%d+),(%d+)%s+@@%s*(.*)" + + if (lineNo == "." or type(lineNo) == "number") then + -- to convert lineNo into proper number, if it was "." originally + inline, lineNo = M.getline(lineNo) + else + inline = lineNo + lineNo = 0 + end + local of, oc, nf, nc, rem = inline:match(pat) return { @@ -33,15 +43,41 @@ function M.createHunkHeader(oldStart, oldLen, newStart, newLen, remaind) " +" .. newStart .. "," .. newLen .. " @@ " .. remaind end +-- Compatibility shim for getline() +function M.getline(where, endWhere) + if vis ~= nil then + local win = vis.win + local line = where + + if where == "." then + line = win.selection.line + end + if endWhere == nil then + return win.file.lines[line], line + end + + -- now endWhere ~= nil and we need to return an array + local out = {} + for i=line, endWhere do + table.insert(out, win.file.lines[i]) + end + + return out, line + else + return vim.fn.getline(where), vim.fn.line(where) + end + end + + -- Return number of lines in the range between start and end line (both -- inclusive) which are from the state before patch and the one after -- patch is applied. -function M.countLines(start, endline, getlfn) +function M.countLines(start, endline) local context_lines = 0 local old_lines = 0 local new_lines = 0 - for line in pairs(getlfn(start, endline)) do + for line, _ in pairs(M.getline(start, endline)) do local first_char = line:sub(1, 1) if first_char == ' ' then local context_lines = context_lines + 1 diff --git a/ftplugin/hunk_spec.lua b/ftplugin/hunk_spec.lua index 13d14f3..75918bb 100644 --- a/ftplugin/hunk_spec.lua +++ b/ftplugin/hunk_spec.lua @@ -2,8 +2,15 @@ describe("Parsing of a hunk header", function() local hk, header, test_header setup(function() - hk = require("hunk") test_header = "@@ -20,8 +20,17 @@ Hunk #1, a/tests/test_ec_curves.py" + hk = require("hunk") + hk.old_getline = hk.getline + hk.getline = function(where) return test_header end + end) + + teardown(function() + hk.getline = hk.old_getline + hk.old_getline = nil end) before_each(function() @@ -16,7 +23,7 @@ describe("Parsing of a hunk header", function() it("original line number is preserved in the attribute line", function() -- not relevant here, because parse() method was run without line# - assert.is_nil(header.line) + assert.is.equal(header.line, 0) end) it("attributes are set correctly", function() @@ -36,6 +43,13 @@ describe("Class functions", function() setup(function() hk = require("hunk") + hk.old_getline = hk.getline + hk.getline = function(beg, fin) return {"a", "b"} end + end) + + teardown(function() + hk.getline = hk.old_getline + hk.old_getline = nil end) -- TODO some protection of hk.createHunkHeader() against bad @@ -48,7 +62,7 @@ describe("Class functions", function() end) it("counts lines in chunk correctly", function() - local header_str = hk.countLines(12,15, function(beg, fin) return {} end) + -- local header_str = hk.countLines(12,15) pending("This test is pending ...") end) end) -- cgit