From 4603216aa07eaba864b19d0936ae0653bcfec064 Mon Sep 17 00:00:00 2001 From: Olivier Gagnon Date: Thu, 14 Oct 2021 22:36:28 -0400 Subject: [PATCH 1/4] autocomplete --- src/Terminal/Terminal.ts | 1 - src/Terminal/commands/run.ts | 9 ------ ...termineAllPossibilitiesForTabCompletion.ts | 32 ++++++++++++++++--- src/Terminal/tabCompletion.ts | 2 +- src/Terminal/ui/TerminalInput.tsx | 7 ++-- 5 files changed, 32 insertions(+), 19 deletions(-) diff --git a/src/Terminal/Terminal.ts b/src/Terminal/Terminal.ts index 8479455f5..35b0f3363 100644 --- a/src/Terminal/Terminal.ts +++ b/src/Terminal/Terminal.ts @@ -543,7 +543,6 @@ export class Terminal implements ITerminal { } clear(): void { - // TODO: remove this once we figure out the height issue. this.outputHistory = [new Output(`Bitburner v${CONSTANTS.Version}`, "primary")]; TerminalEvents.emit(); TerminalClearEvents.emit(); diff --git a/src/Terminal/commands/run.ts b/src/Terminal/commands/run.ts index 70652ad86..99fdf0155 100644 --- a/src/Terminal/commands/run.ts +++ b/src/Terminal/commands/run.ts @@ -19,15 +19,6 @@ export function run( } else { const executableName = args[0] + ""; - // Secret Music player! - // if (executableName === "musicplayer") { - // post( - // '', - // false, - // ); - // return; - // } - // Check if its a script or just a program/executable if (isScriptFilename(executableName)) { runScript(terminal, router, player, server, args); diff --git a/src/Terminal/determineAllPossibilitiesForTabCompletion.ts b/src/Terminal/determineAllPossibilitiesForTabCompletion.ts index d65c8834d..82a2d1ef6 100644 --- a/src/Terminal/determineAllPossibilitiesForTabCompletion.ts +++ b/src/Terminal/determineAllPossibilitiesForTabCompletion.ts @@ -3,9 +3,10 @@ import { getSubdirectories } from "./DirectoryServerHelpers"; import { Aliases, GlobalAliases } from "../Alias"; import { DarkWebItems } from "../DarkWeb/DarkWebItems"; -import { Message } from "../Message/Message"; import { IPlayer } from "../PersonObjects/IPlayer"; import { GetServer, GetAllServers } from "../Server/AllServers"; +import { ParseCommand, ParseCommands } from "./Parser"; +import { isScriptFilename } from "../Script/isScriptFilename"; // An array of all Terminal commands const commands = [ @@ -48,12 +49,12 @@ const commands = [ "weaken", ]; -export function determineAllPossibilitiesForTabCompletion( +export async function determineAllPossibilitiesForTabCompletion( p: IPlayer, input: string, index: number, currPath = "", -): string[] { +): Promise { let allPos: string[] = []; allPos = allPos.concat(Object.keys(GlobalAliases)); const currServ = p.getCurrentServer(); @@ -287,13 +288,34 @@ export function determineAllPossibilitiesForTabCompletion( return allPos; } + async function scriptAutocomplete(): Promise { + if (!isCommand("run")) return; + const commands = ParseCommands(input); + if (commands.length === 0) return; + const command = ParseCommand(commands[commands.length - 1]); + const filename = command[1] + ""; + if (!isScriptFilename(filename)) return; // Not a script. + if (filename.endsWith(".script")) return; // Doesn't work with ns1. + const script = currServ.scripts.find((script) => script.filename === filename); + if (!script) return; // Doesn't exist. + // TODO compile if needs be. + console.log("asd1"); + if (!script.module) return; + const loadedModule = await script.module; + console.log("asd2"); + if (!loadedModule.autocomplete) return; // Doesn't have an autocomplete function. + console.log(loadedModule.autocomplete()); + return loadedModule.autocomplete(); + } + const pos = await scriptAutocomplete(); + console.log(pos); + if (pos) return pos; + if (isCommand("run")) { addAllScripts(); addAllPrograms(); addAllCodingContracts(); addAllDirectories(); - - return allPos; } if (isCommand("cat")) { diff --git a/src/Terminal/tabCompletion.ts b/src/Terminal/tabCompletion.ts index cfeea5bd6..288503f21 100644 --- a/src/Terminal/tabCompletion.ts +++ b/src/Terminal/tabCompletion.ts @@ -44,7 +44,7 @@ export function tabCompletion( } else if (allPossibilities.length === 1) { if (arg === "") { //Autocomplete command - val = allPossibilities[0] + " "; + val = allPossibilities[0]; } else { val = command + " " + allPossibilities[0]; } diff --git a/src/Terminal/ui/TerminalInput.tsx b/src/Terminal/ui/TerminalInput.tsx index dc6ea49a6..c841ccf50 100644 --- a/src/Terminal/ui/TerminalInput.tsx +++ b/src/Terminal/ui/TerminalInput.tsx @@ -162,7 +162,7 @@ export function TerminalInput({ terminal, router, player }: IProps): React.React return () => document.removeEventListener("keydown", keyDown); }); - function onKeyDown(event: React.KeyboardEvent): void { + async function onKeyDown(event: React.KeyboardEvent): Promise { // Run command. if (event.keyCode === KEY.ENTER && value !== "") { event.preventDefault(); @@ -190,7 +190,7 @@ export function TerminalInput({ terminal, router, player }: IProps): React.React if (index < -1) { index = 0; } - const allPos = determineAllPossibilitiesForTabCompletion(player, copy, index, terminal.cwd()); + const allPos = await determineAllPossibilitiesForTabCompletion(player, copy, index, terminal.cwd()); if (allPos.length == 0) { return; } @@ -213,8 +213,9 @@ export function TerminalInput({ terminal, router, player }: IProps): React.React command = commandArray.join(" "); } - const newValue = tabCompletion(command, arg, allPos, value); + let newValue = tabCompletion(command, arg, allPos, value); if (typeof newValue === "string" && newValue !== "") { + if (!newValue.endsWith(" ") && allPos.length === 1) newValue += " "; saveValue(newValue); } if (Array.isArray(newValue)) { From 7417ff8a100c1d990ce20ded6ae561f835ce0bac Mon Sep 17 00:00:00 2001 From: Olivier Gagnon Date: Thu, 14 Oct 2021 23:11:31 -0400 Subject: [PATCH 2/4] tmp --- src/Terminal/determineAllPossibilitiesForTabCompletion.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/Terminal/determineAllPossibilitiesForTabCompletion.ts b/src/Terminal/determineAllPossibilitiesForTabCompletion.ts index 82a2d1ef6..ea4ef3337 100644 --- a/src/Terminal/determineAllPossibilitiesForTabCompletion.ts +++ b/src/Terminal/determineAllPossibilitiesForTabCompletion.ts @@ -299,16 +299,12 @@ export async function determineAllPossibilitiesForTabCompletion( const script = currServ.scripts.find((script) => script.filename === filename); if (!script) return; // Doesn't exist. // TODO compile if needs be. - console.log("asd1"); if (!script.module) return; const loadedModule = await script.module; - console.log("asd2"); if (!loadedModule.autocomplete) return; // Doesn't have an autocomplete function. - console.log(loadedModule.autocomplete()); return loadedModule.autocomplete(); } const pos = await scriptAutocomplete(); - console.log(pos); if (pos) return pos; if (isCommand("run")) { From 6b0e5416c48cbcffc86c3f5fc67f993bb36e9ec0 Mon Sep 17 00:00:00 2001 From: Olivier Gagnon Date: Fri, 15 Oct 2021 12:47:43 -0400 Subject: [PATCH 3/4] wtf --- .../advancedfunctions/autocomplete.rst | 36 +++++++++ src/NetscriptFunctions.ts | 78 ++----------------- src/NetscriptFunctions/Flags.ts | 37 +++++++++ src/NetscriptFunctions/toNative.ts | 36 +++++++++ src/NetscriptJSEvaluator.ts | 32 ++++---- ...termineAllPossibilitiesForTabCompletion.ts | 25 +++++- 6 files changed, 154 insertions(+), 90 deletions(-) create mode 100644 doc/source/netscript/advancedfunctions/autocomplete.rst create mode 100644 src/NetscriptFunctions/Flags.ts create mode 100644 src/NetscriptFunctions/toNative.ts diff --git a/doc/source/netscript/advancedfunctions/autocomplete.rst b/doc/source/netscript/advancedfunctions/autocomplete.rst new file mode 100644 index 000000000..c64020a82 --- /dev/null +++ b/doc/source/netscript/advancedfunctions/autocomplete.rst @@ -0,0 +1,36 @@ +autocomplete() Netscript Function +============================ + +.. warning:: This feature is not officially supported yet and the API might change. + +.. js:function:: autocomplete(data, args) + + :RAM cost: 0 GB + :param Object data: general data about the game you might want to autocomplete. + :param string[] args: current arguments. + + data is an object with the following properties:: + + { + servers: list of all servers in the game. + txts: list of all text files on the current server. + scripts: list of all scripts on the current server. + } + + Example: + + .. code-block:: javascript + + export function autocomplete(data, args) { + return [...data.servers]; // This script autocompletes the list of servers. + return [...data.servers, ...data.scripts]; // Autocomplete servers and scripts + return ["low", "medium", "high"]; // Autocomplete 3 specific strings. + } + + Terminal: + + .. code-block:: javascript + + $ run demo.ns mega\t + // results in + $ run demo.ns megacorp diff --git a/src/NetscriptFunctions.ts b/src/NetscriptFunctions.ts index 2caa77aea..be4f43db8 100644 --- a/src/NetscriptFunctions.ts +++ b/src/NetscriptFunctions.ts @@ -1,5 +1,4 @@ import { vsprintf, sprintf } from "sprintf-js"; -import * as libarg from "arg"; import { getRamCost } from "./Netscript/RamCostGenerator"; import { WorkerScriptStartStopEventEmitter } from "./Netscript/WorkerScriptStartStopEventEmitter"; @@ -58,7 +57,6 @@ import { killWorkerScript } from "./Netscript/killWorkerScript"; import { workerScripts } from "./Netscript/WorkerScripts"; import { WorkerScript } from "./Netscript/WorkerScript"; import { makeRuntimeRejectMsg, netscriptDelay, resolveNetscriptRequestedThreads } from "./NetscriptEvaluator"; -import { Interpreter } from "./ThirdParty/JSInterpreter"; import { Router } from "./ui/GameRoot"; import { numeralWrapper } from "./ui/numeralFormat"; @@ -84,44 +82,12 @@ import { INetscriptFormulas, NetscriptFormulas } from "./NetscriptFunctions/Form import { INetscriptAugmentations, NetscriptAugmentations } from "./NetscriptFunctions/Augmentations"; import { INetscriptStockMarket, NetscriptStockMarket } from "./NetscriptFunctions/StockMarket"; +import { toNative } from "./NetscriptFunctions/toNative"; + import { dialogBoxCreate } from "./ui/React/DialogBox"; import { SnackbarEvents } from "./ui/React/Snackbar"; import { Locations } from "./Locations/Locations"; - -const defaultInterpreter = new Interpreter("", () => undefined); - -// the acorn interpreter has a bug where it doesn't convert arrays correctly. -// so we have to more or less copy it here. -function toNative(pseudoObj: any): any { - if (pseudoObj == null) return null; - if ( - !pseudoObj.hasOwnProperty("properties") || - !pseudoObj.hasOwnProperty("getter") || - !pseudoObj.hasOwnProperty("setter") || - !pseudoObj.hasOwnProperty("proto") - ) { - return pseudoObj; // it wasn't a pseudo object anyway. - } - - let nativeObj: any; - if (pseudoObj.hasOwnProperty("class") && pseudoObj.class === "Array") { - nativeObj = []; - const length = defaultInterpreter.getProperty(pseudoObj, "length"); - for (let i = 0; i < length; i++) { - if (defaultInterpreter.hasProperty(pseudoObj, i)) { - nativeObj[i] = toNative(defaultInterpreter.getProperty(pseudoObj, i)); - } - } - } else { - // Object. - nativeObj = {}; - for (const key in pseudoObj.properties) { - const val = pseudoObj.properties[key]; - nativeObj[key] = toNative(val); - } - } - return nativeObj; -} +import { Flags } from "./NetscriptFunctions/Flags"; interface NS extends INetscriptExtra, INetscriptAugmentations, INetscriptStockMarket { [key: string]: any; @@ -363,6 +329,9 @@ function NetscriptFunctions(workerScript: WorkerScript): NS { return Factions[name]; }; + console.log(workerScript); + console.log(workerScript.args); + const hack = function (ip: any, manual: any, { threads: requestedThreads, stock }: any = {}): Promise { if (ip === undefined) { throw makeRuntimeErrorMsg("hack", "Takes 1 argument."); @@ -1846,7 +1815,6 @@ function NetscriptFunctions(workerScript: WorkerScript): NS { throw makeRuntimeErrorMsg("read", `Could not find port: ${port}. This is a bug. Report to dev.`); } const x = iport.read(); - console.log(x); return x; } else if (isString(port)) { // Read from script or text file @@ -1895,7 +1863,6 @@ function NetscriptFunctions(workerScript: WorkerScript): NS { throw makeRuntimeErrorMsg("peek", `Could not find port: ${port}. This is a bug. Report to dev.`); } const x = iport.peek(); - console.log(x); return x; }, clear: function (port: any): any { @@ -3284,38 +3251,7 @@ function NetscriptFunctions(workerScript: WorkerScript): NS { } workerScript.atExit = f; }, - flags: function (data: any): any { - data = toNative(data); - // We always want the help flag. - const args: { - [key: string]: any; - } = {}; - - for (const d of data) { - let t: any = String; - if (typeof d[1] === "number") { - t = Number; - } else if (typeof d[1] === "boolean") { - t = Boolean; - } else if (Array.isArray(d[1])) { - t = [String]; - } - const numDashes = d[0].length > 1 ? 2 : 1; - args["-".repeat(numDashes) + d[0]] = t; - } - const ret = libarg(args, { argv: workerScript.args }); - for (const d of data) { - if (!ret.hasOwnProperty("--" + d[0]) || !ret.hasOwnProperty("-" + d[0])) ret[d[0]] = d[1]; - } - for (const key of Object.keys(ret)) { - if (!key.startsWith("-")) continue; - const value = ret[key]; - delete ret[key]; - const numDashes = key.length === 2 ? 1 : 2; - ret[key.slice(numDashes)] = value; - } - return ret; - }, + flags: Flags(workerScript.args), ...extra, }; diff --git a/src/NetscriptFunctions/Flags.ts b/src/NetscriptFunctions/Flags.ts new file mode 100644 index 000000000..37fbda386 --- /dev/null +++ b/src/NetscriptFunctions/Flags.ts @@ -0,0 +1,37 @@ +import { toNative } from "./toNative"; +import * as libarg from "arg"; + +export function Flags(vargs: string[]): any { + return function (data: any): any { + data = toNative(data); + // We always want the help flag. + const args: { + [key: string]: any; + } = {}; + + for (const d of data) { + let t: any = String; + if (typeof d[1] === "number") { + t = Number; + } else if (typeof d[1] === "boolean") { + t = Boolean; + } else if (Array.isArray(d[1])) { + t = [String]; + } + const numDashes = d[0].length > 1 ? 2 : 1; + args["-".repeat(numDashes) + d[0]] = t; + } + const ret = libarg(args, { argv: vargs }); + for (const d of data) { + if (!ret.hasOwnProperty("--" + d[0]) || !ret.hasOwnProperty("-" + d[0])) ret[d[0]] = d[1]; + } + for (const key of Object.keys(ret)) { + if (!key.startsWith("-")) continue; + const value = ret[key]; + delete ret[key]; + const numDashes = key.length === 2 ? 1 : 2; + ret[key.slice(numDashes)] = value; + } + return ret; + }; +} diff --git a/src/NetscriptFunctions/toNative.ts b/src/NetscriptFunctions/toNative.ts new file mode 100644 index 000000000..1f43fb03c --- /dev/null +++ b/src/NetscriptFunctions/toNative.ts @@ -0,0 +1,36 @@ +import { Interpreter } from "../ThirdParty/JSInterpreter"; + +const defaultInterpreter = new Interpreter("", () => undefined); + +// the acorn interpreter has a bug where it doesn't convert arrays correctly. +// so we have to more or less copy it here. +export function toNative(pseudoObj: any): any { + if (pseudoObj == null) return null; + if ( + !pseudoObj.hasOwnProperty("properties") || + !pseudoObj.hasOwnProperty("getter") || + !pseudoObj.hasOwnProperty("setter") || + !pseudoObj.hasOwnProperty("proto") + ) { + return pseudoObj; // it wasn't a pseudo object anyway. + } + + let nativeObj: any; + if (pseudoObj.hasOwnProperty("class") && pseudoObj.class === "Array") { + nativeObj = []; + const length = defaultInterpreter.getProperty(pseudoObj, "length"); + for (let i = 0; i < length; i++) { + if (defaultInterpreter.hasProperty(pseudoObj, i)) { + nativeObj[i] = toNative(defaultInterpreter.getProperty(pseudoObj, i)); + } + } + } else { + // Object. + nativeObj = {}; + for (const key in pseudoObj.properties) { + const val = pseudoObj.properties[key]; + nativeObj[key] = toNative(val); + } + } + return nativeObj; +} diff --git a/src/NetscriptJSEvaluator.ts b/src/NetscriptJSEvaluator.ts index 1e70e5cf2..6f615914a 100644 --- a/src/NetscriptJSEvaluator.ts +++ b/src/NetscriptJSEvaluator.ts @@ -8,7 +8,21 @@ function makeScriptBlob(code: string): Blob { return new Blob([code], { type: "text/javascript" }); } -export function compile(script: Script, scripts: Script[]): void {} +export function compile(script: Script, scripts: Script[]): void { + if (!shouldCompile(script, scripts)) return; + // The URL at the top is the one we want to import. It will + // recursively import all the other modules in the urlStack. + // + // Webpack likes to turn the import into a require, which sort of + // but not really behaves like import. Particularly, it cannot + // load fully dynamic content. So we hide the import from webpack + // by placing it inside an eval call. + script.markUpdated(); + const uurls = _getScriptUrls(script, scripts, []); + script.url = uurls[uurls.length - 1].url; + script.module = new Promise((resolve) => resolve(eval("import(uurls[uurls.length - 1].url)"))); + script.dependencies = uurls; +} // Begin executing a user JS script, and return a promise that resolves // or rejects when the script finishes. @@ -19,23 +33,9 @@ export function compile(script: Script, scripts: Script[]): void {} // When the promise returned by this resolves, we'll have finished // running the main function of the script. export async function executeJSScript(scripts: Script[] = [], workerScript: WorkerScript): Promise { - let uurls: ScriptUrl[] = []; const script = workerScript.getScript(); if (script === null) throw new Error("script is null"); - if (shouldCompile(script, scripts)) { - // The URL at the top is the one we want to import. It will - // recursively import all the other modules in the urlStack. - // - // Webpack likes to turn the import into a require, which sort of - // but not really behaves like import. Particularly, it cannot - // load fully dynamic content. So we hide the import from webpack - // by placing it inside an eval call. - script.markUpdated(); - uurls = _getScriptUrls(script, scripts, []); - script.url = uurls[uurls.length - 1].url; - script.module = new Promise((resolve) => resolve(eval("import(uurls[uurls.length - 1].url)"))); - script.dependencies = uurls; - } + compile(script, scripts); const loadedModule = await script.module; const ns = workerScript.env.vars; diff --git a/src/Terminal/determineAllPossibilitiesForTabCompletion.ts b/src/Terminal/determineAllPossibilitiesForTabCompletion.ts index ea4ef3337..0dab7788b 100644 --- a/src/Terminal/determineAllPossibilitiesForTabCompletion.ts +++ b/src/Terminal/determineAllPossibilitiesForTabCompletion.ts @@ -7,6 +7,9 @@ import { IPlayer } from "../PersonObjects/IPlayer"; import { GetServer, GetAllServers } from "../Server/AllServers"; import { ParseCommand, ParseCommands } from "./Parser"; import { isScriptFilename } from "../Script/isScriptFilename"; +import { compile } from "../NetscriptJSEvaluator"; +import { Flags } from "../NetscriptFunctions/Flags"; +import * as libarg from "arg"; // An array of all Terminal commands const commands = [ @@ -298,11 +301,27 @@ export async function determineAllPossibilitiesForTabCompletion( if (filename.endsWith(".script")) return; // Doesn't work with ns1. const script = currServ.scripts.find((script) => script.filename === filename); if (!script) return; // Doesn't exist. - // TODO compile if needs be. - if (!script.module) return; + if (!script.module) { + compile(script, currServ.scripts); + } const loadedModule = await script.module; if (!loadedModule.autocomplete) return; // Doesn't have an autocomplete function. - return loadedModule.autocomplete(); + + const runArgs = { "--tail": Boolean, "-t": Number }; + const flags = libarg(runArgs, { + permissive: true, + argv: command.slice(2), + }); + + return loadedModule.autocomplete( + { + servers: GetAllServers().map((server) => server.hostname), + scripts: currServ.scripts.map((script) => script.filename), + txts: currServ.textFiles.map((txt) => txt.fn), + flags: Flags(flags._), + }, + flags._, + ); } const pos = await scriptAutocomplete(); if (pos) return pos; From c1d4ced3311bb1450d2d4f598b0016cb046480ba Mon Sep 17 00:00:00 2001 From: Olivier Gagnon Date: Fri, 15 Oct 2021 13:12:18 -0400 Subject: [PATCH 4/4] autocomplete --- src/Hacknet/HacknetHelpers.tsx | 1 - src/Netscript/WorkerScript.ts | 6 ++-- src/NetscriptFunctions.ts | 3 -- src/Server/Server.ts | 1 - ...termineAllPossibilitiesForTabCompletion.ts | 30 +++++++++++++------ src/utils/JSONReviver.ts | 2 +- 6 files changed, 24 insertions(+), 19 deletions(-) diff --git a/src/Hacknet/HacknetHelpers.tsx b/src/Hacknet/HacknetHelpers.tsx index 0047543f3..0df69c071 100644 --- a/src/Hacknet/HacknetHelpers.tsx +++ b/src/Hacknet/HacknetHelpers.tsx @@ -512,7 +512,6 @@ export function purchaseHashUpgrade(player: IPlayer, upgName: string, upgTarget: const old = target.moneyMax; target.changeMaximumMoney(upg.value); - console.log(target.moneyMax / old); } catch (e) { player.hashManager.refundUpgrade(upgName); return false; diff --git a/src/Netscript/WorkerScript.ts b/src/Netscript/WorkerScript.ts index 0d69351b1..084024e1a 100644 --- a/src/Netscript/WorkerScript.ts +++ b/src/Netscript/WorkerScript.ts @@ -137,15 +137,13 @@ export class WorkerScript { if (!found) { throw new Error(`WorkerScript constructed with invalid script filename: ${this.name}`); } - + this.scriptRef = runningScriptObj; + this.args = runningScriptObj.args.slice(); this.env = new Environment(null); if (typeof nsFuncsGenerator === "function") { this.env.vars = nsFuncsGenerator(this); } this.env.set("args", runningScriptObj.args.slice()); - - this.scriptRef = runningScriptObj; - this.args = runningScriptObj.args.slice(); } /** diff --git a/src/NetscriptFunctions.ts b/src/NetscriptFunctions.ts index be4f43db8..933e79a00 100644 --- a/src/NetscriptFunctions.ts +++ b/src/NetscriptFunctions.ts @@ -329,9 +329,6 @@ function NetscriptFunctions(workerScript: WorkerScript): NS { return Factions[name]; }; - console.log(workerScript); - console.log(workerScript.args); - const hack = function (ip: any, manual: any, { threads: requestedThreads, stock }: any = {}): Promise { if (ip === undefined) { throw makeRuntimeErrorMsg("hack", "Takes 1 argument."); diff --git a/src/Server/Server.ts b/src/Server/Server.ts index fdec8c148..0f24ec61e 100644 --- a/src/Server/Server.ts +++ b/src/Server/Server.ts @@ -132,7 +132,6 @@ export class Server extends BaseServer { const aboveCap = this.moneyMax - softCap; n = 1 + (n - 1) / Math.log(aboveCap) / Math.log(8); } - console.log(n); this.moneyMax *= n; } diff --git a/src/Terminal/determineAllPossibilitiesForTabCompletion.ts b/src/Terminal/determineAllPossibilitiesForTabCompletion.ts index 0dab7788b..68c94cffc 100644 --- a/src/Terminal/determineAllPossibilitiesForTabCompletion.ts +++ b/src/Terminal/determineAllPossibilitiesForTabCompletion.ts @@ -312,16 +312,28 @@ export async function determineAllPossibilitiesForTabCompletion( permissive: true, argv: command.slice(2), }); - - return loadedModule.autocomplete( - { - servers: GetAllServers().map((server) => server.hostname), - scripts: currServ.scripts.map((script) => script.filename), - txts: currServ.textFiles.map((txt) => txt.fn), - flags: Flags(flags._), - }, - flags._, + const flagFunc = Flags(flags._); + let pos: string[] = []; + let pos2: string[] = []; + pos = pos.concat( + loadedModule.autocomplete( + { + servers: GetAllServers().map((server) => server.hostname), + scripts: currServ.scripts.map((script) => script.filename), + txts: currServ.textFiles.map((txt) => txt.fn), + flags: (schema: any) => { + pos2 = schema.map((f: any) => "--" + f[0]); + try { + return flagFunc(schema); + } catch (err) { + return undefined; + } + }, + }, + flags._, + ), ); + return pos.concat(pos2); } const pos = await scriptAutocomplete(); if (pos) return pos; diff --git a/src/utils/JSONReviver.ts b/src/utils/JSONReviver.ts index 2ec5df665..53eda183c 100644 --- a/src/utils/JSONReviver.ts +++ b/src/utils/JSONReviver.ts @@ -19,7 +19,7 @@ export function Reviver(key: string, value: IReviverValue | null): any { // Compatibility for version v0.43.1 // TODO Remove this eventually if (value.ctor === "AllServersMap") { - console.log("Converting AllServersMap for v0.43.1"); + console.warning("Converting AllServersMap for v0.43.1"); return value.data; }