import { evaluateDirectoryPath, evaluateFilePath, getFirstParentDirectory, isInRootDirectory, isValidDirectoryPath, removeLeadingSlash, removeTrailingSlash, } from "./Terminal/DirectoryHelpers"; import { determineAllPossibilitiesForTabCompletion } from "./Terminal/determineAllPossibilitiesForTabCompletion"; import { TerminalHelpText, HelpTexts } from "./Terminal/HelpText"; import { tabCompletion } from "./Terminal/tabCompletion"; import { createFconf } from "./Fconf/Fconf"; import { parseAliasDeclaration, printAliases, removeAlias, substituteAliases } from "./Alias"; import { BitNodeMultipliers } from "./BitNode/BitNodeMultipliers"; import { CodingContractResult } from "./CodingContracts"; import { CONSTANTS } from "./Constants"; import { Programs } from "./Programs/Programs"; import { executeDarkwebTerminalCommand, checkIfConnectedToDarkweb } from "./DarkWeb/DarkWeb"; import { Engine } from "./engine"; import { FconfSettings } from "./Fconf/FconfSettings"; import { calculateHackingChance, calculateHackingExpGain, calculatePercentMoneyHacked, calculateHackingTime, calculateGrowTime, calculateWeakenTime, } from "./Hacking"; import { HacknetServer } from "./Hacknet/HacknetServer"; import { iTutorialNextStep, iTutorialSteps, ITutorial } from "./InteractiveTutorial"; import { showLiterature } from "./Literature/LiteratureHelpers"; import { Message } from "./Message/Message"; import { showMessage } from "./Message/MessageHelpers"; import { startWorkerScript } from "./NetscriptWorker"; import { killWorkerScript } from "./Netscript/killWorkerScript"; import { WorkerScriptStartStopEventEmitter } from "./Netscript/WorkerScriptStartStopEventEmitter"; import { Player } from "./Player"; import { hackWorldDaemon } from "./RedPill"; import { RunningScript } from "./Script/RunningScript"; import { compareArrays } from "../utils/helpers/compareArrays"; import { getRamUsageFromRunningScript } from "./Script/RunningScriptHelpers"; import { findRunningScript, findRunningScriptByPid } from "./Script/ScriptHelpers"; import { isScriptFilename } from "./Script/ScriptHelpersTS"; import { AllServers } from "./Server/AllServers"; import { GetServerByHostname, getServer, getServerOnNetwork } from "./Server/ServerHelpers"; import { SpecialServerIps, SpecialServerNames } from "./Server/SpecialServerIps"; import { setTimeoutRef } from "./utils/SetTimeoutRef"; import { Page, routing } from "./ui/navigationTracking"; import { numeralWrapper } from "./ui/numeralFormat"; import { KEY } from "../utils/helpers/keyCodes"; import { arrayToString } from "../utils/helpers/arrayToString"; import { getTimestamp } from "../utils/helpers/getTimestamp"; import { logBoxCreate } from "../utils/LogBox"; import { post, postElement, postContent, postError, hackProgressBarPost, hackProgressPost } from "./ui/postToTerminal"; import { convertTimeMsToTimeElapsedString } from "../utils/StringHelperFunctions"; import { Money } from "./ui/React/Money"; import { createPopup } from "./ui/React/createPopup"; import { BitFlumePopup } from "./BitNode/ui/BitFlumePopup"; import autosize from "autosize"; import * as JSZip from "jszip"; import * as FileSaver from "file-saver"; import * as libarg from "arg"; import React from "react"; function postVersion() { post("Bitburner v" + CONSTANTS.Version); } // Helper function that checks if an argument (which is a string) is a valid number function isNumber(str) { if (typeof str != "string") { return false; } // Only process strings return !isNaN(str) && !isNaN(parseFloat(str)); } function getTerminalInput() { return document.getElementById("terminal-input-text-box").value; } // Defines key commands in terminal $(document).keydown(function (event) { // Terminal if (routing.isOn(Page.Terminal)) { var terminalInput = document.getElementById("terminal-input-text-box"); if (terminalInput != null && !event.ctrlKey && !event.shiftKey && !Terminal.contractOpen) { terminalInput.focus(); } if (event.keyCode === KEY.ENTER) { event.preventDefault(); // Prevent newline from being entered in Script Editor const command = getTerminalInput(); const dir = Terminal.currDir; post( "[" + (FconfSettings.ENABLE_TIMESTAMPS ? getTimestamp() + " " : "") + Player.getCurrentServer().hostname + ` ~${dir}]> ${command}`, ); if (command.length > 0) { Terminal.resetTerminalInput(); // Clear input first Terminal.executeCommands(command); } } if (event.keyCode === KEY.C && event.ctrlKey) { if (Engine._actionInProgress) { // Cancel action post("Cancelling..."); Engine._actionInProgress = false; Terminal.finishAction(true); } else if (FconfSettings.ENABLE_BASH_HOTKEYS) { // Dont prevent default so it still copies Terminal.resetTerminalInput(); // Clear Terminal } } if (event.keyCode === KEY.L && event.ctrlKey) { event.preventDefault(); Terminal.executeCommand("clear"); // Clear screen } // Ctrl p same as up arrow // Ctrl n same as down arrow if ( event.keyCode === KEY.UPARROW || (FconfSettings.ENABLE_BASH_HOTKEYS && event.keyCode === KEY.P && event.ctrlKey) ) { if (FconfSettings.ENABLE_BASH_HOTKEYS) { event.preventDefault(); } // Cycle through past commands if (terminalInput == null) { return; } var i = Terminal.commandHistoryIndex; var len = Terminal.commandHistory.length; if (len == 0) { return; } if (i < 0 || i > len) { Terminal.commandHistoryIndex = len; } if (i != 0) { --Terminal.commandHistoryIndex; } var prevCommand = Terminal.commandHistory[Terminal.commandHistoryIndex]; terminalInput.value = prevCommand; setTimeoutRef(function () { terminalInput.selectionStart = terminalInput.selectionEnd = 10000; }, 10); } if ( event.keyCode === KEY.DOWNARROW || (FconfSettings.ENABLE_BASH_HOTKEYS && event.keyCode === KEY.M && event.ctrlKey) ) { if (FconfSettings.ENABLE_BASH_HOTKEYS) { event.preventDefault(); } // Cycle through past commands if (terminalInput == null) { return; } var i = Terminal.commandHistoryIndex; var len = Terminal.commandHistory.length; if (len == 0) { return; } if (i < 0 || i > len) { Terminal.commandHistoryIndex = len; } // Latest command, put nothing if (i == len || i == len - 1) { Terminal.commandHistoryIndex = len; terminalInput.value = ""; } else { ++Terminal.commandHistoryIndex; var prevCommand = Terminal.commandHistory[Terminal.commandHistoryIndex]; terminalInput.value = prevCommand; } } 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; } const allPos = determineAllPossibilitiesForTabCompletion(Player, input, index, Terminal.currDir); 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(); } // 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"); } if ((event.keyCode === KEY.H || event.keyCode === KEY.D) && event.ctrlKey) { 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 } } }); // 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; } else if (terminalCtrlPressed || shiftKeyPressed || Terminal.contractOpen) { // Don't focus } else { var inputTextBox = document.getElementById("terminal-input-text-box"); if (inputTextBox != null) { inputTextBox.focus(); } terminalCtrlPressed = false; shiftKeyPressed = false; } } }); $(document).keyup(function (e) { if (routing.isOn(Page.Terminal)) { if (e.which == KEY.CTRL) { terminalCtrlPressed = false; } if (e.shiftKey) { shiftKeyPressed = false; } } }); let Terminal = { // Flags to determine whether the player is currently running a hack or an analyze hackFlag: false, backdoorFlag: false, analyzeFlag: false, actionStarted: false, actionTime: 0, commandHistory: [], commandHistoryIndex: 0, // True if a Coding Contract prompt is opened contractOpen: false, // Full Path of current directory // Excludes the trailing forward slash currDir: "/", resetTerminalInput: function (keepInput = false) { let input = ""; if (keepInput) { input = getTerminalInput(); } const dir = Terminal.currDir; if (FconfSettings.WRAP_INPUT) { document.getElementById("terminal-input-td").innerHTML = `
[${Player.getCurrentServer().hostname} ~${dir}]$
` + `