Merge branch 'dev' of github.com:danielyxie/bitburner into dev

This commit is contained in:
Olivier Gagnon 2022-03-30 00:18:05 -04:00
commit ab93cfa887
15 changed files with 153 additions and 90 deletions

@ -35,6 +35,7 @@ import { joinFaction } from "../Faction/FactionHelpers";
import { WorkerScript } from "../Netscript/WorkerScript"; import { WorkerScript } from "../Netscript/WorkerScript";
import { FactionNames } from "../Faction/data/FactionNames"; import { FactionNames } from "../Faction/data/FactionNames";
import { BlackOperationNames } from "./data/BlackOperationNames"; import { BlackOperationNames } from "./data/BlackOperationNames";
import { KEY } from "../utils/helpers/keyCodes";
interface BlackOpsAttempt { interface BlackOpsAttempt {
error?: string; error?: string;
@ -793,7 +794,7 @@ export class Bladeburner implements IBladeburner {
if (c === '"') { if (c === '"') {
// Double quotes // Double quotes
const endQuote = command.indexOf('"', i + 1); const endQuote = command.indexOf('"', i + 1);
if (endQuote !== -1 && (endQuote === command.length - 1 || command.charAt(endQuote + 1) === " ")) { if (endQuote !== -1 && (endQuote === command.length - 1 || command.charAt(endQuote + 1) === KEY.SPACE)) {
args.push(command.substr(i + 1, endQuote - i - 1)); args.push(command.substr(i + 1, endQuote - i - 1));
if (endQuote === command.length - 1) { if (endQuote === command.length - 1) {
start = i = endQuote + 1; start = i = endQuote + 1;
@ -805,7 +806,7 @@ export class Bladeburner implements IBladeburner {
} else if (c === "'") { } else if (c === "'") {
// Single quotes, same thing as above // Single quotes, same thing as above
const endQuote = command.indexOf("'", i + 1); const endQuote = command.indexOf("'", i + 1);
if (endQuote !== -1 && (endQuote === command.length - 1 || command.charAt(endQuote + 1) === " ")) { if (endQuote !== -1 && (endQuote === command.length - 1 || command.charAt(endQuote + 1) === KEY.SPACE)) {
args.push(command.substr(i + 1, endQuote - i - 1)); args.push(command.substr(i + 1, endQuote - i - 1));
if (endQuote === command.length - 1) { if (endQuote === command.length - 1) {
start = i = endQuote + 1; start = i = endQuote + 1;
@ -814,7 +815,7 @@ export class Bladeburner implements IBladeburner {
} }
continue; continue;
} }
} else if (c === " ") { } else if (c === KEY.SPACE) {
args.push(command.substr(start, i - start)); args.push(command.substr(start, i - start));
start = i + 1; start = i + 1;
} }

@ -89,7 +89,7 @@ export function Console(props: IProps): React.ReactElement {
const consoleHistory = props.bladeburner.consoleHistory; const consoleHistory = props.bladeburner.consoleHistory;
if (event.key === KEY.UPARROW) { if (event.key === KEY.UP_ARROW) {
// up // up
let i = consoleHistoryIndex; let i = consoleHistoryIndex;
const len = consoleHistory.length; const len = consoleHistory.length;
@ -109,7 +109,7 @@ export function Console(props: IProps): React.ReactElement {
setCommand(prevCommand); setCommand(prevCommand);
} }
if (event.key === KEY.DOWNARROW) { if (event.key === KEY.DOWN_ARROW) {
const i = consoleHistoryIndex; const i = consoleHistoryIndex;
const len = consoleHistory.length; const len = consoleHistory.length;
@ -140,14 +140,16 @@ export function Console(props: IProps): React.ReactElement {
return ( return (
<Paper sx={{ p: 1 }}> <Paper sx={{ p: 1 }}>
<Box sx={{ <Box
height: '60vh', sx={{
paddingBottom: '8px', height: "60vh",
display: 'flex', paddingBottom: "8px",
alignItems: 'stretch', display: "flex",
whiteSpace: 'pre-wrap', alignItems: "stretch",
whiteSpace: "pre-wrap",
}} }}
onClick={handleClick}> onClick={handleClick}
>
<Box> <Box>
<Logs entries={[...props.bladeburner.consoleLogs]} /> <Logs entries={[...props.bladeburner.consoleLogs]} />
</Box> </Box>
@ -195,9 +197,7 @@ function Logs({ entries }: ILogProps): React.ReactElement {
return ( return (
<List sx={{ height: "100%", overflow: "auto", p: 1 }} ref={scrollHook}> <List sx={{ height: "100%", overflow: "auto", p: 1 }} ref={scrollHook}>
{entries && entries.map((log: any, i: number) => ( {entries && entries.map((log: any, i: number) => <Line key={i} content={log} />)}
<Line key={i} content={log} />
))}
</List> </List>
); );
} }

@ -7,6 +7,7 @@ import { random } from "../utils";
import { interpolate } from "./Difficulty"; import { interpolate } from "./Difficulty";
import { BlinkingCursor } from "./BlinkingCursor"; import { BlinkingCursor } from "./BlinkingCursor";
import Typography from "@mui/material/Typography"; import Typography from "@mui/material/Typography";
import { KEY } from "../../utils/helpers/keyCodes";
interface Difficulty { interface Difficulty {
[key: string]: number; [key: string]: number;
@ -36,7 +37,7 @@ export function BackwardGame(props: IMinigameProps): React.ReactElement {
function press(this: Document, event: KeyboardEvent): void { function press(this: Document, event: KeyboardEvent): void {
event.preventDefault(); event.preventDefault();
if (event.key === "Backspace") return; if (event.key === KEY.BACKSPACE) return;
const nextGuess = guess + event.key.toUpperCase(); const nextGuess = guess + event.key.toUpperCase();
if (!answer.startsWith(nextGuess)) props.onFailure(); if (!answer.startsWith(nextGuess)) props.onFailure();
else if (answer === nextGuess) props.onSuccess(); else if (answer === nextGuess) props.onSuccess();

@ -7,6 +7,7 @@ import { random } from "../utils";
import { interpolate } from "./Difficulty"; import { interpolate } from "./Difficulty";
import { BlinkingCursor } from "./BlinkingCursor"; import { BlinkingCursor } from "./BlinkingCursor";
import Typography from "@mui/material/Typography"; import Typography from "@mui/material/Typography";
import { KEY } from "../../utils/helpers/keyCodes";
interface Difficulty { interface Difficulty {
[key: string]: number; [key: string]: number;
@ -29,28 +30,29 @@ const difficulties: {
function generateLeftSide(difficulty: Difficulty): string { function generateLeftSide(difficulty: Difficulty): string {
let str = ""; let str = "";
const options = [KEY.OPEN_BRACKET, KEY.LESS_THAN, KEY.OPEN_PARENTHESIS, KEY.OPEN_BRACE];
const length = random(difficulty.min, difficulty.max); const length = random(difficulty.min, difficulty.max);
for (let i = 0; i < length; i++) { for (let i = 0; i < length; i++) {
str += ["[", "<", "(", "{"][Math.floor(Math.random() * 4)]; str += options[Math.floor(Math.random() * 4)];
} }
return str; return str;
} }
function getChar(event: KeyboardEvent): string { function getChar(event: KeyboardEvent): string {
if (event.key === ")") return ")"; if (event.key === KEY.CLOSE_PARENTHESIS) return KEY.CLOSE_PARENTHESIS;
if (event.key === "]") return "]"; if (event.key === KEY.CLOSE_BRACKET) return KEY.CLOSE_BRACKET;
if (event.key === "}") return "}"; if (event.key === KEY.CLOSE_BRACE) return KEY.CLOSE_BRACE;
if (event.key === ">") return ">"; if (event.key === KEY.GREATER_THAN) return KEY.GREATER_THAN;
return ""; return "";
} }
function match(left: string, right: string): boolean { function match(left: string, right: string): boolean {
return ( return (
(left === "[" && right === "]") || (left === KEY.OPEN_BRACKET && right === KEY.CLOSE_BRACKET) ||
(left === "<" && right === ">") || (left === KEY.LESS_THAN && right === KEY.GREATER_THAN) ||
(left === "(" && right === ")") || (left === KEY.OPEN_PARENTHESIS && right === KEY.CLOSE_PARENTHESIS) ||
(left === "{" && right === "}") (left === KEY.OPEN_BRACE && right === KEY.CLOSE_BRACE)
); );
} }

@ -5,6 +5,8 @@ import { KeyHandler } from "./KeyHandler";
import { GameTimer } from "./GameTimer"; import { GameTimer } from "./GameTimer";
import { interpolate } from "./Difficulty"; import { interpolate } from "./Difficulty";
import Typography from "@mui/material/Typography"; import Typography from "@mui/material/Typography";
import { KEY } from "../../utils/helpers/keyCodes";
import { downArrowSymbol, upArrowSymbol } from "../utils";
interface Difficulty { interface Difficulty {
[key: string]: number; [key: string]: number;
@ -34,15 +36,15 @@ export function BribeGame(props: IMinigameProps): React.ReactElement {
function press(this: Document, event: KeyboardEvent): void { function press(this: Document, event: KeyboardEvent): void {
event.preventDefault(); event.preventDefault();
const k = event.key; const k = event.key;
if (k === " ") { if (k === KEY.SPACE) {
if (positive.includes(choices[index])) props.onSuccess(); if (positive.includes(choices[index])) props.onSuccess();
else props.onFailure(); else props.onFailure();
return; return;
} }
let newIndex = index; let newIndex = index;
if (["ArrowUp", "w", "ArrowRight", "d"].includes(k)) newIndex++; if ([KEY.UP_ARROW, KEY.W, KEY.RIGHT_ARROW, KEY.D].map((key) => key as string).includes(k)) newIndex++;
if (["ArrowDown", "s", "ArrowLeft", "a"].includes(k)) newIndex--; if ([KEY.DOWN_ARROW, KEY.S, KEY.LEFT_ARROW, KEY.A].map((key) => key as string).includes(k)) newIndex--;
while (newIndex < 0) newIndex += choices.length; while (newIndex < 0) newIndex += choices.length;
while (newIndex > choices.length - 1) newIndex -= choices.length; while (newIndex > choices.length - 1) newIndex -= choices.length;
setIndex(newIndex); setIndex(newIndex);
@ -57,13 +59,13 @@ export function BribeGame(props: IMinigameProps): React.ReactElement {
</Grid> </Grid>
<Grid item xs={6}> <Grid item xs={6}>
<Typography variant="h5" color="primary"> <Typography variant="h5" color="primary">
{upArrowSymbol}
</Typography> </Typography>
<Typography variant="h5" color="primary"> <Typography variant="h5" color="primary">
{choices[index]} {choices[index]}
</Typography> </Typography>
<Typography variant="h5" color="primary"> <Typography variant="h5" color="primary">
{downArrowSymbol}
</Typography> </Typography>
</Grid> </Grid>
</Grid> </Grid>

@ -3,7 +3,7 @@ import Grid from "@mui/material/Grid";
import { IMinigameProps } from "./IMinigameProps"; import { IMinigameProps } from "./IMinigameProps";
import { KeyHandler } from "./KeyHandler"; import { KeyHandler } from "./KeyHandler";
import { GameTimer } from "./GameTimer"; import { GameTimer } from "./GameTimer";
import { random, getArrow } from "../utils"; import { random, getArrow, rightArrowSymbol, leftArrowSymbol, upArrowSymbol, downArrowSymbol } from "../utils";
import { interpolate } from "./Difficulty"; import { interpolate } from "./Difficulty";
import Typography from "@mui/material/Typography"; import Typography from "@mui/material/Typography";
@ -56,7 +56,7 @@ export function CheatCodeGame(props: IMinigameProps): React.ReactElement {
} }
function generateCode(difficulty: Difficulty): string { function generateCode(difficulty: Difficulty): string {
const arrows = ["←", "→", "↑", "↓"]; const arrows = [leftArrowSymbol, rightArrowSymbol, upArrowSymbol, downArrowSymbol];
let code = ""; let code = "";
for (let i = 0; i < random(difficulty.min, difficulty.max); i++) { for (let i = 0; i < random(difficulty.min, difficulty.max); i++) {
let arrow = arrows[Math.floor(4 * Math.random())]; let arrow = arrows[Math.floor(4 * Math.random())];

@ -4,8 +4,9 @@ import { IMinigameProps } from "./IMinigameProps";
import { KeyHandler } from "./KeyHandler"; import { KeyHandler } from "./KeyHandler";
import { GameTimer } from "./GameTimer"; import { GameTimer } from "./GameTimer";
import { interpolate } from "./Difficulty"; import { interpolate } from "./Difficulty";
import { getArrow } from "../utils"; import { downArrowSymbol, getArrow, leftArrowSymbol, rightArrowSymbol, upArrowSymbol } from "../utils";
import Typography from "@mui/material/Typography"; import Typography from "@mui/material/Typography";
import { KEY } from "../../utils/helpers/keyCodes";
interface Difficulty { interface Difficulty {
[key: string]: number; [key: string]: number;
@ -41,16 +42,16 @@ export function Cyberpunk2077Game(props: IMinigameProps): React.ReactElement {
const move = [0, 0]; const move = [0, 0];
const arrow = getArrow(event); const arrow = getArrow(event);
switch (arrow) { switch (arrow) {
case "↑": case upArrowSymbol:
move[1]--; move[1]--;
break; break;
case "←": case leftArrowSymbol:
move[0]--; move[0]--;
break; break;
case "↓": case downArrowSymbol:
move[1]++; move[1]++;
break; break;
case "→": case rightArrowSymbol:
move[0]++; move[0]++;
break; break;
} }
@ -59,7 +60,7 @@ export function Cyberpunk2077Game(props: IMinigameProps): React.ReactElement {
next[1] = (next[1] + grid.length) % grid.length; next[1] = (next[1] + grid.length) % grid.length;
setPos(next); setPos(next);
if (event.key === " ") { if (event.key === KEY.SPACE) {
const selected = grid[pos[1]][pos[0]]; const selected = grid[pos[1]][pos[0]];
const expected = answer[index]; const expected = answer[index];
if (selected !== expected) { if (selected !== expected) {

@ -4,8 +4,9 @@ import { IMinigameProps } from "./IMinigameProps";
import { KeyHandler } from "./KeyHandler"; import { KeyHandler } from "./KeyHandler";
import { GameTimer } from "./GameTimer"; import { GameTimer } from "./GameTimer";
import { interpolate } from "./Difficulty"; import { interpolate } from "./Difficulty";
import { getArrow } from "../utils"; import { downArrowSymbol, getArrow, leftArrowSymbol, rightArrowSymbol, upArrowSymbol } from "../utils";
import Typography from "@mui/material/Typography"; import Typography from "@mui/material/Typography";
import { KEY } from "../../utils/helpers/keyCodes";
interface Difficulty { interface Difficulty {
[key: string]: number; [key: string]: number;
@ -42,16 +43,16 @@ export function MinesweeperGame(props: IMinigameProps): React.ReactElement {
const move = [0, 0]; const move = [0, 0];
const arrow = getArrow(event); const arrow = getArrow(event);
switch (arrow) { switch (arrow) {
case "↑": case upArrowSymbol:
move[1]--; move[1]--;
break; break;
case "←": case leftArrowSymbol:
move[0]--; move[0]--;
break; break;
case "↓": case downArrowSymbol:
move[1]++; move[1]++;
break; break;
case "→": case rightArrowSymbol:
move[0]++; move[0]++;
break; break;
} }
@ -60,7 +61,7 @@ export function MinesweeperGame(props: IMinigameProps): React.ReactElement {
next[1] = (next[1] + minefield.length) % minefield.length; next[1] = (next[1] + minefield.length) % minefield.length;
setPos(next); setPos(next);
if (event.key == " ") { if (event.key == KEY.SPACE) {
if (!minefield[pos[1]][pos[0]]) { if (!minefield[pos[1]][pos[0]]) {
props.onFailure(); props.onFailure();
return; return;

@ -5,6 +5,7 @@ import { KeyHandler } from "./KeyHandler";
import { GameTimer } from "./GameTimer"; import { GameTimer } from "./GameTimer";
import { interpolate } from "./Difficulty"; import { interpolate } from "./Difficulty";
import Typography from "@mui/material/Typography"; import Typography from "@mui/material/Typography";
import { KEY } from "../../utils/helpers/keyCodes";
interface Difficulty { interface Difficulty {
[key: string]: number; [key: string]: number;
@ -30,7 +31,7 @@ export function SlashGame(props: IMinigameProps): React.ReactElement {
function press(this: Document, event: KeyboardEvent): void { function press(this: Document, event: KeyboardEvent): void {
event.preventDefault(); event.preventDefault();
if (event.key !== " ") return; if (event.key !== KEY.SPACE) return;
if (phase !== 2) { if (phase !== 2) {
props.onFailure(); props.onFailure();
} else { } else {

@ -6,6 +6,7 @@ import { KeyHandler } from "./KeyHandler";
import { GameTimer } from "./GameTimer"; import { GameTimer } from "./GameTimer";
import { random } from "../utils"; import { random } from "../utils";
import { interpolate } from "./Difficulty"; import { interpolate } from "./Difficulty";
import { KEY } from "../../utils/helpers/keyCodes";
interface Difficulty { interface Difficulty {
[key: string]: number; [key: string]: number;
@ -27,7 +28,7 @@ const difficulties: {
Impossible: { timer: 4000, wiresmin: 9, wiresmax: 9, rules: 4 }, Impossible: { timer: 4000, wiresmin: 9, wiresmax: 9, rules: 4 },
}; };
const types = ["|", ".", "/", "-", "█", "#"]; const types = [KEY.PIPE, KEY.DOT, KEY.FORWARD_SLASH, KEY.HYPHEN, "█", KEY.HASH];
const colors = ["red", "#FFC107", "blue", "white"]; const colors = ["red", "#FFC107", "blue", "white"];
@ -61,6 +62,10 @@ export function WireCuttingGame(props: IMinigameProps): React.ReactElement {
const [cutWires, setCutWires] = useState(new Array(wires.length).fill(false)); const [cutWires, setCutWires] = useState(new Array(wires.length).fill(false));
const [questions] = useState(generateQuestion(wires, difficulty)); const [questions] = useState(generateQuestion(wires, difficulty));
function checkWire(wireNum: number): boolean {
return questions.some((q) => q.shouldCut(wires[wireNum - 1], wireNum - 1));
}
function press(this: Document, event: KeyboardEvent): void { function press(this: Document, event: KeyboardEvent): void {
event.preventDefault(); event.preventDefault();
const wireNum = parseInt(event.key); const wireNum = parseInt(event.key);
@ -69,7 +74,7 @@ export function WireCuttingGame(props: IMinigameProps): React.ReactElement {
setCutWires((old) => { setCutWires((old) => {
const next = [...old]; const next = [...old];
next[wireNum - 1] = true; next[wireNum - 1] = true;
if (!questions.some((q) => q.shouldCut(wires[wireNum - 1], wireNum - 1))) { if (checkWire(wireNum)) {
props.onFailure(); props.onFailure();
} }

@ -1,21 +1,46 @@
import { KEY } from "../utils/helpers/keyCodes";
export function random(min: number, max: number): number { export function random(min: number, max: number): number {
return Math.random() * (max - min) + min; return Math.random() * (max - min) + min;
} }
export const upArrowSymbol = "↑";
export const downArrowSymbol = "↓";
export const leftArrowSymbol = "←";
export const rightArrowSymbol = "→";
export function getArrow(event: KeyboardEvent): string { export function getArrow(event: KeyboardEvent): string {
switch (event.key) { switch (event.key) {
case "ArrowUp": case KEY.UP_ARROW:
case "w": case KEY.W:
return "↑"; return upArrowSymbol;
case "ArrowLeft": case KEY.LEFT_ARROW:
case "a": case KEY.A:
return "←"; return leftArrowSymbol;
case "ArrowDown": case KEY.DOWN_ARROW:
case "s": case KEY.S:
return "↓"; return downArrowSymbol;
case "ArrowRight": case KEY.RIGHT_ARROW:
case "d": case KEY.D:
return "→"; return rightArrowSymbol;
}
return "";
}
export function getInverseArrow(event: KeyboardEvent): string {
switch (event.key) {
case KEY.DOWN_ARROW:
case KEY.S:
return upArrowSymbol;
case KEY.RIGHT_ARROW:
case KEY.D:
return leftArrowSymbol;
case KEY.UP_ARROW:
case KEY.W:
return downArrowSymbol;
case KEY.LEFT_ARROW:
case KEY.A:
return rightArrowSymbol;
} }
return ""; return "";
} }

@ -276,7 +276,7 @@ export function SidebarRoot(props: IProps): React.ReactElement {
function handleShortcuts(this: Document, event: KeyboardEvent): any { function handleShortcuts(this: Document, event: KeyboardEvent): any {
if (Settings.DisableHotkeys) return; if (Settings.DisableHotkeys) return;
if ((props.player.isWorking && props.player.focus) || redPillFlag) return; if ((props.player.isWorking && props.player.focus) || redPillFlag) return;
if (event.key === "t" && event.altKey) { if (event.key === KEY.T && event.altKey) {
event.preventDefault(); event.preventDefault();
clickTerminal(); clickTerminal();
} else if (event.key === KEY.C && event.altKey) { } else if (event.key === KEY.C && event.altKey) {
@ -522,7 +522,9 @@ export function SidebarRoot(props: IProps): React.ReactElement {
<ListItemIcon> <ListItemIcon>
<Badge badgeContent={invitationsCount !== 0 ? invitationsCount : undefined} color="error"> <Badge badgeContent={invitationsCount !== 0 ? invitationsCount : undefined} color="error">
<Tooltip title={!open ? "Factions" : ""}> <Tooltip title={!open ? "Factions" : ""}>
<ContactsIcon color={![Page.Factions, Page.Faction].includes(props.page) ? "secondary" : "primary"} /> <ContactsIcon
color={![Page.Factions, Page.Faction].includes(props.page) ? "secondary" : "primary"}
/>
</Tooltip> </Tooltip>
</Badge> </Badge>
</ListItemIcon> </ListItemIcon>
@ -570,7 +572,9 @@ export function SidebarRoot(props: IProps): React.ReactElement {
> >
<ListItemIcon> <ListItemIcon>
<Tooltip title={!open ? "Hacknet" : ""}> <Tooltip title={!open ? "Hacknet" : ""}>
<AccountTreeIcon color={flashHacknet ? "error" : props.page !== Page.Hacknet ? "secondary" : "primary"} /> <AccountTreeIcon
color={flashHacknet ? "error" : props.page !== Page.Hacknet ? "secondary" : "primary"}
/>
</Tooltip> </Tooltip>
</ListItemIcon> </ListItemIcon>
<ListItemText> <ListItemText>

@ -1,3 +1,4 @@
import { KEY } from "../utils/helpers/keyCodes";
import { substituteAliases } from "../Alias"; import { substituteAliases } from "../Alias";
// Helper function that checks if an argument (which is a string) is a valid number // Helper function that checks if an argument (which is a string) is a valid number
function isNumber(str: string): boolean { function isNumber(str: string): boolean {
@ -55,11 +56,11 @@ export function ParseCommand(command: string): (string | number | boolean)[] {
} }
const c = command.charAt(i); const c = command.charAt(i);
if (c === '"') { if (c === KEY.DOUBLE_QUOTE) {
// Double quotes // Double quotes
if (!escaped && prevChar === " ") { if (!escaped && prevChar === KEY.SPACE) {
const endQuote = command.indexOf('"', i + 1); const endQuote = command.indexOf(KEY.DOUBLE_QUOTE, i + 1);
if (endQuote !== -1 && (endQuote === command.length - 1 || command.charAt(endQuote + 1) === " ")) { if (endQuote !== -1 && (endQuote === command.length - 1 || command.charAt(endQuote + 1) === KEY.SPACE)) {
args.push(command.substr(i + 1, endQuote - i - 1)); args.push(command.substr(i + 1, endQuote - i - 1));
if (endQuote === command.length - 1) { if (endQuote === command.length - 1) {
start = i = endQuote + 1; start = i = endQuote + 1;
@ -69,15 +70,15 @@ export function ParseCommand(command: string): (string | number | boolean)[] {
continue; continue;
} }
} else if (inQuote === ``) { } else if (inQuote === ``) {
inQuote = `"`; inQuote = KEY.DOUBLE_QUOTE;
} else if (inQuote === `"`) { } else if (inQuote === KEY.DOUBLE_QUOTE) {
inQuote = ``; inQuote = ``;
} }
} else if (c === "'") { } else if (c === KEY.QUOTE) {
// Single quotes, same thing as above // Single quotes, same thing as above
if (!escaped && prevChar === " ") { if (!escaped && prevChar === KEY.SPACE) {
const endQuote = command.indexOf("'", i + 1); const endQuote = command.indexOf(KEY.QUOTE, i + 1);
if (endQuote !== -1 && (endQuote === command.length - 1 || command.charAt(endQuote + 1) === " ")) { if (endQuote !== -1 && (endQuote === command.length - 1 || command.charAt(endQuote + 1) === KEY.SPACE)) {
args.push(command.substr(i + 1, endQuote - i - 1)); args.push(command.substr(i + 1, endQuote - i - 1));
if (endQuote === command.length - 1) { if (endQuote === command.length - 1) {
start = i = endQuote + 1; start = i = endQuote + 1;
@ -87,11 +88,11 @@ export function ParseCommand(command: string): (string | number | boolean)[] {
continue; continue;
} }
} else if (inQuote === ``) { } else if (inQuote === ``) {
inQuote = `'`; inQuote = KEY.QUOTE;
} else if (inQuote === `'`) { } else if (inQuote === KEY.QUOTE) {
inQuote = ``; inQuote = ``;
} }
} else if (c === " " && inQuote === ``) { } else if (c === KEY.SPACE && inQuote === ``) {
const arg = command.substr(start, i - start); const arg = command.substr(start, i - start);
// If this is a number, convert it from a string to number // If this is a number, convert it from a string to number

@ -97,7 +97,7 @@ export function TerminalInput({ terminal, router, player }: IProps): React.React
break; break;
case "deletewordbefore": // Delete rest of word before the cursor case "deletewordbefore": // Delete rest of word before the cursor
for (let delStart = start - 1; delStart > -2; --delStart) { for (let delStart = start - 1; delStart > -2; --delStart) {
if ((inputText.charAt(delStart) === " " || delStart === -1) && delStart !== start - 1) { if ((inputText.charAt(delStart) === KEY.SPACE || delStart === -1) && delStart !== start - 1) {
saveValue(inputText.substr(0, delStart + 1) + inputText.substr(start), () => { saveValue(inputText.substr(0, delStart + 1) + inputText.substr(start), () => {
// Move cursor to correct location // Move cursor to correct location
// foo bar |baz bum --> foo |baz bum // foo bar |baz bum --> foo |baz bum
@ -110,7 +110,7 @@ export function TerminalInput({ terminal, router, player }: IProps): React.React
break; break;
case "deletewordafter": // Delete rest of word after the cursor, including trailing space case "deletewordafter": // Delete rest of word after the cursor, including trailing space
for (let delStart = start + 1; delStart <= value.length + 1; ++delStart) { for (let delStart = start + 1; delStart <= value.length + 1; ++delStart) {
if (inputText.charAt(delStart) === " " || delStart === value.length + 1) { if (inputText.charAt(delStart) === KEY.SPACE || delStart === value.length + 1) {
saveValue(inputText.substr(0, start) + inputText.substr(delStart + 1), () => { saveValue(inputText.substr(0, start) + inputText.substr(delStart + 1), () => {
// Move cursor to correct location // Move cursor to correct location
// foo bar |baz bum --> foo bar |bum // foo bar |baz bum --> foo bar |bum
@ -151,7 +151,7 @@ export function TerminalInput({ terminal, router, player }: IProps): React.React
break; break;
case "prevword": case "prevword":
for (let i = start - 2; i >= 0; --i) { for (let i = start - 2; i >= 0; --i) {
if (ref.value.charAt(i) === " ") { if (ref.value.charAt(i) === KEY.SPACE) {
ref.setSelectionRange(i + 1, i + 1); ref.setSelectionRange(i + 1, i + 1);
return; return;
} }
@ -163,7 +163,7 @@ export function TerminalInput({ terminal, router, player }: IProps): React.React
break; break;
case "nextword": case "nextword":
for (let i = start + 1; i <= inputLength; ++i) { for (let i = start + 1; i <= inputLength; ++i) {
if (ref.value.charAt(i) === " ") { if (ref.value.charAt(i) === KEY.SPACE) {
ref.setSelectionRange(i, i); ref.setSelectionRange(i, i);
return; return;
} }
@ -262,7 +262,7 @@ export function TerminalInput({ terminal, router, player }: IProps): React.React
} }
// Select previous command. // Select previous command.
if (event.key === KEY.UPARROW || (Settings.EnableBashHotkeys && event.key === "p" && event.ctrlKey)) { if (event.key === KEY.UP_ARROW || (Settings.EnableBashHotkeys && event.key === KEY.P && event.ctrlKey)) {
if (Settings.EnableBashHotkeys) { if (Settings.EnableBashHotkeys) {
event.preventDefault(); event.preventDefault();
} }
@ -290,7 +290,7 @@ export function TerminalInput({ terminal, router, player }: IProps): React.React
} }
// Select next command // Select next command
if (event.key === KEY.DOWNARROW || (Settings.EnableBashHotkeys && event.key === "m" && event.ctrlKey)) { if (event.key === KEY.DOWN_ARROW || (Settings.EnableBashHotkeys && event.key === KEY.M && event.ctrlKey)) {
if (Settings.EnableBashHotkeys) { if (Settings.EnableBashHotkeys) {
event.preventDefault(); event.preventDefault();
} }

@ -8,10 +8,29 @@ export enum KEY {
ENTER = "Enter", ENTER = "Enter",
ESC = "Escape", ESC = "Escape",
TAB = "Tab", TAB = "Tab",
UPARROW = "ArrowUp", SPACE = " ",
DOWNARROW = "ArrowDown", BACKSPACE = "Backspace",
LEFTARROW = "ArrowLeft", UP_ARROW = "ArrowUp",
RIGHTARROW = "ArrowRight", DOWN_ARROW = "ArrowDown",
LEFT_ARROW = "ArrowLeft",
RIGHT_ARROW = "ArrowRight",
QUOTE = "'",
DOUBLE_QUOTE = '"',
OPEN_BRACKET = "[",
CLOSE_BRACKET = "]",
LESS_THAN = "<",
GREATER_THAN = ">",
OPEN_PARENTHESIS = "(",
CLOSE_PARENTHESIS = ")",
OPEN_BRACE = "{",
CLOSE_BRACE = "}",
PIPE = "|",
DOT = ".",
FORWARD_SLASH = "/",
HYPHEN = "-",
HASH = "#",
k0 = "0", k0 = "0",
k1 = "1", k1 = "1",