From 5da5546947f3125dfd6aa85ab21074dc83f776d5 Mon Sep 17 00:00:00 2001 From: Lukas Reineke Date: Wed, 27 Dec 2023 09:17:21 +0900 Subject: [PATCH] feat: handle `breakindentopt` for repeat indent --- doc/indent_blankline.txt | 11 +++++-- lua/ibl/autocmds.lua | 2 +- lua/ibl/init.lua | 5 +-- lua/ibl/utils.lua | 36 +++++++++++++++++++++ specs/features/utils_spec.lua | 60 +++++++++++++++++++++++++++++++++++ 5 files changed, 107 insertions(+), 7 deletions(-) diff --git a/doc/indent_blankline.txt b/doc/indent_blankline.txt index dda89aa3..71f98f01 100644 --- a/doc/indent_blankline.txt +++ b/doc/indent_blankline.txt @@ -328,12 +328,19 @@ config.indent *ibl.config.indent* Default: `1` ~ + *ibl.config.indent.repeat_linebreak* • {repeat_linebreak} (boolean) - Repeat indentation guide virtual text on wrapped lines - if |'breakindent'| is set + Repeat indentation guide virtual text on wrapped + lines if |'breakindent'| is set, and |'breakindentopt'| + does not contain any of the following: + • `column` + • `sbr` + • `shift` with a negative value Default: `true` ~ + Note: requires Neovim version 0.10 or higher ~ + Example: ~ >lua { diff --git a/lua/ibl/autocmds.lua b/lua/ibl/autocmds.lua index c4687518..65696efa 100644 --- a/lua/ibl/autocmds.lua +++ b/lua/ibl/autocmds.lua @@ -29,7 +29,7 @@ M.setup = function() }) vim.api.nvim_create_autocmd("OptionSet", { group = group, - pattern = "breakindent,list,listchars,shiftwidth,tabstop,vartabstop", + pattern = "list,listchars,shiftwidth,tabstop,vartabstop,breakindent,breakindentopt", callback = function(opts) ibl.debounced_refresh(opts.buf) end, diff --git a/lua/ibl/init.lua b/lua/ibl/init.lua index 7659f33e..d83d3125 100644 --- a/lua/ibl/init.lua +++ b/lua/ibl/init.lua @@ -9,7 +9,6 @@ local conf = require "ibl.config" local utils = require "ibl.utils" local namespace = vim.api.nvim_create_namespace "indent_blankline" -local has_repeat = vim.fn.has "nvim-0.10" == 1 local M = {} @@ -307,9 +306,7 @@ M.refresh = function(bufnr) end -- Repeat indent virtual text on wrapped lines when 'breakindent' is set. - local repeat_indent = has_repeat - and config.indent.repeat_linebreak - and vim.api.nvim_get_option_value("breakindent", { win = utils.get_win(bufnr) }) + local repeat_indent = utils.has_repeat_indent(bufnr, config) for i, line in ipairs(lines) do local row = i + offset diff --git a/lua/ibl/utils.lua b/lua/ibl/utils.lua index d29d3118..9c1c2a83 100644 --- a/lua/ibl/utils.lua +++ b/lua/ibl/utils.lua @@ -1,4 +1,5 @@ local M = {} +local has_repeat = vim.fn.has "nvim-0.10" == 1 ---@param line string? M.get_whitespace = function(line) @@ -360,4 +361,39 @@ M.fix_horizontal_scroll = function(whitespace_tbl, left_offset) return whitespace_tbl end +---@param bufnr number +---@param config ibl.config +---@return boolean +M.has_repeat_indent = function(bufnr, config) + if not config.indent.repeat_linebreak then + return false + end + if not has_repeat then + return false + end + + local win = M.get_win(bufnr) + if not vim.api.nvim_get_option_value("breakindent", { win = win }) then + return false + end + + local raw_value = vim.api.nvim_get_option_value("breakindentopt", { win = win }) + for _, key_value_str in ipairs(vim.split(raw_value, ",")) do + local key, value = unpack(vim.split(key_value_str, ":")) + key = vim.trim(key) + + if key == "column" then + return false + end + if key == "sbr" then + return false + end + if key == "shift" and (tonumber(value) or 0) < 0 then + return false + end + end + + return true +end + return M diff --git a/specs/features/utils_spec.lua b/specs/features/utils_spec.lua index 69d1ae5f..3cf1ca70 100644 --- a/specs/features/utils_spec.lua +++ b/specs/features/utils_spec.lua @@ -1,5 +1,6 @@ assert = require "luassert" local utils = require "ibl.utils" +local conf = require "ibl.config" describe("get_listchars", function() local listchars = vim.opt.listchars:get() @@ -62,3 +63,62 @@ describe("get_listchars", function() }) end) end) + +describe("has_repeat_indent", function() + local config = conf.get_config(0) + + after_each(function() + vim.opt.breakindent = false + vim.opt.breakindentopt = "" + config.indent.repeat_linebreak = true + end) + + -- test for old Neovim versions + if vim.fn.has "nvim-0.10" ~= 1 then + it("does not use repeat indent on old Neovim versions", function() + vim.opt.breakindent = true + assert.are.equal(utils.has_repeat_indent(0, config), false) + end) + + return + end + + it("does not use repeat indent with breakindent off", function() + assert.are.equal(utils.has_repeat_indent(0, config), false) + end) + + it("does not use repeat indent with breakindent on", function() + vim.opt.breakindent = true + assert.are.equal(utils.has_repeat_indent(0, config), true) + end) + + it("does not use repeat indent when disabled in the config", function() + config.indent.repeat_linebreak = false + vim.opt.breakindent = true + assert.are.equal(utils.has_repeat_indent(0, config), false) + end) + + it("does not use repeat indent when breakindentopt includes sbr", function() + vim.opt.breakindent = true + vim.opt.breakindentopt = "min:5,sbr" + assert.are.equal(utils.has_repeat_indent(0, config), false) + end) + + it("does not use repeat indent when breakindentopt includes column", function() + vim.opt.breakindent = true + vim.opt.breakindentopt = "min:5,column:9" + assert.are.equal(utils.has_repeat_indent(0, config), false) + end) + + it("does not use repeat indent when breakindentopt includes a negative value for shift", function() + vim.opt.breakindent = true + vim.opt.breakindentopt = "min:5,shift:-5" + assert.are.equal(utils.has_repeat_indent(0, config), false) + end) + + it("does use repeat indent when breakindentopt includes a positive value for shift", function() + vim.opt.breakindent = true + vim.opt.breakindentopt = "min:5,shift:5" + assert.are.equal(utils.has_repeat_indent(0, config), true) + end) +end)