import { evaluateDirectoryPath, evaluateFilePath, getFirstParentDirectory, isInRootDirectory, isValidDirectoryPath, isValidFilename, removeLeadingSlash, removeTrailingSlash } from "./Terminal/DirectoryHelpers"; import { determineAllPossibilitiesForTabCompletion } from "./Terminal/determineAllPossibilitiesForTabCompletion"; import { TerminalHelpText, HelpTexts } from "./Terminal/HelpText"; import { tabCompletion } from "./Terminal/tabCompletion"; import { Aliases, GlobalAliases, parseAliasDeclaration, printAliases, removeAlias, substituteAliases } from "./Alias"; import { BitNodeMultipliers } from "./BitNode/BitNodeMultipliers"; import { CodingContract, CodingContractResult, CodingContractRewardType } from "./CodingContracts"; import { CONSTANTS } from "./Constants"; import { Programs } from "./Programs/Programs"; import { executeDarkwebTerminalCommand, checkIfConnectedToDarkweb } from "./DarkWeb/DarkWeb"; import { DarkWebItems } from "./DarkWeb/DarkWebItems"; import { Engine } from "./engine"; import { parseFconfSettings, createFconf } from "./Fconf/Fconf"; 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"; import { Message } from "./Message/Message"; import { showMessage } from "./Message/MessageHelpers"; import { killWorkerScript, addWorkerScript } from "./NetscriptWorker"; import { Player } from "./Player"; import { hackWorldDaemon } from "./RedPill"; import { RunningScript } from "./Script/RunningScript"; import { findRunningScript } from "./Script/ScriptHelpers"; import { isScriptFilename } from "./Script/ScriptHelpersTS"; import { AllServers } from "./Server/AllServers"; import { Server } from "./Server/Server"; import { GetServerByHostname, getServer, getServerOnNetwork } from "./Server/ServerHelpers"; import { Settings } from "./Settings/Settings"; import { SpecialServerIps, SpecialServerNames } from "./Server/SpecialServerIps"; import { getTextFile } from "./TextFile"; import { setTimeoutRef } from "./utils/SetTimeoutRef"; import { Page, routing } from "./ui/navigationTracking"; import { numeralWrapper } from "./ui/numeralFormat"; import { KEY } from "../utils/helpers/keyCodes"; import { addOffset } from "../utils/helpers/addOffset"; import { isString } from "../utils/helpers/isString"; import { arrayToString } from "../utils/helpers/arrayToString"; import { getTimestamp } from "../utils/helpers/getTimestamp"; import { logBoxCreate } from "../utils/LogBox"; import { yesNoBoxCreate, yesNoBoxGetYesButton, yesNoBoxGetNoButton, yesNoBoxClose } from "../utils/YesNoBox"; import { post, postContent, postError, hackProgressBarPost, hackProgressPost } from "./ui/postToTerminal"; import autosize from "autosize"; import * as JSZip from "jszip"; import * as FileSaver from "file-saver"; function postNetburnerText() { 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)); } // 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 = terminalInput.value; 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; }, 0); } 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, 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() { const dir = Terminal.currDir; if (FconfSettings.WRAP_INPUT) { document.getElementById("terminal-input-td").innerHTML = `
[${Player.getCurrentServer().hostname} ~${dir}]$
` + '