(function (mod){
if (typeof exports == "object" && typeof module == "object") mod(require("../../lib/codemirror"), require("./searchcursor"), require("../dialog/dialog"));
else if (typeof define == "function" && define.amd) define(["../../lib/codemirror", "./searchcursor", "../dialog/dialog"] , mod);
else mod(CodeMirror);
}
)(function (CodeMirror){
"use strict";
function searchOverlay(query, caseInsensitive){
if (typeof query == "string") query = new RegExp((_AN_Call_replace("replace", query, /[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&")), caseInsensitive? "gi": "g");
else if (!query.global) query = new RegExp(query.source, query.ignoreCase? "gi": "g");
return {
token: function (stream){
query.lastIndex = stream.pos;
var match = query.exec(stream.string);
if (match && match.index == stream.pos) {
stream.pos += _AN_Read_length("length", match[0]) || 1;
return "searching";
}
else if (match) {
stream.pos = match.index;
}
else {
stream.skipToEnd();
}
}
}
;
}
function SearchState(){
this.posFrom = this.posTo = this.lastQuery = this.query = null ;
this.overlay = null ;
}
function getSearchState(cm){
return _AN_Read_search("search", cm.state) || (_AN_Write_search("search", cm.state, false , new SearchState()));
}
function queryCaseInsensitive(query){
return typeof query == "string" && query == query.toLowerCase();
}
function getSearchCursor(cm, query, pos){
return cm.getSearchCursor(query, pos, queryCaseInsensitive(query));
}
function persistentDialog(cm, text, deflt, f){
cm.openDialog(text, f, {
value: deflt,
selectValueOnOpen: true ,
closeOnEnter: false ,
onClose: function (){
clearSearch(cm);
}
}
);
}
function dialog(cm, text, shortText, deflt, f){
if (cm.openDialog) cm.openDialog(text, f, {
value: deflt,
selectValueOnOpen: true }
);
else f(prompt(shortText, deflt));
}
function confirmDialog(cm, text, shortText, fs){
if (cm.openConfirm) cm.openConfirm(text, fs);
else if (confirm(shortText)) fs[0]();
}
function parseString(string){
return _AN_Call_replace("replace", string, /\\(.)/g, function (_, ch){
if (ch == "n") return "\n";
if (ch == "r") return "\r";
return ch;
}
);
}
function parseQuery(query){
var isRE = query.match(/^\/(.*)\/([a-z]*)$/);
if (isRE) {
try {
query = new RegExp(isRE[1], isRE[2].indexOf("i") == -1? "": "i");
}
catch (e) {
}
}
else {
query = parseString(query);
}
if (typeof query == "string"? query == "": query.test("")) query = /x^/;
return query;
}
var queryDialog = 'Search: (Use /re/ syntax for regexp search)';
function startSearch(cm, state, query){
state.queryText = query;
state.query = parseQuery(query);
cm.removeOverlay(state.overlay, queryCaseInsensitive(state.query));
state.overlay = searchOverlay(state.query, queryCaseInsensitive(state.query));
cm.addOverlay(state.overlay);
if (cm.showMatchesOnScrollbar) {
if (state.annotate) {
_AN_Call_clear('clear', state.annotate);
state.annotate = null ;
}
state.annotate = cm.showMatchesOnScrollbar(state.query, queryCaseInsensitive(state.query));
}
}
function doSearch(cm, rev, persistent){
var state = getSearchState(cm);
if (state.query) return findNext(cm, rev);
var q = cm.getSelection() || state.lastQuery;
if (persistent && cm.openDialog) {
var hiding = null ;
persistentDialog(cm, queryDialog, q, function (query, event){
CodeMirror.e_stop(event);
if (!query) return ;
if (query != state.queryText) startSearch(cm, state, query);
if (hiding) hiding.style.opacity = 1;
findNext(cm, event.shiftKey, function (_, to){
var dialog;
if (to.line < 3 && document.querySelector && (dialog = cm.display.wrapper.querySelector(".CodeMirror-dialog")) && dialog.getBoundingClientRect().bottom - 4 > cm.cursorCoords(to, "window").top) (hiding = dialog).style.opacity = 0.4;
}
);
}
);
}
else {
dialog(cm, queryDialog, "Search for:", q, function (query){
if (query && !state.query) cm.operation(function (){
startSearch(cm, state, query);
state.posFrom = state.posTo = cm.getCursor();
findNext(cm, rev);
}
);
}
);
}
}
function findNext(cm, rev, callback){
cm.operation(function (){
var state = getSearchState(cm);
var cursor = getSearchCursor(cm, state.query, rev? state.posFrom: state.posTo);
if (!cursor.find(rev)) {
cursor = getSearchCursor(cm, state.query, rev? CodeMirror.Pos(cm.lastLine()): CodeMirror.Pos(cm.firstLine(), 0));
if (!cursor.find(rev)) return ;
}
cm.setSelection(cursor.from(), cursor.to());
cm.scrollIntoView({
from: cursor.from(),
to: cursor.to()}
, 20);
state.posFrom = cursor.from();
state.posTo = cursor.to();
if (callback) callback(cursor.from(), cursor.to());
}
);
}
function clearSearch(cm){
cm.operation(function (){
var state = getSearchState(cm);
state.lastQuery = state.query;
if (!state.query) return ;
state.query = state.queryText = null ;
cm.removeOverlay(state.overlay);
if (state.annotate) {
_AN_Call_clear("clear", state.annotate);
state.annotate = null ;
}
}
);
}
var replaceQueryDialog = ' (Use /re/ syntax for regexp search)';
var replacementQueryDialog = 'With: ';
var doReplaceConfirm = "Replace? ";
function replaceAll(cm, query, text){
cm.operation(function (){
for (var cursor = getSearchCursor(cm, query);
cursor.findNext(); ){
if (typeof query != "string") {
var match = cm.getRange(cursor.from(), cursor.to()).match(query);
_AN_Call_replace("replace", cursor, _AN_Call_replace("replace", text, /\$(\d)/g, function (_, i){
return match[i];
}
));
}
else _AN_Call_replace("replace", cursor, text);
}
}
);
}
function replace(cm, all){
if (cm.getOption("readOnly")) return ;
var query = cm.getSelection() || getSearchState(cm).lastQuery;
var dialogText = all? "Replace all:": "Replace:";
dialog(cm, dialogText + replaceQueryDialog, dialogText, query, function (query){
if (!query) return ;
query = parseQuery(query);
dialog(cm, replacementQueryDialog, "Replace with:", "", function (text){
text = parseString(text);
if (all) {
replaceAll(cm, query, text);
}
else {
clearSearch(cm);
var cursor = getSearchCursor(cm, query, cm.getCursor());
var advance = function (){
var start = cursor.from(), match;
if (!(match = cursor.findNext())) {
cursor = getSearchCursor(cm, query);
if (!(match = cursor.findNext()) || (start && cursor.from().line == start.line && cursor.from().ch == start.ch)) return ;
}
cm.setSelection(cursor.from(), cursor.to());
cm.scrollIntoView({
from: cursor.from(),
to: cursor.to()}
);
confirmDialog(cm, doReplaceConfirm, "Replace?", [function (){
doReplace(match);
}
, advance, function (){
replaceAll(cm, query, text);
}
] );
}
;
var doReplace = function (match){
_AN_Call_replace("replace", cursor, typeof query == "string"? text: _AN_Call_replace("replace", text, /\$(\d)/g, function (_, i){
return match[i];
}
));
advance();
}
;
advance();
}
}
);
}
);
}
CodeMirror.commands.find = function (cm){
clearSearch(cm);
doSearch(cm);
}
;
CodeMirror.commands.findPersistent = function (cm){
clearSearch(cm);
doSearch(cm, false , true );
}
;
CodeMirror.commands.findNext = doSearch;
CodeMirror.commands.findPrev = function (cm){
doSearch(cm, true );
}
;
CodeMirror.commands.clearSearch = clearSearch;
CodeMirror.commands.replace = replace;
CodeMirror.commands.replaceAll = function (cm){
replace(cm, true );
}
;
}
);