mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2026-04-20 16:22:56 +02:00
prettify, sorry for the big ass commit
This commit is contained in:
@@ -1,5 +1,4 @@
|
||||
|
||||
export interface Options {
|
||||
theme: string;
|
||||
insertSpaces: boolean;
|
||||
}
|
||||
theme: string;
|
||||
insertSpaces: boolean;
|
||||
}
|
||||
|
||||
@@ -1,39 +1,49 @@
|
||||
import React, { useState } from 'react';
|
||||
import React, { useState } from "react";
|
||||
import { Options } from "./Options";
|
||||
import { StdButton } from "../../ui/React/StdButton";
|
||||
import { removePopup } from "../../ui/React/createPopup";
|
||||
|
||||
interface IProps {
|
||||
id: string;
|
||||
options: Options;
|
||||
save: (options: Options) => void;
|
||||
id: string;
|
||||
options: Options;
|
||||
save: (options: Options) => void;
|
||||
}
|
||||
|
||||
export function OptionsPopup(props: IProps): React.ReactElement {
|
||||
const [theme, setTheme] = useState(props.options.theme);
|
||||
const [insertSpaces, setInsertSpaces] = useState(props.options.insertSpaces);
|
||||
const [theme, setTheme] = useState(props.options.theme);
|
||||
const [insertSpaces, setInsertSpaces] = useState(props.options.insertSpaces);
|
||||
|
||||
function save() {
|
||||
props.save({
|
||||
theme: theme,
|
||||
insertSpaces: insertSpaces,
|
||||
});
|
||||
removePopup(props.id);
|
||||
}
|
||||
function save() {
|
||||
props.save({
|
||||
theme: theme,
|
||||
insertSpaces: insertSpaces,
|
||||
});
|
||||
removePopup(props.id);
|
||||
}
|
||||
|
||||
return (<div className="editor-options-container noselect">
|
||||
<div className="editor-options-line">
|
||||
<p>Theme: </p>
|
||||
<select className="dropdown" onChange={event => setTheme(event.target.value)} defaultValue={theme}>
|
||||
<option value="vs-dark">vs-dark</option>
|
||||
<option value="light">light</option>
|
||||
</select>
|
||||
</div>
|
||||
<div className="editor-options-line">
|
||||
<p>Use whitespace over tabs: </p>
|
||||
<input type="checkbox" onChange={event => setInsertSpaces(event.target.checked)} checked={insertSpaces} />
|
||||
</div>
|
||||
<br />
|
||||
<StdButton style={{width: '50px'}} text={"Save"} onClick={save} />
|
||||
</div>);
|
||||
}
|
||||
return (
|
||||
<div className="editor-options-container noselect">
|
||||
<div className="editor-options-line">
|
||||
<p>Theme: </p>
|
||||
<select
|
||||
className="dropdown"
|
||||
onChange={(event) => setTheme(event.target.value)}
|
||||
defaultValue={theme}
|
||||
>
|
||||
<option value="vs-dark">vs-dark</option>
|
||||
<option value="light">light</option>
|
||||
</select>
|
||||
</div>
|
||||
<div className="editor-options-line">
|
||||
<p>Use whitespace over tabs: </p>
|
||||
<input
|
||||
type="checkbox"
|
||||
onChange={(event) => setInsertSpaces(event.target.checked)}
|
||||
checked={insertSpaces}
|
||||
/>
|
||||
</div>
|
||||
<br />
|
||||
<StdButton style={{ width: "50px" }} text={"Save"} onClick={save} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
+328
-262
@@ -1,4 +1,4 @@
|
||||
import React, { useState, useEffect, useRef } from 'react';
|
||||
import React, { useState, useEffect, useRef } from "react";
|
||||
import { StdButton } from "../../ui/React/StdButton";
|
||||
import Editor from "@monaco-editor/react";
|
||||
import * as monaco from "monaco-editor";
|
||||
@@ -6,7 +6,7 @@ type IStandaloneCodeEditor = monaco.editor.IStandaloneCodeEditor;
|
||||
import { createPopup } from "../../ui/React/createPopup";
|
||||
import { OptionsPopup } from "./OptionsPopup";
|
||||
import { Options } from "./Options";
|
||||
import { js_beautify as beautifyCode } from 'js-beautify';
|
||||
import { js_beautify as beautifyCode } from "js-beautify";
|
||||
import { isValidFilePath } from "../../Terminal/DirectoryHelpers";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { IEngine } from "../../IEngine";
|
||||
@@ -25,40 +25,39 @@ import { WorkerScript } from "../../Netscript/WorkerScript";
|
||||
import { Settings } from "../../Settings/Settings";
|
||||
import { GetServerByHostname } from "../../Server/ServerHelpers";
|
||||
import {
|
||||
iTutorialNextStep,
|
||||
ITutorial,
|
||||
iTutorialSteps,
|
||||
iTutorialNextStep,
|
||||
ITutorial,
|
||||
iTutorialSteps,
|
||||
} from "../../InteractiveTutorial";
|
||||
|
||||
let symbols: string[] = [];
|
||||
(function() {
|
||||
const ns = NetscriptFunctions(({} as WorkerScript));
|
||||
(function () {
|
||||
const ns = NetscriptFunctions({} as WorkerScript);
|
||||
|
||||
function populate(ns: any): string[] {
|
||||
let symbols: string[] = [];
|
||||
const keys = Object.keys(ns);
|
||||
for(const key of keys) {
|
||||
if(typeof ns[key] === 'object') {
|
||||
symbols.push(key);
|
||||
symbols = symbols.concat(populate(ns[key]));
|
||||
}
|
||||
if(typeof ns[key] === 'function') {
|
||||
symbols.push(key);
|
||||
}
|
||||
}
|
||||
return symbols;
|
||||
function populate(ns: any): string[] {
|
||||
let symbols: string[] = [];
|
||||
const keys = Object.keys(ns);
|
||||
for (const key of keys) {
|
||||
if (typeof ns[key] === "object") {
|
||||
symbols.push(key);
|
||||
symbols = symbols.concat(populate(ns[key]));
|
||||
}
|
||||
if (typeof ns[key] === "function") {
|
||||
symbols.push(key);
|
||||
}
|
||||
}
|
||||
symbols = populate(ns);
|
||||
return symbols;
|
||||
}
|
||||
symbols = populate(ns);
|
||||
})();
|
||||
|
||||
interface IProps {
|
||||
filename: string;
|
||||
code: string;
|
||||
player: IPlayer;
|
||||
engine: IEngine;
|
||||
filename: string;
|
||||
code: string;
|
||||
player: IPlayer;
|
||||
engine: IEngine;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
|
||||
*/
|
||||
@@ -77,254 +76,321 @@ let lastCode = "";
|
||||
let lastPosition: monaco.Position | null = null;
|
||||
|
||||
export function Root(props: IProps): React.ReactElement {
|
||||
const editorRef = useRef<IStandaloneCodeEditor | null>(null);
|
||||
const [filename, setFilename] = useState(props.filename ? props.filename : lastFilename);
|
||||
const [code, setCode] = useState<string>(props.code ? props.code : lastCode);
|
||||
const [ram, setRAM] = useState('RAM: ???');
|
||||
const [options, setOptions] = useState<Options>({
|
||||
theme: Settings.MonacoTheme,
|
||||
insertSpaces: Settings.MonacoInsertSpaces,
|
||||
const editorRef = useRef<IStandaloneCodeEditor | null>(null);
|
||||
const [filename, setFilename] = useState(
|
||||
props.filename ? props.filename : lastFilename,
|
||||
);
|
||||
const [code, setCode] = useState<string>(props.code ? props.code : lastCode);
|
||||
const [ram, setRAM] = useState("RAM: ???");
|
||||
const [options, setOptions] = useState<Options>({
|
||||
theme: Settings.MonacoTheme,
|
||||
insertSpaces: Settings.MonacoInsertSpaces,
|
||||
});
|
||||
|
||||
// store the last known state in case we need to restart without nano.
|
||||
useEffect(() => {
|
||||
if (props.filename === "") return;
|
||||
lastFilename = props.filename;
|
||||
lastCode = props.code;
|
||||
lastPosition = null;
|
||||
}, []);
|
||||
|
||||
function save(): void {
|
||||
if (editorRef.current !== null) {
|
||||
const position = editorRef.current.getPosition();
|
||||
if (position !== null) {
|
||||
CursorPositions.saveCursor(filename, {
|
||||
row: position.lineNumber,
|
||||
column: position.column,
|
||||
});
|
||||
}
|
||||
}
|
||||
lastPosition = null;
|
||||
|
||||
// TODO(hydroflame): re-enable the tutorial.
|
||||
if (
|
||||
ITutorial.isRunning &&
|
||||
ITutorial.currStep === iTutorialSteps.TerminalTypeScript
|
||||
) {
|
||||
//Make sure filename + code properly follow tutorial
|
||||
if (filename !== "n00dles.script") {
|
||||
dialogBoxCreate("Leave the script name as 'n00dles'!");
|
||||
return;
|
||||
}
|
||||
if (
|
||||
code.replace(/\s/g, "").indexOf("while(true){hack('n00dles');}") == -1
|
||||
) {
|
||||
dialogBoxCreate("Please copy and paste the code from the tutorial!");
|
||||
return;
|
||||
}
|
||||
|
||||
//Save the script
|
||||
const server = props.player.getCurrentServer();
|
||||
if (server === null)
|
||||
throw new Error("Server should not be null but it is.");
|
||||
for (let i = 0; i < server.scripts.length; i++) {
|
||||
if (filename == server.scripts[i].filename) {
|
||||
server.scripts[i].saveScript(
|
||||
code,
|
||||
props.player.currentServer,
|
||||
server.scripts,
|
||||
);
|
||||
props.engine.loadTerminalContent();
|
||||
return iTutorialNextStep();
|
||||
}
|
||||
}
|
||||
|
||||
// If the current script does NOT exist, create a new one
|
||||
const script = new Script();
|
||||
script.saveScript(code, props.player.currentServer, server.scripts);
|
||||
server.scripts.push(script);
|
||||
|
||||
return iTutorialNextStep();
|
||||
}
|
||||
|
||||
if (filename == "") {
|
||||
dialogBoxCreate("You must specify a filename!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (filename !== ".fconf" && !isValidFilePath(filename)) {
|
||||
dialogBoxCreate(
|
||||
"Script filename can contain only alphanumerics, hyphens, and underscores, and must end with an extension.",
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
const server = props.player.getCurrentServer();
|
||||
if (server === null)
|
||||
throw new Error("Server should not be null but it is.");
|
||||
if (filename === ".fconf") {
|
||||
try {
|
||||
parseFconfSettings(code);
|
||||
} catch (e) {
|
||||
dialogBoxCreate(`Invalid .fconf file: ${e}`);
|
||||
return;
|
||||
}
|
||||
} else if (isScriptFilename(filename)) {
|
||||
//If the current script already exists on the server, overwrite it
|
||||
for (let i = 0; i < server.scripts.length; i++) {
|
||||
if (filename == server.scripts[i].filename) {
|
||||
server.scripts[i].saveScript(
|
||||
code,
|
||||
props.player.currentServer,
|
||||
server.scripts,
|
||||
);
|
||||
props.engine.loadTerminalContent();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//If the current script does NOT exist, create a new one
|
||||
const script = new Script();
|
||||
script.saveScript(code, props.player.currentServer, server.scripts);
|
||||
server.scripts.push(script);
|
||||
} else if (filename.endsWith(".txt")) {
|
||||
for (let i = 0; i < server.textFiles.length; ++i) {
|
||||
if (server.textFiles[i].fn === filename) {
|
||||
server.textFiles[i].write(code);
|
||||
props.engine.loadTerminalContent();
|
||||
return;
|
||||
}
|
||||
}
|
||||
const textFile = new TextFile(filename, code);
|
||||
server.textFiles.push(textFile);
|
||||
} else {
|
||||
dialogBoxCreate(
|
||||
"Invalid filename. Must be either a script (.script, .js, or .ns) or " +
|
||||
" or text file (.txt)",
|
||||
);
|
||||
return;
|
||||
}
|
||||
props.engine.loadTerminalContent();
|
||||
}
|
||||
|
||||
function beautify(): void {
|
||||
if (editorRef.current === null) return;
|
||||
const pretty = beautifyCode(code, {
|
||||
indent_with_tabs: !options.insertSpaces,
|
||||
indent_size: 4,
|
||||
brace_style: "preserve-inline",
|
||||
});
|
||||
editorRef.current.setValue(pretty);
|
||||
}
|
||||
|
||||
// store the last known state in case we need to restart without nano.
|
||||
useEffect(() => {
|
||||
if(props.filename === "") return;
|
||||
lastFilename = props.filename;
|
||||
lastCode = props.code;
|
||||
lastPosition = null;
|
||||
}, []);
|
||||
function onFilenameChange(event: React.ChangeEvent<HTMLInputElement>): void {
|
||||
lastFilename = filename;
|
||||
setFilename(event.target.value);
|
||||
}
|
||||
|
||||
function save(): void {
|
||||
if(editorRef.current !== null) {
|
||||
const position = editorRef.current.getPosition();
|
||||
if(position !== null) {
|
||||
CursorPositions.saveCursor(filename, {
|
||||
row: position.lineNumber,
|
||||
column: position.column,
|
||||
});
|
||||
}
|
||||
}
|
||||
lastPosition = null;
|
||||
function openOptions(): void {
|
||||
const id = "script-editor-options-popup";
|
||||
const newOptions = {
|
||||
theme: "",
|
||||
insertSpaces: false,
|
||||
};
|
||||
Object.assign(newOptions, options);
|
||||
createPopup(id, OptionsPopup, {
|
||||
id: id,
|
||||
options: newOptions,
|
||||
save: (options: Options) => {
|
||||
setOptions(options);
|
||||
Settings.MonacoTheme = options.theme;
|
||||
Settings.MonacoInsertSpaces = options.insertSpaces;
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// TODO(hydroflame): re-enable the tutorial.
|
||||
if (ITutorial.isRunning && ITutorial.currStep === iTutorialSteps.TerminalTypeScript) {
|
||||
//Make sure filename + code properly follow tutorial
|
||||
if (filename !== "n00dles.script") {
|
||||
dialogBoxCreate("Leave the script name as 'n00dles'!");
|
||||
return;
|
||||
}
|
||||
if (code.replace(/\s/g, "").indexOf("while(true){hack('n00dles');}") == -1) {
|
||||
dialogBoxCreate("Please copy and paste the code from the tutorial!");
|
||||
return;
|
||||
}
|
||||
|
||||
//Save the script
|
||||
const server = props.player.getCurrentServer();
|
||||
if(server === null) throw new Error('Server should not be null but it is.');
|
||||
for (let i = 0; i < server.scripts.length; i++) {
|
||||
if (filename == server.scripts[i].filename) {
|
||||
server.scripts[i].saveScript(code, props.player.currentServer, server.scripts);
|
||||
props.engine.loadTerminalContent();
|
||||
return iTutorialNextStep();
|
||||
}
|
||||
}
|
||||
|
||||
// If the current script does NOT exist, create a new one
|
||||
const script = new Script();
|
||||
script.saveScript(code, props.player.currentServer, server.scripts);
|
||||
server.scripts.push(script);
|
||||
|
||||
return iTutorialNextStep();
|
||||
}
|
||||
|
||||
if (filename == "") {
|
||||
dialogBoxCreate("You must specify a filename!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (filename !== ".fconf" && !isValidFilePath(filename)) {
|
||||
dialogBoxCreate("Script filename can contain only alphanumerics, hyphens, and underscores, and must end with an extension.");
|
||||
return;
|
||||
}
|
||||
|
||||
const server = props.player.getCurrentServer();
|
||||
if(server === null) throw new Error('Server should not be null but it is.');
|
||||
if (filename === ".fconf") {
|
||||
try {
|
||||
parseFconfSettings(code);
|
||||
} catch(e) {
|
||||
dialogBoxCreate(`Invalid .fconf file: ${e}`);
|
||||
return;
|
||||
}
|
||||
} else if (isScriptFilename(filename)) {
|
||||
//If the current script already exists on the server, overwrite it
|
||||
for (let i = 0; i < server.scripts.length; i++) {
|
||||
if (filename == server.scripts[i].filename) {
|
||||
server.scripts[i].saveScript(code, props.player.currentServer, server.scripts);
|
||||
props.engine.loadTerminalContent();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//If the current script does NOT exist, create a new one
|
||||
const script = new Script();
|
||||
script.saveScript(code, props.player.currentServer, server.scripts);
|
||||
server.scripts.push(script);
|
||||
} else if (filename.endsWith(".txt")) {
|
||||
for (let i = 0; i < server.textFiles.length; ++i) {
|
||||
if (server.textFiles[i].fn === filename) {
|
||||
server.textFiles[i].write(code);
|
||||
props.engine.loadTerminalContent();
|
||||
return;
|
||||
}
|
||||
}
|
||||
const textFile = new TextFile(filename, code);
|
||||
server.textFiles.push(textFile);
|
||||
} else {
|
||||
dialogBoxCreate("Invalid filename. Must be either a script (.script, .js, or .ns) or " +
|
||||
" or text file (.txt)")
|
||||
return;
|
||||
}
|
||||
props.engine.loadTerminalContent();
|
||||
function updateCode(newCode?: string): void {
|
||||
if (newCode === undefined) return;
|
||||
lastCode = newCode;
|
||||
if (editorRef.current !== null) {
|
||||
lastPosition = editorRef.current.getPosition();
|
||||
}
|
||||
setCode(newCode);
|
||||
}
|
||||
|
||||
function beautify(): void {
|
||||
if (editorRef.current === null) return;
|
||||
const pretty = beautifyCode(code, {
|
||||
indent_with_tabs: !options.insertSpaces,
|
||||
indent_size: 4,
|
||||
brace_style: "preserve-inline",
|
||||
});
|
||||
editorRef.current.setValue(pretty);
|
||||
async function updateRAM(): Promise<void> {
|
||||
const codeCopy = code + "";
|
||||
const ramUsage = await calculateRamUsage(
|
||||
codeCopy,
|
||||
props.player.getCurrentServer().scripts,
|
||||
);
|
||||
if (ramUsage > 0) {
|
||||
setRAM("RAM: " + numeralWrapper.formatRAM(ramUsage));
|
||||
return;
|
||||
}
|
||||
|
||||
function onFilenameChange(event: React.ChangeEvent<HTMLInputElement>): void {
|
||||
lastFilename = filename;
|
||||
setFilename(event.target.value);
|
||||
switch (ramUsage) {
|
||||
case RamCalculationErrorCode.ImportError: {
|
||||
setRAM("RAM: Import Error");
|
||||
break;
|
||||
}
|
||||
case RamCalculationErrorCode.URLImportError: {
|
||||
setRAM("RAM: HTTP Import Error");
|
||||
break;
|
||||
}
|
||||
case RamCalculationErrorCode.SyntaxError:
|
||||
default: {
|
||||
setRAM("RAM: Syntax Error");
|
||||
break;
|
||||
}
|
||||
}
|
||||
return new Promise<void>(() => undefined);
|
||||
}
|
||||
|
||||
function openOptions(): void {
|
||||
const id="script-editor-options-popup";
|
||||
const newOptions = {
|
||||
theme: '',
|
||||
insertSpaces: false,
|
||||
};
|
||||
Object.assign(newOptions, options);
|
||||
createPopup(id, OptionsPopup, {
|
||||
id: id,
|
||||
options: newOptions,
|
||||
save: (options: Options) => {
|
||||
setOptions(options);
|
||||
Settings.MonacoTheme = options.theme;
|
||||
Settings.MonacoInsertSpaces = options.insertSpaces;
|
||||
},
|
||||
});
|
||||
useEffect(() => {
|
||||
const id = setInterval(updateRAM, 1000);
|
||||
return () => clearInterval(id);
|
||||
}, [code]);
|
||||
|
||||
useEffect(() => {
|
||||
function maybeSave(event: KeyboardEvent) {
|
||||
if (Settings.DisableHotkeys) return;
|
||||
//Ctrl + b
|
||||
if (event.keyCode == 66 && (event.ctrlKey || event.metaKey)) {
|
||||
event.preventDefault();
|
||||
save();
|
||||
}
|
||||
}
|
||||
document.addEventListener("keydown", maybeSave);
|
||||
return () => document.removeEventListener("keydown", maybeSave);
|
||||
});
|
||||
|
||||
function updateCode(newCode?: string): void {
|
||||
if(newCode === undefined) return;
|
||||
lastCode = newCode;
|
||||
if(editorRef.current !== null) {
|
||||
lastPosition = editorRef.current.getPosition();
|
||||
function onMount(editor: IStandaloneCodeEditor): void {
|
||||
editorRef.current = editor;
|
||||
if (editorRef.current === null) return;
|
||||
const position = CursorPositions.getCursor(filename);
|
||||
if (position.row !== -1)
|
||||
editorRef.current.setPosition({
|
||||
lineNumber: position.row,
|
||||
column: position.column,
|
||||
});
|
||||
else if (lastPosition !== null)
|
||||
editorRef.current.setPosition({
|
||||
lineNumber: lastPosition.lineNumber,
|
||||
column: lastPosition.column + 1,
|
||||
});
|
||||
editorRef.current.focus();
|
||||
}
|
||||
|
||||
function beforeMount(monaco: any): void {
|
||||
monaco.languages.registerCompletionItemProvider("javascript", {
|
||||
provideCompletionItems: () => {
|
||||
const suggestions = [];
|
||||
for (const symbol of symbols) {
|
||||
suggestions.push({
|
||||
label: symbol,
|
||||
kind: monaco.languages.CompletionItemKind.Function,
|
||||
insertText: symbol,
|
||||
insertTextRules:
|
||||
monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
|
||||
});
|
||||
}
|
||||
setCode(newCode);
|
||||
}
|
||||
return { suggestions: suggestions };
|
||||
},
|
||||
});
|
||||
monaco.languages.typescript.javascriptDefaults.addExtraLib(
|
||||
libSource,
|
||||
"netscript.d.ts",
|
||||
);
|
||||
monaco.languages.typescript.typescriptDefaults.addExtraLib(
|
||||
libSource,
|
||||
"netscript.d.ts",
|
||||
);
|
||||
}
|
||||
|
||||
async function updateRAM(): Promise<void> {
|
||||
const codeCopy = code+"";
|
||||
const ramUsage = await calculateRamUsage(codeCopy, props.player.getCurrentServer().scripts);
|
||||
if (ramUsage > 0) {
|
||||
setRAM("RAM: " + numeralWrapper.formatRAM(ramUsage));
|
||||
return;
|
||||
}
|
||||
switch (ramUsage) {
|
||||
case RamCalculationErrorCode.ImportError: {
|
||||
setRAM("RAM: Import Error");
|
||||
break;
|
||||
}
|
||||
case RamCalculationErrorCode.URLImportError: {
|
||||
setRAM("RAM: HTTP Import Error");
|
||||
break;
|
||||
}
|
||||
case RamCalculationErrorCode.SyntaxError:
|
||||
default: {
|
||||
setRAM("RAM: Syntax Error");
|
||||
break;
|
||||
}
|
||||
}
|
||||
return new Promise<void>(() => undefined);
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
const id = setInterval(updateRAM, 1000);
|
||||
return () => clearInterval(id);
|
||||
}, [code]);
|
||||
|
||||
useEffect(() => {
|
||||
function maybeSave(event: KeyboardEvent) {
|
||||
if (Settings.DisableHotkeys) return;
|
||||
//Ctrl + b
|
||||
if (event.keyCode == 66 && (event.ctrlKey || event.metaKey)) {
|
||||
event.preventDefault();
|
||||
save();
|
||||
}
|
||||
}
|
||||
document.addEventListener('keydown', maybeSave);
|
||||
return () => document.removeEventListener('keydown', maybeSave);
|
||||
})
|
||||
|
||||
function onMount(editor: IStandaloneCodeEditor): void {
|
||||
editorRef.current = editor;
|
||||
if(editorRef.current === null) return;
|
||||
const position = CursorPositions.getCursor(filename);
|
||||
if(position.row !== -1)
|
||||
editorRef.current.setPosition({lineNumber: position.row, column: position.column});
|
||||
else if(lastPosition !== null)
|
||||
editorRef.current.setPosition({lineNumber: lastPosition.lineNumber, column: lastPosition.column+1});
|
||||
editorRef.current.focus();
|
||||
}
|
||||
|
||||
function beforeMount(monaco: any): void {
|
||||
monaco.languages.registerCompletionItemProvider('javascript', {
|
||||
provideCompletionItems: () => {
|
||||
const suggestions = [];
|
||||
for(const symbol of symbols) {
|
||||
suggestions.push({
|
||||
label: symbol,
|
||||
kind: monaco.languages.CompletionItemKind.Function,
|
||||
insertText: symbol,
|
||||
insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
|
||||
});
|
||||
}
|
||||
return { suggestions: suggestions };
|
||||
},
|
||||
});
|
||||
monaco.languages.typescript.javascriptDefaults.addExtraLib(libSource, 'netscript.d.ts');
|
||||
monaco.languages.typescript.typescriptDefaults.addExtraLib(libSource, 'netscript.d.ts');
|
||||
}
|
||||
|
||||
return (<div id="script-editor-wrapper">
|
||||
<div id="script-editor-filename-wrapper">
|
||||
<p id="script-editor-filename-tag" className="noselect"> <strong style={{backgroundColor:'#555'}}>Script name: </strong></p>
|
||||
<input id="script-editor-filename" type="text" maxLength={100} tabIndex={1} value={filename} onChange={onFilenameChange} />
|
||||
<StdButton text={"options"} onClick={openOptions} />
|
||||
</div>
|
||||
<Editor
|
||||
beforeMount={beforeMount}
|
||||
onMount={onMount}
|
||||
loading={<p>Loading script editor!</p>}
|
||||
height="80%"
|
||||
defaultLanguage="javascript"
|
||||
defaultValue={code}
|
||||
onChange={updateCode}
|
||||
theme={options.theme}
|
||||
options={options}
|
||||
return (
|
||||
<div id="script-editor-wrapper">
|
||||
<div id="script-editor-filename-wrapper">
|
||||
<p id="script-editor-filename-tag" className="noselect">
|
||||
{" "}
|
||||
<strong style={{ backgroundColor: "#555" }}>Script name: </strong>
|
||||
</p>
|
||||
<input
|
||||
id="script-editor-filename"
|
||||
type="text"
|
||||
maxLength={100}
|
||||
tabIndex={1}
|
||||
value={filename}
|
||||
onChange={onFilenameChange}
|
||||
/>
|
||||
<div id="script-editor-buttons-wrapper">
|
||||
<StdButton text={"Beautify"} onClick={beautify} />
|
||||
<p id="script-editor-status-text" style={{display:"inline-block", margin:"10px"}}>{ram}</p>
|
||||
<button className="std-button" style={{display: "inline-block"}} onClick={save}>Save & Close (Ctrl/Cmd + b)</button>
|
||||
<a className="std-button" style={{display: "inline-block"}} target="_blank" href="https://bitburner.readthedocs.io/en/latest/index.html">Netscript Documentation</a>
|
||||
</div>
|
||||
</div>);
|
||||
<StdButton text={"options"} onClick={openOptions} />
|
||||
</div>
|
||||
<Editor
|
||||
beforeMount={beforeMount}
|
||||
onMount={onMount}
|
||||
loading={<p>Loading script editor!</p>}
|
||||
height="80%"
|
||||
defaultLanguage="javascript"
|
||||
defaultValue={code}
|
||||
onChange={updateCode}
|
||||
theme={options.theme}
|
||||
options={options}
|
||||
/>
|
||||
<div id="script-editor-buttons-wrapper">
|
||||
<StdButton text={"Beautify"} onClick={beautify} />
|
||||
<p
|
||||
id="script-editor-status-text"
|
||||
style={{ display: "inline-block", margin: "10px" }}
|
||||
>
|
||||
{ram}
|
||||
</p>
|
||||
<button
|
||||
className="std-button"
|
||||
style={{ display: "inline-block" }}
|
||||
onClick={save}
|
||||
>
|
||||
Save & Close (Ctrl/Cmd + b)
|
||||
</button>
|
||||
<a
|
||||
className="std-button"
|
||||
style={{ display: "inline-block" }}
|
||||
target="_blank"
|
||||
href="https://bitburner.readthedocs.io/en/latest/index.html"
|
||||
>
|
||||
Netscript Documentation
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user