@@ -70,6 +70,14 @@ func (ce *codeEditor) handleTab(shift, ctrl bool) bool {
7070 return true
7171 }
7272
73+ startLine , endLine := ce .getSelectedLines ()
74+ containsOnlyBlankLines := ce .foreachLine (startLine , endLine ,
75+ func (line string , start , end int ) bool { return trimLeftSpace (line ) == `` })
76+ if containsOnlyBlankLines {
77+ // Nothing to indent or un-indent.
78+ return true
79+ }
80+
7381 if shift {
7482 // Handle Shift+Tab for un-indenting the current line.
7583 // TODO(grantnelson-wf): Implement
@@ -149,72 +157,95 @@ func (ce *codeEditor) handleSave(shift, ctrl bool) bool {
149157 return true
150158}
151159
160+ const commentPrefix = `// `
161+
152162// handleCommentToggle handles toggling comments on the current line or selection.
153163func (ce * codeEditor ) handleCommentToggle (shift , ctrl bool ) bool {
154164 if ! ctrl || shift {
155165 // Allow default behavior for '/' without a Ctrl or Shift+/.
156166 return false
157167 }
158168
159- const commentPrefix = `// `
160-
161169 startLine , endLine := ce .getSelectedLines ()
162- leastIndent := - 1
163- nonBlankLineCount := 0
170+ containsOnlyBlankLines := true
171+ containsUncommentedLine := false
164172 ce .foreachLine (startLine , endLine , func (line string , start , end int ) bool {
165173 if trimmed := trimLeftSpace (line ); trimmed != `` {
166- indent := len (line ) - len (trimmed )
167- if leastIndent < 0 || indent < leastIndent {
168- leastIndent = indent
174+ containsOnlyBlankLines = false
175+ if ! strings .HasPrefix (trimmed , commentPrefix ) {
176+ containsUncommentedLine = true
177+ return false
169178 }
170- nonBlankLineCount ++
171179 }
172180 return true
173181 })
174182
175- if nonBlankLineCount <= 0 {
176- // No non-blank lines, nothing to comment/ uncomment.
183+ if containsOnlyBlankLines {
184+ // Nothing to comment or uncomment.
177185 return true
178186 }
179187
180- containsUncommentedLine := false
188+ if containsUncommentedLine {
189+ ce .addCommenting (startLine , endLine )
190+ return true
191+ }
192+
193+ ce .removeCommenting (startLine , endLine )
194+ return true
195+ }
196+
197+ // addCommenting will add the comment prefix to each non-blank line in
198+ // the given range including any lines that already are commented.
199+ func (ce * codeEditor ) addCommenting (startLine , endLine int ) {
200+ leastIndent := - 1
181201 ce .foreachLine (startLine , endLine , func (line string , start , end int ) bool {
182- trimmed := strings .TrimSpace (line )
183- if trimmed != `` && ! strings .HasPrefix (trimmed , commentPrefix ) {
184- containsUncommentedLine = true
202+ if trimmed := trimLeftSpace (line ); trimmed != `` {
203+ if indent := len (line ) - len (trimmed ); leastIndent < 0 || indent < leastIndent {
204+ leastIndent = indent
205+ }
185206 }
186207 return true
187208 })
188209
189- if containsUncommentedLine {
190- // Comment the selected lines including any commented lines.
191- code := ce .Code ()[:startLine ]
192- ce .foreachLine (startLine , endLine , func (line string , start , end int ) bool {
193- if line == "\n " || strings .TrimSpace (line ) == `` {
194- code += line // Empty line, just add as-is.
195- return true
196- }
197- code += line [:leastIndent ] + commentPrefix + line [leastIndent :]
210+ selStart , selEnd := ce .GetSelection ()
211+ newStart , newEnd := selStart , selEnd
212+ code := ce .Code ()[:startLine ]
213+ ce .foreachLine (startLine , endLine , func (line string , start , end int ) bool {
214+ if strings .TrimSpace (line ) == `` {
215+ code += line // Empty line, just add as-is.
198216 return true
199- })
200- code += ce .Code ()[endLine :]
201-
202- start , end := ce .GetSelection ()
203- // TODO(grantnelson-wf): Handle when the end or start ends up before the comment prefix.
204- newStart := start + len (commentPrefix )
205- newEnd := end + len (commentPrefix )* nonBlankLineCount
206-
207- ce .SetCode (code )
208- ce .SetSelection (newStart , newEnd , code )
217+ }
218+ if selStart > start + leastIndent {
219+ newStart += len (commentPrefix )
220+ }
221+ if selEnd > start + leastIndent {
222+ newEnd += len (commentPrefix )
223+ }
224+ code += line [:leastIndent ] + commentPrefix + line [leastIndent :]
209225 return true
210- }
226+ })
227+ code += ce .Code ()[endLine :]
228+
229+ ce .SetCode (code )
230+ ce .SetSelection (newStart , newEnd , code )
231+ }
211232
212- // Uncomment any line that starts with the comment prefix (and preceding whitespace).
233+ // removeCommenting will uncomment any line that starts with the comment prefix
234+ // (and preceding whitespace).
235+ func (ce * codeEditor ) removeCommenting (startLine , endLine int ) {
236+ selStart , selEnd := ce .GetSelection ()
237+ newStart , newEnd := selStart , selEnd
213238 code := ce .Code ()[:startLine ]
214239 ce .foreachLine (startLine , endLine , func (line string , start , end int ) bool {
215240 if trimmed := trimLeftSpace (line ); trimmed != `` {
216241 if index := strings .Index (line , commentPrefix ); index >= 0 {
217242 code += line [:index ] + line [index + len (commentPrefix ):]
243+ if selStart > start + index {
244+ newStart -= len (commentPrefix )
245+ }
246+ if selEnd > start + index {
247+ newEnd -= len (commentPrefix )
248+ }
218249 return true
219250 }
220251 }
@@ -223,14 +254,8 @@ func (ce *codeEditor) handleCommentToggle(shift, ctrl bool) bool {
223254 })
224255 code += ce .Code ()[endLine :]
225256
226- start , end := ce .GetSelection ()
227- // TODO(grantnelson-wf): Handle when the end or start ends up before the comment prefix.
228- newStart := start - len (commentPrefix )
229- newEnd := end - len (commentPrefix )* nonBlankLineCount
230-
231257 ce .SetCode (code )
232258 ce .SetSelection (newStart , newEnd , code )
233- return true
234259}
235260
236261// getSelectedLines returns the start and end character indices of that
@@ -246,7 +271,7 @@ func (ce *codeEditor) getSelectedLines() (int, int) {
246271 startLine := 0
247272 if start >= 0 && start <= codeLen {
248273 startLine = strings .LastIndex (code [:start ], "\n " ) + 1
249- if startLine < 0 {
274+ if startLine <= 0 {
250275 startLine = 0
251276 }
252277 }
0 commit comments