mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2024-11-27 01:53:48 +01:00
Merge pull request #2078 from billyvg/feat/open-multiple-files-from-cli
feat: open multiple files from cli
This commit is contained in:
commit
5021013cb7
@ -39,8 +39,8 @@ import { PromptEvent } from "../../ui/React/PromptManager";
|
|||||||
import libSource from "!!raw-loader!../NetscriptDefinitions.d.ts";
|
import libSource from "!!raw-loader!../NetscriptDefinitions.d.ts";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
filename: string;
|
// Map of filename -> code
|
||||||
code: string;
|
files: Record<string, string>;
|
||||||
hostname: string;
|
hostname: string;
|
||||||
player: IPlayer;
|
player: IPlayer;
|
||||||
router: IRouter;
|
router: IRouter;
|
||||||
@ -330,47 +330,54 @@ export function Root(props: IProps): React.ReactElement {
|
|||||||
|
|
||||||
if (editorRef.current === null || monacoRef.current === null) return;
|
if (editorRef.current === null || monacoRef.current === null) return;
|
||||||
|
|
||||||
if (props.filename) {
|
const files = Object.entries(props.files);
|
||||||
// Check if file is already opened
|
|
||||||
const openScriptIndex = openScripts.findIndex(
|
|
||||||
(script) => script.fileName === props.filename && script.hostname === props.hostname,
|
|
||||||
);
|
|
||||||
if (openScriptIndex !== -1) {
|
|
||||||
// Script is already opened
|
|
||||||
if (
|
|
||||||
openScripts[openScriptIndex].model === undefined ||
|
|
||||||
openScripts[openScriptIndex].model === null ||
|
|
||||||
openScripts[openScriptIndex].model.isDisposed()
|
|
||||||
) {
|
|
||||||
regenerateModel(openScripts[openScriptIndex]);
|
|
||||||
}
|
|
||||||
|
|
||||||
setCurrentScript(openScripts[openScriptIndex]);
|
if (!files.length && currentScript !== null) {
|
||||||
editorRef.current.setModel(openScripts[openScriptIndex].model);
|
|
||||||
editorRef.current.setPosition(openScripts[openScriptIndex].lastPosition);
|
|
||||||
editorRef.current.revealLineInCenter(openScripts[openScriptIndex].lastPosition.lineNumber);
|
|
||||||
updateRAM(openScripts[openScriptIndex].code);
|
|
||||||
} else {
|
|
||||||
// Open script
|
|
||||||
const newScript = new OpenScript(
|
|
||||||
props.filename,
|
|
||||||
props.code,
|
|
||||||
props.hostname,
|
|
||||||
new monacoRef.current.Position(0, 0),
|
|
||||||
monacoRef.current.editor.createModel(props.code, props.filename.endsWith(".txt") ? "plaintext" : "javascript"),
|
|
||||||
);
|
|
||||||
setOpenScripts((oldArray) => [...oldArray, newScript]);
|
|
||||||
setCurrentScript({ ...newScript });
|
|
||||||
editorRef.current.setModel(newScript.model);
|
|
||||||
updateRAM(newScript.code);
|
|
||||||
}
|
|
||||||
} else if (currentScript !== null) {
|
|
||||||
// Open currentscript
|
// Open currentscript
|
||||||
regenerateModel(currentScript);
|
regenerateModel(currentScript);
|
||||||
editorRef.current.setModel(currentScript.model);
|
editorRef.current.setModel(currentScript.model);
|
||||||
editorRef.current.setPosition(currentScript.lastPosition);
|
editorRef.current.setPosition(currentScript.lastPosition);
|
||||||
editorRef.current.revealLineInCenter(currentScript.lastPosition.lineNumber);
|
editorRef.current.revealLineInCenter(currentScript.lastPosition.lineNumber);
|
||||||
updateRAM(currentScript.code);
|
updateRAM(currentScript.code);
|
||||||
|
editorRef.current.focus();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!files.length) {
|
||||||
|
editorRef.current.focus();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const [filename, code] of files) {
|
||||||
|
// Check if file is already opened
|
||||||
|
const openScript = openScripts.find(
|
||||||
|
(script) => script.fileName === filename && script.hostname === props.hostname,
|
||||||
|
);
|
||||||
|
if (openScript) {
|
||||||
|
// Script is already opened
|
||||||
|
if (openScript.model === undefined || openScript.model === null || openScript.model.isDisposed()) {
|
||||||
|
regenerateModel(openScript);
|
||||||
|
}
|
||||||
|
|
||||||
|
setCurrentScript(openScript);
|
||||||
|
editorRef.current.setModel(openScript.model);
|
||||||
|
editorRef.current.setPosition(openScript.lastPosition);
|
||||||
|
editorRef.current.revealLineInCenter(openScript.lastPosition.lineNumber);
|
||||||
|
updateRAM(openScript.code);
|
||||||
|
} else {
|
||||||
|
// Open script
|
||||||
|
const newScript = new OpenScript(
|
||||||
|
filename,
|
||||||
|
code,
|
||||||
|
props.hostname,
|
||||||
|
new monacoRef.current.Position(0, 0),
|
||||||
|
monacoRef.current.editor.createModel(code, filename.endsWith(".txt") ? "plaintext" : "javascript"),
|
||||||
|
);
|
||||||
|
setOpenScripts((oldArray) => [...oldArray, newScript]);
|
||||||
|
setCurrentScript({ ...newScript });
|
||||||
|
editorRef.current.setModel(newScript.model);
|
||||||
|
updateRAM(newScript.code);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
editorRef.current.focus();
|
editorRef.current.focus();
|
||||||
|
@ -29,7 +29,7 @@ export const TerminalHelpText: string[] = [
|
|||||||
"lscpu Displays the number of CPU cores on the machine",
|
"lscpu Displays the number of CPU cores on the machine",
|
||||||
"mem [script] [-t] [n] Displays the amount of RAM required to run the script",
|
"mem [script] [-t] [n] Displays the amount of RAM required to run the script",
|
||||||
"mv [src] [dest] Move/rename a text or script file",
|
"mv [src] [dest] Move/rename a text or script file",
|
||||||
"nano [file] Text editor - Open up and edit a script or text file",
|
"nano [file ...] Text editor - Open up and edit one or more scripts or text files",
|
||||||
"ps Display all scripts that are currently running",
|
"ps Display all scripts that are currently running",
|
||||||
"rm [file] Delete a file from the server",
|
"rm [file] Delete a file from the server",
|
||||||
"run [name] [-t n] [--tail] [args...] Execute a program or script",
|
"run [name] [-t n] [--tail] [args...] Execute a program or script",
|
||||||
@ -40,7 +40,7 @@ export const TerminalHelpText: string[] = [
|
|||||||
"tail [script] [args...] Displays dynamic logs for the specified script",
|
"tail [script] [args...] Displays dynamic logs for the specified script",
|
||||||
"top Displays all running scripts and their RAM usage",
|
"top Displays all running scripts and their RAM usage",
|
||||||
"unalias [alias name] Deletes the specified alias",
|
"unalias [alias name] Deletes the specified alias",
|
||||||
"vim [file] Text editor - Open up and edit a script or text file in vim mode",
|
"vim [file ...] Text editor - Open up and edit one or more scripts or text files in vim mode",
|
||||||
"weaken [server] Reduce the security of a server",
|
"weaken [server] Reduce the security of a server",
|
||||||
"wget [url] [target file] Retrieves code/text from a web server",
|
"wget [url] [target file] Retrieves code/text from a web server",
|
||||||
];
|
];
|
||||||
@ -305,9 +305,9 @@ export const HelpTexts: IMap<string[]> = {
|
|||||||
"mv myScript.js myOldScript.js",
|
"mv myScript.js myOldScript.js",
|
||||||
],
|
],
|
||||||
nano: [
|
nano: [
|
||||||
"nano [file name]",
|
"nano [file ...]",
|
||||||
" ",
|
" ",
|
||||||
"Opens up the specified file in the Text Editor. Only scripts (.script) or text files (.txt) can be ",
|
"Opens up the specified file(s) in the Text Editor. Only scripts (.script) or text files (.txt) can be ",
|
||||||
"edited using the Text Editor. If the file does not already exist, then a new, empty one ",
|
"edited using the Text Editor. If the file does not already exist, then a new, empty one ",
|
||||||
"will be created",
|
"will be created",
|
||||||
],
|
],
|
||||||
@ -404,9 +404,9 @@ export const HelpTexts: IMap<string[]> = {
|
|||||||
"It is not necessary to differentiate between global and non-global aliases when using 'unalias'",
|
"It is not necessary to differentiate between global and non-global aliases when using 'unalias'",
|
||||||
],
|
],
|
||||||
vim: [
|
vim: [
|
||||||
"vim [file name]",
|
"vim [file ...]",
|
||||||
" ",
|
" ",
|
||||||
"Opens up the specified file in the Text Editor in vim mode. Only scripts (.script) or text files (.txt) can be ",
|
"Opens up the specified file(s) in the Text Editor in vim mode. Only scripts (.script) or text files (.txt) can be ",
|
||||||
"edited using the Text Editor. If the file does not already exist, then a new, empty one ",
|
"edited using the Text Editor. If the file does not already exist, then a new, empty one ",
|
||||||
"will be created",
|
"will be created",
|
||||||
],
|
],
|
||||||
|
@ -13,53 +13,56 @@ interface EditorParameters {
|
|||||||
args: (string | number | boolean)[];
|
args: (string | number | boolean)[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isNs2(filename: string): boolean {
|
||||||
|
return filename.endsWith(".ns") || filename.endsWith(".js");
|
||||||
|
}
|
||||||
|
|
||||||
export function commonEditor(command: string, {
|
const newNs2Template = `/** @param {NS} ns **/
|
||||||
terminal,
|
export async function main(ns) {
|
||||||
router,
|
|
||||||
player,
|
}`;
|
||||||
server,
|
|
||||||
args,
|
export function commonEditor(
|
||||||
}: EditorParameters, scriptEditorRouteOptions?: ScriptEditorRouteOptions): void {
|
command: string,
|
||||||
if (args.length !== 1) {
|
{ terminal, router, player, server, args }: EditorParameters,
|
||||||
|
scriptEditorRouteOptions?: ScriptEditorRouteOptions,
|
||||||
|
): void {
|
||||||
|
if (args.length < 1) {
|
||||||
terminal.error(`Incorrect usage of ${command} command. Usage: ${command} [scriptname]`);
|
terminal.error(`Incorrect usage of ${command} command. Usage: ${command} [scriptname]`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const filename = args[0] + "";
|
const files = args.map((arg) => {
|
||||||
|
const filename = `${arg}`;
|
||||||
|
|
||||||
if (isScriptFilename(filename)) {
|
if (isScriptFilename(filename)) {
|
||||||
const filepath = terminal.getFilepath(filename);
|
const filepath = terminal.getFilepath(filename);
|
||||||
const script = terminal.getScript(player, filename);
|
const script = terminal.getScript(player, filename);
|
||||||
if (script == null) {
|
const fileIsNs2 = isNs2(filename);
|
||||||
let code = "";
|
const code = script !== null ? script.code : fileIsNs2 ? newNs2Template : "";
|
||||||
if (filename.endsWith(".ns") || filename.endsWith(".js")) {
|
|
||||||
code = `/** @param {NS} ns **/
|
|
||||||
export async function main(ns) {
|
|
||||||
|
|
||||||
}`;
|
if (code === newNs2Template) {
|
||||||
}
|
|
||||||
CursorPositions.saveCursor(filename, {
|
CursorPositions.saveCursor(filename, {
|
||||||
row: 3,
|
row: 3,
|
||||||
column: 5,
|
column: 5,
|
||||||
});
|
});
|
||||||
router.toScriptEditor(filepath, code, scriptEditorRouteOptions);
|
|
||||||
} else {
|
|
||||||
router.toScriptEditor(filepath, script.code, scriptEditorRouteOptions);
|
|
||||||
}
|
}
|
||||||
} else if (filename.endsWith(".txt")) {
|
|
||||||
|
return [filepath, code];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (filename.endsWith(".txt")) {
|
||||||
const filepath = terminal.getFilepath(filename);
|
const filepath = terminal.getFilepath(filename);
|
||||||
const txt = terminal.getTextFile(player, filename);
|
const txt = terminal.getTextFile(player, filename);
|
||||||
if (txt == null) {
|
return [filepath, txt == null ? "" : txt.text];
|
||||||
router.toScriptEditor(filepath, "", scriptEditorRouteOptions);
|
|
||||||
} else {
|
|
||||||
router.toScriptEditor(filepath, txt.text, scriptEditorRouteOptions);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
terminal.error("Invalid file. Only scripts (.script, .ns, .js), or text files (.txt) can be edited with vim");
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
throw new Error(`Invalid file. Only scripts (.script, .ns, .js), or text files (.txt) can be edited with ${command}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
router.toScriptEditor(Object.fromEntries(files), scriptEditorRouteOptions);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
terminal.error(e + "");
|
terminal.error(`${e}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -95,10 +95,6 @@ const useStyles = makeStyles((theme: Theme) =>
|
|||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
let filename = "";
|
|
||||||
let code = "";
|
|
||||||
let vim = false;
|
|
||||||
|
|
||||||
export let Router: IRouter = {
|
export let Router: IRouter = {
|
||||||
page: () => {
|
page: () => {
|
||||||
throw new Error("Router called before initialization");
|
throw new Error("Router called before initialization");
|
||||||
@ -197,6 +193,7 @@ function determineStartPage(player: IPlayer): Page {
|
|||||||
|
|
||||||
export function GameRoot({ player, engine, terminal }: IProps): React.ReactElement {
|
export function GameRoot({ player, engine, terminal }: IProps): React.ReactElement {
|
||||||
const classes = useStyles();
|
const classes = useStyles();
|
||||||
|
const [{files, vim}, setEditorOptions] = useState({files: {}, vim: false})
|
||||||
const [page, setPage] = useState(determineStartPage(player));
|
const [page, setPage] = useState(determineStartPage(player));
|
||||||
const setRerender = useState(0)[1];
|
const setRerender = useState(0)[1];
|
||||||
const [faction, setFaction] = useState<Faction>(
|
const [faction, setFaction] = useState<Faction>(
|
||||||
@ -247,10 +244,11 @@ export function GameRoot({ player, engine, terminal }: IProps): React.ReactEleme
|
|||||||
toHacknetNodes: () => setPage(Page.Hacknet),
|
toHacknetNodes: () => setPage(Page.Hacknet),
|
||||||
toMilestones: () => setPage(Page.Milestones),
|
toMilestones: () => setPage(Page.Milestones),
|
||||||
toResleeves: () => setPage(Page.Resleeves),
|
toResleeves: () => setPage(Page.Resleeves),
|
||||||
toScriptEditor: (fn: string, c: string, options?: ScriptEditorRouteOptions) => {
|
toScriptEditor: (files: Record<string, string>, options?: ScriptEditorRouteOptions) => {
|
||||||
filename = fn;
|
setEditorOptions({
|
||||||
code = c;
|
files,
|
||||||
vim = !!options?.vim;
|
vim: !!options?.vim,
|
||||||
|
});
|
||||||
setPage(Page.ScriptEditor);
|
setPage(Page.ScriptEditor);
|
||||||
},
|
},
|
||||||
toSleeves: () => setPage(Page.Sleeves),
|
toSleeves: () => setPage(Page.Sleeves),
|
||||||
@ -292,8 +290,6 @@ export function GameRoot({ player, engine, terminal }: IProps): React.ReactEleme
|
|||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
filename = "";
|
|
||||||
code = "";
|
|
||||||
if (page !== Page.Terminal) window.scrollTo(0, 0);
|
if (page !== Page.Terminal) window.scrollTo(0, 0);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -332,8 +328,7 @@ export function GameRoot({ player, engine, terminal }: IProps): React.ReactEleme
|
|||||||
<CharacterStats />
|
<CharacterStats />
|
||||||
) : page === Page.ScriptEditor ? (
|
) : page === Page.ScriptEditor ? (
|
||||||
<ScriptEditorRoot
|
<ScriptEditorRoot
|
||||||
filename={filename}
|
files={files}
|
||||||
code={code}
|
|
||||||
hostname={player.getCurrentServer().hostname}
|
hostname={player.getCurrentServer().hostname}
|
||||||
player={player}
|
player={player}
|
||||||
router={Router}
|
router={Router}
|
||||||
|
@ -70,7 +70,7 @@ export interface IRouter {
|
|||||||
toJob(): void;
|
toJob(): void;
|
||||||
toMilestones(): void;
|
toMilestones(): void;
|
||||||
toResleeves(): void;
|
toResleeves(): void;
|
||||||
toScriptEditor(filename?: string, code?: string, options?: ScriptEditorRouteOptions): void;
|
toScriptEditor(files?: Record<string, string>, options?: ScriptEditorRouteOptions): void;
|
||||||
toSleeves(): void;
|
toSleeves(): void;
|
||||||
toStockMarket(): void;
|
toStockMarket(): void;
|
||||||
toTerminal(): void;
|
toTerminal(): void;
|
||||||
|
Loading…
Reference in New Issue
Block a user