2019-04-11 10:37:40 +02:00
|
|
|
import { determineAllPossibilitiesForTabCompletion } from "./Terminal/determineAllPossibilitiesForTabCompletion";
|
|
|
|
import { tabCompletion } from "./Terminal/tabCompletion";
|
2019-04-10 08:07:12 +02:00
|
|
|
|
2019-04-11 10:37:40 +02:00
|
|
|
import { CONSTANTS } from "./Constants";
|
|
|
|
import { Engine } from "./engine";
|
|
|
|
import { FconfSettings } from "./Fconf/FconfSettings";
|
|
|
|
import { Player } from "./Player";
|
|
|
|
import { setTimeoutRef } from "./utils/SetTimeoutRef";
|
|
|
|
import { Page, routing } from "./ui/navigationTracking";
|
|
|
|
import { KEY } from "../utils/helpers/keyCodes";
|
|
|
|
import { getTimestamp } from "../utils/helpers/getTimestamp";
|
2021-09-16 01:50:44 +02:00
|
|
|
import { post } from "./ui/postToTerminal";
|
|
|
|
|
|
|
|
import { Terminal as TTerminal } from "./Terminal/Terminal";
|
2016-12-21 19:36:42 +01:00
|
|
|
|
2021-09-16 02:06:48 +02:00
|
|
|
const NewTerminal = new TTerminal();
|
|
|
|
|
2019-04-11 10:37:40 +02:00
|
|
|
import autosize from "autosize";
|
2018-03-12 20:39:04 +01:00
|
|
|
|
2021-09-10 22:08:58 +02:00
|
|
|
function postVersion() {
|
2021-09-05 01:09:30 +02:00
|
|
|
post("Bitburner v" + CONSTANTS.Version);
|
2016-10-20 23:11:01 +02:00
|
|
|
}
|
|
|
|
|
2021-03-24 02:30:15 +01:00
|
|
|
function getTerminalInput() {
|
2021-09-05 01:09:30 +02:00
|
|
|
return document.getElementById("terminal-input-text-box").value;
|
2021-03-24 02:30:15 +01:00
|
|
|
}
|
|
|
|
|
2019-04-10 08:07:12 +02:00
|
|
|
// Defines key commands in terminal
|
2021-09-05 01:09:30 +02:00
|
|
|
$(document).keydown(function (event) {
|
|
|
|
// Terminal
|
|
|
|
if (routing.isOn(Page.Terminal)) {
|
|
|
|
var terminalInput = document.getElementById("terminal-input-text-box");
|
2021-09-16 02:06:48 +02:00
|
|
|
if (terminalInput != null && !event.ctrlKey && !event.shiftKey && !NewTerminal.contractOpen) {
|
2021-09-05 01:09:30 +02:00
|
|
|
terminalInput.focus();
|
|
|
|
}
|
2018-07-31 02:16:39 +02:00
|
|
|
|
2021-09-05 01:09:30 +02:00
|
|
|
if (event.keyCode === KEY.ENTER) {
|
|
|
|
event.preventDefault(); // Prevent newline from being entered in Script Editor
|
|
|
|
const command = getTerminalInput();
|
2021-09-16 02:06:48 +02:00
|
|
|
const dir = NewTerminal.currDir;
|
2021-09-05 01:09:30 +02:00
|
|
|
post(
|
|
|
|
"<span class='prompt'>[" +
|
|
|
|
(FconfSettings.ENABLE_TIMESTAMPS ? getTimestamp() + " " : "") +
|
|
|
|
Player.getCurrentServer().hostname +
|
|
|
|
` ~${dir}]></span> ${command}`,
|
|
|
|
);
|
|
|
|
|
|
|
|
if (command.length > 0) {
|
|
|
|
Terminal.resetTerminalInput(); // Clear input first
|
2021-09-16 02:06:48 +02:00
|
|
|
NewTerminal.executeCommands(Engine, Player, command);
|
2021-09-05 01:09:30 +02:00
|
|
|
}
|
|
|
|
}
|
2017-07-25 03:06:40 +02:00
|
|
|
|
2021-09-05 01:09:30 +02:00
|
|
|
if (event.keyCode === KEY.C && event.ctrlKey) {
|
|
|
|
if (Engine._actionInProgress) {
|
|
|
|
// Cancel action
|
|
|
|
post("Cancelling...");
|
|
|
|
Engine._actionInProgress = false;
|
2021-09-16 02:06:48 +02:00
|
|
|
NewTerminal.finishAction(true);
|
2021-09-05 01:09:30 +02:00
|
|
|
} else if (FconfSettings.ENABLE_BASH_HOTKEYS) {
|
|
|
|
// Dont prevent default so it still copies
|
|
|
|
Terminal.resetTerminalInput(); // Clear Terminal
|
|
|
|
}
|
|
|
|
}
|
2017-07-25 03:06:40 +02:00
|
|
|
|
2021-09-05 01:09:30 +02:00
|
|
|
if (event.keyCode === KEY.L && event.ctrlKey) {
|
|
|
|
event.preventDefault();
|
2021-09-16 02:06:48 +02:00
|
|
|
NewTerminal.executeCommands(Engine, Player, "clear"); // Clear screen
|
2021-09-05 01:09:30 +02:00
|
|
|
}
|
2018-03-12 20:39:04 +01:00
|
|
|
|
2021-09-05 01:09:30 +02:00
|
|
|
// Ctrl p same as up arrow
|
|
|
|
// Ctrl n same as down arrow
|
|
|
|
|
|
|
|
if (
|
|
|
|
event.keyCode === KEY.UPARROW ||
|
2021-09-09 05:47:34 +02:00
|
|
|
(FconfSettings.ENABLE_BASH_HOTKEYS && event.keyCode === KEY.P && event.ctrlKey)
|
2021-09-05 01:09:30 +02:00
|
|
|
) {
|
|
|
|
if (FconfSettings.ENABLE_BASH_HOTKEYS) {
|
|
|
|
event.preventDefault();
|
|
|
|
}
|
|
|
|
// Cycle through past commands
|
|
|
|
if (terminalInput == null) {
|
|
|
|
return;
|
|
|
|
}
|
2021-09-16 02:06:48 +02:00
|
|
|
var i = NewTerminal.commandHistoryIndex;
|
|
|
|
var len = NewTerminal.commandHistory.length;
|
2021-09-05 01:09:30 +02:00
|
|
|
|
|
|
|
if (len == 0) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (i < 0 || i > len) {
|
2021-09-16 02:06:48 +02:00
|
|
|
NewTerminal.commandHistoryIndex = len;
|
2021-09-05 01:09:30 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (i != 0) {
|
2021-09-16 02:06:48 +02:00
|
|
|
--NewTerminal.commandHistoryIndex;
|
2021-09-05 01:09:30 +02:00
|
|
|
}
|
2021-09-16 02:06:48 +02:00
|
|
|
var prevCommand = NewTerminal.commandHistory[NewTerminal.commandHistoryIndex];
|
2021-09-05 01:09:30 +02:00
|
|
|
terminalInput.value = prevCommand;
|
|
|
|
setTimeoutRef(function () {
|
|
|
|
terminalInput.selectionStart = terminalInput.selectionEnd = 10000;
|
|
|
|
}, 10);
|
|
|
|
}
|
2018-03-12 20:39:04 +01:00
|
|
|
|
2021-09-05 01:09:30 +02:00
|
|
|
if (
|
|
|
|
event.keyCode === KEY.DOWNARROW ||
|
2021-09-09 05:47:34 +02:00
|
|
|
(FconfSettings.ENABLE_BASH_HOTKEYS && event.keyCode === KEY.M && event.ctrlKey)
|
2021-09-05 01:09:30 +02:00
|
|
|
) {
|
|
|
|
if (FconfSettings.ENABLE_BASH_HOTKEYS) {
|
|
|
|
event.preventDefault();
|
|
|
|
}
|
|
|
|
// Cycle through past commands
|
|
|
|
if (terminalInput == null) {
|
|
|
|
return;
|
|
|
|
}
|
2021-09-16 02:06:48 +02:00
|
|
|
var i = NewTerminal.commandHistoryIndex;
|
|
|
|
var len = NewTerminal.commandHistory.length;
|
2021-09-05 01:09:30 +02:00
|
|
|
|
|
|
|
if (len == 0) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (i < 0 || i > len) {
|
2021-09-16 02:06:48 +02:00
|
|
|
NewTerminal.commandHistoryIndex = len;
|
2021-09-05 01:09:30 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Latest command, put nothing
|
|
|
|
if (i == len || i == len - 1) {
|
2021-09-16 02:06:48 +02:00
|
|
|
NewTerminal.commandHistoryIndex = len;
|
2021-09-05 01:09:30 +02:00
|
|
|
terminalInput.value = "";
|
|
|
|
} else {
|
2021-09-16 02:06:48 +02:00
|
|
|
++NewTerminal.commandHistoryIndex;
|
|
|
|
var prevCommand = NewTerminal.commandHistory[NewTerminal.commandHistoryIndex];
|
2021-09-05 01:09:30 +02:00
|
|
|
terminalInput.value = prevCommand;
|
|
|
|
}
|
|
|
|
}
|
2017-07-25 03:06:40 +02:00
|
|
|
|
2021-09-05 01:09:30 +02:00
|
|
|
if (event.keyCode === KEY.TAB) {
|
|
|
|
event.preventDefault();
|
|
|
|
|
|
|
|
// Autocomplete
|
|
|
|
if (terminalInput == null) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
let input = terminalInput.value;
|
|
|
|
if (input == "") {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
const semiColonIndex = input.lastIndexOf(";");
|
|
|
|
if (semiColonIndex !== -1) {
|
|
|
|
input = input.slice(semiColonIndex + 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
input = input.trim();
|
|
|
|
input = input.replace(/\s\s+/g, " ");
|
|
|
|
|
|
|
|
const commandArray = input.split(" ");
|
|
|
|
let index = commandArray.length - 2;
|
|
|
|
if (index < -1) {
|
|
|
|
index = 0;
|
|
|
|
}
|
2021-09-16 02:06:48 +02:00
|
|
|
const allPos = determineAllPossibilitiesForTabCompletion(Player, input, index, NewTerminal.currDir);
|
2021-09-05 01:09:30 +02:00
|
|
|
if (allPos.length == 0) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
let arg = "";
|
|
|
|
let command = "";
|
|
|
|
if (commandArray.length == 0) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (commandArray.length == 1) {
|
|
|
|
command = commandArray[0];
|
|
|
|
} else if (commandArray.length == 2) {
|
|
|
|
command = commandArray[0];
|
|
|
|
arg = commandArray[1];
|
|
|
|
} else if (commandArray.length == 3) {
|
|
|
|
command = commandArray[0] + " " + commandArray[1];
|
|
|
|
arg = commandArray[2];
|
|
|
|
} else {
|
|
|
|
arg = commandArray.pop();
|
|
|
|
command = commandArray.join(" ");
|
|
|
|
}
|
|
|
|
|
|
|
|
tabCompletion(command, arg, allPos);
|
|
|
|
terminalInput.focus();
|
|
|
|
}
|
2017-07-25 03:06:40 +02:00
|
|
|
|
2021-09-05 01:09:30 +02:00
|
|
|
// Extra Bash Emulation Hotkeys, must be enabled through .fconf
|
|
|
|
if (FconfSettings.ENABLE_BASH_HOTKEYS) {
|
|
|
|
if (event.keyCode === KEY.A && event.ctrlKey) {
|
|
|
|
event.preventDefault();
|
|
|
|
Terminal.moveTextCursor("home");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (event.keyCode === KEY.E && event.ctrlKey) {
|
|
|
|
event.preventDefault();
|
|
|
|
Terminal.moveTextCursor("end");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (event.keyCode === KEY.B && event.ctrlKey) {
|
|
|
|
event.preventDefault();
|
|
|
|
Terminal.moveTextCursor("prevchar");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (event.keyCode === KEY.B && event.altKey) {
|
|
|
|
event.preventDefault();
|
|
|
|
Terminal.moveTextCursor("prevword");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (event.keyCode === KEY.F && event.ctrlKey) {
|
|
|
|
event.preventDefault();
|
|
|
|
Terminal.moveTextCursor("nextchar");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (event.keyCode === KEY.F && event.altKey) {
|
|
|
|
event.preventDefault();
|
|
|
|
Terminal.moveTextCursor("nextword");
|
|
|
|
}
|
|
|
|
|
2021-09-09 05:47:34 +02:00
|
|
|
if ((event.keyCode === KEY.H || event.keyCode === KEY.D) && event.ctrlKey) {
|
2021-09-05 01:09:30 +02:00
|
|
|
Terminal.modifyInput("backspace");
|
|
|
|
event.preventDefault();
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO AFTER THIS:
|
|
|
|
// alt + d deletes word after cursor
|
|
|
|
// ^w deletes word before cursor
|
|
|
|
// ^k clears line after cursor
|
|
|
|
// ^u clears line before cursor
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
2017-07-25 03:06:40 +02:00
|
|
|
|
2021-09-05 01:09:30 +02:00
|
|
|
// Keep terminal in focus
|
|
|
|
let terminalCtrlPressed = false,
|
|
|
|
shiftKeyPressed = false;
|
|
|
|
$(document).ready(function () {
|
|
|
|
if (routing.isOn(Page.Terminal)) {
|
|
|
|
$(".terminal-input").focus();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
$(document).keydown(function (e) {
|
|
|
|
if (routing.isOn(Page.Terminal)) {
|
|
|
|
if (e.which == KEY.CTRL) {
|
|
|
|
terminalCtrlPressed = true;
|
|
|
|
} else if (e.shiftKey) {
|
|
|
|
shiftKeyPressed = true;
|
2021-09-16 02:06:48 +02:00
|
|
|
} else if (terminalCtrlPressed || shiftKeyPressed || NewTerminal.contractOpen) {
|
2021-09-05 01:09:30 +02:00
|
|
|
// Don't focus
|
|
|
|
} else {
|
|
|
|
var inputTextBox = document.getElementById("terminal-input-text-box");
|
|
|
|
if (inputTextBox != null) {
|
|
|
|
inputTextBox.focus();
|
|
|
|
}
|
|
|
|
|
|
|
|
terminalCtrlPressed = false;
|
|
|
|
shiftKeyPressed = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
2017-07-25 03:06:40 +02:00
|
|
|
|
2021-09-05 01:09:30 +02:00
|
|
|
$(document).keyup(function (e) {
|
|
|
|
if (routing.isOn(Page.Terminal)) {
|
|
|
|
if (e.which == KEY.CTRL) {
|
|
|
|
terminalCtrlPressed = false;
|
|
|
|
}
|
|
|
|
if (e.shiftKey) {
|
|
|
|
shiftKeyPressed = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
2018-07-20 16:28:03 +02:00
|
|
|
|
2021-09-05 01:09:30 +02:00
|
|
|
let Terminal = {
|
|
|
|
resetTerminalInput: function (keepInput = false) {
|
|
|
|
let input = "";
|
|
|
|
if (keepInput) {
|
|
|
|
input = getTerminalInput();
|
|
|
|
}
|
2021-09-16 02:06:48 +02:00
|
|
|
const dir = NewTerminal.currDir;
|
2021-09-05 01:09:30 +02:00
|
|
|
if (FconfSettings.WRAP_INPUT) {
|
|
|
|
document.getElementById("terminal-input-td").innerHTML =
|
2021-09-09 05:47:34 +02:00
|
|
|
`<div id='terminal-input-header' class='prompt'>[${Player.getCurrentServer().hostname} ~${dir}]$ </div>` +
|
2021-09-05 01:09:30 +02:00
|
|
|
`<textarea type="text" id="terminal-input-text-box" class="terminal-input" tabindex="1" value=\"${input}\" autocomplete="off" />`;
|
|
|
|
|
|
|
|
// Auto re-size the line element as it wraps
|
|
|
|
autosize(document.getElementById("terminal-input-text-box"));
|
|
|
|
} else {
|
|
|
|
document.getElementById("terminal-input-td").innerHTML =
|
2021-09-09 05:47:34 +02:00
|
|
|
`<div id='terminal-input-header' class='prompt'>[${Player.getCurrentServer().hostname} ~${dir}]$ </div>` +
|
2021-09-05 01:09:30 +02:00
|
|
|
`<input type="text" id="terminal-input-text-box" class="terminal-input" tabindex="1" value=\"${input}\" autocomplete="off" />`;
|
|
|
|
}
|
|
|
|
const hdr = document.getElementById("terminal-input-header");
|
|
|
|
hdr.style.display = "inline";
|
|
|
|
|
|
|
|
const terminalInput = document.getElementById("terminal-input-text-box");
|
|
|
|
if (typeof terminalInput.selectionStart == "number") {
|
2021-09-09 05:47:34 +02:00
|
|
|
terminalInput.selectionStart = terminalInput.selectionEnd = terminalInput.value.length;
|
2021-09-05 01:09:30 +02:00
|
|
|
} else if (typeof terminalInput.createTextRange != "undefined") {
|
|
|
|
terminalInput.focus();
|
|
|
|
var range = el.createTextRange();
|
|
|
|
range.collapse(false);
|
|
|
|
range.select();
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
modifyInput: function (mod) {
|
|
|
|
try {
|
|
|
|
var terminalInput = document.getElementById("terminal-input-text-box");
|
|
|
|
if (terminalInput == null) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
terminalInput.focus();
|
|
|
|
|
|
|
|
var inputLength = terminalInput.value.length;
|
|
|
|
var start = terminalInput.selectionStart;
|
|
|
|
var inputText = terminalInput.value;
|
|
|
|
|
|
|
|
switch (mod.toLowerCase()) {
|
|
|
|
case "backspace":
|
|
|
|
if (start > 0 && start <= inputLength + 1) {
|
2021-09-09 05:47:34 +02:00
|
|
|
terminalInput.value = inputText.substr(0, start - 1) + inputText.substr(start);
|
2021-09-05 01:09:30 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case "deletewordbefore": // Delete rest of word before the cursor
|
|
|
|
for (var delStart = start - 1; delStart > 0; --delStart) {
|
|
|
|
if (inputText.charAt(delStart) === " ") {
|
2021-09-09 05:47:34 +02:00
|
|
|
terminalInput.value = inputText.substr(0, delStart) + inputText.substr(start);
|
2021-09-05 01:09:30 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case "deletewordafter": // Delete rest of word after the cursor
|
2021-09-09 05:47:34 +02:00
|
|
|
for (var delStart = start + 1; delStart <= text.length + 1; ++delStart) {
|
2021-09-05 01:09:30 +02:00
|
|
|
if (inputText.charAt(delStart) === " ") {
|
2021-09-09 05:47:34 +02:00
|
|
|
terminalInput.value = inputText.substr(0, start) + inputText.substr(delStart);
|
2021-09-05 01:09:30 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case "clearafter": // Deletes everything after cursor
|
|
|
|
break;
|
|
|
|
case "clearbefore:": // Deleetes everything before cursor
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} catch (e) {
|
|
|
|
console.error("Exception in Terminal.modifyInput: " + e);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
moveTextCursor: function (loc) {
|
|
|
|
try {
|
|
|
|
var terminalInput = document.getElementById("terminal-input-text-box");
|
|
|
|
if (terminalInput == null) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
terminalInput.focus();
|
|
|
|
|
|
|
|
var inputLength = terminalInput.value.length;
|
|
|
|
var start = terminalInput.selectionStart;
|
|
|
|
|
|
|
|
switch (loc.toLowerCase()) {
|
|
|
|
case "home":
|
|
|
|
terminalInput.setSelectionRange(0, 0);
|
|
|
|
break;
|
|
|
|
case "end":
|
|
|
|
terminalInput.setSelectionRange(inputLength, inputLength);
|
|
|
|
break;
|
|
|
|
case "prevchar":
|
|
|
|
if (start > 0) {
|
|
|
|
terminalInput.setSelectionRange(start - 1, start - 1);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case "prevword":
|
|
|
|
for (var i = start - 2; i >= 0; --i) {
|
|
|
|
if (terminalInput.value.charAt(i) === " ") {
|
|
|
|
terminalInput.setSelectionRange(i + 1, i + 1);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
terminalInput.setSelectionRange(0, 0);
|
|
|
|
break;
|
|
|
|
case "nextchar":
|
|
|
|
terminalInput.setSelectionRange(start + 1, start + 1);
|
|
|
|
break;
|
|
|
|
case "nextword":
|
|
|
|
for (var i = start + 1; i <= inputLength; ++i) {
|
|
|
|
if (terminalInput.value.charAt(i) === " ") {
|
|
|
|
terminalInput.setSelectionRange(i, i);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
terminalInput.setSelectionRange(inputLength, inputLength);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
console.warn("Invalid loc argument in Terminal.moveTextCursor()");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} catch (e) {
|
|
|
|
console.error("Exception in Terminal.moveTextCursor: " + e);
|
|
|
|
}
|
|
|
|
},
|
2017-07-25 03:06:40 +02:00
|
|
|
};
|
2017-08-30 19:44:29 +02:00
|
|
|
|
2021-09-10 22:08:58 +02:00
|
|
|
export { postVersion, Terminal };
|