From 71c347aacd08063f895f794e50470b5ec85f012c Mon Sep 17 00:00:00 2001 From: Mihai Sucan Date: Sat, 12 Feb 2011 20:26:24 +0200 Subject: [PATCH 1/7] Fix for issue 57: highlight all instances of a selected word. --- lib/ace/css/editor.css | 5 +++++ lib/ace/editor.js | 32 ++++++++++++++++++++++++++++++++ lib/ace/mouse_handler.js | 3 ++- lib/ace/theme/tm.css | 7 ++++++- 4 files changed, 45 insertions(+), 2 deletions(-) diff --git a/lib/ace/css/editor.css b/lib/ace/css/editor.css index c2f3abff..82401624 100644 --- a/lib/ace/css/editor.css +++ b/lib/ace/css/editor.css @@ -143,3 +143,8 @@ position: absolute; z-index: 2; } + +.ace_marker-layer .ace_selected_word { + position: absolute; + z-index: 6; +} diff --git a/lib/ace/editor.js b/lib/ace/editor.js index 9d785ca7..7cc6cdb7 100644 --- a/lib/ace/editor.js +++ b/lib/ace/editor.js @@ -74,6 +74,7 @@ var Editor =function(renderer, session) { this.$selectionMarker = null; this.$highlightLineMarker = null; this.$blockScrolling = 0; + this.$selectedWordMarkers = []; this.$search = new Search().set({ wrap: true @@ -235,6 +236,36 @@ var Editor =function(renderer, session) { }, 10); }; + this.highlightSelection = function() { + if (this.$selectedWordMarkers.length) + this.clearSelectionHighlight(); + + var selectedRange = this.getSelectionRange(); + if (selectedRange.isEmpty()) + return; + + var newOptions = {wrap:true, wholeWord: true}; + newOptions.needle = this.session.getTextRange(selectedRange); + if (!newOptions.needle) + return; + + var currentOptions = this.$search.getOptions(); + this.$search.set(newOptions); + + var ranges = this.$search.findAll(this.session); + this.$selectedWordMarkers = []; + ranges.forEach(function(range) { + if (!range.contains(selectedRange.start.row, selectedRange.start.column)) + this.$selectedWordMarkers.push(this.renderer.addMarker(range, "ace_selected_word")); + }, this); + }; + + this.clearSelectionHighlight = function() { + this.$selectedWordMarkers.forEach(function(marker) { + this.renderer.removeMarker(marker); + }, this); + }; + this.focus = function() { // Safari need the timeout // iOS and Firefox need it called immediately @@ -323,6 +354,7 @@ var Editor =function(renderer, session) { } this.onCursorChange(e); + this.clearSelectionHighlight(); }; this.onDocumentChangeBreakpoint = function() { diff --git a/lib/ace/mouse_handler.js b/lib/ace/mouse_handler.js index 5e836383..244fc461 100644 --- a/lib/ace/mouse_handler.js +++ b/lib/ace/mouse_handler.js @@ -146,6 +146,7 @@ var MouseHandler = function(editor) { this.onMouseDoubleClick = function(e) { this.editor.selection.selectWord(); + this.editor.highlightSelection(); this.$clickSelection = this.editor.getSelectionRange(); }; @@ -165,4 +166,4 @@ var MouseHandler = function(editor) { }).call(MouseHandler.prototype); exports.MouseHandler = MouseHandler; -}); \ No newline at end of file +}); diff --git a/lib/ace/theme/tm.css b/lib/ace/theme/tm.css index 0993335c..987901d1 100644 --- a/lib/ace/theme/tm.css +++ b/lib/ace/theme/tm.css @@ -131,6 +131,11 @@ background: rgb(232, 242, 254); } +.ace-tm .ace_marker-layer .ace_selected_word { + background: rgb(250, 250, 255); + border: 1px solid rgb(200, 200, 250); +} + .ace-tm .ace_string.ace_regex { color: rgb(255, 0, 0) -} \ No newline at end of file +} From 1b3d7816c5784287819cbf4a7b209f6319516154 Mon Sep 17 00:00:00 2001 From: Mihai Sucan Date: Sat, 12 Feb 2011 20:40:58 +0200 Subject: [PATCH 2/7] Make sure the current search needle is not lost. --- lib/ace/editor.js | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/lib/ace/editor.js b/lib/ace/editor.js index 7cc6cdb7..74a82d1e 100644 --- a/lib/ace/editor.js +++ b/lib/ace/editor.js @@ -74,7 +74,7 @@ var Editor =function(renderer, session) { this.$selectionMarker = null; this.$highlightLineMarker = null; this.$blockScrolling = 0; - this.$selectedWordMarkers = []; + this.$selectionOccurrences = []; this.$search = new Search().set({ wrap: true @@ -237,7 +237,7 @@ var Editor =function(renderer, session) { }; this.highlightSelection = function() { - if (this.$selectedWordMarkers.length) + if (this.$selectionOccurrences.length) this.clearSelectionHighlight(); var selectedRange = this.getSelectionRange(); @@ -253,15 +253,17 @@ var Editor =function(renderer, session) { this.$search.set(newOptions); var ranges = this.$search.findAll(this.session); - this.$selectedWordMarkers = []; + this.$selectionOccurrences = []; ranges.forEach(function(range) { if (!range.contains(selectedRange.start.row, selectedRange.start.column)) - this.$selectedWordMarkers.push(this.renderer.addMarker(range, "ace_selected_word")); + this.$selectionOccurrences.push(this.renderer.addMarker(range, "ace_selected_word")); }, this); + + this.$search.set(currentOptions); }; this.clearSelectionHighlight = function() { - this.$selectedWordMarkers.forEach(function(marker) { + this.$selectionOccurrences.forEach(function(marker) { this.renderer.removeMarker(marker); }, this); }; From b903679c1c6529312cec24f8547d0e42de72f9aa Mon Sep 17 00:00:00 2001 From: Mihai Sucan Date: Sun, 13 Feb 2011 14:32:27 +0200 Subject: [PATCH 3/7] pilot --- support/pilot | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/support/pilot b/support/pilot index 5d642573..cbfac498 160000 --- a/support/pilot +++ b/support/pilot @@ -1 +1 @@ -Subproject commit 5d642573259ba8a77456d3fa066beb2f1b2be23a +Subproject commit cbfac498d30d43fdb7687d198c5b752736222c2f From b6e136201d89e8fd82043ceed2256724dfd2fa1f Mon Sep 17 00:00:00 2001 From: Mihai Sucan Date: Sat, 12 Feb 2011 20:26:24 +0200 Subject: [PATCH 4/7] Fix for issue 57: highlight all instances of a selected word. --- lib/ace/css/editor.css | 5 +++++ lib/ace/editor.js | 32 ++++++++++++++++++++++++++++++++ lib/ace/mouse_handler.js | 3 ++- lib/ace/theme/tm.css | 7 ++++++- 4 files changed, 45 insertions(+), 2 deletions(-) diff --git a/lib/ace/css/editor.css b/lib/ace/css/editor.css index c2f3abff..82401624 100644 --- a/lib/ace/css/editor.css +++ b/lib/ace/css/editor.css @@ -143,3 +143,8 @@ position: absolute; z-index: 2; } + +.ace_marker-layer .ace_selected_word { + position: absolute; + z-index: 6; +} diff --git a/lib/ace/editor.js b/lib/ace/editor.js index 9d785ca7..7cc6cdb7 100644 --- a/lib/ace/editor.js +++ b/lib/ace/editor.js @@ -74,6 +74,7 @@ var Editor =function(renderer, session) { this.$selectionMarker = null; this.$highlightLineMarker = null; this.$blockScrolling = 0; + this.$selectedWordMarkers = []; this.$search = new Search().set({ wrap: true @@ -235,6 +236,36 @@ var Editor =function(renderer, session) { }, 10); }; + this.highlightSelection = function() { + if (this.$selectedWordMarkers.length) + this.clearSelectionHighlight(); + + var selectedRange = this.getSelectionRange(); + if (selectedRange.isEmpty()) + return; + + var newOptions = {wrap:true, wholeWord: true}; + newOptions.needle = this.session.getTextRange(selectedRange); + if (!newOptions.needle) + return; + + var currentOptions = this.$search.getOptions(); + this.$search.set(newOptions); + + var ranges = this.$search.findAll(this.session); + this.$selectedWordMarkers = []; + ranges.forEach(function(range) { + if (!range.contains(selectedRange.start.row, selectedRange.start.column)) + this.$selectedWordMarkers.push(this.renderer.addMarker(range, "ace_selected_word")); + }, this); + }; + + this.clearSelectionHighlight = function() { + this.$selectedWordMarkers.forEach(function(marker) { + this.renderer.removeMarker(marker); + }, this); + }; + this.focus = function() { // Safari need the timeout // iOS and Firefox need it called immediately @@ -323,6 +354,7 @@ var Editor =function(renderer, session) { } this.onCursorChange(e); + this.clearSelectionHighlight(); }; this.onDocumentChangeBreakpoint = function() { diff --git a/lib/ace/mouse_handler.js b/lib/ace/mouse_handler.js index 5e836383..244fc461 100644 --- a/lib/ace/mouse_handler.js +++ b/lib/ace/mouse_handler.js @@ -146,6 +146,7 @@ var MouseHandler = function(editor) { this.onMouseDoubleClick = function(e) { this.editor.selection.selectWord(); + this.editor.highlightSelection(); this.$clickSelection = this.editor.getSelectionRange(); }; @@ -165,4 +166,4 @@ var MouseHandler = function(editor) { }).call(MouseHandler.prototype); exports.MouseHandler = MouseHandler; -}); \ No newline at end of file +}); diff --git a/lib/ace/theme/tm.css b/lib/ace/theme/tm.css index 0993335c..987901d1 100644 --- a/lib/ace/theme/tm.css +++ b/lib/ace/theme/tm.css @@ -131,6 +131,11 @@ background: rgb(232, 242, 254); } +.ace-tm .ace_marker-layer .ace_selected_word { + background: rgb(250, 250, 255); + border: 1px solid rgb(200, 200, 250); +} + .ace-tm .ace_string.ace_regex { color: rgb(255, 0, 0) -} \ No newline at end of file +} From 24e135775567fdebc5ed22b9a7fcd266c732453a Mon Sep 17 00:00:00 2001 From: Mihai Sucan Date: Sat, 12 Feb 2011 20:40:58 +0200 Subject: [PATCH 5/7] Make sure the current search needle is not lost. --- lib/ace/editor.js | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/lib/ace/editor.js b/lib/ace/editor.js index 7cc6cdb7..74a82d1e 100644 --- a/lib/ace/editor.js +++ b/lib/ace/editor.js @@ -74,7 +74,7 @@ var Editor =function(renderer, session) { this.$selectionMarker = null; this.$highlightLineMarker = null; this.$blockScrolling = 0; - this.$selectedWordMarkers = []; + this.$selectionOccurrences = []; this.$search = new Search().set({ wrap: true @@ -237,7 +237,7 @@ var Editor =function(renderer, session) { }; this.highlightSelection = function() { - if (this.$selectedWordMarkers.length) + if (this.$selectionOccurrences.length) this.clearSelectionHighlight(); var selectedRange = this.getSelectionRange(); @@ -253,15 +253,17 @@ var Editor =function(renderer, session) { this.$search.set(newOptions); var ranges = this.$search.findAll(this.session); - this.$selectedWordMarkers = []; + this.$selectionOccurrences = []; ranges.forEach(function(range) { if (!range.contains(selectedRange.start.row, selectedRange.start.column)) - this.$selectedWordMarkers.push(this.renderer.addMarker(range, "ace_selected_word")); + this.$selectionOccurrences.push(this.renderer.addMarker(range, "ace_selected_word")); }, this); + + this.$search.set(currentOptions); }; this.clearSelectionHighlight = function() { - this.$selectedWordMarkers.forEach(function(marker) { + this.$selectionOccurrences.forEach(function(marker) { this.renderer.removeMarker(marker); }, this); }; From 0c959834a867aff03ae3559b6d0cb90cfab79bda Mon Sep 17 00:00:00 2001 From: Mihai Sucan Date: Sun, 13 Feb 2011 17:07:42 +0200 Subject: [PATCH 6/7] More fixes. - Only highlight selected words. - Highlight selected words by keyboard as well, not just mouse double click. --- lib/ace/editor.js | 32 +++++++++++++++++++++++++------- lib/ace/mouse_handler.js | 1 - 2 files changed, 25 insertions(+), 8 deletions(-) diff --git a/lib/ace/editor.js b/lib/ace/editor.js index 74a82d1e..0471d6cc 100644 --- a/lib/ace/editor.js +++ b/lib/ace/editor.js @@ -23,6 +23,7 @@ * Fabian Jakobs * Irakli Gozalishvili (http://jeditoolkit.com) * Julian Viereck + * Mihai Sucan * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or @@ -240,22 +241,39 @@ var Editor =function(renderer, session) { if (this.$selectionOccurrences.length) this.clearSelectionHighlight(); - var selectedRange = this.getSelectionRange(); - if (selectedRange.isEmpty()) + var selection = this.getSelectionRange(); + if (selection.isEmpty() || selection.isMultiLine()) return; - var newOptions = {wrap:true, wholeWord: true}; - newOptions.needle = this.session.getTextRange(selectedRange); - if (!newOptions.needle) + var startOuter = selection.start.column - 1; + var endOuter = selection.end.column + 1; + var line = this.session.getLine(selection.start.row); + var lineCols = line.length - 1; + var needle = line.substring(Math.max(startOuter, 0), + Math.min(endOuter, lineCols)); + + // Make sure the outer characters are not part of the word. + if ((startOuter >= 0 && !/[^\w\d]/.test(needle.charAt(0))) || + (endOuter <= lineCols && !/[^\w\d]/.test(needle.charAt(needle.length - 1)))) return; + needle = line.substring(selection.start.column, selection.end.column); + if (!/^[\w\d]+$/.test(needle)) + return; + + var newOptions = { + wrap: true, + wholeWord: true, + needle: needle, + }; + var currentOptions = this.$search.getOptions(); this.$search.set(newOptions); var ranges = this.$search.findAll(this.session); this.$selectionOccurrences = []; ranges.forEach(function(range) { - if (!range.contains(selectedRange.start.row, selectedRange.start.column)) + if (!range.contains(selection.start.row, selection.start.column)) this.$selectionOccurrences.push(this.renderer.addMarker(range, "ace_selected_word")); }, this); @@ -356,7 +374,7 @@ var Editor =function(renderer, session) { } this.onCursorChange(e); - this.clearSelectionHighlight(); + this.highlightSelection(); }; this.onDocumentChangeBreakpoint = function() { diff --git a/lib/ace/mouse_handler.js b/lib/ace/mouse_handler.js index 244fc461..b3a16833 100644 --- a/lib/ace/mouse_handler.js +++ b/lib/ace/mouse_handler.js @@ -146,7 +146,6 @@ var MouseHandler = function(editor) { this.onMouseDoubleClick = function(e) { this.editor.selection.selectWord(); - this.editor.highlightSelection(); this.$clickSelection = this.editor.getSelectionRange(); }; From be0d9a2be7792324c5c368f08949f6c0c44617a2 Mon Sep 17 00:00:00 2001 From: Mihai Sucan Date: Mon, 14 Feb 2011 20:43:54 +0200 Subject: [PATCH 7/7] More fixes for issue 57. - move the selection highlight code to the Text mode. - store $selectionOccurrences in the editor session. - add option to toggle selection highlighting. In demo page as well. --- demo/demo.js | 4 +++ index.html | 4 +++ lib/ace/editor.js | 71 ++++++++++++-------------------------------- lib/ace/mode/text.js | 63 ++++++++++++++++++++++++++++++++++++++- 4 files changed, 89 insertions(+), 53 deletions(-) diff --git a/demo/demo.js b/demo/demo.js index 0437c78c..5b4b883f 100644 --- a/demo/demo.js +++ b/demo/demo.js @@ -257,6 +257,10 @@ exports.launch = function(env) { env.editor.renderer.setShowPrintMargin(checked); }); + bindCheckbox("highlight_selected_word", function(checked) { + env.editor.setHighlightSelectedWord(checked); + }); + function bindCheckbox(id, callback) { var el = document.getElementById(id); var onCheck = function() { diff --git a/index.html b/index.html index d4557f3b..9fa06ea9 100644 --- a/index.html +++ b/index.html @@ -108,6 +108,10 @@ + + + + diff --git a/lib/ace/editor.js b/lib/ace/editor.js index 8f712f59..ad95be22 100644 --- a/lib/ace/editor.js +++ b/lib/ace/editor.js @@ -23,7 +23,6 @@ * Fabian Jakobs * Irakli Gozalishvili (http://jeditoolkit.com) * Julian Viereck - * Mihai Sucan * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or @@ -75,7 +74,6 @@ var Editor =function(renderer, session) { this.$selectionMarker = null; this.$highlightLineMarker = null; this.$blockScrolling = 0; - this.$selectionOccurrences = []; this.$search = new Search().set({ wrap: true @@ -237,55 +235,6 @@ var Editor =function(renderer, session) { }, 10); }; - this.highlightSelection = function() { - if (this.$selectionOccurrences.length) - this.clearSelectionHighlight(); - - var selection = this.getSelectionRange(); - if (selection.isEmpty() || selection.isMultiLine()) - return; - - var startOuter = selection.start.column - 1; - var endOuter = selection.end.column + 1; - var line = this.session.getLine(selection.start.row); - var lineCols = line.length - 1; - var needle = line.substring(Math.max(startOuter, 0), - Math.min(endOuter, lineCols)); - - // Make sure the outer characters are not part of the word. - if ((startOuter >= 0 && !/[^\w\d]/.test(needle.charAt(0))) || - (endOuter <= lineCols && !/[^\w\d]/.test(needle.charAt(needle.length - 1)))) - return; - - needle = line.substring(selection.start.column, selection.end.column); - if (!/^[\w\d]+$/.test(needle)) - return; - - var newOptions = { - wrap: true, - wholeWord: true, - needle: needle - }; - - var currentOptions = this.$search.getOptions(); - this.$search.set(newOptions); - - var ranges = this.$search.findAll(this.session); - this.$selectionOccurrences = []; - ranges.forEach(function(range) { - if (!range.contains(selection.start.row, selection.start.column)) - this.$selectionOccurrences.push(this.renderer.addMarker(range, "ace_selected_word")); - }, this); - - this.$search.set(currentOptions); - }; - - this.clearSelectionHighlight = function() { - this.$selectionOccurrences.forEach(function(marker) { - this.renderer.removeMarker(marker); - }, this); - }; - this.focus = function() { // Safari need the timeout // iOS and Firefox need it called immediately @@ -374,7 +323,9 @@ var Editor =function(renderer, session) { } this.onCursorChange(e); - this.highlightSelection(); + + if (this.$highlightSelectedWord) + this.mode.highlightSelection(this); }; this.onDocumentChangeBreakpoint = function() { @@ -559,6 +510,22 @@ var Editor =function(renderer, session) { return this.$highlightActiveLine; }; + this.$highlightSelectedWord = true; + this.setHighlightSelectedWord = function(shouldHighlight) { + if (this.$highlightSelectedWord == shouldHighlight) + return; + + this.$highlightSelectedWord = shouldHighlight; + if (shouldHighlight) + this.mode.highlightSelection(this); + else + this.mode.clearSelectionHighlight(this); + }; + + this.getHighlightSelectedWord = function() { + return this.$highlightSelectedWord; + }; + this.setShowInvisibles = function(showInvisibles) { if (this.getShowInvisibles() == showInvisibles) return; diff --git a/lib/ace/mode/text.js b/lib/ace/mode/text.js index fe1c9f17..6fc68588 100644 --- a/lib/ace/mode/text.js +++ b/lib/ace/mode/text.js @@ -1,4 +1,5 @@ -/* ***** BEGIN LICENSE BLOCK ***** +/* vim:ts=4:sts=4:sw=4: + * ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Mozilla Public License Version @@ -20,6 +21,7 @@ * * Contributor(s): * Fabian Jakobs + * Mihai Sucan * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or @@ -77,6 +79,65 @@ var Mode = function() { return null; }; + this.highlightSelection = function(editor) { + var session = editor.session; + if (!session.$selectionOccurrences) + session.$selectionOccurrences = []; + + if (session.$selectionOccurrences.length) + this.clearSelectionHighlight(editor); + + var selection = editor.getSelectionRange(); + if (selection.isEmpty() || selection.isMultiLine()) + return; + + var startOuter = selection.start.column - 1; + var endOuter = selection.end.column + 1; + var line = session.getLine(selection.start.row); + var lineCols = line.length - 1; + var needle = line.substring(Math.max(startOuter, 0), + Math.min(endOuter, lineCols)); + + // Make sure the outer characters are not part of the word. + if ((startOuter >= 0 && !/[^\w\d]/.test(needle.charAt(0))) || + (endOuter <= lineCols && !/[^\w\d]/.test(needle.charAt(needle.length - 1)))) + return; + + needle = line.substring(selection.start.column, selection.end.column); + if (!/^[\w\d]+$/.test(needle)) + return; + + var newOptions = { + wrap: true, + wholeWord: true, + needle: needle + }; + + var currentOptions = editor.$search.getOptions(); + editor.$search.set(newOptions); + + var ranges = editor.$search.findAll(session); + session.$selectionOccurrences = []; + ranges.forEach(function(range) { + if (!range.contains(selection.start.row, selection.start.column)) { + var marker = editor.renderer.addMarker(range, + "ace_selected_word"); + session.$selectionOccurrences.push(marker); + } + }); + + editor.$search.set(currentOptions); + }; + + this.clearSelectionHighlight = function(editor) { + if (!editor.session.$selectionOccurrences) + return; + + editor.session.$selectionOccurrences.forEach(function(marker) { + editor.renderer.removeMarker(marker); + }); + }; + }).call(Mode.prototype); exports.Mode = Mode;