@@ -61,13 +61,13 @@ define(function (require, exports, module) {
6161
6262 for ( i = lineSyntax . length ; i < blockSyntax . length ; i ++ ) {
6363 character = blockSyntax . charAt ( i ) ;
64- subExps . push ( prevChars + "[^" + character + "]" ) ;
64+ subExps . push ( prevChars + "[^" + StringUtils . regexEscape ( character ) + "]" ) ;
6565 if ( prevChars ) {
6666 subExps . push ( prevChars + "$" ) ;
6767 }
6868 prevChars += character ;
6969 }
70- return new RegExp ( "^\\s*" + lineSyntax + "($|" + subExps . join ( "|" ) + ")" ) ;
70+ return new RegExp ( "^\\s*" + StringUtils . regexEscape ( lineSyntax ) + "($|" + subExps . join ( "|" ) + ")" ) ;
7171 }
7272
7373 /**
@@ -79,27 +79,32 @@ define(function (require, exports, module) {
7979 * @return {Array.<RegExp> }
8080 */
8181 function _createLineExpressions ( prefixes , blockPrefix , blockSuffix ) {
82- var lineExp = [ ] , escapedPrefix , regExp ;
82+ var lineExp = [ ] , escapedPrefix , nothingPushed ;
8383
8484 prefixes . forEach ( function ( prefix ) {
8585 escapedPrefix = StringUtils . regexEscape ( prefix ) ;
86+ nothingPushed = true ;
87+
8688 if ( blockPrefix && blockPrefix . indexOf ( prefix ) === 0 ) {
87- regExp = _createSpecialLineExp ( prefix , blockPrefix ) ;
88- } else if ( blockSuffix && blockSuffix . indexOf ( prefix ) === 0 ) {
89- regExp = _createSpecialLineExp ( prefix , blockSuffix ) ;
90- } else {
91- regExp = new RegExp ( "^\\s*" + escapedPrefix ) ;
89+ lineExp . push ( _createSpecialLineExp ( prefix , blockPrefix ) ) ;
90+ nothingPushed = false ;
91+ }
92+ if ( blockSuffix && blockPrefix !== blockSuffix && blockSuffix . indexOf ( prefix ) === 0 ) {
93+ lineExp . push ( _createSpecialLineExp ( prefix , blockSuffix ) ) ;
94+ nothingPushed = false ;
95+ }
96+ if ( nothingPushed ) {
97+ lineExp . push ( new RegExp ( "^\\s*" + escapedPrefix ) ) ;
9298 }
93- lineExp . push ( regExp ) ;
9499 } ) ;
95100 return lineExp ;
96101 }
97102
98103 /**
99104 * @private
100105 * Returns true if any regular expression matches the given string
101- * @param {!string } string - where to look
102- * @param {!Array.<RegExp> } expressions - what to look
106+ * @param {!string } string where to look
107+ * @param {!Array.<RegExp> } expressions what to look
103108 * @return {boolean }
104109 */
105110 function _matchExpressions ( string , expressions ) {
@@ -130,7 +135,8 @@ define(function (require, exports, module) {
130135
131136 /**
132137 * @private
133- * Searchs for an uncommented line between startLine and endLine
138+ * Searches between startLine and endLine to check if there is at least one line commented with a line comment, and
139+ * skips all the block comments.
134140 * @param {!Editor } editor
135141 * @param {!number } startLine valid line inside the document
136142 * @param {!number } endLine valid line inside the document
@@ -144,7 +150,7 @@ define(function (require, exports, module) {
144150 for ( i = startLine ; i <= endLine ; i ++ ) {
145151 line = editor . document . getLine ( i ) ;
146152 // A line is commented out if it starts with 0-N whitespace chars, then a line comment prefix
147- if ( line . match ( / \S / ) && ! _matchExpressions ( line , lineExp ) ) {
153+ if ( ! line . length || ( line . match ( / \S / ) && ! _matchExpressions ( line , lineExp ) ) ) {
148154 containsNotLineComment = true ;
149155 break ;
150156 }
@@ -277,15 +283,15 @@ define(function (require, exports, module) {
277283 * Generates an edit that adds or removes block-comment tokens to the selection, preserving selection
278284 * and cursor position. Applies to the currently focused Editor.
279285 *
280- * If the selection is inside a block-comment or one block-comment is inside or partially
281- * inside the selection we uncomment; otherwise we comment out.
286+ * If the selection is inside a block-comment or one block-comment is inside or partially inside the selection
287+ * it will uncomment, otherwise it will comment out, unless if there are multiple block comments inside the selection,
288+ * where it does nothing.
282289 * Commenting out adds the prefix before the selection and the suffix after.
283290 * Uncommenting removes them.
284291 *
285- * As a special case, if slashComment is true and the start or end of the selection is inside a
286- * line-comment it needs to do a line uncomment if is not actually inside a bigger block comment and all
287- * the lines in the selection are line-commented. In this case, we return null to indicate to the caller
288- * that it needs to handle this selection as a line comment.
292+ * If all the lines inside the selection are line-comment and if the selection is not inside a block-comment, it will
293+ * line uncomment all the lines, otherwise it will block comment/uncomment. In the first case, we return null to
294+ * indicate to the caller that it needs to handle this selection as a line comment.
289295 *
290296 * @param {!Editor } editor
291297 * @param {!string } prefix, e.g. "<!--"
@@ -358,6 +364,7 @@ define(function (require, exports, module) {
358364
359365 // If we are in a line that only has a prefix or a suffix and the prefix and suffix are the same string,
360366 // lets find first if this is a prefix or suffix and move the token to the inside of the block comment.
367+ // This means that the token will be anywere inside the block comment, including the lines with the delimiters.
361368 // This is required so that later we can find the prefix by moving backwards and the suffix by moving forwards.
362369 if ( ctx . token . string === prefix && prefix === suffix ) {
363370 searchCtx = TokenUtils . getInitialContext ( editor . _codeMirror , { line : ctx . pos . line , ch : ctx . token . start } ) ;
@@ -372,7 +379,7 @@ define(function (require, exports, module) {
372379
373380 if ( isBlockComment ) {
374381 // Save the initial position to start searching for the suffix from here
375- initialPos = $ . extend ( { } , ctx . pos ) ;
382+ initialPos = _ . cloneDeep ( ctx . pos ) ;
376383
377384 // Find the position of the start of the prefix
378385 result = true ;
@@ -381,8 +388,11 @@ define(function (require, exports, module) {
381388 }
382389 prefixPos = result && { line : ctx . pos . line , ch : ctx . token . start } ;
383390
384- // Restore the context at the initial position and find the position of the start of the suffix
385- ctx = TokenUtils . getInitialContext ( editor . _codeMirror , { line : initialPos . line , ch : initialPos . ch } ) ;
391+ // Restore the context at the initial position to find the position of the start of the suffix,
392+ // but only when we found the prefix alone in one line
393+ if ( ctx . token . string === prefix && prefix === suffix ) {
394+ ctx = TokenUtils . getInitialContext ( editor . _codeMirror , _ . cloneDeep ( initialPos ) ) ;
395+ }
386396
387397 while ( result && ! ctx . token . string . match ( suffixExp ) ) {
388398 result = TokenUtils . moveSkippingWhitespace ( TokenUtils . moveNextToken , ctx ) ;
@@ -397,7 +407,7 @@ define(function (require, exports, module) {
397407 invalidComment = result && ! ! ctx . token . string . match ( prefixExp ) ;
398408
399409 // We moved the token at the start when it was in a whitespace, but maybe we shouldn't have done it
400- if ( prefixPos && editor . indexFromPos ( sel . end ) < editor . indexFromPos ( prefixPos ) ) {
410+ if ( ( suffixPos && CodeMirror . cmpPos ( sel . start , suffixPos ) > 0 ) || ( prefixPos && CodeMirror . cmpPos ( sel . end , prefixPos ) < 0 ) ) {
401411 canComment = true ;
402412 }
403413
0 commit comments