Merge branch 'master' of https://github.com/ajaxorg/ace into stationary_tooltip_option
This commit is contained in:
commit
66f615ba94
7 changed files with 749 additions and 85 deletions
|
|
@ -32,25 +32,26 @@ define(function(require, exports, module) {
|
|||
"use strict";
|
||||
|
||||
var dom = require("ace/lib/dom");
|
||||
var oop = require("ace/lib/oop");
|
||||
var event = require("ace/lib/event");
|
||||
var Range = require("ace/range").Range;
|
||||
var Tooltip = require("ace/tooltip").Tooltip;
|
||||
|
||||
var tooltipNode;
|
||||
|
||||
var TokenTooltip = function(editor) {
|
||||
function TokenTooltip (editor) {
|
||||
if (editor.tokenTooltip)
|
||||
return;
|
||||
editor.tokenTooltip = this;
|
||||
Tooltip.call(this, editor.container);
|
||||
editor.tokenTooltip = this;
|
||||
this.editor = editor;
|
||||
|
||||
editor.tooltip = tooltipNode || this.$init();
|
||||
|
||||
this.update = this.update.bind(this);
|
||||
this.onMouseMove = this.onMouseMove.bind(this);
|
||||
this.onMouseOut = this.onMouseOut.bind(this);
|
||||
event.addListener(editor.renderer.scroller, "mousemove", this.onMouseMove);
|
||||
event.addListener(editor.renderer.content, "mouseout", this.onMouseOut);
|
||||
};
|
||||
}
|
||||
|
||||
oop.inherits(TokenTooltip, Tooltip);
|
||||
|
||||
(function(){
|
||||
this.token = {};
|
||||
|
|
@ -86,15 +87,10 @@ var TokenTooltip = function(editor) {
|
|||
}
|
||||
if (!token) {
|
||||
session.removeMarker(this.marker);
|
||||
tooltipNode.style.display = "none";
|
||||
this.isOpen = false;
|
||||
this.hide();
|
||||
return;
|
||||
}
|
||||
if (!this.isOpen) {
|
||||
tooltipNode.style.display = "";
|
||||
this.isOpen = true;
|
||||
}
|
||||
|
||||
|
||||
var tokenText = token.type;
|
||||
if (token.state)
|
||||
tokenText += "|" + token.state;
|
||||
|
|
@ -102,15 +98,15 @@ var TokenTooltip = function(editor) {
|
|||
tokenText += "\n merge";
|
||||
if (token.stateTransitions)
|
||||
tokenText += "\n " + token.stateTransitions.join("\n ");
|
||||
|
||||
|
||||
if (this.tokenText != tokenText) {
|
||||
tooltipNode.textContent = tokenText;
|
||||
this.tooltipWidth = tooltipNode.offsetWidth;
|
||||
this.tooltipHeight = tooltipNode.offsetHeight;
|
||||
this.setText(tokenText);
|
||||
this.width = this.getWidth();
|
||||
this.height = this.getHeight();
|
||||
this.tokenText = tokenText;
|
||||
}
|
||||
|
||||
this.updateTooltipPosition(this.x, this.y);
|
||||
|
||||
this.show(null, this.x, this.y);
|
||||
|
||||
this.token = token;
|
||||
session.removeMarker(this.marker);
|
||||
|
|
@ -123,56 +119,34 @@ var TokenTooltip = function(editor) {
|
|||
this.y = e.clientY;
|
||||
if (this.isOpen) {
|
||||
this.lastT = e.timeStamp;
|
||||
this.updateTooltipPosition(this.x, this.y);
|
||||
this.setPosition(this.x, this.y);
|
||||
}
|
||||
if (!this.$timer)
|
||||
this.$timer = setTimeout(this.update, 100);
|
||||
};
|
||||
|
||||
|
||||
this.onMouseOut = function(e) {
|
||||
var t = e && e.relatedTarget;
|
||||
var ct = e && e.currentTarget;
|
||||
while(t && (t = t.parentNode)) {
|
||||
if (t == ct)
|
||||
return;
|
||||
}
|
||||
tooltipNode.style.display = "none";
|
||||
if (e && e.currentTarget.contains(e.relatedTarget))
|
||||
return;
|
||||
this.hide();
|
||||
this.editor.session.removeMarker(this.marker);
|
||||
this.$timer = clearTimeout(this.$timer);
|
||||
this.isOpen = false;
|
||||
};
|
||||
|
||||
this.updateTooltipPosition = function(x, y) {
|
||||
var st = tooltipNode.style;
|
||||
if (x + 10 + this.tooltipWidth > this.maxWidth)
|
||||
x = window.innerWidth - this.tooltipWidth - 10;
|
||||
if (y > window.innerHeight * 0.75 || y + 20 + this.tooltipHeight > this.maxHeight)
|
||||
y = y - this.tooltipHeight - 30;
|
||||
|
||||
st.left = x + 10 + "px";
|
||||
st.top = y + 20 + "px";
|
||||
};
|
||||
|
||||
this.$init = function() {
|
||||
tooltipNode = document.documentElement.appendChild(dom.createElement("div"));
|
||||
var st = tooltipNode.style;
|
||||
st.position = "fixed";
|
||||
st.display = "none";
|
||||
st.background = "lightyellow";
|
||||
st.borderRadius = "";
|
||||
st.border = "1px solid gray";
|
||||
st.padding = "1px";
|
||||
st.zIndex = 1000;
|
||||
st.fontFamily = "monospace";
|
||||
st.whiteSpace = "pre-line";
|
||||
return tooltipNode;
|
||||
this.setPosition = function(x, y) {
|
||||
if (x + 10 + this.width > this.maxWidth)
|
||||
x = window.innerWidth - this.width - 10;
|
||||
if (y > window.innerHeight * 0.75 || y + 20 + this.height > this.maxHeight)
|
||||
y = y - this.height - 30;
|
||||
|
||||
Tooltip.prototype.setPosition.call(this, x + 10, y + 20);
|
||||
};
|
||||
|
||||
this.destroy = function() {
|
||||
this.onMouseOut();
|
||||
event.removeListener(this.editor.renderer.scroller, "mousemove", this.onMouseMove);
|
||||
event.removeListener(this.editor.renderer.content, "mouseout", this.onMouseOut);
|
||||
delete this.editor.tokenTooltip;
|
||||
delete this.editor.tokenTooltip;
|
||||
};
|
||||
|
||||
}).call(TokenTooltip.prototype);
|
||||
|
|
@ -180,4 +154,3 @@ var TokenTooltip = function(editor) {
|
|||
exports.TokenTooltip = TokenTooltip;
|
||||
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -301,7 +301,7 @@
|
|||
background-position: center center, top left;
|
||||
}
|
||||
|
||||
.ace_gutter-tooltip {
|
||||
.ace_tooltip {
|
||||
background-color: #FFF;
|
||||
background-image: -webkit-linear-gradient(top, transparent, rgba(0, 0, 0, 0.1));
|
||||
background-image: linear-gradient(to bottom, transparent, rgba(0, 0, 0, 0.1));
|
||||
|
|
@ -309,21 +309,22 @@
|
|||
border-radius: 1px;
|
||||
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.3);
|
||||
color: black;
|
||||
display: inline-block;
|
||||
max-width: 500px;
|
||||
padding: 4px;
|
||||
display: block;
|
||||
max-width: 100%;
|
||||
padding: 3px 4px;
|
||||
position: fixed;
|
||||
z-index: 999999;
|
||||
-moz-box-sizing: border-box;
|
||||
-webkit-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
cursor: default;
|
||||
white-space: pre-line;
|
||||
white-space: pre;
|
||||
word-wrap: break-word;
|
||||
line-height: normal;
|
||||
font-style: normal;
|
||||
font-weight: normal;
|
||||
letter-spacing: normal;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.ace_folding-enabled > .ace_gutter-cell {
|
||||
|
|
|
|||
532
lib/ace/keyboard/vim_test.js
Normal file
532
lib/ace/keyboard/vim_test.js
Normal file
|
|
@ -0,0 +1,532 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Distributed under the BSD license:
|
||||
*
|
||||
* Copyright (c) 2014, Ajax.org B.V.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of Ajax.org B.V. nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
if (typeof process !== "undefined") {
|
||||
require("amd-loader");
|
||||
}
|
||||
|
||||
define(function(require, exports, module) {
|
||||
"use strict";
|
||||
|
||||
function repeat(str, times) {
|
||||
return new Array(times + 1).join(str);
|
||||
}
|
||||
|
||||
var EditSession = require("./../edit_session").EditSession,
|
||||
Editor = require("./../editor").Editor,
|
||||
UndoManager = require("./../undomanager").UndoManager,
|
||||
MockRenderer = require("./../test/mockrenderer").MockRenderer,
|
||||
assert = require("./../test/assertions"),
|
||||
keys = require("./../lib/keys"),
|
||||
vim = require("./vim"),
|
||||
editor,
|
||||
keyCodeByFuncKey = {},
|
||||
tests = {};
|
||||
|
||||
//Helper functions
|
||||
|
||||
function initKeyCodeByFuncKey() {
|
||||
for (var keyCode in keys.FUNCTION_KEYS) {
|
||||
var funcKey = keys.FUNCTION_KEYS[keyCode];
|
||||
keyCodeByFuncKey[funcKey] = keyCode;
|
||||
}
|
||||
}
|
||||
|
||||
function initEditor(docString) {
|
||||
var session = new EditSession(docString.split("\n"));
|
||||
var undoManager = new UndoManager();
|
||||
session.setUndoManager(undoManager);
|
||||
editor = new Editor(new MockRenderer(), session);
|
||||
editor.setKeyboardHandler(vim.handler);
|
||||
}
|
||||
|
||||
function sendKeys() {
|
||||
//Vim handler needs to be sent a key at a time for undo to work
|
||||
//Handle any mix of command keys and text input arguments
|
||||
for (var argInt=0; argInt<arguments.length; argInt++) {
|
||||
var arg = arguments[argInt];
|
||||
var keyMods = arg.split(/[\-]/);
|
||||
var trailingKeys = keyMods.pop();
|
||||
var hashId = 0;
|
||||
for (var keyModIndex in keyMods) {
|
||||
var keyMod = keyMods[keyModIndex];
|
||||
var lowerKeyMod = keyMod.toLowerCase();
|
||||
if (keys.KEY_MODS.hasOwnProperty(lowerKeyMod)) {
|
||||
hashId |= keys.KEY_MODS[lowerKeyMod];
|
||||
}
|
||||
}
|
||||
if (hashId === 0) {
|
||||
trailingKeys = arg;
|
||||
}
|
||||
var keyCode;
|
||||
if (keyCodeByFuncKey.hasOwnProperty(trailingKeys)) {
|
||||
keyCode = keyCodeByFuncKey[trailingKeys];
|
||||
editor.onCommandKey({}, hashId, keyCode);
|
||||
} else {
|
||||
if (hashId !== 0) {
|
||||
keyCode = trailingKeys.toUpperCase().charCodeAt(0);
|
||||
editor.onCommandKey({}, hashId, keyCode);
|
||||
} else {
|
||||
for (var i=0; i<trailingKeys.length; i++) {
|
||||
var key = trailingKeys.charAt(i);
|
||||
editor.onTextInput(key);
|
||||
editor.session.$syncInformUndoManager();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function assertContent(expectedText) {
|
||||
var actualText = editor.session.toString();
|
||||
assert.strictEqual(actualText, expectedText, "Content expected: " + expectedText + ", actual: " + actualText);
|
||||
}
|
||||
|
||||
function assertPosition(expectedRow, expectedCol) {
|
||||
var actualPosition = editor.getCursorPosition();
|
||||
var actualRow = actualPosition.row;
|
||||
var actualCol = actualPosition.column;
|
||||
assert.strictEqual(actualRow, expectedRow, "Row expected: " + expectedRow + ", actual: " + actualRow);
|
||||
assert.strictEqual(actualCol, expectedCol, "Column expected: " + expectedCol + ", actual: " + actualCol);
|
||||
}
|
||||
|
||||
function addTest(title, chapter, section, testFunction) {
|
||||
var href = "http://vimdoc.sourceforge.net/htmldoc/usr_" + chapter + ".html#" + chapter + "." + section;
|
||||
var testName;
|
||||
if (location.protocol === "file:") { //running in console mode
|
||||
testName = "test " + title + " (See " + href + ")";
|
||||
} else {
|
||||
testName = "test <a href=\"" + href + "\" target=\"_blank\">" + title + "</a>";
|
||||
}
|
||||
tests[testName] = testFunction;
|
||||
}
|
||||
|
||||
//Define the tests
|
||||
|
||||
initKeyCodeByFuncKey();
|
||||
|
||||
addTest("Insert text", "02", "2", function() {
|
||||
var text = "A very intelligent turtle\nFound programming UNIX a hurdle";
|
||||
initEditor("");
|
||||
sendKeys("i", text, "Esc");
|
||||
assertContent(text);
|
||||
sendKeys("Esc", "Esc");
|
||||
assertContent(text);
|
||||
});
|
||||
|
||||
addTest("Moving around", "02", "3", function() {
|
||||
initEditor(" k \nh l\n j ");
|
||||
sendKeys("hjj");
|
||||
assertPosition(2, 0);
|
||||
sendKeys("jll");
|
||||
assertPosition(2, 2);
|
||||
sendKeys("lkk");
|
||||
assertPosition(0, 2);
|
||||
sendKeys("khh");
|
||||
assertPosition(0, 0);
|
||||
});
|
||||
|
||||
addTest("Deleting characters", "02", "4", function() {
|
||||
var text = "A very intelligent turtle\nFound programming UNIX a hurdle";
|
||||
initEditor(text);
|
||||
sendKeys("xxxxxxx");
|
||||
assertContent(text.substring(7));
|
||||
sendKeys("iA young ", "Esc");
|
||||
assertContent("A young intelligent turtle\nFound programming UNIX a hurdle");
|
||||
sendKeys("dd");
|
||||
assertContent("Found programming UNIX a hurdle");
|
||||
sendKeys("ddiA young intelligent\nturtle", "Esc", "kJ");
|
||||
assertContent("A young intelligent turtle");
|
||||
});
|
||||
|
||||
addTest("Undo and Redo [PARTIAL]", "02", "5", function() {
|
||||
var text = "A young intelligent turtle";
|
||||
initEditor(text);
|
||||
sendKeys("ddu");
|
||||
assertContent(text);
|
||||
sendKeys("0xxxxxxx");
|
||||
assertContent(text.substring(7));
|
||||
for (var i=6; i>=0; i--) {
|
||||
sendKeys("u");
|
||||
assertContent(text.substring(i));
|
||||
}
|
||||
sendKeys("ctrl-r", "ctrl-r");
|
||||
assertContent(text.substring(2));
|
||||
text = "A very intelligent turtle";
|
||||
sendKeys("ddi", text, "Esc");
|
||||
sendKeys("0wxxxxxwwxxxxxx");
|
||||
assertContent("A intelligent ");
|
||||
/* "U" fails
|
||||
sendKeys("U");
|
||||
assertContent(text);
|
||||
sendKeys("u");
|
||||
assertContent("A intelligent ");
|
||||
*/
|
||||
});
|
||||
|
||||
addTest("Other editing commands [PARTIAL]", "02", "6", function() {
|
||||
var text = "and that's not saying much for the turtle.";
|
||||
initEditor(text);
|
||||
sendKeys("$xa!!!", "Esc");
|
||||
assertContent(text.slice(0, -1) + "!!!");
|
||||
var text1 = "A very intelligent turtle";
|
||||
var text2 = "Found programming UNIX a hurdle";
|
||||
sendKeys("ddi", text1 + "\n" + text2, "Esc");
|
||||
var text3 = "That liked using Vim";
|
||||
sendKeys("ko", text3, "Esc");
|
||||
assertContent([text1, text3, text2].join("\n"));
|
||||
sendKeys("O", "Esc");
|
||||
assertContent([text1, "", text3, text2].join("\n"));
|
||||
/* "3a!" fails
|
||||
sendKeys("3a!", "Esc");
|
||||
*/
|
||||
sendKeys("a!!!", "Esc");
|
||||
assertContent([text1, "!!!", text3, text2].join("\n"));
|
||||
sendKeys("hhh3x");
|
||||
assertContent([text1, "", text3, text2].join("\n"));
|
||||
});
|
||||
|
||||
addTest("Getting out [PARTIAL]", "02", "7", function() {
|
||||
initEditor("");
|
||||
sendKeys("ZZ");
|
||||
/*
|
||||
sendKeys("aSome text", "Esc");
|
||||
sendKeys(":q", "Return");
|
||||
sendKeys(":q!", "Return");
|
||||
|
||||
sendKeys(":e!", "Return");
|
||||
*/
|
||||
});
|
||||
|
||||
addTest("Finding help [PARTIAL]", "02", "8", function() {
|
||||
initEditor("");
|
||||
sendKeys(":help", "Return");
|
||||
sendKeys("F1");
|
||||
});
|
||||
|
||||
addTest("Word movement [PARTIAL]", "03", "1", function() {
|
||||
var text = "This is a line with example text";
|
||||
initEditor(text);
|
||||
sendKeys("www3w");
|
||||
assertPosition(0, 28);
|
||||
sendKeys("b2b");
|
||||
assertPosition(0, 10);
|
||||
sendKeys("3le");
|
||||
assertPosition(0, 18);
|
||||
/* "ge" fails
|
||||
sendKeys("2ge");
|
||||
assertPosition(0, 8);
|
||||
TODO: What iskeyword behavior is assumed for Ace?
|
||||
Need to test "b,w,ge,e,gE, B, W, E" behaviors
|
||||
sendKeys("ddaThis is-a line, with special/separated/words (and some more).", "Esc");
|
||||
sendKeys("$4b");
|
||||
assertPosition(0, 21);
|
||||
*/
|
||||
});
|
||||
|
||||
addTest("Moving to the start or end of a line [PARTIAL]", "03", "2", function() {
|
||||
var text = " This is a line with example text";
|
||||
var textLength = text.length;
|
||||
initEditor(text);
|
||||
sendKeys("$");
|
||||
assertPosition(0, 36);
|
||||
sendKeys("0");
|
||||
assertPosition(0, 0);
|
||||
/* "End" and "Home" fails
|
||||
sendKeys("End");
|
||||
assertPosition(0, 36);
|
||||
sendKeys("Home");
|
||||
assertPosition(0, 0);
|
||||
*/
|
||||
sendKeys("^");
|
||||
assertPosition(0, 5);
|
||||
sendKeys("$^");
|
||||
assertPosition(0, 5);
|
||||
sendKeys("ddaA young intelligent turtle\nFound programming UNIX a hurdle", "Esc", "k0");
|
||||
assertPosition(0, 0);
|
||||
/* <count>$ fails
|
||||
sendKeys("2$");
|
||||
assertPosition(1, 30);
|
||||
*/
|
||||
});
|
||||
|
||||
addTest("Moving to a character [PARTIAL]", "03", "3", function() {
|
||||
var text = "To err is human. To really foul up you need a computer.";
|
||||
initEditor(repeat(text, 2));
|
||||
sendKeys("fh");
|
||||
assertPosition(0, 10);
|
||||
sendKeys("3fl");
|
||||
assertPosition(0, 31);
|
||||
sendKeys("Fh");
|
||||
assertPosition(0, 10);
|
||||
sendKeys("Fh");
|
||||
assertPosition(0, 10);
|
||||
sendKeys("2tn");
|
||||
assertPosition(0, 39);
|
||||
sendKeys("Th");
|
||||
assertPosition(0, 11);
|
||||
sendKeys("tn");
|
||||
assertPosition(0, 13);
|
||||
sendKeys(";");
|
||||
assertPosition(0, 39);
|
||||
/* Problem with mockrenderer?
|
||||
sendKeys(";");
|
||||
assertPosition(0, 39);
|
||||
*/
|
||||
sendKeys(",");
|
||||
assertPosition(0, 15);
|
||||
sendKeys("0f", "Esc", "w");
|
||||
assertPosition(0, 3);
|
||||
});
|
||||
|
||||
addTest("Matching a parenthesis", "03", "4", function() {
|
||||
var text = "if (a == (b * c) / d)\nif [a == [b * c] / d]\nif {a == {b * c} / d}";
|
||||
initEditor(text);
|
||||
sendKeys("%");
|
||||
assertPosition(0, 20);
|
||||
sendKeys("%");
|
||||
assertPosition(0, 3);
|
||||
sendKeys("0j%");
|
||||
assertPosition(1, 20);
|
||||
sendKeys("%");
|
||||
assertPosition(1, 3);
|
||||
sendKeys("0j%");
|
||||
assertPosition(2, 20);
|
||||
sendKeys("%");
|
||||
assertPosition(2, 3);
|
||||
});
|
||||
|
||||
addTest("Moving to a specific line [PARTIAL]", "03", "5", function() {
|
||||
var text = "first line of a file\n" + repeat("text text text text\n", 8) + "last line of a file";
|
||||
initEditor(text);
|
||||
sendKeys("7G");
|
||||
assertPosition(6, 0);
|
||||
sendKeys("gg");
|
||||
assertPosition(0, 0);
|
||||
sendKeys("G");
|
||||
assertPosition(9, 0);
|
||||
/* <percent>% motion fails
|
||||
sendKeys("50%");
|
||||
assertPosition(4, 0);
|
||||
sendKeys("90%");
|
||||
assertPosition(8, 0);
|
||||
"H, M, L" motion supported, but mockrenderer.js has no 'getScrollBottomRow', etc.
|
||||
sendKeys("L");
|
||||
assertPosition(9, 0);
|
||||
sendKeys("M");
|
||||
assertPosition(4, 0);
|
||||
sendKeys("H");
|
||||
assertPosition(0, 0);
|
||||
*/
|
||||
});
|
||||
|
||||
addTest("Telling where you are [PARTIAL]", "03", "6", function() {
|
||||
// Ctrl-G, :set commands not implemented?
|
||||
});
|
||||
|
||||
addTest("Scrolling around [PARTIAL]", "03", "7", function() {
|
||||
/* Ctrl-D, Ctrl-U, Ctrl-E, Ctrl-Y, zz, zt, zb cannot be tested with mockrenderer
|
||||
var text = repeat("some text\n", 4) + "\n123456\n7890\n" + repeat("\nexample", 4);
|
||||
initEditor(text);
|
||||
sendKeys("Ctrl-D");
|
||||
*/
|
||||
});
|
||||
|
||||
addTest("Simple searches [PARTIAL]", "03", "8", function() {
|
||||
var text = repeat("To find the word #include\n", 10);
|
||||
initEditor(text);
|
||||
/* Search fails, (is a command line really necessary for this to work?
|
||||
sendKeys("/include", "Return");
|
||||
assertPosition(0, 18);
|
||||
sendKeys("/#include", "Return");
|
||||
assertPosition(1, 17);
|
||||
sendKeys("nnn");
|
||||
assertPosition(4, 17);
|
||||
sendKeys("3n");
|
||||
assertPosition(7, 17);
|
||||
sendKeys("?word", "Return");
|
||||
assertPosition(7, 12);
|
||||
sendKeys("N");
|
||||
assertPosition(8, 12);
|
||||
sendKeys("/#include", "Return");
|
||||
assertPosition(8, 17);
|
||||
sendKeys("N");
|
||||
assertPosition(7, 17);
|
||||
//Skipping ':set ignorecase' and ':set noignorecase'
|
||||
//Skipping search history
|
||||
//TODO additional search tests
|
||||
*" and "#" searches fail, no getPixelPosition in mockrenderer
|
||||
sendKeys("gg*");
|
||||
assertPosition(1, 5);
|
||||
*/
|
||||
});
|
||||
|
||||
addTest("Simple search patterns [PARTIAL]", "03", "9", function() {
|
||||
});
|
||||
|
||||
addTest("Using marks [PARTIAL]", "03", "10", function() {
|
||||
/* '', ``, Ctrl-O, Ctrl-I fail
|
||||
var text1 = "example text\n"
|
||||
var text2 = "line 33 text\n"
|
||||
var text3 = "There you are\n"
|
||||
var text = repeat(text1, 32) + text2 + repeat(text1, 2) + text3 + text1;
|
||||
initEditor(text);
|
||||
sendKeys("G");
|
||||
sendKeys("``");
|
||||
assertPosition(0, 0);
|
||||
sendKeys("``");
|
||||
assertPosition(37, 0);
|
||||
sendKeys("10k``");
|
||||
assertPosition(0, 0);
|
||||
sendKeys("33G");
|
||||
assertPosition(33, 0);
|
||||
sendKeys("/^The");
|
||||
assertPosition((36, 0);
|
||||
sendKeys("Ctrl-O");
|
||||
assertPosition(33, 0);
|
||||
sendKeys("Ctrl-O");
|
||||
assertPosition(0, 0);
|
||||
sendKeys("Ctrl-I");
|
||||
assertPosition(33, 0);
|
||||
sendKeys("Ctrl-I");
|
||||
assertPosition(36, 0);
|
||||
sendKeys(":0$msG$me's");
|
||||
assertPosition(0, 0);
|
||||
sendKeys("`s");
|
||||
assertPosition(0, 11);
|
||||
sendKeys("'e");
|
||||
assertPosition(36, 0);
|
||||
sendKeys("`e"):
|
||||
assertPosition(36, 11);
|
||||
*/
|
||||
});
|
||||
|
||||
addTest("Operators and motions [PARTIAL]", "04", "1", function() {
|
||||
initEditor("To err is human. To really foul up you need a computer.");
|
||||
sendKeys("5wd4w");
|
||||
assertContent("To err is human. you need a computer.");
|
||||
/* "d<count>e" fails
|
||||
sendKeys("d2e");
|
||||
assertContent("To err is human. a computer.");
|
||||
|
||||
sendKeys("2hd$");
|
||||
assertContent("To err is human");
|
||||
*/
|
||||
});
|
||||
|
||||
addTest("Changing text [PARTIAL]", "04", "2", function() {
|
||||
initEditor("To err is human");
|
||||
/*
|
||||
// "c<count>w" fails
|
||||
// sendKeys("wc2wbe", "Esc");
|
||||
// assertContent("To be human");
|
||||
sendKeys("uccabc def", "Esc");
|
||||
assertContent("abc def");
|
||||
sendKeys("0c$123", "Esc");
|
||||
assertContent("123");
|
||||
sendKeys("hx");
|
||||
assertContent("13");
|
||||
sendKeys("X");
|
||||
assertContent("3");
|
||||
sendKeys("a 2 1", "Esc", "0wD");
|
||||
assertContent("3 ");
|
||||
sendKeys("a2 1", "Esc", "0wC4 5", "Esc");
|
||||
assertContent("3 4 5");
|
||||
sendKeys("0ws6", "Esc");
|
||||
assertContent("3 6 5");
|
||||
sendKeys("S1 3 2", "Esc");
|
||||
assertContent("1 3 2");
|
||||
sendKeys("$a4 6 5", "Esc", "03d2w");
|
||||
assertContent("");
|
||||
sendKeys("athere is somerhing grong here", "Esc", "0rTww4lrtwrw");
|
||||
assertContent("There is something wrong here");
|
||||
sendKeys("03w5rx");
|
||||
assertContent("There is something xxxxx here");
|
||||
// "r<Return>" fails - also replaces trailing space
|
||||
sendKeys("r", "Return");
|
||||
assertContent("There is something xxxx\n here");
|
||||
//TODO - 4r<Return>
|
||||
*/
|
||||
});
|
||||
|
||||
addTest("Repeating a change [PARTIAL]", "04", "3", function() {
|
||||
/*
|
||||
initEditor("To <B>generate</B> a table of <B>contents");
|
||||
sendKeys("f<df>f<.f<."); //strangeness after this
|
||||
assertContent("To generate a table of contents");;
|
||||
sendKeys("dd");
|
||||
assertContent("");
|
||||
sendKeys("Esc", "Esc");
|
||||
sendKeys("afind");
|
||||
var text = "find the first \"four\"\n" +
|
||||
"change the word to \"five\"\n" +
|
||||
"find the next \"four\"\n" +
|
||||
"repeat the change to \"five\"\n" +
|
||||
"find the next \"four\"\n" +
|
||||
"repeat the change\n" +
|
||||
"etc.";
|
||||
sendKeys(text);
|
||||
assertContent(text);
|
||||
sendKeys("Esc");
|
||||
sendKeys("0");
|
||||
// search doesn't work with mockrenderer
|
||||
sendKeys("/four", "<Return>", "cwfive", "Esc", "n.n.");
|
||||
text.replace(/four/g, "five");
|
||||
assertContent(text);
|
||||
*/
|
||||
});
|
||||
|
||||
addTest("Visual mode [PARTIAL]", "04", "4", function() {
|
||||
});
|
||||
|
||||
addTest("Moving text [PARTIAL]", "04", "5", function() {
|
||||
});
|
||||
|
||||
addTest("Copying text [PARTIAL]", "04", "6", function() {
|
||||
});
|
||||
|
||||
addTest("Using the clipboard [PARTIAL]", "04", "7", function() {
|
||||
});
|
||||
|
||||
addTest("Text objects [PARTIAL]", "04", "8", function() {
|
||||
});
|
||||
|
||||
addTest("Replace mode [PARTIAL]", "04", "9", function() {
|
||||
});
|
||||
|
||||
tests.name = "vim_test.js";
|
||||
|
||||
module.exports = tests;
|
||||
|
||||
});
|
||||
|
||||
if (typeof module !== "undefined" && module === require.main) {
|
||||
require("asyncjs").test.testcase(module.exports).exec();
|
||||
}
|
||||
|
|
@ -31,11 +31,14 @@
|
|||
define(function(require, exports, module) {
|
||||
"use strict";
|
||||
var dom = require("../lib/dom");
|
||||
var oop = require("../lib/oop");
|
||||
var event = require("../lib/event");
|
||||
var Tooltip = require("../tooltip").Tooltip;
|
||||
|
||||
function GutterHandler(mouseHandler) {
|
||||
var editor = mouseHandler.editor;
|
||||
var gutter = editor.renderer.$gutterLayer;
|
||||
var tooltip = new GutterTooltip(editor.container);
|
||||
|
||||
mouseHandler.editor.setDefaultHandler("guttermousedown", function(e) {
|
||||
if (!editor.isFocused() || e.getButton() != 0)
|
||||
|
|
@ -63,18 +66,9 @@ function GutterHandler(mouseHandler) {
|
|||
});
|
||||
|
||||
|
||||
var tooltipTimeout, mouseEvent, tooltip, tooltipAnnotation;
|
||||
function createTooltip() {
|
||||
tooltip = dom.createElement("div");
|
||||
tooltip.className = "ace_gutter-tooltip";
|
||||
tooltip.style.display = "none";
|
||||
editor.container.appendChild(tooltip);
|
||||
}
|
||||
var tooltipTimeout, mouseEvent, tooltipAnnotation;
|
||||
|
||||
function showTooltip() {
|
||||
if (!tooltip) {
|
||||
createTooltip();
|
||||
}
|
||||
var row = mouseEvent.getDocumentPosition().row;
|
||||
var annotation = gutter.$annotations[row];
|
||||
if (!annotation)
|
||||
|
|
@ -92,8 +86,8 @@ function GutterHandler(mouseHandler) {
|
|||
return;
|
||||
tooltipAnnotation = annotation.text.join("<br/>");
|
||||
|
||||
tooltip.style.display = "block";
|
||||
tooltip.innerHTML = tooltipAnnotation;
|
||||
tooltip.setHtml(tooltipAnnotation);
|
||||
tooltip.show();
|
||||
editor.on("mousewheel", hideTooltip);
|
||||
|
||||
if (mouseHandler.$tooltipFollowsMouse) {
|
||||
|
|
@ -112,23 +106,14 @@ function GutterHandler(mouseHandler) {
|
|||
if (tooltipTimeout)
|
||||
tooltipTimeout = clearTimeout(tooltipTimeout);
|
||||
if (tooltipAnnotation) {
|
||||
tooltip.style.display = "none";
|
||||
tooltip.hide();
|
||||
tooltipAnnotation = null;
|
||||
editor.removeEventListener("mousewheel", hideTooltip);
|
||||
}
|
||||
}
|
||||
|
||||
function moveTooltip(e) {
|
||||
var rect = editor.renderer.$gutter.getBoundingClientRect();
|
||||
tooltip.style.left = e.x + 15 + "px";
|
||||
if (e.y + 3 * editor.renderer.lineHeight + 15 < rect.bottom) {
|
||||
tooltip.style.bottom = "";
|
||||
tooltip.style.top = e.y + 15 + "px";
|
||||
} else {
|
||||
tooltip.style.top = "";
|
||||
var innerHeight = window.innerHeight || document.documentElement.clientHeight;
|
||||
tooltip.style.bottom = innerHeight - e.y + 5 + "px";
|
||||
}
|
||||
tooltip.setPosition(e.x, e.y);
|
||||
}
|
||||
|
||||
mouseHandler.editor.setDefaultHandler("guttermousemove", function(e) {
|
||||
|
|
@ -165,6 +150,33 @@ function GutterHandler(mouseHandler) {
|
|||
editor.on("changeSession", hideTooltip);
|
||||
}
|
||||
|
||||
function GutterTooltip(parentNode) {
|
||||
Tooltip.call(this, parentNode);
|
||||
}
|
||||
|
||||
oop.inherits(GutterTooltip, Tooltip);
|
||||
|
||||
(function(){
|
||||
this.setPosition = function(x, y) {
|
||||
var windowWidth = window.innerWidth || document.documentElement.clientWidth;
|
||||
var windowHeight = window.innerHeight || document.documentElement.clientHeight;
|
||||
var width = this.getWidth();
|
||||
var height = this.getHeight();
|
||||
x += 15;
|
||||
y += 15;
|
||||
if (x + width > windowWidth) {
|
||||
x -= (x + width) - windowWidth;
|
||||
}
|
||||
if (y + height > windowHeight) {
|
||||
y -= 20 + height;
|
||||
}
|
||||
Tooltip.prototype.setPosition.call(this, x, y);
|
||||
};
|
||||
|
||||
}).call(GutterTooltip.prototype);
|
||||
|
||||
|
||||
|
||||
exports.GutterHandler = GutterHandler;
|
||||
|
||||
});
|
||||
|
|
|
|||
|
|
@ -235,8 +235,15 @@ function DefaultHandlers(mouseHandler) {
|
|||
};
|
||||
|
||||
this.onMouseWheel = function(ev) {
|
||||
if (ev.getShiftKey() || ev.getAccelKey())
|
||||
if (ev.getAccelKey())
|
||||
return;
|
||||
|
||||
//shift wheel to horiz scroll
|
||||
if (ev.getShiftKey() && ev.wheelY && !ev.wheelX) {
|
||||
ev.wheelX = ev.wheelY;
|
||||
ev.wheelY = 0;
|
||||
}
|
||||
|
||||
var t = ev.domEvent.timeStamp;
|
||||
var dt = t - (this.$lastScrollTime||0);
|
||||
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ var testNames = [
|
|||
"ace/incremental_search_test",
|
||||
"ace/keyboard/emacs_test",
|
||||
"ace/keyboard/keybinding_test",
|
||||
"ace/keyboard/vim_test",
|
||||
"ace/layer/text_test",
|
||||
"ace/lib/event_emitter_test",
|
||||
"ace/mode/coffee/parser_test",
|
||||
|
|
|
|||
138
lib/ace/tooltip.js
Normal file
138
lib/ace/tooltip.js
Normal file
|
|
@ -0,0 +1,138 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Distributed under the BSD license:
|
||||
*
|
||||
* Copyright (c) 2010, Ajax.org B.V.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of Ajax.org B.V. nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
define(function(require, exports, module) {
|
||||
"use strict";
|
||||
|
||||
var oop = require("./lib/oop");
|
||||
var dom = require("./lib/dom");
|
||||
|
||||
/**
|
||||
* @class Tooltip
|
||||
**/
|
||||
|
||||
/**
|
||||
* @param {Element} parentNode
|
||||
*
|
||||
* @constructor
|
||||
**/
|
||||
function Tooltip (parentNode) {
|
||||
this.isOpen = false;
|
||||
this.$element = null;
|
||||
this.$parentNode = parentNode;
|
||||
}
|
||||
|
||||
(function() {
|
||||
this.$init = function() {
|
||||
this.$element = dom.createElement("div");
|
||||
this.$element.className = "ace_tooltip";
|
||||
this.$element.style.display = "none";
|
||||
this.$parentNode.appendChild(this.$element);
|
||||
return this.$element;
|
||||
};
|
||||
|
||||
/**
|
||||
* @returns {Element}
|
||||
**/
|
||||
this.getElement = function() {
|
||||
return this.$element || this.$init();
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {String} text
|
||||
**/
|
||||
this.setText = function(text) {
|
||||
dom.setInnerText(this.getElement(), text);
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {String} html
|
||||
**/
|
||||
this.setHtml = function(html) {
|
||||
this.getElement().innerHTML = html;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {Number} x
|
||||
* @param {Number} y
|
||||
**/
|
||||
this.setPosition = function(x, y) {
|
||||
this.getElement().style.left = x + "px";
|
||||
this.getElement().style.top = y + "px";
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {String} className
|
||||
**/
|
||||
this.setClassName = function(className) {
|
||||
dom.addCssClass(this.getElement(), className);
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {String} text
|
||||
* @param {Number} x
|
||||
* @param {Number} y
|
||||
**/
|
||||
this.show = function(text, x, y) {
|
||||
if (text != null)
|
||||
this.setText(text);
|
||||
if (x != null && y != null)
|
||||
this.setPosition(x, y);
|
||||
if (!this.isOpen) {
|
||||
this.getElement().style.display = "block";
|
||||
this.isOpen = true;
|
||||
}
|
||||
};
|
||||
|
||||
this.hide = function() {
|
||||
if (this.isOpen) {
|
||||
this.getElement().style.display = "none";
|
||||
this.isOpen = false;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @returns {Number}
|
||||
**/
|
||||
this.getHeight = function() {
|
||||
return this.getElement().offsetHeight;
|
||||
};
|
||||
|
||||
/**
|
||||
* @returns {Number}
|
||||
**/
|
||||
this.getWidth = function() {
|
||||
return this.getElement().offsetWidth;
|
||||
};
|
||||
|
||||
}).call(Tooltip.prototype);
|
||||
|
||||
exports.Tooltip = Tooltip;
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue