local vim_repeat = require 'u.repeat' local CodeWriter = require 'u.codewriter' local Range = require 'u.range' local M = {} ---@param bracket_range Range ---@param left string ---@param right string local function split(bracket_range, left, right) local code = CodeWriter.from_pos(bracket_range.start) code:write_raw(left) local curr = bracket_range.start:next() if curr == nil then return end local last_start = curr -- Sanity check: if we "skipped" past the start/stop of the overall range, then something is wrong: -- This can happen with greater-/less- than signs that are mathematical, and not brackets: while curr > bracket_range.start and curr < bracket_range.stop do if vim.tbl_contains({ '{', '[', '(', '<' }, curr:char()) then -- skip over bracketed groups: local next = curr:find_match() if next == nil then break end curr = next else if vim.tbl_contains({ ',', ';' }, curr:char()) then -- accumulate item: local item = vim.trim(Range.new(last_start, curr):text()) if item ~= '' then code:indent():write(item) end local next_last_start = curr:next() if next_last_start == nil then break end last_start = next_last_start end -- Prepare for next iteration: local next = curr:next() if next == nil then break end curr = next end end -- accumulate last, unfinished item: local pos_before_right = bracket_range.stop:must_next(-1) if last_start < pos_before_right then local item = vim.trim(Range.new(last_start, pos_before_right):text()) if item ~= '' then code:indent():write(item) end end code:write(right) bracket_range:replace(code.lines) end ---@param bracket_range Range ---@param left string ---@param right string local function join(bracket_range, left, right) local inner_range = Range.new(bracket_range.start:must_next(), bracket_range.stop:must_next(-1), bracket_range.mode) local newline = vim .iter(inner_range:lines()) :map(function(l) return vim.trim(l) end) :filter(function(l) return l ~= '' end) :join ' ' bracket_range:replace { left .. newline .. right } end local function splitjoin() local bracket_range = Range.find_nearest_brackets() if bracket_range == nil then return end local lines = bracket_range:lines() local left = lines[1]:sub(1, 1) -- left bracket local right = lines[#lines]:sub(-1, -1) -- right bracket if #lines == 1 then split(bracket_range, left, right) else join(bracket_range, left, right) end end function M.setup() vim.keymap.set('n', 'gS', function() vim_repeat.run(splitjoin) end) end return M