this repo has no description

Revamp selection, split into `select`, `select_verbatim`, `select_all`.

The first and last one takes plus sections, rather than the legacy
behavior of taking the section as is, even if it is a diff section.

+150 -15
+70 -9
lua/vcmarkers/actions.lua
··· 1 1 local M = {} 2 2 3 3 local markers = require "vcmarkers.markers" 4 + local marker_format = require "vcmarkers.marker_format" 4 5 local highlight = require "vcmarkers.highlight" 5 6 6 7 ---@param bufnr number Buffer number. ··· 109 110 end 110 111 end 111 112 113 + ---@class MarkerContext 114 + ---@field marker? Marker The marker under the cursor, if any. 115 + ---@field section? Section The section under the cursor, if any. 116 + ---@field section_index? integer The index of the section under the cursor, if any. 117 + 112 118 ---@param bufnr integer The buffer number. 113 - function M.select_section(bufnr) 114 - local lnum = vim.fn.line "." 119 + ---@param lnum integer The line number. 120 + ---@return MarkerContext 121 + local function _get_marker_context(bufnr, lnum) 115 122 local diff_markers = vim.b[bufnr].vcmarkers_markers 116 123 local marker = markers.cur_marker(lnum, diff_markers) 117 124 if not marker then ··· 120 127 vim.log.levels.WARN, 121 128 { title = "VCMarkers" } 122 129 ) 123 - return 130 + return {} 124 131 end 125 132 126 - local section = markers.current_section(marker, lnum) 133 + local index, section = markers.current_section(marker, lnum) 127 134 if not section then 128 135 vim.notify( 129 136 "No section under cursor", 130 137 vim.log.levels.WARN, 131 138 { title = "VCMarkers" } 132 139 ) 133 - return 140 + return { marker = marker } 134 141 end 142 + return { 143 + marker = marker, 144 + section = section, 145 + section_index = index, 146 + } 147 + end 135 148 136 - -- Could check that the section is actually a "plus" section, 137 - -- but let's trust the user for now. 149 + --- Replace the lines of a marker with the given lines. 150 + --- @param bufnr integer The buffer number. 151 + --- @param marker Marker The marker to replace. 152 + --- @param lines string[] The lines to replace with. 153 + --- @param move_cursor boolean Whether to move the cursor to the start of the marker after replacing. 154 + local function _replace_marker(bufnr, marker, lines, move_cursor) 138 155 vim.api.nvim_buf_set_lines( 139 156 bufnr, 140 157 marker.start_line, 141 158 marker.end_line, 142 159 true, 143 - section.lines 160 + lines 144 161 ) 145 - vim.api.nvim_win_set_cursor(0, { marker.start_line + 1, 0 }) 162 + if move_cursor then 163 + -- Put cursor at a predictable place, at the start line of marker. 164 + vim.api.nvim_win_set_cursor(0, { marker.start_line + 1, 0 }) 165 + end 166 + end 167 + 168 + ---@param bufnr integer The buffer number. 169 + function M.select_section_verbatim(bufnr) 170 + local lnum = vim.fn.line "." 171 + local ctx = _get_marker_context(bufnr, lnum) 172 + if not ctx.marker or not ctx.section then 173 + return 174 + end 175 + _replace_marker(bufnr, ctx.marker, ctx.section.lines, true) 176 + end 177 + 178 + ---@param bufnr integer The buffer number. 179 + function M.select_section_plus(bufnr) 180 + local lnum = vim.fn.line "." 181 + local ctx = _get_marker_context(bufnr, lnum) 182 + if not ctx.marker or not ctx.section_index then 183 + return 184 + end 185 + 186 + local plus_sections = marker_format.plus_sections(ctx.marker) 187 + local section = plus_sections[ctx.section_index] 188 + _replace_marker(bufnr, ctx.marker, section.lines, true) 189 + end 190 + 191 + -- For backward compatibility. 192 + M.select_section = M.select_section_verbatim 193 + 194 + ---@param bufnr integer The buffer number. 195 + function M.select_all(bufnr) 196 + local lnum = vim.fn.line "." 197 + local ctx = _get_marker_context(bufnr, lnum) 198 + if not ctx.marker then 199 + return 200 + end 201 + local plus_sections = marker_format.plus_sections(ctx.marker) 202 + local all_lines = {} 203 + for _, section in ipairs(plus_sections) do 204 + vim.list_extend(all_lines, section.lines) 205 + end 206 + _replace_marker(bufnr, ctx.marker, all_lines, true) 146 207 end 147 208 148 209 --- Convert markers to a different format.
+3 -1
lua/vcmarkers/init.lua
··· 30 30 stop = _no_args(M.actions.stop), 31 31 prev_marker = _with_count(M.actions.prev_marker), 32 32 next_marker = _with_count(M.actions.next_marker), 33 - select = _no_args(M.actions.select_section), 33 + select = _no_args(M.actions.select_section_plus), 34 + select_all = _no_args(M.actions.select_all), 35 + select_verbatim = _no_args(M.actions.select_section_verbatim), 34 36 fold = _no_args(M.fold.toggle), 35 37 cycle = _no_args(M.actions.cycle_marker), 36 38 }
+12
lua/vcmarkers/marker_format.lua
··· 323 323 end 324 324 end 325 325 326 + ---Return only the plus sections of a marker. 327 + ---@param marker Marker 328 + ---@return Side[] 329 + function M.plus_sections(marker) 330 + local sides, _ = _deconstruct_marker(marker) 331 + local plus_sides = {} 332 + for i = 1, #sides, 2 do 333 + plus_sides[#plus_sides + 1] = sides[i] 334 + end 335 + return plus_sides 336 + end 337 + 326 338 --- Cycle the marker format. 327 339 ---@param jj_marker Marker 328 340 ---@return Marker
+4 -4
lua/vcmarkers/markers.lua
··· 23 23 24 24 ---@param marker Marker 25 25 ---@param lnum integer 26 - ---@return Section|nil 26 + ---@return integer?, Section? 27 27 function M.current_section(marker, lnum) 28 28 lnum = lnum - 1 -- Convert to zero-based line number. 29 - for _, section in ipairs(marker.sections) do 29 + for i, section in ipairs(marker.sections) do 30 30 local start = section.header_line or section.content_line 31 31 if start <= lnum and lnum < section.content_line + #section.lines then 32 - return section 32 + return i, section 33 33 end 34 34 end 35 - return nil 35 + return nil, nil 36 36 end 37 37 38 38 ---@param section Section
+61 -1
lua/vcmarkers_tests/functional/test_selection_actions.lua
··· 27 27 +first conflict new 1 28 28 after 29 29 ]], 30 + action = actions.select_section, 30 31 }, 31 32 select_second_section = { 32 33 line = 6, ··· 35 36 first conflict new 2 36 37 after 37 38 ]], 39 + action = actions.select_section, 40 + }, 41 + -- select_section_verbatim is an alias for select_section 42 + select_verbatim_first_section = { 43 + line = 5, 44 + expected = [[ 45 + before 46 + -first conflict old 47 + +first conflict new 1 48 + after 49 + ]], 50 + action = actions.select_section_verbatim, 51 + }, 52 + select_verbatim_second_section = { 53 + line = 6, 54 + expected = [[ 55 + before 56 + first conflict new 2 57 + after 58 + ]], 59 + action = actions.select_section_verbatim, 60 + }, 61 + select_plus_first_section = { 62 + line = 5, 63 + expected = [[ 64 + before 65 + first conflict new 1 66 + after 67 + ]], 68 + action = actions.select_section_plus, 69 + }, 70 + select_plus_second_section = { 71 + line = 6, 72 + expected = [[ 73 + before 74 + first conflict new 2 75 + after 76 + ]], 77 + action = actions.select_section_verbatim, 78 + }, 79 + select_all_first_section = { 80 + line = 5, 81 + expected = [[ 82 + before 83 + first conflict new 1 84 + first conflict new 2 85 + after 86 + ]], 87 + action = actions.select_all, 88 + }, 89 + select_all_second_section = { 90 + line = 6, 91 + expected = [[ 92 + before 93 + first conflict new 1 94 + first conflict new 2 95 + after 96 + ]], 97 + action = actions.select_all, 38 98 }, 39 99 }, 40 100 test = function(case) ··· 45 105 helpers.wait_update() 46 106 47 107 helpers.set_cursor(case.line, 0) 48 - actions.select_section(bufnr) 108 + case.action(bufnr) 49 109 50 110 testing.assert_list_eq( 51 111 helpers.get_lines(bufnr),