continuecomment.js 5.3 KB

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