1(function() { 2 "use strict"; 3 4 var noOptions = {}; 5 var nonWS = /[^\s\u00a0]/; 6 var Pos = CodeMirror.Pos; 7 8 function firstNonWS(str) { 9 var found = str.search(nonWS); 10 return found == -1 ? 0 : found; 11 } 12 13 CodeMirror.commands.toggleComment = function(cm) { 14 var from = cm.getCursor("start"), to = cm.getCursor("end"); 15 cm.uncomment(from, to) || cm.lineComment(from, to); 16 }; 17 18 CodeMirror.defineExtension("lineComment", function(from, to, options) { 19 if (!options) options = noOptions; 20 var self = this, mode = CodeMirror.innerMode(self.getMode(), self.getTokenAt(from).state).mode; 21 var commentString = options.lineComment || mode.lineComment; 22 if (!commentString) { 23 if (options.blockCommentStart || mode.blockCommentStart) { 24 options.fullLines = true; 25 self.blockComment(from, to, options); 26 } 27 return; 28 } 29 var firstLine = self.getLine(from.line); 30 if (firstLine == null) return; 31 var end = Math.min(to.ch != 0 || to.line == from.line ? to.line + 1 : to.line, self.lastLine() + 1); 32 var pad = options.padding == null ? " " : options.padding; 33 var blankLines = options.commentBlankLines; 34 35 self.operation(function() { 36 if (options.indent) { 37 var baseString = firstLine.slice(0, firstNonWS(firstLine)); 38 for (var i = from.line; i < end; ++i) { 39 var line = self.getLine(i), cut = baseString.length; 40 if (!blankLines && !nonWS.test(line)) continue; 41 if (line.slice(0, cut) != baseString) cut = firstNonWS(line); 42 self.replaceRange(baseString + commentString + pad, Pos(i, 0), Pos(i, cut)); 43 } 44 } else { 45 for (var i = from.line; i < end; ++i) { 46 if (blankLines || nonWS.test(self.getLine(i))) 47 self.replaceRange(commentString + pad, Pos(i, 0)); 48 } 49 } 50 }); 51 }); 52 53 CodeMirror.defineExtension("blockComment", function(from, to, options) { 54 if (!options) options = noOptions; 55 var self = this, mode = CodeMirror.innerMode(self.getMode(), self.getTokenAt(from).state).mode; 56 var startString = options.blockCommentStart || mode.blockCommentStart; 57 var endString = options.blockCommentEnd || mode.blockCommentEnd; 58 if (!startString || !endString) { 59 if ((options.lineComment || mode.lineComment) && options.fullLines != false) 60 self.lineComment(from, to, options); 61 return; 62 } 63 64 var end = Math.min(to.line, self.lastLine()); 65 if (end != from.line && to.ch == 0 && nonWS.test(self.getLine(end))) --end; 66 67 var pad = options.padding == null ? " " : options.padding; 68 if (from.line > end) return; 69 70 self.operation(function() { 71 if (options.fullLines != false) { 72 var lastLineHasText = nonWS.test(self.getLine(end)); 73 self.replaceRange(pad + endString, Pos(end)); 74 self.replaceRange(startString + pad, Pos(from.line, 0)); 75 var lead = options.blockCommentLead || mode.blockCommentLead; 76 if (lead != null) for (var i = from.line + 1; i <= end; ++i) 77 if (i != end || lastLineHasText) 78 self.replaceRange(lead + pad, Pos(i, 0)); 79 } else { 80 self.replaceRange(endString, to); 81 self.replaceRange(startString, from); 82 } 83 }); 84 }); 85 86 CodeMirror.defineExtension("uncomment", function(from, to, options) { 87 if (!options) options = noOptions; 88 var self = this, mode = CodeMirror.innerMode(self.getMode(), self.getTokenAt(from).state).mode; 89 var end = Math.min(to.line, self.lastLine()), start = Math.min(from.line, end); 90 91 // Try finding line comments 92 var lineString = options.lineComment || mode.lineComment, lines = []; 93 var pad = options.padding == null ? " " : options.padding; 94 lineComment: for(;;) { 95 if (!lineString) break; 96 for (var i = start; i <= end; ++i) { 97 var line = self.getLine(i); 98 var found = line.indexOf(lineString); 99 if (found == -1 && (i != end || i == start) && nonWS.test(line)) break lineComment; 100 if (i != start && found > -1 && nonWS.test(line.slice(0, found))) break lineComment; 101 lines.push(line); 102 } 103 self.operation(function() { 104 for (var i = start; i <= end; ++i) { 105 var line = lines[i - start]; 106 var pos = line.indexOf(lineString), endPos = pos + lineString.length; 107 if (pos < 0) continue; 108 if (line.slice(endPos, endPos + pad.length) == pad) endPos += pad.length; 109 self.replaceRange("", Pos(i, pos), Pos(i, endPos)); 110 } 111 }); 112 return true; 113 } 114 115 // Try block comments 116 var startString = options.blockCommentStart || mode.blockCommentStart; 117 var endString = options.blockCommentEnd || mode.blockCommentEnd; 118 if (!startString || !endString) return false; 119 var lead = options.blockCommentLead || mode.blockCommentLead; 120 var startLine = self.getLine(start), endLine = end == start ? startLine : self.getLine(end); 121 var open = startLine.indexOf(startString), close = endLine.lastIndexOf(endString); 122 if (close == -1 && start != end) { 123 endLine = self.getLine(--end); 124 close = endLine.lastIndexOf(endString); 125 } 126 if (open == -1 || close == -1) return false; 127 128 self.operation(function() { 129 self.replaceRange("", Pos(end, close - (pad && endLine.slice(close - pad.length, close) == pad ? pad.length : 0)), 130 Pos(end, close + endString.length)); 131 var openEnd = open + startString.length; 132 if (pad && startLine.slice(openEnd, openEnd + pad.length) == pad) openEnd += pad.length; 133 self.replaceRange("", Pos(start, open), Pos(start, openEnd)); 134 if (lead) for (var i = start + 1; i <= end; ++i) { 135 var line = self.getLine(i), found = line.indexOf(lead); 136 if (found == -1 || nonWS.test(line.slice(0, found))) continue; 137 var foundEnd = found + lead.length; 138 if (pad && line.slice(foundEnd, foundEnd + pad.length) == pad) foundEnd += pad.length; 139 self.replaceRange("", Pos(i, found), Pos(i, foundEnd)); 140 } 141 }); 142 return true; 143 }); 144})(); 145