Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions demo/kitchen-sink/demo.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ var saveOption = util.saveOption;
require("ace/ext/elastic_tabstops_lite");
require("ace/incremental_search");

require("ace/ext/whitespaces_in_selection");

var TokenTooltip = require("./token_tooltip").TokenTooltip;
require("ace/config").defineOptions(Editor.prototype, "editor", {
showTokenInfo: {
Expand Down Expand Up @@ -485,6 +487,10 @@ optionsPanel.add({
position: 3000,
path: "useAceLinters"
},
"Show whitespaces in selection": {
position: 3100,
path: "showWhitespacesInSelection"
},
"Show Textarea Position": devUtil.textPositionDebugger,
"Text Input Debugger": devUtil.textInputDebugger,
}
Expand Down
10 changes: 10 additions & 0 deletions src/ext/whitespaces_in_selection-css.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
module.exports = `
.ace_whitespaces_in_selection {
color: rgba(0,0,0,0.29);
}

.ace_dark .ace_whitespaces_in_selection {
color: rgba(187, 181, 181, 0.5);
}
`;

61 changes: 61 additions & 0 deletions src/ext/whitespaces_in_selection.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/**
* ## Show whitespaces in the current selection
*
* This extension adds a configuration option `showWhitespacesInSelection` to the editor
* that highlights whitespaces within the current selection. When enabled, it adds a
* marker to the selection that makes whitespaces visible.
*/

"use strict";

require("../layer/text_markers");
const Editor = require("../editor").Editor;
const config = require("../config");
const dom = require("../lib/dom");
const whitespacesCss = require("./whitespaces_in_selection-css");
dom.importCssString(whitespacesCss, "ace_whitespaces_in_selection", false);

config.defineOptions(Editor.prototype, "editor", {
showWhitespacesInSelection: {
set: function(val) {
this.$showWhitespacesInSelection = val;

if (val) {
if (!this.$boundChangeSelectionForWhitespace) {
this.$boundChangeSelectionForWhitespace = $onChangeSelectionForWhitespace.bind(this);
}
this.on("changeSelection", this.$boundChangeSelectionForWhitespace);
} else {
this.off("changeSelection", this.$boundChangeSelectionForWhitespace);

if (this.session && this.session.$invisibleMarkerId) {
this.session.removeTextMarker(this.session.$invisibleMarkerId);
this.session.$invisibleMarkerId = null;
}

this.$boundChangeSelectionForWhitespace = null;
}
},
get: function() {
return this.$showWhitespacesInSelection;
},
initialValue: false
}
});

function $onChangeSelectionForWhitespace() {
let invisibleMarkerId = this.session.$invisibleMarkerId;
if (invisibleMarkerId) {
this.session.removeTextMarker(invisibleMarkerId);
this.session.$invisibleMarkerId = null;
}

var currentRange = this.selection.getRange();
if (!currentRange.isEmpty()) {
this.session.$invisibleMarkerId = this.session.addTextMarker(
currentRange,
"ace_whitespaces_in_selection",
"invisible"
);
}
}
54 changes: 54 additions & 0 deletions src/ext/whitespaces_in_selection_test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
"use strict";

require("../test/mockdom");
var assert = require("assert");
var EditSession = require("../edit_session").EditSession;
var Editor = require("../editor").Editor;
var MockRenderer = require("../test/mockrenderer").MockRenderer;
require("./whitespaces_in_selection");

module.exports = {
setUp: function() {
this.session = new EditSession("hello world\n with spaces");
this.editor = new Editor(new MockRenderer(), this.session);
},

tearDown: function() {
this.session.destroy();
},

"test: turning on extension": function() {
assert.equal(this.editor.getOption("showWhitespacesInSelection"), false);
this.editor.setOption("showWhitespacesInSelection", true);
assert.equal(this.editor.getOption("showWhitespacesInSelection"), true);

assert.ok(this.editor.$boundChangeSelectionForWhitespace);
},

"test: turning off extension": function() {
this.editor.setOption("showWhitespacesInSelection", true);
assert.equal(this.editor.getOption("showWhitespacesInSelection"), true);
this.editor.selection.setRange({start: {row: 0, column: 0}, end: {row: 0, column: 5}});

this.editor.setOption("showWhitespacesInSelection", false);
assert.equal(this.editor.getOption("showWhitespacesInSelection"), false);

assert.equal(this.editor.$boundChangeSelectionForWhitespace, null);
},

"test: marker present after selection": function() {
this.editor.setOption("showWhitespacesInSelection", true);

this.editor.selection.setRange({start: {row: 0, column: 0}, end: {row: 0, column: 5}});

assert.ok(this.session.$invisibleMarkerId);

var markers = this.session.getTextMarkers();
assert.ok(markers[this.session.$invisibleMarkerId]);
assert.equal(markers[this.session.$invisibleMarkerId].className, "ace_whitespaces_in_selection");
}
};

if (typeof module !== "undefined" && module === require.main) {
require("asyncjs").test.testcase(module.exports).exec();
}
4 changes: 3 additions & 1 deletion src/layer/text.js
Original file line number Diff line number Diff line change
Expand Up @@ -449,7 +449,9 @@ class Text {
return value.substr(cols);
} else if (value[0] == "\t") {
for (var i=0; i<cols; i++) {
parent.appendChild(this.$tabStrings["\t"].cloneNode(true));
const tabSpan = this.$tabStrings["\t"].cloneNode(true);
tabSpan["charCount"] = 1;
parent.appendChild(tabSpan);
}
this.$highlightIndentGuide();
return value.substr(cols);
Expand Down
Loading