hardwrap.js 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. (function(mod) {
  2. if (typeof exports == "object" && typeof module == "object") // CommonJS
  3. mod(require("../../lib/codemirror"));
  4. else if (typeof define == "function" && define.amd) // AMD
  5. define(["../../lib/codemirror"], mod);
  6. else // Plain browser env
  7. mod(CodeMirror);
  8. })(function(CodeMirror) {
  9. "use strict";
  10. var Pos = CodeMirror.Pos;
  11. function findParagraph(cm, pos, options) {
  12. var startRE = options.paragraphStart || cm.getHelper(pos, "paragraphStart");
  13. for (var start = pos.line, first = cm.firstLine(); start > first; --start) {
  14. var line = cm.getLine(start);
  15. if (startRE && startRE.test(line)) break;
  16. if (!/\S/.test(line)) { ++start; break; }
  17. }
  18. var endRE = options.paragraphEnd || cm.getHelper(pos, "paragraphEnd");
  19. for (var end = pos.line + 1, last = cm.lastLine(); end <= last; ++end) {
  20. var line = cm.getLine(end);
  21. if (endRE && endRE.test(line)) { ++end; break; }
  22. if (!/\S/.test(line)) break;
  23. }
  24. return {from: start, to: end};
  25. }
  26. function findBreakPoint(text, column, wrapOn, killTrailingSpace) {
  27. for (var at = column; at > 0; --at)
  28. if (wrapOn.test(text.slice(at - 1, at + 1))) break;
  29. if (at == 0) at = column;
  30. var endOfText = at;
  31. if (killTrailingSpace)
  32. while (text.charAt(endOfText - 1) == " ") --endOfText;
  33. return {from: endOfText, to: at};
  34. }
  35. function wrapRange(cm, from, to, options) {
  36. from = cm.clipPos(from); to = cm.clipPos(to);
  37. var column = options.column || 80;
  38. var wrapOn = options.wrapOn || /\s\S|-[^\.\d]/;
  39. var killTrailing = options.killTrailingSpace !== false;
  40. var changes = [], curLine = "", curNo = from.line;
  41. var lines = cm.getRange(from, to, false);
  42. if (!lines.length) return null;
  43. var leadingSpace = lines[0].match(/^[ \t]*/)[0];
  44. for (var i = 0; i < lines.length; ++i) {
  45. var text = lines[i], oldLen = curLine.length, spaceInserted = 0;
  46. if (curLine && text && !wrapOn.test(curLine.charAt(curLine.length - 1) + text.charAt(0))) {
  47. curLine += " ";
  48. spaceInserted = 1;
  49. }
  50. var spaceTrimmed = "";
  51. if (i) {
  52. spaceTrimmed = text.match(/^\s*/)[0];
  53. text = text.slice(spaceTrimmed.length);
  54. }
  55. curLine += text;
  56. if (i) {
  57. var firstBreak = curLine.length > column && leadingSpace == spaceTrimmed &&
  58. findBreakPoint(curLine, column, wrapOn, killTrailing);
  59. // If this isn't broken, or is broken at a different point, remove old break
  60. if (!firstBreak || firstBreak.from != oldLen || firstBreak.to != oldLen + spaceInserted) {
  61. changes.push({text: [spaceInserted ? " " : ""],
  62. from: Pos(curNo, oldLen),
  63. to: Pos(curNo + 1, spaceTrimmed.length)});
  64. } else {
  65. curLine = leadingSpace + text;
  66. ++curNo;
  67. }
  68. }
  69. while (curLine.length > column) {
  70. var bp = findBreakPoint(curLine, column, wrapOn, killTrailing);
  71. changes.push({text: ["", leadingSpace],
  72. from: Pos(curNo, bp.from),
  73. to: Pos(curNo, bp.to)});
  74. curLine = leadingSpace + curLine.slice(bp.to);
  75. ++curNo;
  76. }
  77. }
  78. if (changes.length) cm.operation(function() {
  79. for (var i = 0; i < changes.length; ++i) {
  80. var change = changes[i];
  81. cm.replaceRange(change.text, change.from, change.to);
  82. }
  83. });
  84. return changes.length ? {from: changes[0].from, to: CodeMirror.changeEnd(changes[changes.length - 1])} : null;
  85. }
  86. CodeMirror.defineExtension("wrapParagraph", function(pos, options) {
  87. options = options || {};
  88. if (!pos) pos = this.getCursor();
  89. var para = findParagraph(this, pos, options);
  90. return wrapRange(this, Pos(para.from, 0), Pos(para.to - 1), options);
  91. });
  92. CodeMirror.commands.wrapLines = function(cm) {
  93. cm.operation(function() {
  94. var ranges = cm.listSelections(), at = cm.lastLine() + 1;
  95. for (var i = ranges.length - 1; i >= 0; i--) {
  96. var range = ranges[i], span;
  97. if (range.empty()) {
  98. var para = findParagraph(cm, range.head, {});
  99. span = {from: Pos(para.from, 0), to: Pos(para.to - 1)};
  100. } else {
  101. span = {from: range.from(), to: range.to()};
  102. }
  103. if (span.to.line >= at) continue;
  104. at = span.from.line;
  105. wrapRange(cm, span.from, span.to, {});
  106. }
  107. });
  108. };
  109. CodeMirror.defineExtension("wrapRange", function(from, to, options) {
  110. return wrapRange(this, from, to, options || {});
  111. });
  112. CodeMirror.defineExtension("wrapParagraphsInRange", function(from, to, options) {
  113. options = options || {};
  114. var cm = this, paras = [];
  115. for (var line = from.line; line <= to.line;) {
  116. var para = findParagraph(cm, Pos(line, 0), options);
  117. paras.push(para);
  118. line = para.to;
  119. }
  120. var madeChange = false;
  121. if (paras.length) cm.operation(function() {
  122. for (var i = paras.length - 1; i >= 0; --i)
  123. madeChange = madeChange || wrapRange(cm, Pos(paras[i].from, 0), Pos(paras[i].to - 1), options);
  124. });
  125. return madeChange;
  126. });
  127. });