|
9 | 9 | else // Plain browser env |
10 | 10 | mod(CodeMirror); |
11 | 11 | })(function(CodeMirror) { |
| 12 | + var nonspace = /\S/g; |
| 13 | + var repeat = String.prototype.repeat || function (n) { return Array(n + 1).join(this); }; |
12 | 14 | function continueComment(cm) { |
13 | 15 | if (cm.getOption("disableInput")) return CodeMirror.Pass; |
14 | 16 | var ranges = cm.listSelections(), mode, inserts = []; |
|
19 | 21 | if (!mode) mode = modeHere; |
20 | 22 | else if (mode != modeHere) return CodeMirror.Pass; |
21 | 23 |
|
22 | | - var insert = null; |
23 | | - if (mode.blockCommentStart && mode.blockCommentContinue) { |
24 | | - var line = cm.getLine(pos.line).slice(0, pos.ch) |
25 | | - var end = line.lastIndexOf(mode.blockCommentEnd), found |
26 | | - if (end != -1 && end == pos.ch - mode.blockCommentEnd.length) { |
27 | | - // Comment ended, don't continue it |
28 | | - } else if ((found = line.lastIndexOf(mode.blockCommentStart)) > -1 && found > end) { |
29 | | - insert = line.slice(0, found) |
30 | | - if (/\S/.test(insert)) { |
31 | | - insert = "" |
32 | | - for (var j = 0; j < found; ++j) insert += " " |
| 24 | + var insert = null, line, found; |
| 25 | + var blockStart = mode.blockCommentStart, lineCmt = mode.lineComment; |
| 26 | + if (blockStart && mode.blockCommentContinue) { |
| 27 | + line = cm.getLine(pos.line); |
| 28 | + var end = line.lastIndexOf(mode.blockCommentEnd, pos.ch - mode.blockCommentEnd.length); |
| 29 | + // 1. if this block comment ended |
| 30 | + // 2. if this is actually inside a line comment |
| 31 | + if (end != -1 && end == pos.ch - mode.blockCommentEnd.length || |
| 32 | + lineCmt && (found = line.lastIndexOf(lineCmt, pos.ch - 1)) > -1 && |
| 33 | + /\bcomment\b/.test(cm.getTokenTypeAt({line: pos.line, ch: found + 1}))) { |
| 34 | + // ...then don't continue it |
| 35 | + } else if ((found = line.lastIndexOf(blockStart, pos.ch - blockStart.length)) > -1 && |
| 36 | + found > end) { |
| 37 | + // reuse the existing leading spaces/tabs/mixed |
| 38 | + // or build the correct indent using CM's tab/indent options |
| 39 | + if (nonspaceAfter(0, line) >= found) { |
| 40 | + insert = line.slice(0, found); |
| 41 | + } else { |
| 42 | + var tabSize = cm.options.tabSize, numTabs; |
| 43 | + found = CodeMirror.countColumn(line, found, tabSize); |
| 44 | + insert = !cm.options.indentWithTabs ? repeat.call(" ", found) : |
| 45 | + repeat.call("\t", (numTabs = Math.floor(found / tabSize))) + |
| 46 | + repeat.call(" ", found - tabSize * numTabs); |
33 | 47 | } |
34 | | - } else if ((found = line.indexOf(mode.blockCommentContinue)) > -1 && !/\S/.test(line.slice(0, found))) { |
35 | | - insert = line.slice(0, found) |
| 48 | + } else if ((found = line.indexOf(mode.blockCommentContinue)) > -1 && |
| 49 | + found <= pos.ch && |
| 50 | + found <= nonspaceAfter(0, line)) { |
| 51 | + insert = line.slice(0, found); |
36 | 52 | } |
37 | 53 | if (insert != null) insert += mode.blockCommentContinue |
38 | 54 | } |
39 | | - if (insert == null && mode.lineComment && continueLineCommentEnabled(cm)) { |
40 | | - var line = cm.getLine(pos.line), found = line.indexOf(mode.lineComment); |
41 | | - if (found > -1) { |
42 | | - insert = line.slice(0, found); |
43 | | - if (/\S/.test(insert)) insert = null; |
44 | | - else insert += mode.lineComment + line.slice(found + mode.lineComment.length).match(/^\s*/)[0]; |
| 55 | + if (insert == null && lineCmt && continueLineCommentEnabled(cm)) { |
| 56 | + if (line == null) line = cm.getLine(pos.line); |
| 57 | + found = line.indexOf(lineCmt); |
| 58 | + // cursor at pos 0, line comment also at pos 0 => shift it down, don't continue |
| 59 | + if (!pos.ch && !found) insert = ""; |
| 60 | + // continue only if the line starts with an optional space + line comment |
| 61 | + else if (found > -1 && nonspaceAfter(0, line) >= found) { |
| 62 | + // don't continue if there's only space(s) after cursor or the end of the line |
| 63 | + insert = nonspaceAfter(pos.ch, line) > -1; |
| 64 | + // but always continue if the next line starts with a line comment too |
| 65 | + if (!insert) { |
| 66 | + var next = cm.getLine(pos.line + 1) || '', |
| 67 | + nextFound = next.indexOf(lineCmt); |
| 68 | + insert = nextFound > -1 && nonspaceAfter(0, next) >= nextFound || null; |
| 69 | + } |
| 70 | + if (insert) { |
| 71 | + insert = line.slice(0, found) + lineCmt + |
| 72 | + line.slice(found + lineCmt.length).match(/^\s*/)[0]; |
| 73 | + } |
45 | 74 | } |
46 | 75 | } |
47 | 76 | if (insert == null) return CodeMirror.Pass; |
|
54 | 83 | }); |
55 | 84 | } |
56 | 85 |
|
| 86 | + function nonspaceAfter(ch, str) { |
| 87 | + nonspace.lastIndex = ch; |
| 88 | + var m = nonspace.exec(str); |
| 89 | + return m ? m.index : -1; |
| 90 | + } |
| 91 | + |
57 | 92 | function continueLineCommentEnabled(cm) { |
58 | 93 | var opt = cm.getOption("continueComments"); |
59 | 94 | if (opt && typeof opt == "object") |
|
0 commit comments