mirror of
https://github.com/renbaoshuo/S2OJ.git
synced 2024-11-30 02:16:19 +00:00
96d4a3ecf7
Due to historical reasons, the code is in subfolder "1". With SVN removal, we place the code back and remove the annoying "1" folder.
129 lines
4.8 KiB
JavaScript
129 lines
4.8 KiB
JavaScript
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
|
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
|
|
|
// Highlighting text that matches the selection
|
|
//
|
|
// Defines an option highlightSelectionMatches, which, when enabled,
|
|
// will style strings that match the selection throughout the
|
|
// document.
|
|
//
|
|
// The option can be set to true to simply enable it, or to a
|
|
// {minChars, style, wordsOnly, showToken, delay} object to explicitly
|
|
// configure it. minChars is the minimum amount of characters that should be
|
|
// selected for the behavior to occur, and style is the token style to
|
|
// apply to the matches. This will be prefixed by "cm-" to create an
|
|
// actual CSS class name. If wordsOnly is enabled, the matches will be
|
|
// highlighted only if the selected text is a word. showToken, when enabled,
|
|
// will cause the current token to be highlighted when nothing is selected.
|
|
// delay is used to specify how much time to wait, in milliseconds, before
|
|
// highlighting the matches.
|
|
|
|
(function(mod) {
|
|
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
|
mod(require("../../lib/codemirror"));
|
|
else if (typeof define == "function" && define.amd) // AMD
|
|
define(["../../lib/codemirror"], mod);
|
|
else // Plain browser env
|
|
mod(CodeMirror);
|
|
})(function(CodeMirror) {
|
|
"use strict";
|
|
|
|
var DEFAULT_MIN_CHARS = 2;
|
|
var DEFAULT_TOKEN_STYLE = "matchhighlight";
|
|
var DEFAULT_DELAY = 100;
|
|
var DEFAULT_WORDS_ONLY = false;
|
|
|
|
function State(options) {
|
|
if (typeof options == "object") {
|
|
this.minChars = options.minChars;
|
|
this.style = options.style;
|
|
this.showToken = options.showToken;
|
|
this.delay = options.delay;
|
|
this.wordsOnly = options.wordsOnly;
|
|
}
|
|
if (this.style == null) this.style = DEFAULT_TOKEN_STYLE;
|
|
if (this.minChars == null) this.minChars = DEFAULT_MIN_CHARS;
|
|
if (this.delay == null) this.delay = DEFAULT_DELAY;
|
|
if (this.wordsOnly == null) this.wordsOnly = DEFAULT_WORDS_ONLY;
|
|
this.overlay = this.timeout = null;
|
|
}
|
|
|
|
CodeMirror.defineOption("highlightSelectionMatches", false, function(cm, val, old) {
|
|
if (old && old != CodeMirror.Init) {
|
|
var over = cm.state.matchHighlighter.overlay;
|
|
if (over) cm.removeOverlay(over);
|
|
clearTimeout(cm.state.matchHighlighter.timeout);
|
|
cm.state.matchHighlighter = null;
|
|
cm.off("cursorActivity", cursorActivity);
|
|
}
|
|
if (val) {
|
|
cm.state.matchHighlighter = new State(val);
|
|
highlightMatches(cm);
|
|
cm.on("cursorActivity", cursorActivity);
|
|
}
|
|
});
|
|
|
|
function cursorActivity(cm) {
|
|
var state = cm.state.matchHighlighter;
|
|
clearTimeout(state.timeout);
|
|
state.timeout = setTimeout(function() {highlightMatches(cm);}, state.delay);
|
|
}
|
|
|
|
function highlightMatches(cm) {
|
|
cm.operation(function() {
|
|
var state = cm.state.matchHighlighter;
|
|
if (state.overlay) {
|
|
cm.removeOverlay(state.overlay);
|
|
state.overlay = null;
|
|
}
|
|
if (!cm.somethingSelected() && state.showToken) {
|
|
var re = state.showToken === true ? /[\w$]/ : state.showToken;
|
|
var cur = cm.getCursor(), line = cm.getLine(cur.line), start = cur.ch, end = start;
|
|
while (start && re.test(line.charAt(start - 1))) --start;
|
|
while (end < line.length && re.test(line.charAt(end))) ++end;
|
|
if (start < end)
|
|
cm.addOverlay(state.overlay = makeOverlay(line.slice(start, end), re, state.style));
|
|
return;
|
|
}
|
|
var from = cm.getCursor("from"), to = cm.getCursor("to");
|
|
if (from.line != to.line) return;
|
|
if (state.wordsOnly && !isWord(cm, from, to)) return;
|
|
var selection = cm.getRange(from, to).replace(/^\s+|\s+$/g, "");
|
|
if (selection.length >= state.minChars)
|
|
cm.addOverlay(state.overlay = makeOverlay(selection, false, state.style));
|
|
});
|
|
}
|
|
|
|
function isWord(cm, from, to) {
|
|
var str = cm.getRange(from, to);
|
|
if (str.match(/^\w+$/) !== null) {
|
|
if (from.ch > 0) {
|
|
var pos = {line: from.line, ch: from.ch - 1};
|
|
var chr = cm.getRange(pos, from);
|
|
if (chr.match(/\W/) === null) return false;
|
|
}
|
|
if (to.ch < cm.getLine(from.line).length) {
|
|
var pos = {line: to.line, ch: to.ch + 1};
|
|
var chr = cm.getRange(to, pos);
|
|
if (chr.match(/\W/) === null) return false;
|
|
}
|
|
return true;
|
|
} else return false;
|
|
}
|
|
|
|
function boundariesAround(stream, re) {
|
|
return (!stream.start || !re.test(stream.string.charAt(stream.start - 1))) &&
|
|
(stream.pos == stream.string.length || !re.test(stream.string.charAt(stream.pos)));
|
|
}
|
|
|
|
function makeOverlay(query, hasBoundary, style) {
|
|
return {token: function(stream) {
|
|
if (stream.match(query) &&
|
|
(!hasBoundary || boundariesAround(stream, hasBoundary)))
|
|
return style;
|
|
stream.next();
|
|
stream.skipTo(query.charAt(0)) || stream.skipToEnd();
|
|
}};
|
|
}
|
|
});
|