2021-09-16 08:52:45 +02:00
|
|
|
import { Terminal } from "./Terminal";
|
2023-05-29 12:54:16 +02:00
|
|
|
import { trimQuotes } from "./utils/helpers/string";
|
2017-08-30 19:44:29 +02:00
|
|
|
|
2023-05-05 09:55:59 +02:00
|
|
|
export const Aliases = new Map<string, string>();
|
|
|
|
export const GlobalAliases = new Map<string, string>();
|
2017-08-30 19:44:29 +02:00
|
|
|
|
2019-04-05 11:08:41 +02:00
|
|
|
export function loadAliases(saveString: string): void {
|
2023-05-05 09:55:59 +02:00
|
|
|
Aliases.clear();
|
|
|
|
const parsedAliases: unknown = JSON.parse(saveString);
|
|
|
|
if (!parsedAliases || typeof parsedAliases !== "object") return;
|
|
|
|
for (const [name, alias] of Object.entries(parsedAliases)) {
|
|
|
|
if (typeof name === "string" && typeof alias === "string") Aliases.set(name, alias);
|
2021-09-05 01:09:30 +02:00
|
|
|
}
|
2017-08-30 19:44:29 +02:00
|
|
|
}
|
|
|
|
|
2019-04-05 11:08:41 +02:00
|
|
|
export function loadGlobalAliases(saveString: string): void {
|
2023-05-05 09:55:59 +02:00
|
|
|
GlobalAliases.clear();
|
|
|
|
const parsedAliases: unknown = JSON.parse(saveString);
|
|
|
|
if (!parsedAliases || typeof parsedAliases !== "object") return;
|
|
|
|
for (const [name, alias] of Object.entries(parsedAliases)) {
|
|
|
|
if (typeof name === "string" && typeof alias === "string") GlobalAliases.set(name, alias);
|
2021-09-05 01:09:30 +02:00
|
|
|
}
|
2017-08-30 19:44:29 +02:00
|
|
|
}
|
2017-05-23 17:12:09 +02:00
|
|
|
|
2019-04-13 03:22:46 +02:00
|
|
|
// Prints all aliases to terminal
|
2019-04-05 11:08:41 +02:00
|
|
|
export function printAliases(): void {
|
2023-05-05 09:55:59 +02:00
|
|
|
for (const [name, alias] of Aliases) Terminal.print("alias " + name + "=" + alias);
|
|
|
|
for (const [name, alias] of GlobalAliases) Terminal.print("global alias " + name + "=" + alias);
|
2017-05-23 17:12:09 +02:00
|
|
|
}
|
|
|
|
|
2019-04-13 03:22:46 +02:00
|
|
|
// Returns true if successful, false otherwise
|
2021-04-29 02:07:26 +02:00
|
|
|
export function parseAliasDeclaration(dec: string, global = false): boolean {
|
2022-07-26 14:08:51 +02:00
|
|
|
const re = /^([\w|!%,@-]+)=(.+)$/;
|
2021-09-05 01:09:30 +02:00
|
|
|
const matches = dec.match(re);
|
2022-07-26 14:08:51 +02:00
|
|
|
if (matches == null || matches.length != 3) {
|
2021-09-05 01:09:30 +02:00
|
|
|
return false;
|
|
|
|
}
|
2023-05-29 12:54:16 +02:00
|
|
|
matches[2] = trimQuotes(matches[2]);
|
2021-12-29 20:04:58 +01:00
|
|
|
|
2021-09-05 01:09:30 +02:00
|
|
|
if (global) {
|
2022-07-26 14:08:51 +02:00
|
|
|
addGlobalAlias(matches[1], matches[2]);
|
2021-09-05 01:09:30 +02:00
|
|
|
} else {
|
2022-07-26 14:08:51 +02:00
|
|
|
addAlias(matches[1], matches[2]);
|
2021-09-05 01:09:30 +02:00
|
|
|
}
|
|
|
|
return true;
|
2017-05-23 17:12:09 +02:00
|
|
|
}
|
|
|
|
|
2019-04-05 11:08:41 +02:00
|
|
|
function addAlias(name: string, value: string): void {
|
2023-05-05 09:55:59 +02:00
|
|
|
GlobalAliases.delete(name);
|
|
|
|
Aliases.set(name, value.trim());
|
2017-05-23 17:12:09 +02:00
|
|
|
}
|
|
|
|
|
2019-04-05 11:08:41 +02:00
|
|
|
function addGlobalAlias(name: string, value: string): void {
|
2023-05-05 09:55:59 +02:00
|
|
|
Aliases.delete(name);
|
|
|
|
GlobalAliases.set(name, value.trim());
|
2017-06-30 18:44:03 +02:00
|
|
|
}
|
|
|
|
|
2019-04-05 11:08:41 +02:00
|
|
|
export function removeAlias(name: string): boolean {
|
2023-05-05 09:55:59 +02:00
|
|
|
const hadAlias = Aliases.has(name) || GlobalAliases.has(name);
|
|
|
|
Aliases.delete(name);
|
|
|
|
GlobalAliases.delete(name);
|
|
|
|
return hadAlias;
|
2017-06-21 19:12:08 +02:00
|
|
|
}
|
|
|
|
|
2019-04-13 03:22:46 +02:00
|
|
|
/**
|
|
|
|
* Returns the original string with any aliases substituted in.
|
|
|
|
* Aliases are only applied to "whole words", one level deep
|
2023-08-28 20:26:25 +02:00
|
|
|
* @param origCommand the original command string
|
2019-04-13 03:22:46 +02:00
|
|
|
*/
|
2019-04-05 11:08:41 +02:00
|
|
|
export function substituteAliases(origCommand: string): string {
|
2023-08-28 20:26:25 +02:00
|
|
|
return applyAliases(origCommand);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Recursively evaluates aliases and applies them to the command string,
|
|
|
|
* unless there are any reference loops or the reference chain is too deep
|
|
|
|
* @param origCommand the original command string
|
|
|
|
* @param depth the current recursion depth
|
|
|
|
* @param currentlyProcessingAliases any aliases that have been applied in the recursive evaluation leading to this point
|
|
|
|
* @return { string } the provided command with all of its referenced aliases evaluated
|
|
|
|
*/
|
|
|
|
function applyAliases(origCommand: string, depth = 0, currentlyProcessingAliases: string[] = []) {
|
|
|
|
if (!origCommand) {
|
|
|
|
return origCommand;
|
|
|
|
}
|
2021-09-05 01:09:30 +02:00
|
|
|
const commandArray = origCommand.split(" ");
|
|
|
|
|
2023-08-28 20:26:25 +02:00
|
|
|
// Do not apply aliases when defining a new alias
|
|
|
|
if (commandArray[0] === "unalias" || commandArray[0] === "alias") {
|
|
|
|
return commandArray.join(" ");
|
|
|
|
}
|
2021-09-05 01:09:30 +02:00
|
|
|
|
2023-08-28 20:26:25 +02:00
|
|
|
// First get non-global aliases, and recursively apply them
|
|
|
|
// (unless there are any reference loops or the reference chain is too deep)
|
|
|
|
const localAlias = Aliases.get(commandArray[0]);
|
|
|
|
if (localAlias && !currentlyProcessingAliases.includes(localAlias)) {
|
|
|
|
const appliedAlias = applyAliases(localAlias, depth + 1, [commandArray[0], ...currentlyProcessingAliases]);
|
|
|
|
commandArray.splice(0, 1, ...appliedAlias.split(" "));
|
2021-09-05 01:09:30 +02:00
|
|
|
}
|
2023-08-28 20:26:25 +02:00
|
|
|
|
|
|
|
// Once local aliasing is complete (or if none are present) handle any global aliases
|
|
|
|
const processedCommands = commandArray.reduce((resolvedCommandArray: string[], command) => {
|
|
|
|
const globalAlias = GlobalAliases.get(command);
|
|
|
|
if (globalAlias && !currentlyProcessingAliases.includes(globalAlias)) {
|
|
|
|
const appliedAlias = applyAliases(globalAlias, depth + 1, [command, ...currentlyProcessingAliases]);
|
|
|
|
resolvedCommandArray.push(appliedAlias);
|
|
|
|
} else {
|
|
|
|
// If there is no alias, or if the alias has a circular reference, leave the command as-is
|
|
|
|
resolvedCommandArray.push(command);
|
|
|
|
}
|
|
|
|
return resolvedCommandArray;
|
|
|
|
}, []);
|
|
|
|
|
|
|
|
return processedCommands.join(" ");
|
2017-08-30 19:44:29 +02:00
|
|
|
}
|