bitburner-src/src/Terminal/tabCompletion.ts
Olivier Gagnon 4603216aa0 autocomplete
2021-10-14 22:36:28 -04:00

94 lines
2.9 KiB
TypeScript

import { containsAllStrings, longestCommonStart } from "../utils/StringHelperFunctions";
/**
* Implements tab completion for the Terminal
*
* @param command {string} Terminal command, excluding the last incomplete argument
* @param arg {string} Last argument that is being completed
* @param allPossibilities {string[]} All values that `arg` can complete to
*/
export function tabCompletion(
command: string,
arg: string,
allPossibilities: string[],
oldValue: string,
): string[] | string | undefined {
if (!(allPossibilities.constructor === Array)) {
return;
}
if (!containsAllStrings(allPossibilities)) {
return;
}
// Remove all options in allPossibilities that do not match the current string
// that we are attempting to autocomplete
if (arg === "") {
for (let i = allPossibilities.length - 1; i >= 0; --i) {
if (!allPossibilities[i].toLowerCase().startsWith(command.toLowerCase())) {
allPossibilities.splice(i, 1);
}
}
} else {
for (let i = allPossibilities.length - 1; i >= 0; --i) {
if (!allPossibilities[i].toLowerCase().startsWith(arg.toLowerCase())) {
allPossibilities.splice(i, 1);
}
}
}
const semiColonIndex = oldValue.lastIndexOf(";");
let val = "";
if (allPossibilities.length === 0) {
return;
} else if (allPossibilities.length === 1) {
if (arg === "") {
//Autocomplete command
val = allPossibilities[0];
} else {
val = command + " " + allPossibilities[0];
}
if (semiColonIndex === -1) {
// No semicolon, so replace the whole command
return val;
} else {
// Replace only after the last semicolon
return oldValue.slice(0, semiColonIndex + 1) + " " + val;
}
} else {
const longestStartSubstr = longestCommonStart(allPossibilities);
/**
* If the longest common starting substring of remaining possibilities is the same
* as whatevers already in terminal, just list all possible options. Otherwise,
* change the input in the terminal to the longest common starting substr
*/
if (arg === "") {
if (longestStartSubstr === command) {
return allPossibilities;
} else {
if (semiColonIndex === -1) {
// No semicolon, so replace the whole command
return longestStartSubstr;
} else {
// Replace only after the last semicolon
return `${oldValue.slice(0, semiColonIndex + 1)} ${longestStartSubstr}`;
}
}
} else {
if (longestStartSubstr === arg) {
// List all possible options
return allPossibilities;
} else {
if (semiColonIndex == -1) {
// No semicolon, so replace the whole command
return `${command} ${longestStartSubstr}`;
} else {
// Replace only after the last semicolon
return `${oldValue.slice(0, semiColonIndex + 1)} ${command} ${longestStartSubstr}`;
}
}
}
}
}