From 7bb5b305be6d35b8f2322ae53de95152cd77eb62 Mon Sep 17 00:00:00 2001 From: Robert Krahn Date: Tue, 4 Nov 2014 13:01:08 -0800 Subject: [PATCH 1/3] isearch: add regexp support --- lib/ace/incremental_search.js | 56 ++++++++++++++++++++++++++++-- lib/ace/incremental_search_test.js | 21 +++++++---- 2 files changed, 67 insertions(+), 10 deletions(-) diff --git a/lib/ace/incremental_search.js b/lib/ace/incremental_search.js index 88615006..4e7f7bf3 100644 --- a/lib/ace/incremental_search.js +++ b/lib/ace/incremental_search.js @@ -64,6 +64,34 @@ function IncrementalSearch() { oop.inherits(IncrementalSearch, Search); +// regexp handling + +function isRegExp(obj) { + return obj instanceof RegExp; +} + +function regExpToObject(re) { + var string = String(re), + start = string.indexOf('/'), + flagStart = string.lastIndexOf('/'); + return { + expression: string.slice(start+1, flagStart), + flags: string.slice(flagStart+1) + } +} + +function stringToRegExp(string, flags) { + try { + return new RegExp(string, flags); + } catch (e) { return string; } +} + +function objectToRegExp(obj) { + return stringToRegExp(obj.expression, obj.flags); +} + +// iSearch class + ;(function() { this.activate = function(ed, backwards) { @@ -140,7 +168,9 @@ oop.inherits(IncrementalSearch, Search); // try to find the next occurence and enable highlighting marker options.start = this.$currentPos; var session = this.$editor.session, - found = this.find(session); + found = this.find(session), + shouldSelect = this.$editor.emacsMark ? + !!this.$editor.emacsMark() : !this.$editor.selection.isEmpty(); if (found) { if (options.backwards) found = Range.fromPoints(found.end, found.start); this.$editor.moveCursorToPosition(found.end); @@ -156,13 +186,21 @@ oop.inherits(IncrementalSearch, Search); this.addString = function(s) { return this.highlightAndFindWithNeedle(false, function(needle) { - return needle + s; + if (!isRegExp(needle)) + return needle + s; + var reObj = regExpToObject(needle); + reObj.expression += s; + return objectToRegExp(reObj); }); } this.removeChar = function(c) { return this.highlightAndFindWithNeedle(false, function(needle) { - return needle.length > 0 ? needle.substring(0, needle.length-1) : needle; + if (!isRegExp(needle)) + return needle.substring(0, needle.length-1); + var reObj = regExpToObject(needle); + reObj.expression = reObj.expression.substring(0, reObj.expression.length-1); + return objectToRegExp(reObj); }); } @@ -189,6 +227,18 @@ oop.inherits(IncrementalSearch, Search); this.addString(text); } + this.convertNeedleToRegExp = function() { + return this.highlightAndFindWithNeedle(false, function(needle) { + return isRegExp(needle) ? needle : stringToRegExp(needle, 'ig'); + }); + } + + this.convertNeedleToString = function() { + return this.highlightAndFindWithNeedle(false, function(needle) { + return isRegExp(needle) ? regExpToObject(needle).expression : needle; + }); + } + this.statusMessage = function(found) { var options = this.$options, msg = ''; msg += options.backwards ? 'reverse-' : ''; diff --git a/lib/ace/incremental_search_test.js b/lib/ace/incremental_search_test.js index 262e09a7..c99e9382 100644 --- a/lib/ace/incremental_search_test.js +++ b/lib/ace/incremental_search_test.js @@ -35,10 +35,12 @@ if (typeof process !== "undefined") { define(function(require, exports, module) { "use strict"; +var config = require("./config"); var EditSession = require("./edit_session").EditSession; var Editor = require("./editor").Editor; var MockRenderer = require("./test/mockrenderer").MockRenderer; var Range = require("./range").Range; +var MultiSelect = require("./multi_select").MultiSelect; var assert = require("./test/assertions"); var IncrementalSearch = require("./incremental_search").IncrementalSearch; @@ -69,6 +71,7 @@ module.exports = { setUp: function() { var session = new EditSession(["abc123", "xyz124"]); editor = new Editor(new MockRenderer(), session); + new MultiSelect(editor); iSearch = new IncrementalSearch(); }, @@ -190,13 +193,17 @@ module.exports = { testRanges("Range: [0/0] -> [0/5]", [editor.getSelectionRange()], "sel range"); }, - "test: extend selection in emacs mark mode" : function() { - var emacs = require('./keyboard/emacs'); - editor.keyBinding.addKeyboardHandler(emacs.handler); - emacs.handler.commands.setMark.exec(editor); - iSearch.activate(editor); - iSearch.addString('1'); iSearch.addString('2');; - testRanges("Range: [0/0] -> [0/5]", [editor.getSelectionRange()], "sel range"); + "test: extend selection in emacs mark mode" : function(next) { + config.loadModule("ace/keyboard/emacs", function(emacs) { + // var emacs = require('./keyboard/emacs'); + editor.keyBinding.addKeyboardHandler(emacs.handler); + emacs.handler.commands.setMark.exec(editor); + iSearch.activate(editor); + iSearch.addString('1'); iSearch.addString('2'); + + testRanges("Range: [0/0] -> [0/5]", [editor.getSelectionRange()], "sel range"); + next(); + }); } }; From a93646d2f704f15d759adc8fe0d20be39fc86528 Mon Sep 17 00:00:00 2001 From: Robert Krahn Date: Tue, 4 Nov 2014 13:01:29 -0800 Subject: [PATCH 2/3] isearch: commands searchAsRegExp and selectAllMatches --- .../commands/incremental_search_commands.js | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/lib/ace/commands/incremental_search_commands.js b/lib/ace/commands/incremental_search_commands.js index 8ef80303..a0a0fe5f 100644 --- a/lib/ace/commands/incremental_search_commands.js +++ b/lib/ace/commands/incremental_search_commands.js @@ -162,6 +162,28 @@ exports.iSearchCommands = [{ exec: function(iSearch) { iSearch.$editor.execCommand('recenterTopBottom'); }, readOnly: true, isIncrementalSearchCommand: true +}, { + name: 'selectAllMatches', + bindKey: 'Ctrl-space', + exec: function(iSearch) { + var ed = iSearch.$editor, + hl = ed.session.$isearchHighlight, + ranges = hl && hl.cache ? hl.cache + .reduce(function(ranges, ea) { + return ranges.concat(ea ? ea : []); }, []) : []; + iSearch.deactivate(false); + ranges.forEach(ed.selection.addRange.bind(ed.selection)); + }, + readOnly: true, + isIncrementalSearchCommand: true +}, { + name: 'searchAsRegExp', + bindKey: 'Alt-r', + exec: function(iSearch) { + iSearch.convertNeedleToRegExp(); + }, + readOnly: true, + isIncrementalSearchCommand: true }]; function IncrementalSearchKeyboardHandler(iSearch) { From 775cdedefb1baeb94410bb5449f5f121c4437ed4 Mon Sep 17 00:00:00 2001 From: Robert Krahn Date: Tue, 4 Nov 2014 16:00:48 -0800 Subject: [PATCH 3/3] isearch test fix --- lib/ace/incremental_search_test.js | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/lib/ace/incremental_search_test.js b/lib/ace/incremental_search_test.js index c99e9382..991291c5 100644 --- a/lib/ace/incremental_search_test.js +++ b/lib/ace/incremental_search_test.js @@ -35,7 +35,7 @@ if (typeof process !== "undefined") { define(function(require, exports, module) { "use strict"; -var config = require("./config"); +var emacs = require('./keyboard/emacs'); var EditSession = require("./edit_session").EditSession; var Editor = require("./editor").Editor; var MockRenderer = require("./test/mockrenderer").MockRenderer; @@ -193,17 +193,14 @@ module.exports = { testRanges("Range: [0/0] -> [0/5]", [editor.getSelectionRange()], "sel range"); }, - "test: extend selection in emacs mark mode" : function(next) { - config.loadModule("ace/keyboard/emacs", function(emacs) { - // var emacs = require('./keyboard/emacs'); - editor.keyBinding.addKeyboardHandler(emacs.handler); - emacs.handler.commands.setMark.exec(editor); - iSearch.activate(editor); - iSearch.addString('1'); iSearch.addString('2'); - - testRanges("Range: [0/0] -> [0/5]", [editor.getSelectionRange()], "sel range"); - next(); - }); + "test: extend selection in emacs mark mode" : function() { + var emacs = require('./keyboard/emacs'); + editor.keyBinding.addKeyboardHandler(emacs.handler); + emacs.handler.commands.setMark.exec(editor); + iSearch.activate(editor); + iSearch.addString('1'); iSearch.addString('2'); + + testRanges("Range: [0/0] -> [0/5]", [editor.getSelectionRange()], "sel range"); } };