1d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org// CodeMirror, copyright (c) by Marijn Haverbeke and others 2d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org// Distributed under an MIT license: http://codemirror.net/LICENSE 3d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org 4d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org// Because sometimes you need to mark the selected *text*. 5d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org// 6d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org// Adds an option 'styleSelectedText' which, when enabled, gives 7d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org// selected text the CSS class given as option value, or 85089f9c6ecd9b0802f1cf456b69350255a93ae09agl@chromium.org// "CodeMirror-selectedtext" when the value is not a string. 9d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org 10d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org(function(mod) { 11d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org if (typeof exports == "object" && typeof module == "object") // CommonJS 12d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org mod(require("../../lib/codemirror")); 13d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org else if (typeof define == "function" && define.amd) // AMD 14d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org define(["../../lib/codemirror"], mod); 15d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org else // Plain browser env 16d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org mod(CodeMirror); 1793aedf7d27cb93f93077f9f7f758e830a392bdfcbashi@google.com})(function(CodeMirror) { 18d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org "use strict"; 19d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org 20d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org CodeMirror.defineOption("styleSelectedText", false, function(cm, val, old) { 21d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org var prev = old && old != CodeMirror.Init; 22d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org if (val && !prev) { 23d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org cm.state.markedSelection = []; 24d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org cm.state.markedSelectionStyle = typeof val == "string" ? val : "CodeMirror-selectedtext"; 25d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org reset(cm); 26a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org cm.on("cursorActivity", onCursorActivity); 27d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org cm.on("change", onChange); 28d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org } else if (!val && prev) { 29d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org cm.off("cursorActivity", onCursorActivity); 30d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org cm.off("change", onChange); 31d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org clear(cm); 32d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org cm.state.markedSelection = cm.state.markedSelectionStyle = null; 33d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org } 34d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org }); 35d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org 36d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org function onCursorActivity(cm) { 37d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org cm.operation(function() { update(cm); }); 38d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org } 395089f9c6ecd9b0802f1cf456b69350255a93ae09agl@chromium.org 40d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org function onChange(cm) { 41d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org if (cm.state.markedSelection.length) 42d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org cm.operation(function() { clear(cm); }); 43d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org } 44d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org 45d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org var CHUNK_SIZE = 8; 46d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org var Pos = CodeMirror.Pos; 47d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org var cmp = CodeMirror.cmpPos; 48d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org 49d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org function coverRange(cm, from, to, addAt) { 50d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org if (cmp(from, to) == 0) return; 51d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org var array = cm.state.markedSelection; 52d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org var cls = cm.state.markedSelectionStyle; 53d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org for (var line = from.line;;) { 54d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org var start = line == from.line ? from : Pos(line, 0); 55d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org var endLine = line + CHUNK_SIZE, atEnd = endLine >= to.line; 56d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org var end = atEnd ? to : Pos(endLine, 0); 57d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org var mark = cm.markText(start, end, {className: cls}); 58d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org if (addAt == null) array.push(mark); 59d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org else array.splice(addAt++, 0, mark); 60d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org if (atEnd) break; 61d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org line = endLine; 62d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org } 63d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org } 64d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org 65d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org function clear(cm) { 66d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org var array = cm.state.markedSelection; 67d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org for (var i = 0; i < array.length; ++i) array[i].clear(); 68d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org array.length = 0; 69d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org } 70d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org 71d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org function reset(cm) { 72d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org clear(cm); 73d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org var ranges = cm.listSelections(); 74d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org for (var i = 0; i < ranges.length; i++) 75d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org coverRange(cm, ranges[i].from(), ranges[i].to()); 76d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org } 77d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org 785089f9c6ecd9b0802f1cf456b69350255a93ae09agl@chromium.org function update(cm) { 795089f9c6ecd9b0802f1cf456b69350255a93ae09agl@chromium.org if (!cm.somethingSelected()) return clear(cm); 805089f9c6ecd9b0802f1cf456b69350255a93ae09agl@chromium.org if (cm.listSelections().length > 1) return reset(cm); 815089f9c6ecd9b0802f1cf456b69350255a93ae09agl@chromium.org 825089f9c6ecd9b0802f1cf456b69350255a93ae09agl@chromium.org var from = cm.getCursor("start"), to = cm.getCursor("end"); 835089f9c6ecd9b0802f1cf456b69350255a93ae09agl@chromium.org 845089f9c6ecd9b0802f1cf456b69350255a93ae09agl@chromium.org var array = cm.state.markedSelection; 855089f9c6ecd9b0802f1cf456b69350255a93ae09agl@chromium.org if (!array.length) return coverRange(cm, from, to); 865089f9c6ecd9b0802f1cf456b69350255a93ae09agl@chromium.org 875089f9c6ecd9b0802f1cf456b69350255a93ae09agl@chromium.org var coverStart = array[0].find(), coverEnd = array[array.length - 1].find(); 885089f9c6ecd9b0802f1cf456b69350255a93ae09agl@chromium.org if (!coverStart || !coverEnd || to.line - from.line < CHUNK_SIZE || 895089f9c6ecd9b0802f1cf456b69350255a93ae09agl@chromium.org cmp(from, coverEnd.to) >= 0 || cmp(to, coverStart.from) <= 0) 905089f9c6ecd9b0802f1cf456b69350255a93ae09agl@chromium.org return reset(cm); 915089f9c6ecd9b0802f1cf456b69350255a93ae09agl@chromium.org 925089f9c6ecd9b0802f1cf456b69350255a93ae09agl@chromium.org while (cmp(from, coverStart.from) > 0) { 935089f9c6ecd9b0802f1cf456b69350255a93ae09agl@chromium.org array.shift().clear(); 945089f9c6ecd9b0802f1cf456b69350255a93ae09agl@chromium.org coverStart = array[0].find(); 955089f9c6ecd9b0802f1cf456b69350255a93ae09agl@chromium.org } 965089f9c6ecd9b0802f1cf456b69350255a93ae09agl@chromium.org if (cmp(from, coverStart.from) < 0) { 97d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org if (coverStart.to.line - from.line < CHUNK_SIZE) { 98d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org array.shift().clear(); 99d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org coverRange(cm, from, coverStart.to, 0); 100d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org } else { 101d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org coverRange(cm, from, coverStart.from, 0); 102d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org } 103d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org } 104d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org 105d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org while (cmp(to, coverEnd.to) < 0) { 106a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org array.pop().clear(); 107d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org coverEnd = array[array.length - 1].find(); 108a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org } 109a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org if (cmp(to, coverEnd.to) > 0) { 110a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org if (to.line - coverEnd.from.line < CHUNK_SIZE) { 111a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org array.pop().clear(); 112a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org coverRange(cm, coverEnd.from, to); 113d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org } else { 114a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org coverRange(cm, coverEnd.to, to); 115d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org } 116a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org } 117d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org } 118a4099a3bb81adafc5593090c1185ec82933a3d6eyusukes@chromium.org}); 119d257d186ae2a08042a412824678f98241a1a4f3cyusukes@chromium.org