ada9461
Branches > main > ada9461 > files
Nvim - Re-enable parinfer, fix multi-line edits
Commit: ada9461afdb15b1d69c9f3456e4d6262cdf84521
Parent: f198332
2 changed files:
nvim/ftplugin/clojure.lua view file
@@ -1,2 +1,2 @@ require("plugins.conjure")--- require("parinfer.plugin").setup()+require("parinfer.plugin").setup()nvim/lua/parinfer/plugin.lua view file
@@ -14,11 +14,10 @@ smart = parinfer.smartMode} local ns = api.nvim_create_namespace("parinfer")+local group = api.nvim_create_augroup("parinfer", {clear = true}) -local state = setmetatable({}, {__index = function(t, k)- t[k] = {}- return t[k]-end})+--- Per buffer: the text and changedtick as of the last run, and the cursor before the current edit+local state = {} -- Returns true if 'val' is truthy, and not 0, otherwise returns false -- 0 and 1 are commonly used in vim functions for true/false, but 0 is a truthy value in Lua@@ -31,8 +30,8 @@ end -- Looks up and returns 'opt' in the buffer-local and global option tables vim.b and vim.g-local function get_option(opt)- local b = vim.b[opt]+local function get_option(bufnr, opt)+ local b = vim.b[bufnr][opt] if b == nil then return vim.g[opt] else@@ -40,212 +39,135 @@ end end -local function invoke_parinfer(bufnr, text, lnum, col)- local prev_lnum, prev_col = unpack(state[bufnr]["prev-cursor"])- local changes = state[bufnr].changes- local request = {commentChars = get_option("parinfer_comment_chars"),- prevCursorLine = prev_lnum,- prevCursorX = prev_col,- cursorLine = lnum,- cursorX = col + 1,- changes = changes,- forceBalance = normalize_bool(get_option("parinfer_force_balance"))}- local response = modes[get_option("parinfer_mode")](text, request)- state[bufnr].changes = {}- return response-end+--- Collapses everything that happened since the last run into one change.+--- Linewise edits (V>, Vd + p, :m, ...) used to be passed as several on_bytes changes, each in the+--- coordinates of a buffer that had been changed again since. Smart mode then shifted the+--- indentation of the wrong lines (or the same lines more than once) and mangled the forms.+local function get_change(old, new)+ if old == nil or old == new then return nil end -local function build_replacement_lines(new_lines, start_b, count_b)- local t = {}- local i = 0-- for num = start_b, start_b + count_b do- local line = new_lines[num]- if line ~= nil then- i = i + 1- t[i] = line- end+ local max = math.min(#old, #new)+ local prefix = 0+ while prefix < max and old:byte(prefix + 1) == new:byte(prefix + 1) do+ prefix = prefix + 1+ end+ local suffix = 0+ while suffix < max - prefix and old:byte(#old - suffix) == new:byte(#new - suffix) do+ suffix = suffix + 1 end - return t+ local before = old:sub(1, prefix)+ local _, line_breaks = before:gsub("\n", "")+ local line_start = before:find("[^\n]*$")+ return {lineNo = line_breaks + 1,+ x = prefix - line_start + 2,+ oldText = old:sub(prefix + 1, #old - suffix),+ newText = new:sub(prefix + 1, #new - suffix)} end -local function apply_hunk(bufnr, new_lines, hunk)- local start_a, count_a, start_b, count_b = unpack(hunk)- api.nvim_buf_set_lines(bufnr, start_a - 1, start_a + count_a, false, build_replacement_lines(new_lines, start_b, count_b))-end+local function update_buffer(bufnr, old_text, new_text)+ local new_lines = vim.split(new_text, "\n", {plain = true})+ local hunks = diff(old_text .. "\n", new_text .. "\n", {result_type = "indices"}) -local function update_buffer(bufnr, old_contents, new_contents)- api.nvim_command("silent! undojoin")- state[bufnr].locked = true-- local new_lines = vim.split(new_contents, "\n")- local hunks = diff(old_contents, new_contents, {result_type = "indices"})- for _, hunk in ipairs(hunks) do- apply_hunk(bufnr, new_lines, hunk)+ vim.cmd("silent! undojoin")+ --- Bottom up, so applying a hunk doesn't move the lines of the ones after it+ for i = #hunks, 1, -1 do