TERMINAL: Fix original alias syntax (#545)

This commit is contained in:
Snarling 2023-05-29 06:54:16 -04:00 committed by omuretsu
parent 7f852373d8
commit 5f2a1c3f27
11 changed files with 48 additions and 23 deletions

@ -1,4 +1,5 @@
import { Terminal } from "./Terminal";
import { trimQuotes } from "./utils/helpers/string";
export const Aliases = new Map<string, string>();
export const GlobalAliases = new Map<string, string>();
@ -34,6 +35,7 @@ export function parseAliasDeclaration(dec: string, global = false): boolean {
if (matches == null || matches.length != 3) {
return false;
}
matches[2] = trimQuotes(matches[2]);
if (global) {
addGlobalAlias(matches[1], matches[2]);

@ -8,7 +8,7 @@ import { calculateEffectWithFactors } from "../utils/calculateEffectWithFactors"
import { OfficeSpace } from "./OfficeSpace";
import { Product } from "./Product";
import { dialogBoxCreate } from "../ui/React/DialogBox";
import { isString } from "../utils/helpers/isString";
import { isString } from "../utils/helpers/string";
import { MaterialInfo } from "./MaterialInfo";
import { Warehouse } from "./Warehouse";
import { Corporation } from "./Corporation";

@ -11,7 +11,7 @@ import { PurchaseMaterialModal } from "./modals/PurchaseMaterialModal";
import { formatBigNumber, formatCorpStat, formatMoney, formatQuality } from "../../ui/formatNumber";
import { isString } from "../../utils/helpers/isString";
import { isString } from "../../utils/helpers/string";
import { Money } from "../../ui/React/Money";
import { useCorporation, useDivision } from "./Context";

@ -11,7 +11,7 @@ import { CancelProductModal } from "./modals/CancelProductModal";
import { formatBigNumber, formatCorpStat, formatMoney, formatPercent } from "../../ui/formatNumber";
import { isString } from "../../utils/helpers/isString";
import { isString } from "../../utils/helpers/string";
import { Money } from "../../ui/React/Money";
import { useCorporation, useDivision } from "./Context";

@ -1,7 +1,7 @@
export const TerminalHelpText: string[] = [
"Type 'help name' to learn more about the command ",
" ",
' alias [-g] ["name=value"] Create or display Terminal aliases',
' alias [-g] [name="value"] Create or display Terminal aliases',
" analyze Get information about the current machine ",
" backdoor Install a backdoor on the current machine ",
" buy [-l/-a/program] Purchase a program through the Dark Web",
@ -69,20 +69,20 @@ const TemplatedHelpTexts: Record<string, (command: string) => string[]> = {
export const HelpTexts: Record<string, string[]> = {
alias: [
'Usage: alias [-g] ["name=value"] ',
'Usage: alias [-g] [name="value"] ',
" ",
"Create or display aliases. An alias enables a replacement of a word with another string. ",
"It can be used to abbreviate a commonly used command, or commonly used parts of a command. The NAME ",
"of an alias defines the word that will be replaced, while the VALUE defines what it will be replaced by. For example, ",
"you could create the alias 'nuke' for the Terminal command 'run NUKE.exe' using the following: ",
" ",
' alias "nuke=run NUKE.exe"',
' alias nuke="run NUKE.exe"',
" ",
"Then, to run the NUKE.exe program you would just have to enter 'nuke' in Terminal rather than the full command. ",
"It is important to note that 'default' aliases will only be substituted for the first word of a Terminal command. For ",
"example, if the following alias was set: ",
" ",
' alias "worm=HTTPWorm.exe"',
' alias worm="HTTPWorm.exe"',
" ",
"and then you tried to run the following terminal command: ",
" ",
@ -91,7 +91,7 @@ export const HelpTexts: Record<string, string[]> = {
"This would fail because the worm alias is not the first word of a Terminal command. To allow an alias to be substituted ",
"anywhere in a Terminal command, rather than just the first word, you must set it to be a global alias using the -g flag: ",
" ",
' alias -g "worm=HTTPWorm.exe"',
' alias -g worm="HTTPWorm.exe"',
" ",
"Now, the 'worm' alias will be substituted anytime it shows up as an individual word in a Terminal command. ",
" ",

@ -1,3 +1,4 @@
import { trimQuotes } from "../utils/helpers/string";
import { substituteAliases } from "../Alias";
// Helper function to parse individual arguments into number/boolean/string as appropriate
function parseArg(arg: string): string | number | boolean {
@ -5,11 +6,7 @@ function parseArg(arg: string): string | number | boolean {
if (arg === "false") return false;
const argAsNumber = Number(arg);
if (!isNaN(argAsNumber)) return argAsNumber;
// For quoted strings just return the inner string
if ((arg.startsWith('"') && arg.endsWith('"')) || (arg.startsWith("'") && arg.endsWith("'"))) {
return arg.substring(1, arg.length - 1);
}
return arg;
return trimQuotes(arg);
}
/** split a commands string into a commands array */
@ -31,7 +28,7 @@ export function parseCommands(commandsText: string): string[] {
/** get a commandArgs array from a single command string */
export function parseCommand(command: string): (string | number | boolean)[] {
// Match every command arg in a given command string
const argDetection = /(?:("[^"]*"|'[^']*'|[^\s]+))/g;
const argDetection = /(?:([^ ;"']*"[^"]*"|[^ ;"']*'[^']*'|[^\s]+))/g;
const commandArgs = command.match(argDetection);
if (!commandArgs) return [];
return commandArgs.map(parseArg);

@ -20,5 +20,5 @@ export function alias(args: (string | number | boolean)[]): void {
}
}
}
Terminal.error('Incorrect usage of alias command. Usage: alias [-g] ["aliasname=value"]');
Terminal.error('Incorrect usage of alias command. Usage: alias [-g] [aliasname="value"]');
}

@ -1,5 +1,5 @@
import { Settings } from "../Settings/Settings";
import { isString } from "./helpers/isString";
import { isString } from "./helpers/string";
/*
Converts a date representing time in milliseconds to a string with the format H hours M minutes and S seconds

@ -1,7 +0,0 @@
/**
* Checks whether the value passed in can be considered a string.
* @param value The value to check if it is a string.
*/
export function isString(value: unknown): value is string {
return typeof value === "string" || value instanceof String;
}

@ -0,0 +1,17 @@
// We can probably get rid of isString in favor of just checking typeof value==="string".
// We are not and should not ever be using `new String()` for anything. Will remove in 2.3.1
/**
* Checks whether the value passed in can be considered a string.
* @param value The value to check if it is a string.
*/
export function isString(value: unknown): value is string {
return typeof value === "string" || value instanceof String;
}
/** Removes a single layer of matching single or double quotes, if present. */
export function trimQuotes(value: string): string {
if (value.length < 2) return value;
if (value.at(0) !== value.at(-1)) return value;
if (value.at(0) !== "'" && value.at(0) !== '"') return value;
return value.substring(1, value.length - 1);
}

@ -0,0 +1,16 @@
import { parseCommand } from "../../../src/Terminal/Parser";
test("parseCommand Tests", () => {
const expectedParsings = {
// A quoted string that is not the entire argument should retain the quotes
'alias -g n00dles="home;connect n00dles"': ["alias", "-g", 'n00dles="home;connect n00dles"'],
// Normal quoted string handling
'alias -g "n00dles=home;connect n00dles"': ["alias", "-g", "n00dles=home;connect n00dles"],
// Check parsing even if quoted section appears within another quoted section, with differing whitespace between args and in quotes
'run myScript.js "" " " " " hello \' whoa" " \'': ["run", "myScript.js", "", " ", " ", "hello", ' whoa" " '],
// extra whitespace at start and end of string are ignored
' run myScript.js "" " " " " hello \' whoa" " \' ': ["run", "myScript.js", "", " ", " ", "hello", ' whoa" " '],
};
for (const [commandString, expectedArray] of Object.entries(expectedParsings)) {
expect(parseCommand(commandString)).toEqual(expectedArray);
}
});