Skip to content
Snippets Groups Projects
Commit ca167af8 authored by Marijn Haverbeke's avatar Marijn Haverbeke
Browse files

[hardwrap addon] Add

parent 3e12cbda
No related branches found
No related tags found
No related merge requests found
(function() {
"use strict";
var Pos = CodeMirror.Pos;
function findParagraph(cm, pos, options) {
var startRE = options.paragraphStart || cm.getHelper(pos, "paragraphStart");
for (var start = pos.line, first = cm.firstLine(); start > first; --start) {
var line = cm.getLine(start);
if (startRE && startRE.test(line)) break;
if (!/\S/.test(line)) { ++start; break; }
}
var endRE = options.paragraphEnd || cm.getHelper(pos, "paragraphEnd");
for (var end = pos.line + 1, last = cm.lastLine(); end <= last; ++end) {
var line = cm.getLine(end);
if (endRE && endRE.test(line)) { ++end; break; }
if (!/\S/.test(line)) break;
}
return {from: start, to: end};
}
function findBreakPoint(text, column, wrapOn, killTrailingSpace) {
for (var at = column; at > 0; --at)
if (wrapOn.test(text.slice(at - 1, at + 1))) break;
if (at == 0) at = column;
var endOfText = at;
if (killTrailingSpace)
while (text.charAt(endOfText - 1) == " ") --endOfText;
return {from: endOfText, to: at};
}
function wrapRange(cm, from, to, options) {
from = cm.clipPos(from); to = cm.clipPos(to);
var column = options.column || 80;
var wrapOn = options.wrapOn || /\s\S|-[^\.\d]/;
var killTrailing = options.killTrailingSpace !== false;
var changes = [], curLine = "", curNo = from.line;
var lines = cm.getRange(from, to, false);
for (var i = 0; i < lines.length; ++i) {
var text = lines[i], oldLen = curLine.length, spaceInserted = 0;
if (curLine && text && !wrapOn.test(curLine.charAt(curLine.length - 1) + text.charAt(0))) {
curLine += " ";
spaceInserted = 1;
}
curLine += text;
if (i) {
var firstBreak = curLine.length > column && findBreakPoint(curLine, column, wrapOn, killTrailing);
// If this isn't broken, or is broken at a different point, remove old break
if (!firstBreak || firstBreak.from != oldLen || firstBreak.to != oldLen + spaceInserted) {
changes.push({text: spaceInserted ? " " : "",
from: Pos(curNo, oldLen),
to: Pos(curNo + 1, 0)});
} else {
curLine = text;
++curNo;
}
}
while (curLine.length > column) {
var bp = findBreakPoint(curLine, column, wrapOn, killTrailing);
changes.push({text: "\n",
from: Pos(curNo, bp.from),
to: Pos(curNo, bp.to)});
curLine = curLine.slice(bp.to);
++curNo;
}
}
if (changes.length) cm.operation(function() {
for (var i = 0; i < changes.length; ++i) {
var change = changes[i];
cm.replaceRange(change.text, change.from, change.to);
}
});
}
CodeMirror.defineExtension("wrapParagraph", function(pos, options) {
options = options || {};
if (!pos) pos = this.getCursor();
var para = findParagraph(this, pos, options);
wrapRange(this, Pos(para.from, 0), Pos(para.to - 1), options);
});
CodeMirror.defineExtension("wrapRange", function(from, to, options) {
wrapRange(this, from, to, options || {});
});
CodeMirror.defineExtension("wrapParagraphsInRange", function(from, to, options) {
options = options || {};
var cm = this;
cm.operation(function() {
for (var line = from.line; line <= to.line;) {
var para = findParagraph(cm, Pos(line, 0), options);
wrapRange(cm, Pos(para.from, 0), Pos(para.to - 1), options);
line = para.to;
}
});
});
})();
<!doctype html>
<title>CodeMirror: Hard-wrapping Demo</title>
<meta charset="utf-8"/>
<link rel=stylesheet href="../doc/docs.css">
<link rel="stylesheet" href="../lib/codemirror.css">
<script src="../lib/codemirror.js"></script>
<script src="../mode/markdown/markdown.js"></script>
<script src="../addon/wrap/hardwrap.js"></script>
<style type="text/css">
.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}
</style>
<div id=nav>
<a href="http://codemirror.net"><img id=logo src="../doc/logo.png"></a>
<ul>
<li><a href="../index.html">Home</a>
<li><a href="../doc/manual.html">Manual</a>
<li><a href="https://github.com/marijnh/codemirror">Code</a>
</ul>
<ul>
<li><a class=active href="#">Hard-wrapping</a>
</ul>
</div>
<article>
<h2>Hard-wrapping Demo</h2>
<form><textarea id="code" name="code">Lorem ipsum dolor sit amet, vim augue dictas constituto ex,
sit falli simul viderer te. Graeco scaevola maluisset sit
ut, in idque viris praesent sea. Ea sea eirmod indoctum
repudiare. Vel noluisse suscipit pericula ut. In ius nulla
alienum molestie. Mei essent discere democritum id.
Equidem ponderum expetendis ius in, mea an erroribus
constituto, congue timeam perfecto ad est. Ius ut primis
timeam, per in ullum mediocrem. An case vero labitur pri,
vel dicit laoreet et. An qui prompta conclusionemque, eam
timeam sapientem in, cum dictas epicurei eu.
Usu cu vide dictas deseruisse, eum choro graece adipiscing
ut. Cibo qualisque ius ad, et dicat scripta mea, eam nihil
mentitum aliquando cu. Debet aperiam splendide at quo, ad
paulo nostro commodo duo. Sea adhuc utinam conclusionemque
id, quas doming malorum nec ad. Tollit eruditi vivendum ad
ius, eos soleat ignota ad.
</textarea></form>
<p>Demonstration of
the <a href="../doc/manual.html#addon_hardwrap">hardwrap</a> addon.
The above editor has its change event hooked up to
the <code>wrapParagraphsInRange</code> method, so that the paragraphs
are reflown as you are typing.</p>
<script>
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
mode: "markdown",
lineNumbers: true
});
var wait, options = {column: 60};
editor.on("change", function(cm, change) {
clearTimeout(wait);
wait = setTimeout(function() {
cm.wrapParagraphsInRange(change.from, change.to, options);
}, 200);
});
</script>
</article>
......@@ -166,6 +166,7 @@
<option value="http://codemirror.net/addon/fold/foldcode.js">foldcode.js</option>
<option value="http://codemirror.net/addon/fold/foldgutter.js">foldgutter.js</option>
<option value="http://codemirror.net/addon/display/fullscreen.js">fullscreen.js</option>
<option value="http://codemirror.net/addon/wrap/hardwrap.js">hardwrap.js</option>
<option value="http://codemirror.net/addon/hint/html-hint.js">html-hint.js</option>
<option value="http://codemirror.net/addon/fold/indent-fold.js">indent-fold.js</option>
<option value="http://codemirror.net/addon/hint/javascript-hint.js">javascript-hint.js</option>
......
......@@ -14,9 +14,10 @@
<script src="../mode/css/css.js"></script>
<script src="../mode/htmlmixed/htmlmixed.js"></script>
<style>
dt { text-indent: -2em; padding-left: 2em; }
dd { margin-left: 1.5em; }
dl dl {margin: 0;}
dt { text-indent: -2em; padding-left: 2em; margin-top: 1em; }
dd { margin-left: 1.5em; margin-bottom: 1em; }
dt {margin-top: 1em;}
dd dl, dd dt, dd dd, dd ul { margin-top: 0; margin-bottom: 0; }
</style>
<div id=nav>
......@@ -2147,6 +2148,39 @@
on <a href="../addon/display/fullscreen.css"><code>fullscreen.css</code></a>. <a href="../demo/fullscreen.html">Demo
here</a>.</dd>
<dt id="addon_hardwrap"><a href="../addon/wrap/hardwrap.js"><code>wrap/hardwrap.js</code></a></dt>
<dd>Addon to perform hard line wrapping/breaking for paragraphs
of text. Adds these methods to editor instances:
<dl>
<dt><code><strong>wrapParagraph</strong>(?pos: {line, ch}, ?options: object)</code></dt>
<dd>Wraps the paragraph at the given position.
If <code>pos</code> is not given, it defaults to the cursor
position.</dd>
<dt><code><strong>wrapRange</strong>(from: {line, ch}, to: {line, ch}, ?options: object)</code></dt>
<dd>Wraps the given range as one big paragraph.</dd>
<dt><code><strong>wrapParagraphsInRange</strong>(from: {line, ch}, to: {line, ch}, ?options: object)</code></dt>
<dd>Wrapps the paragraphs in (and overlapping with) the
given range individually.</dd>
</dl>
The following options are recognized:
<dl>
<dt><code><strong>paragraphStart</strong>, <strong>paragraphEnd</strong>: RegExp</code></dt>
<dd>Blank lines are always considered paragraph boundaries.
These options can be used to specify a pattern that causes
lines to be considered the start or end of a paragraph.</dd>
<dt><code><strong>column</strong>: number</code></dt>
<dd>The column to wrap at. Defaults to 80.</dd>
<dt><code><strong>wrapOn</strong>: RegExp</code></dt>
<dd>A regular expression that matches only those
two-character strings that allow wrapping. By default, the
addon wraps on whitespace and after dash characters.</dd>
<dt><code><strong>killTrailingSpace</strong>: boolean</code></dt>
<dd>Whether trailing space caused by wrapping should be
preserved, or deleted. Defaults to true.</dd>
</dl>
A demo of the addon is available <a href="../demo/hardwrap.html">here</a>.
</dd>
<dt id="addon_merge"><a href="../addon/merge/merge.js"><code>merge/merge.js</code></a></dt>
<dd>Implements an interface for merging changes, using either a
2-way or a 3-way view. The <code>CodeMirror.MergeView</code>
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment