You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

114 lines
4.7 KiB

7 months ago
  1. // CodeMirror, copyright (c) by Marijn Haverbeke and others
  2. // Distributed under an MIT license: https://codemirror.net/5/LICENSE
  3. (function(mod) {
  4. if (typeof exports == "object" && typeof module == "object") // CommonJS
  5. mod(require("../../lib/codemirror"));
  6. else if (typeof define == "function" && define.amd) // AMD
  7. define(["../../lib/codemirror"], mod);
  8. else // Plain browser env
  9. mod(CodeMirror);
  10. })(function(CodeMirror) {
  11. var nonspace = /\S/g;
  12. var repeat = String.prototype.repeat || function (n) { return Array(n + 1).join(this); };
  13. function continueComment(cm) {
  14. if (cm.getOption("disableInput")) return CodeMirror.Pass;
  15. var ranges = cm.listSelections(), mode, inserts = [];
  16. for (var i = 0; i < ranges.length; i++) {
  17. var pos = ranges[i].head
  18. if (!/\bcomment\b/.test(cm.getTokenTypeAt(pos))) return CodeMirror.Pass;
  19. var modeHere = cm.getModeAt(pos)
  20. if (!mode) mode = modeHere;
  21. else if (mode != modeHere) return CodeMirror.Pass;
  22. var insert = null, line, found;
  23. var blockStart = mode.blockCommentStart, lineCmt = mode.lineComment;
  24. if (blockStart && mode.blockCommentContinue) {
  25. line = cm.getLine(pos.line);
  26. var end = line.lastIndexOf(mode.blockCommentEnd, pos.ch - mode.blockCommentEnd.length);
  27. // 1. if this block comment ended
  28. // 2. if this is actually inside a line comment
  29. if (end != -1 && end == pos.ch - mode.blockCommentEnd.length ||
  30. lineCmt && (found = line.lastIndexOf(lineCmt, pos.ch - 1)) > -1 &&
  31. /\bcomment\b/.test(cm.getTokenTypeAt({line: pos.line, ch: found + 1}))) {
  32. // ...then don't continue it
  33. } else if (pos.ch >= blockStart.length &&
  34. (found = line.lastIndexOf(blockStart, pos.ch - blockStart.length)) > -1 &&
  35. found > end) {
  36. // reuse the existing leading spaces/tabs/mixed
  37. // or build the correct indent using CM's tab/indent options
  38. if (nonspaceAfter(0, line) >= found) {
  39. insert = line.slice(0, found);
  40. } else {
  41. var tabSize = cm.options.tabSize, numTabs;
  42. found = CodeMirror.countColumn(line, found, tabSize);
  43. insert = !cm.options.indentWithTabs ? repeat.call(" ", found) :
  44. repeat.call("\t", (numTabs = Math.floor(found / tabSize))) +
  45. repeat.call(" ", found - tabSize * numTabs);
  46. }
  47. } else if ((found = line.indexOf(mode.blockCommentContinue)) > -1 &&
  48. found <= pos.ch &&
  49. found <= nonspaceAfter(0, line)) {
  50. insert = line.slice(0, found);
  51. }
  52. if (insert != null) insert += mode.blockCommentContinue
  53. }
  54. if (insert == null && lineCmt && continueLineCommentEnabled(cm)) {
  55. if (line == null) line = cm.getLine(pos.line);
  56. found = line.indexOf(lineCmt);
  57. // cursor at pos 0, line comment also at pos 0 => shift it down, don't continue
  58. if (!pos.ch && !found) insert = "";
  59. // continue only if the line starts with an optional space + line comment
  60. else if (found > -1 && nonspaceAfter(0, line) >= found) {
  61. // don't continue if there's only space(s) after cursor or the end of the line
  62. insert = nonspaceAfter(pos.ch, line) > -1;
  63. // but always continue if the next line starts with a line comment too
  64. if (!insert) {
  65. var next = cm.getLine(pos.line + 1) || '',
  66. nextFound = next.indexOf(lineCmt);
  67. insert = nextFound > -1 && nonspaceAfter(0, next) >= nextFound || null;
  68. }
  69. if (insert) {
  70. insert = line.slice(0, found) + lineCmt +
  71. line.slice(found + lineCmt.length).match(/^\s*/)[0];
  72. }
  73. }
  74. }
  75. if (insert == null) return CodeMirror.Pass;
  76. inserts[i] = "\n" + insert;
  77. }
  78. cm.operation(function() {
  79. for (var i = ranges.length - 1; i >= 0; i--)
  80. cm.replaceRange(inserts[i], ranges[i].from(), ranges[i].to(), "+insert");
  81. });
  82. }
  83. function nonspaceAfter(ch, str) {
  84. nonspace.lastIndex = ch;
  85. var m = nonspace.exec(str);
  86. return m ? m.index : -1;
  87. }
  88. function continueLineCommentEnabled(cm) {
  89. var opt = cm.getOption("continueComments");
  90. if (opt && typeof opt == "object")
  91. return opt.continueLineComment !== false;
  92. return true;
  93. }
  94. CodeMirror.defineOption("continueComments", null, function(cm, val, prev) {
  95. if (prev && prev != CodeMirror.Init)
  96. cm.removeKeyMap("continueComment");
  97. if (val) {
  98. var key = "Enter";
  99. if (typeof val == "string")
  100. key = val;
  101. else if (typeof val == "object" && val.key)
  102. key = val.key;
  103. var map = {name: "continueComment"};
  104. map[key] = continueComment;
  105. cm.addKeyMap(map);
  106. }
  107. });
  108. });