mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2024-12-18 20:25:45 +01:00
wtf
This commit is contained in:
parent
745fb4fdf6
commit
6b0e5416c4
36
doc/source/netscript/advancedfunctions/autocomplete.rst
Normal file
36
doc/source/netscript/advancedfunctions/autocomplete.rst
Normal file
@ -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
|
@ -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<number> {
|
||||
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,
|
||||
};
|
||||
|
||||
|
37
src/NetscriptFunctions/Flags.ts
Normal file
37
src/NetscriptFunctions/Flags.ts
Normal file
@ -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;
|
||||
};
|
||||
}
|
36
src/NetscriptFunctions/toNative.ts
Normal file
36
src/NetscriptFunctions/toNative.ts
Normal file
@ -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;
|
||||
}
|
@ -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<void> {
|
||||
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;
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user