1 | // CodeMirror, copyright (c) by Marijn Haverbeke and others |
---|
2 | // Distributed under an MIT license: http://codemirror.net/LICENSE |
---|
3 | |
---|
4 | (function(mod) { |
---|
5 | if (typeof exports == "object" && typeof module == "object") // CommonJS |
---|
6 | mod(require("../../lib/codemirror")); |
---|
7 | else if (typeof define == "function" && define.amd) // AMD |
---|
8 | define(["../../lib/codemirror"], mod); |
---|
9 | else // Plain browser env |
---|
10 | mod(CodeMirror); |
---|
11 | })(function(CodeMirror) { |
---|
12 | "use strict"; |
---|
13 | |
---|
14 | var noOptions = {}; |
---|
15 | var nonWS = /[^\s\u00a0]/; |
---|
16 | var Pos = CodeMirror.Pos; |
---|
17 | |
---|
18 | function firstNonWS(str) { |
---|
19 | var found = str.search(nonWS); |
---|
20 | return found == -1 ? 0 : found; |
---|
21 | } |
---|
22 | |
---|
23 | CodeMirror.commands.toggleComment = function(cm) { |
---|
24 | var minLine = Infinity, ranges = cm.listSelections(), mode = null; |
---|
25 | for (var i = ranges.length - 1; i >= 0; i--) { |
---|
26 | var from = ranges[i].from(), to = ranges[i].to(); |
---|
27 | if (from.line >= minLine) continue; |
---|
28 | if (to.line >= minLine) to = Pos(minLine, 0); |
---|
29 | minLine = from.line; |
---|
30 | if (mode == null) { |
---|
31 | if (cm.uncomment(from, to)) mode = "un"; |
---|
32 | else { cm.lineComment(from, to); mode = "line"; } |
---|
33 | } else if (mode == "un") { |
---|
34 | cm.uncomment(from, to); |
---|
35 | } else { |
---|
36 | cm.lineComment(from, to); |
---|
37 | } |
---|
38 | } |
---|
39 | }; |
---|
40 | |
---|
41 | CodeMirror.defineExtension("lineComment", function(from, to, options) { |
---|
42 | if (!options) options = noOptions; |
---|
43 | var self = this, mode = self.getModeAt(from); |
---|
44 | var commentString = options.lineComment || mode.lineComment; |
---|
45 | if (!commentString) { |
---|
46 | if (options.blockCommentStart || mode.blockCommentStart) { |
---|
47 | options.fullLines = true; |
---|
48 | self.blockComment(from, to, options); |
---|
49 | } |
---|
50 | return; |
---|
51 | } |
---|
52 | var firstLine = self.getLine(from.line); |
---|
53 | if (firstLine == null) return; |
---|
54 | var end = Math.min(to.ch != 0 || to.line == from.line ? to.line + 1 : to.line, self.lastLine() + 1); |
---|
55 | var pad = options.padding == null ? " " : options.padding; |
---|
56 | var blankLines = options.commentBlankLines || from.line == to.line; |
---|
57 | |
---|
58 | self.operation(function() { |
---|
59 | if (options.indent) { |
---|
60 | var baseString = firstLine.slice(0, firstNonWS(firstLine)); |
---|
61 | for (var i = from.line; i < end; ++i) { |
---|
62 | var line = self.getLine(i), cut = baseString.length; |
---|
63 | if (!blankLines && !nonWS.test(line)) continue; |
---|
64 | if (line.slice(0, cut) != baseString) cut = firstNonWS(line); |
---|
65 | self.replaceRange(baseString + commentString + pad, Pos(i, 0), Pos(i, cut)); |
---|
66 | } |
---|
67 | } else { |
---|
68 | for (var i = from.line; i < end; ++i) { |
---|
69 | if (blankLines || nonWS.test(self.getLine(i))) |
---|
70 | self.replaceRange(commentString + pad, Pos(i, 0)); |
---|
71 | } |
---|
72 | } |
---|
73 | }); |
---|
74 | }); |
---|
75 | |
---|
76 | CodeMirror.defineExtension("blockComment", function(from, to, options) { |
---|
77 | if (!options) options = noOptions; |
---|
78 | var self = this, mode = self.getModeAt(from); |
---|
79 | var startString = options.blockCommentStart || mode.blockCommentStart; |
---|
80 | var endString = options.blockCommentEnd || mode.blockCommentEnd; |
---|
81 | if (!startString || !endString) { |
---|
82 | if ((options.lineComment || mode.lineComment) && options.fullLines != false) |
---|
83 | self.lineComment(from, to, options); |
---|
84 | return; |
---|
85 | } |
---|
86 | |
---|
87 | var end = Math.min(to.line, self.lastLine()); |
---|
88 | if (end != from.line && to.ch == 0 && nonWS.test(self.getLine(end))) --end; |
---|
89 | |
---|
90 | var pad = options.padding == null ? " " : options.padding; |
---|
91 | if (from.line > end) return; |
---|
92 | |
---|
93 | self.operation(function() { |
---|
94 | if (options.fullLines != false) { |
---|
95 | var lastLineHasText = nonWS.test(self.getLine(end)); |
---|
96 | self.replaceRange(pad + endString, Pos(end)); |
---|
97 | self.replaceRange(startString + pad, Pos(from.line, 0)); |
---|
98 | var lead = options.blockCommentLead || mode.blockCommentLead; |
---|
99 | if (lead != null) for (var i = from.line + 1; i <= end; ++i) |
---|
100 | if (i != end || lastLineHasText) |
---|
101 | self.replaceRange(lead + pad, Pos(i, 0)); |
---|
102 | } else { |
---|
103 | self.replaceRange(endString, to); |
---|
104 | self.replaceRange(startString, from); |
---|
105 | } |
---|
106 | }); |
---|
107 | }); |
---|
108 | |
---|
109 | CodeMirror.defineExtension("uncomment", function(from, to, options) { |
---|
110 | if (!options) options = noOptions; |
---|
111 | var self = this, mode = self.getModeAt(from); |
---|
112 | var end = Math.min(to.ch != 0 || to.line == from.line ? to.line : to.line - 1, self.lastLine()), start = Math.min(from.line, end); |
---|
113 | |
---|
114 | // Try finding line comments |
---|
115 | var lineString = options.lineComment || mode.lineComment, lines = []; |
---|
116 | var pad = options.padding == null ? " " : options.padding, didSomething; |
---|
117 | lineComment: { |
---|
118 | if (!lineString) break lineComment; |
---|
119 | for (var i = start; i <= end; ++i) { |
---|
120 | var line = self.getLine(i); |
---|
121 | var found = line.indexOf(lineString); |
---|
122 | if (found > -1 && !/comment/.test(self.getTokenTypeAt(Pos(i, found + 1)))) found = -1; |
---|
123 | if (found == -1 && (i != end || i == start) && nonWS.test(line)) break lineComment; |
---|
124 | if (found > -1 && nonWS.test(line.slice(0, found))) break lineComment; |
---|
125 | lines.push(line); |
---|
126 | } |
---|
127 | self.operation(function() { |
---|
128 | for (var i = start; i <= end; ++i) { |
---|
129 | var line = lines[i - start]; |
---|
130 | var pos = line.indexOf(lineString), endPos = pos + lineString.length; |
---|
131 | if (pos < 0) continue; |
---|
132 | if (line.slice(endPos, endPos + pad.length) == pad) endPos += pad.length; |
---|
133 | didSomething = true; |
---|
134 | self.replaceRange("", Pos(i, pos), Pos(i, endPos)); |
---|
135 | } |
---|
136 | }); |
---|
137 | if (didSomething) return true; |
---|
138 | } |
---|
139 | |
---|
140 | // Try block comments |
---|
141 | var startString = options.blockCommentStart || mode.blockCommentStart; |
---|
142 | var endString = options.blockCommentEnd || mode.blockCommentEnd; |
---|
143 | if (!startString || !endString) return false; |
---|
144 | var lead = options.blockCommentLead || mode.blockCommentLead; |
---|
145 | var startLine = self.getLine(start), endLine = end == start ? startLine : self.getLine(end); |
---|
146 | var open = startLine.indexOf(startString), close = endLine.lastIndexOf(endString); |
---|
147 | if (close == -1 && start != end) { |
---|
148 | endLine = self.getLine(--end); |
---|
149 | close = endLine.lastIndexOf(endString); |
---|
150 | } |
---|
151 | if (open == -1 || close == -1 || |
---|
152 | !/comment/.test(self.getTokenTypeAt(Pos(start, open + 1))) || |
---|
153 | !/comment/.test(self.getTokenTypeAt(Pos(end, close + 1)))) |
---|
154 | return false; |
---|
155 | |
---|
156 | // Avoid killing block comments completely outside the selection. |
---|
157 | // Positions of the last startString before the start of the selection, and the first endString after it. |
---|
158 | var lastStart = startLine.lastIndexOf(startString, from.ch); |
---|
159 | var firstEnd = lastStart == -1 ? -1 : startLine.slice(0, from.ch).indexOf(endString, lastStart + startString.length); |
---|
160 | if (lastStart != -1 && firstEnd != -1 && firstEnd + endString.length != from.ch) return false; |
---|
161 | // Positions of the first endString after the end of the selection, and the last startString before it. |
---|
162 | firstEnd = endLine.indexOf(endString, to.ch); |
---|
163 | var almostLastStart = endLine.slice(to.ch).lastIndexOf(startString, firstEnd - to.ch); |
---|
164 | lastStart = (firstEnd == -1 || almostLastStart == -1) ? -1 : to.ch + almostLastStart; |
---|
165 | if (firstEnd != -1 && lastStart != -1 && lastStart != to.ch) return false; |
---|
166 | |
---|
167 | self.operation(function() { |
---|
168 | self.replaceRange("", Pos(end, close - (pad && endLine.slice(close - pad.length, close) == pad ? pad.length : 0)), |
---|
169 | Pos(end, close + endString.length)); |
---|
170 | var openEnd = open + startString.length; |
---|
171 | if (pad && startLine.slice(openEnd, openEnd + pad.length) == pad) openEnd += pad.length; |
---|
172 | self.replaceRange("", Pos(start, open), Pos(start, openEnd)); |
---|
173 | if (lead) for (var i = start + 1; i <= end; ++i) { |
---|
174 | var line = self.getLine(i), found = line.indexOf(lead); |
---|
175 | if (found == -1 || nonWS.test(line.slice(0, found))) continue; |
---|
176 | var foundEnd = found + lead.length; |
---|
177 | if (pad && line.slice(foundEnd, foundEnd + pad.length) == pad) foundEnd += pad.length; |
---|
178 | self.replaceRange("", Pos(i, found), Pos(i, foundEnd)); |
---|
179 | } |
---|
180 | }); |
---|
181 | return true; |
---|
182 | }); |
---|
183 | }); |
---|