@@ -85,21 +85,40 @@ async function applyStructuralCommentsToSingleSelectionLines(
8585 affectedLineNumbers : number [ ]
8686) {
8787 const originalSelections = [ ...editor . selections ] ;
88+ const singleSelection = editor . selections [ 0 ] ;
8889 const descendingLineNumbers = [ ...new Set ( affectedLineNumbers ) ] . sort ( ( a , b ) => b - a ) ;
8990 const affectedLineSet = new Set ( affectedLineNumbers ) ;
9091 const originalFirstNonWSMap = new Map < number , number > ( ) ;
92+ const originalInsertionColumnMap = new Map < number , number > ( ) ;
93+ let partialSelectionStartOffset : number | undefined ;
9194 let alignedCommentColumn : number | undefined ;
9295
9396 // Calculate aligned comment column and store original indentation.
9497 for ( const lineNum of affectedLineNumbers ) {
9598 const line = editor . document . lineAt ( lineNum ) ;
9699 const firstNonWhitespace = line . firstNonWhitespaceCharacterIndex ;
97100 originalFirstNonWSMap . set ( lineNum , firstNonWhitespace ) ;
101+
102+ let insertionColumnCandidate = firstNonWhitespace ;
103+ if (
104+ lineNum === singleSelection . start . line &&
105+ ! singleSelection . isEmpty &&
106+ singleSelection . start . character > firstNonWhitespace
107+ ) {
108+ insertionColumnCandidate = singleSelection . start . character ;
109+ if ( affectedLineNumbers . length > 1 ) {
110+ partialSelectionStartOffset = editor . document . offsetAt (
111+ new vscode . Position ( lineNum , singleSelection . start . character )
112+ ) ;
113+ }
114+ }
115+ originalInsertionColumnMap . set ( lineNum , insertionColumnCandidate ) ;
116+
98117 if ( ! line . isEmptyOrWhitespace ) {
99118 alignedCommentColumn =
100119 alignedCommentColumn === undefined
101- ? firstNonWhitespace
102- : Math . min ( alignedCommentColumn , firstNonWhitespace ) ;
120+ ? insertionColumnCandidate
121+ : Math . min ( alignedCommentColumn , insertionColumnCandidate ) ;
103122 }
104123 }
105124
@@ -114,10 +133,14 @@ async function applyStructuralCommentsToSingleSelectionLines(
114133 for ( const lineNum of descendingLineNumbers ) {
115134 const currentLine = editor . document . lineAt ( lineNum ) ;
116135 const firstNonWhitespace = originalFirstNonWSMap . get ( lineNum ) ?? 0 ;
117- const insertionColumn =
118- affectedLineNumbers . length > 1 ? resolvedAlignedCommentColumn : firstNonWhitespace ;
136+ const rawInsertionColumn =
137+ affectedLineNumbers . length > 1
138+ ? resolvedAlignedCommentColumn
139+ : originalInsertionColumnMap . get ( lineNum ) ?? firstNonWhitespace ;
140+ const insertionColumn = Math . min ( rawInsertionColumn , currentLine . text . length ) ;
141+ originalInsertionColumnMap . set ( lineNum , insertionColumn ) ;
119142 const insertionOffset = editor . document . offsetAt (
120- new vscode . Position ( lineNum , firstNonWhitespace )
143+ new vscode . Position ( lineNum , insertionColumn )
121144 ) ;
122145
123146 const wouldBreakWhere = _semiColonWouldBreakStructureWhere ( mirrorDoc , insertionOffset ) ;
@@ -132,7 +155,8 @@ async function applyStructuralCommentsToSingleSelectionLines(
132155 const resolvedBreakOffset = resolveStructuralBreakOffset (
133156 mirrorDoc ,
134157 wouldBreakWhere ,
135- affectedLineSet
158+ affectedLineSet ,
159+ partialSelectionStartOffset
136160 ) ;
137161 if ( resolvedBreakOffset === false ) {
138162 skipBreak = true ;
@@ -182,7 +206,23 @@ async function applyStructuralCommentsToSingleSelectionLines(
182206 return inserted ;
183207 }
184208
185- function adjustPosition ( pos : vscode . Position ) : vscode . Position {
209+ function adjustPosition (
210+ pos : vscode . Position ,
211+ boundary : 'start' | 'end' ,
212+ selectionIsEmpty : boolean
213+ ) : vscode . Position {
214+ const isSelectionStartAtInsertionColumn = (
215+ insertionColumn : number | undefined ,
216+ position : vscode . Position
217+ ) => {
218+ return (
219+ ! selectionIsEmpty &&
220+ boundary === 'start' &&
221+ insertionColumn !== undefined &&
222+ position . character === insertionColumn
223+ ) ;
224+ } ;
225+
186226 const shiftedLine = pos . line + countInsertedLinesBefore ( pos . line ) ;
187227
188228 if ( shiftedLine >= editor . document . lineCount ) {
@@ -192,21 +232,34 @@ async function applyStructuralCommentsToSingleSelectionLines(
192232 const line = editor . document . lineAt ( shiftedLine ) ;
193233 const newFirstNonWS = line . firstNonWhitespaceCharacterIndex ;
194234 const lineContent = line . text . slice ( newFirstNonWS ) ;
235+ const insertionColumn = originalInsertionColumnMap . get ( pos . line ) ;
195236
196- if ( ! lineContent . startsWith ( ';; ' ) ) {
197- return new vscode . Position ( shiftedLine , Math . min ( pos . character , line . text . length ) ) ;
237+ if ( isSelectionStartAtInsertionColumn ( insertionColumn , pos ) ) {
238+ return new vscode . Position ( shiftedLine , insertionColumn ) ;
198239 }
199240
200- const origFirstNonWS = originalFirstNonWSMap . get ( pos . line ) ?? pos . character ;
201- const contentOffset = Math . max ( 0 , pos . character - origFirstNonWS ) ;
202- const newCol = Math . min ( newFirstNonWS + 3 + contentOffset , line . text . length ) ;
203- return new vscode . Position ( shiftedLine , newCol ) ;
241+ if ( lineContent . startsWith ( ';; ' ) ) {
242+ const origFirstNonWS = originalFirstNonWSMap . get ( pos . line ) ?? pos . character ;
243+ const baseColumnForOffset = insertionColumn ?? origFirstNonWS ;
244+ const contentOffset = Math . max ( 0 , pos . character - baseColumnForOffset ) ;
245+ const newCol = Math . min ( newFirstNonWS + 3 + contentOffset , line . text . length ) ;
246+ return new vscode . Position ( shiftedLine , newCol ) ;
247+ }
248+
249+ if ( insertionColumn !== undefined && pos . character >= insertionColumn ) {
250+ return new vscode . Position ( shiftedLine , Math . min ( pos . character + 3 , line . text . length ) ) ;
251+ }
252+
253+ return new vscode . Position ( shiftedLine , Math . min ( pos . character , line . text . length ) ) ;
204254 }
205255
206256 editor . selections = originalSelections . map ( ( selection ) => {
207- const newAnchor = adjustPosition ( selection . anchor ) ;
208- const newActive = adjustPosition ( selection . active ) ;
209- return new vscode . Selection ( newAnchor , newActive ) ;
257+ const newStart = adjustPosition ( selection . start , 'start' , selection . isEmpty ) ;
258+ const newEnd = adjustPosition ( selection . end , 'end' , selection . isEmpty ) ;
259+ const isReversed = selection . anchor . isAfter ( selection . active ) ;
260+ return isReversed
261+ ? new vscode . Selection ( newEnd , newStart )
262+ : new vscode . Selection ( newStart , newEnd ) ;
210263 } ) ;
211264}
212265
@@ -221,7 +274,8 @@ async function applyStructuralCommentsToSingleSelectionLines(
221274function resolveStructuralBreakOffset (
222275 mirrorDoc : EditableDocument ,
223276 wouldBreakWhere : number ,
224- affectedLineSet : Set < number >
277+ affectedLineSet : Set < number > ,
278+ partialSelectionStartOffset ?: number
225279) : number | false {
226280 const cursor = mirrorDoc . getTokenCursor ( wouldBreakWhere ) ;
227281 const token = cursor . getToken ( ) ;
@@ -233,10 +287,12 @@ function resolveStructuralBreakOffset(
233287 const tok = probe . getToken ( ) ;
234288 if ( tok . type === 'close' ) {
235289 const finder = probe . clone ( ) ;
236- if ( ! finder . backwardList ( ) ) {
237- return probe . offsetStart ;
238- }
239- if ( ! affectedLineSet . has ( finder . line ) ) {
290+ if (
291+ ! finder . backwardList ( ) ||
292+ ( partialSelectionStartOffset !== undefined &&
293+ finder . offsetStart < partialSelectionStartOffset ) ||
294+ ! affectedLineSet . has ( finder . line )
295+ ) {
240296 return probe . offsetStart ;
241297 }
242298 }
0 commit comments