mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-22 17:55:50 +00:00
Bug 1578283 - Don't scroll jsterm viewport when inserting a tab character. r=Honza.
When we wanted to insert a string in the webconsole input, we were setting the input value, and setting the cursor manually. But since the editor setCursor function is calling alignLine, there could be cases where the editor scroll position would jump, feeling awkward for the user. It turns out we can simplify this code a lot since codeMirror provides a replaceRange function, which is a perfect replacement for what we were using, without having to manage the cursor position. The only downside to that is that inserting characters this way *does* fire a `changes` event, that we are listening to in the JsTerm to request autocompletion (which we don't need as we only insert characters when accepting a completion or adding a tab). To mitigate that, we pass a specific jsterm origin string to replaceRange, which let's us discriminate in the changes event listener if those changes originate from jsterm only actions. A test is added to ensure this works as expected (the test was failing without the fix). Differential Revision: https://phabricator.services.mozilla.com/D44466 --HG-- extra : moz-landing-system : lando
This commit is contained in:
parent
d4fab048af
commit
010f6b2666
@ -65,6 +65,8 @@ const {
|
||||
HISTORY_FORWARD,
|
||||
} = require("devtools/client/webconsole/constants");
|
||||
|
||||
const JSTERM_CODEMIRROR_ORIGIN = "jsterm";
|
||||
|
||||
/**
|
||||
* Create a JSTerminal (a JavaScript command line). This is attached to an
|
||||
* existing HeadsUpDisplay (a Web Console instance). This code is responsible
|
||||
@ -645,10 +647,20 @@ class JSTerm extends Component {
|
||||
/**
|
||||
* The editor "changes" event handler.
|
||||
*/
|
||||
_onEditorChanges() {
|
||||
_onEditorChanges(cm, changes) {
|
||||
const value = this._getValue();
|
||||
|
||||
if (this.lastInputValue !== value) {
|
||||
if (this.props.autocomplete || this.autocompletePopup.isOpen) {
|
||||
// We don't autocomplete if the changes were made by JsTerm (e.g. autocomplete was
|
||||
// accepted).
|
||||
const isJsTermChangeOnly = changes.every(
|
||||
({ origin }) => origin === JSTERM_CODEMIRROR_ORIGIN
|
||||
);
|
||||
|
||||
if (
|
||||
!isJsTermChangeOnly &&
|
||||
(this.props.autocomplete || this.autocompletePopup.isOpen)
|
||||
) {
|
||||
this.autocompleteUpdate();
|
||||
}
|
||||
this.lastInputValue = value;
|
||||
@ -944,27 +956,15 @@ class JSTerm extends Component {
|
||||
return;
|
||||
}
|
||||
|
||||
const value = this._getValue();
|
||||
let prefix = this.getInputValueBeforeCursor();
|
||||
const suffix = value.replace(prefix, "");
|
||||
const cursor = this.editor.getCursor();
|
||||
const from = {
|
||||
line: cursor.line,
|
||||
ch: cursor.ch - numberOfCharsToReplaceCharsBeforeCursor,
|
||||
};
|
||||
|
||||
if (numberOfCharsToReplaceCharsBeforeCursor) {
|
||||
prefix = prefix.substring(
|
||||
0,
|
||||
prefix.length - numberOfCharsToReplaceCharsBeforeCursor
|
||||
);
|
||||
}
|
||||
|
||||
// We need to retrieve the cursor before setting the new value.
|
||||
const { line, ch } = this.editor.getCursor();
|
||||
|
||||
this._setValue(prefix + str + suffix);
|
||||
|
||||
// Set the cursor on the same line it was already at, after the autocompleted text
|
||||
this.editor.setCursor({
|
||||
line,
|
||||
ch: ch + str.length - numberOfCharsToReplaceCharsBeforeCursor,
|
||||
});
|
||||
this.editor
|
||||
.getDoc()
|
||||
.replaceRange(str, from, cursor, JSTERM_CODEMIRROR_ORIGIN);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -262,6 +262,7 @@ skip-if = (os == "win" && processor == "aarch64") # disabled on aarch64 due to 1
|
||||
[browser_jsterm_history_arrow_keys.js]
|
||||
[browser_jsterm_history_nav.js]
|
||||
[browser_jsterm_history_persist.js]
|
||||
[browser_jsterm_insert_tab_when_overflows_no_scroll.js]
|
||||
[browser_jsterm_inspect.js]
|
||||
[browser_jsterm_inspect_panels.js]
|
||||
[browser_jsterm_instance_of.js]
|
||||
|
@ -0,0 +1,41 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
// Check that when the input overflows, inserting a tab doesn't not impact the
|
||||
// scroll position. See Bug 1578283.
|
||||
|
||||
"use strict";
|
||||
|
||||
const TEST_URI = "data:text/html,<meta charset=utf8>";
|
||||
|
||||
add_task(async function() {
|
||||
const hud = await openNewTabAndConsole(TEST_URI);
|
||||
const cmScroller = hud.ui.outputNode.querySelector(".CodeMirror-scroll");
|
||||
|
||||
info("Fill in the input with a hundred lines to make it overflow");
|
||||
await setInputValue(hud, "x;\n".repeat(100));
|
||||
|
||||
ok(hasVerticalOverflow(cmScroller), "input overflows");
|
||||
|
||||
info("Put the cursor at the very beginning");
|
||||
hud.jsterm.editor.setCursor({
|
||||
line: 0,
|
||||
ch: 0,
|
||||
});
|
||||
is(cmScroller.scrollTop, 0, "input is scrolled all the way up");
|
||||
|
||||
info("Move the cursor one line down and hit Tab");
|
||||
EventUtils.synthesizeKey("KEY_ArrowDown");
|
||||
EventUtils.synthesizeKey("KEY_Tab");
|
||||
checkInputValueAndCursorPosition(
|
||||
hud,
|
||||
`x;\n\t|x;\n${"x;\n".repeat(98)}`,
|
||||
"a tab char was added at the start of the second line after hitting Tab"
|
||||
);
|
||||
is(
|
||||
cmScroller.scrollTop,
|
||||
0,
|
||||
"Scroll position wasn't affected by new char addition"
|
||||
);
|
||||
});
|
Loading…
Reference in New Issue
Block a user