Skip to content
This repository was archived by the owner on Apr 16, 2026. It is now read-only.

Commit 5a1976b

Browse files
committed
Add insertLeft option to setBookmark
1 parent 8f63800 commit 5a1976b

3 files changed

Lines changed: 43 additions & 17 deletions

File tree

doc/manual.html

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -411,8 +411,9 @@ <h2 id="events">Events</h2>
411411
</dl>
412412

413413
<p>Marked range handles, as returned
414-
by <a href="#markText"><code>markText</code></a>, emit the
415-
following event:</p>
414+
by <a href="#markText"><code>markText</code></a>
415+
and <a href="#setBookmark"><code>setBookmark</code></a>, emit the
416+
following events:</p>
416417

417418
<dl>
418419
<dt id="event_clear"><code>"clear" ()</code></dt>
@@ -929,16 +930,24 @@ <h3 id="api_marker">Text-marking methods</h3>
929930
the <a href="#mark_replacedWith"><code>replacedWith</code></a>
930931
option, if any.</dd>
931932

932-
<dt id="setBookmark"><code>doc.setBookmark(pos, widget) → object</code></dt>
933+
<dt id="setBookmark"><code>doc.setBookmark(pos, options) → object</code></dt>
933934
<dd>Inserts a bookmark, a handle that follows the text around it
934935
as it is being edited, at the given position. A bookmark has two
935936
methods <code>find()</code> and <code>clear()</code>. The first
936937
returns the current position of the bookmark, if it is still in
937938
the document, and the second explicitly removes the bookmark.
938-
The widget argument is optional, and can be used to display a
939-
DOM node at the current location of the bookmark (analogous to
940-
the <a href="#mark_replacedWith"><code>replacedWith</code></a>
941-
option to <code>markText</code>).</dd>
939+
The options argument is optional. If given, the following
940+
properties are recognized:
941+
<dl>
942+
<dt><code>widget</code></dt><dd>Can be used to display a DOM
943+
node at the current location of the bookmark (analogous to
944+
the <a href="#mark_replacedWith"><code>replacedWith</code></a>
945+
option to <code>markText</code>).</dd>
946+
<dt><code>insertLeft</code></dt><dd>By default, text typed
947+
when the cursor is on top of the bookmark will end up to the
948+
right of the bookmark. Set this option to true to make it go
949+
to the left instead.</dd>
950+
</dl></dd>
942951

943952
<dt id="findMarksAt"><code>doc.findMarksAt(pos) → array</code></dt>
944953
<dd>Returns an array of all the bookmarks and marked ranges

lib/codemirror.js

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3431,11 +3431,11 @@ window.CodeMirror = (function() {
34313431
span.marker.attachLine(line);
34323432
}
34333433

3434-
function markedSpansBefore(old, startCh) {
3434+
function markedSpansBefore(old, startCh, isInsert) {
34353435
if (old) for (var i = 0, nw; i < old.length; ++i) {
34363436
var span = old[i], marker = span.marker;
34373437
var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from <= startCh : span.from < startCh);
3438-
if (startsBefore || marker.type == "bookmark" && span.from == startCh) {
3438+
if (startsBefore || marker.type == "bookmark" && span.from == startCh && (!isInsert || !span.marker.insertLeft)) {
34393439
var endsAfter = span.to == null || (marker.inclusiveRight ? span.to >= startCh : span.to > startCh);
34403440
(nw || (nw = [])).push({from: span.from,
34413441
to: endsAfter ? null : span.to,
@@ -3445,11 +3445,11 @@ window.CodeMirror = (function() {
34453445
return nw;
34463446
}
34473447

3448-
function markedSpansAfter(old, startCh, endCh) {
3448+
function markedSpansAfter(old, endCh, isInsert) {
34493449
if (old) for (var i = 0, nw; i < old.length; ++i) {
34503450
var span = old[i], marker = span.marker;
34513451
var endsAfter = span.to == null || (marker.inclusiveRight ? span.to >= endCh : span.to > endCh);
3452-
if (endsAfter || marker.type == "bookmark" && span.from == endCh && span.from != startCh) {
3452+
if (endsAfter || marker.type == "bookmark" && span.from == endCh && (!isInsert || span.marker.insertLeft)) {
34533453
var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from <= endCh : span.from < endCh);
34543454
(nw || (nw = [])).push({from: startsBefore ? null : span.from - endCh,
34553455
to: span.to == null ? null : span.to - endCh,
@@ -3464,10 +3464,10 @@ window.CodeMirror = (function() {
34643464
var oldLast = isLine(doc, change.to.line) && getLine(doc, change.to.line).markedSpans;
34653465
if (!oldFirst && !oldLast) return null;
34663466

3467-
var startCh = change.from.ch, endCh = change.to.ch;
3467+
var startCh = change.from.ch, endCh = change.to.ch, isInsert = posEq(change.from, change.to);
34683468
// Get the spans that 'stick out' on both sides
3469-
var first = markedSpansBefore(oldFirst, startCh);
3470-
var last = markedSpansAfter(oldLast, change.from.line == change.to.line ? startCh : NaN, endCh);
3469+
var first = markedSpansBefore(oldFirst, startCh, isInsert);
3470+
var last = markedSpansAfter(oldLast, endCh, isInsert);
34713471

34723472
// Next, merge those two ends
34733473
var sameLine = change.text.length == 1, offset = lst(change.text).length + (sameLine ? startCh : 0);
@@ -4267,9 +4267,11 @@ window.CodeMirror = (function() {
42674267
markText: function(from, to, options) {
42684268
return markText(this, clipPos(this, from), clipPos(this, to), options, "range");
42694269
},
4270-
setBookmark: function(pos, widget) {
4270+
setBookmark: function(pos, options) {
4271+
var realOpts = {replacedWith: options && (options.nodeType == null ? options.widget : options),
4272+
insertLeft: options && options.insertLeft};
42714273
pos = clipPos(this, pos);
4272-
return markText(this, pos, pos, widget ? {replacedWith: widget} : {}, "bookmark");
4274+
return markText(this, pos, pos, realOpts, "bookmark");
42734275
},
42744276
findMarksAt: function(pos) {
42754277
pos = clipPos(this, pos);

test/test.js

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -460,6 +460,21 @@ testCM("bookmark", function(cm) {
460460
});
461461
});
462462

463+
testCM("bookmarkInsertLeft", function(cm) {
464+
var br = cm.setBookmark({line: 0, ch: 2}, {insertLeft: false});
465+
var bl = cm.setBookmark({line: 0, ch: 2}, {insertLeft: true});
466+
cm.setCursor({line: 0, ch: 2});
467+
cm.replaceSelection("hi");
468+
eqPos(br.find(), {line: 0, ch: 2});
469+
eqPos(bl.find(), {line: 0, ch: 4});
470+
cm.replaceRange("", {line: 0, ch: 4}, {line: 0, ch: 5});
471+
cm.replaceRange("", {line: 0, ch: 2}, {line: 0, ch: 4});
472+
cm.replaceRange("", {line: 0, ch: 1}, {line: 0, ch: 2});
473+
// Verify that deleting next to bookmarks doesn't kill them
474+
eqPos(br.find(), {line: 0, ch: 1});
475+
eqPos(bl.find(), {line: 0, ch: 1});
476+
}, {value: "abcdef"});
477+
463478
testCM("bug577", function(cm) {
464479
cm.setValue("a\nb");
465480
cm.clearHistory();
@@ -726,7 +741,7 @@ testCM("badNestedFold", function(cm) {
726741
});
727742

728743
testCM("inlineWidget", function(cm) {
729-
var w = cm.setBookmark({line: 0, ch: 2}, document.createTextNode("uu"));
744+
var w = cm.setBookmark({line: 0, ch: 2}, {widget: document.createTextNode("uu")});
730745
cm.setCursor(0, 2);
731746
CodeMirror.commands.goLineDown(cm);
732747
eqPos(cm.getCursor(), {line: 1, ch: 4});

0 commit comments

Comments
 (0)