···11local M = {}
2233local markers = require "vcmarkers.markers"
44+local marker_format = require "vcmarkers.marker_format"
45local highlight = require "vcmarkers.highlight"
5667---@param bufnr number Buffer number.
···109110 end
110111end
111112113113+---@class MarkerContext
114114+---@field marker? Marker The marker under the cursor, if any.
115115+---@field section? Section The section under the cursor, if any.
116116+---@field section_index? integer The index of the section under the cursor, if any.
117117+112118---@param bufnr integer The buffer number.
113113-function M.select_section(bufnr)
114114- local lnum = vim.fn.line "."
119119+---@param lnum integer The line number.
120120+---@return MarkerContext
121121+local function _get_marker_context(bufnr, lnum)
115122 local diff_markers = vim.b[bufnr].vcmarkers_markers
116123 local marker = markers.cur_marker(lnum, diff_markers)
117124 if not marker then
···120127 vim.log.levels.WARN,
121128 { title = "VCMarkers" }
122129 )
123123- return
130130+ return {}
124131 end
125132126126- local section = markers.current_section(marker, lnum)
133133+ local index, section = markers.current_section(marker, lnum)
127134 if not section then
128135 vim.notify(
129136 "No section under cursor",
130137 vim.log.levels.WARN,
131138 { title = "VCMarkers" }
132139 )
133133- return
140140+ return { marker = marker }
134141 end
142142+ return {
143143+ marker = marker,
144144+ section = section,
145145+ section_index = index,
146146+ }
147147+end
135148136136- -- Could check that the section is actually a "plus" section,
137137- -- but let's trust the user for now.
149149+--- Replace the lines of a marker with the given lines.
150150+--- @param bufnr integer The buffer number.
151151+--- @param marker Marker The marker to replace.
152152+--- @param lines string[] The lines to replace with.
153153+--- @param move_cursor boolean Whether to move the cursor to the start of the marker after replacing.
154154+local function _replace_marker(bufnr, marker, lines, move_cursor)
138155 vim.api.nvim_buf_set_lines(
139156 bufnr,
140157 marker.start_line,
141158 marker.end_line,
142159 true,
143143- section.lines
160160+ lines
144161 )
145145- vim.api.nvim_win_set_cursor(0, { marker.start_line + 1, 0 })
162162+ if move_cursor then
163163+ -- Put cursor at a predictable place, at the start line of marker.
164164+ vim.api.nvim_win_set_cursor(0, { marker.start_line + 1, 0 })
165165+ end
166166+end
167167+168168+---@param bufnr integer The buffer number.
169169+function M.select_section_verbatim(bufnr)
170170+ local lnum = vim.fn.line "."
171171+ local ctx = _get_marker_context(bufnr, lnum)
172172+ if not ctx.marker or not ctx.section then
173173+ return
174174+ end
175175+ _replace_marker(bufnr, ctx.marker, ctx.section.lines, true)
176176+end
177177+178178+---@param bufnr integer The buffer number.
179179+function M.select_section_plus(bufnr)
180180+ local lnum = vim.fn.line "."
181181+ local ctx = _get_marker_context(bufnr, lnum)
182182+ if not ctx.marker or not ctx.section_index then
183183+ return
184184+ end
185185+186186+ local plus_sections = marker_format.plus_sections(ctx.marker)
187187+ local section = plus_sections[ctx.section_index]
188188+ _replace_marker(bufnr, ctx.marker, section.lines, true)
189189+end
190190+191191+-- For backward compatibility.
192192+M.select_section = M.select_section_verbatim
193193+194194+---@param bufnr integer The buffer number.
195195+function M.select_all(bufnr)
196196+ local lnum = vim.fn.line "."
197197+ local ctx = _get_marker_context(bufnr, lnum)
198198+ if not ctx.marker then
199199+ return
200200+ end
201201+ local plus_sections = marker_format.plus_sections(ctx.marker)
202202+ local all_lines = {}
203203+ for _, section in ipairs(plus_sections) do
204204+ vim.list_extend(all_lines, section.lines)
205205+ end
206206+ _replace_marker(bufnr, ctx.marker, all_lines, true)
146207end
147208148209--- Convert markers to a different format.
···323323 end
324324end
325325326326+---Return only the plus sections of a marker.
327327+---@param marker Marker
328328+---@return Side[]
329329+function M.plus_sections(marker)
330330+ local sides, _ = _deconstruct_marker(marker)
331331+ local plus_sides = {}
332332+ for i = 1, #sides, 2 do
333333+ plus_sides[#plus_sides + 1] = sides[i]
334334+ end
335335+ return plus_sides
336336+end
337337+326338--- Cycle the marker format.
327339---@param jj_marker Marker
328340---@return Marker
+4-4
lua/vcmarkers/markers.lua
···23232424---@param marker Marker
2525---@param lnum integer
2626----@return Section|nil
2626+---@return integer?, Section?
2727function M.current_section(marker, lnum)
2828 lnum = lnum - 1 -- Convert to zero-based line number.
2929- for _, section in ipairs(marker.sections) do
2929+ for i, section in ipairs(marker.sections) do
3030 local start = section.header_line or section.content_line
3131 if start <= lnum and lnum < section.content_line + #section.lines then
3232- return section
3232+ return i, section
3333 end
3434 end
3535- return nil
3535+ return nil, nil
3636end
37373838---@param section Section