mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2024-11-26 17:43:48 +01:00
Merge pull request #1984 from billyvg/feat/add-vim-mode
feat: Add vim mode to script editor
This commit is contained in:
commit
25f78f2b30
7
dist/ext/monaco-vim.js
vendored
Normal file
7
dist/ext/monaco-vim.js
vendored
Normal file
File diff suppressed because one or more lines are too long
@ -17,12 +17,13 @@
|
|||||||
<link rel="stylesheet" data-name="vs/editor/editor.main" href="dist/ext/monaco-editor/min/vs/editor/editor.main.css"/>
|
<link rel="stylesheet" data-name="vs/editor/editor.main" href="dist/ext/monaco-editor/min/vs/editor/editor.main.css"/>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
var require = { paths: { vs: "dist/ext/monaco-editor/min/vs" } };
|
var require = { paths: { vs: "dist/ext/monaco-editor/min/vs", "monaco-vim": "dist/ext/monaco-vim" } };
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script src="dist/ext/monaco-editor/min/vs/loader.js"></script>
|
<script src="dist/ext/monaco-editor/min/vs/loader.js"></script>
|
||||||
<script src="dist/ext/monaco-editor/min/vs/editor/editor.main.nls.js"></script>
|
<script src="dist/ext/monaco-editor/min/vs/editor/editor.main.nls.js"></script>
|
||||||
<script src="dist/ext/monaco-editor/min/vs/editor/editor.main.js"></script>
|
<script src="dist/ext/monaco-editor/min/vs/editor/editor.main.js"></script>
|
||||||
|
<script src="dist/ext/monaco-vim.js"></script>
|
||||||
|
|
||||||
<!-- Google Analytics -->
|
<!-- Google Analytics -->
|
||||||
<script>
|
<script>
|
||||||
|
@ -2,4 +2,5 @@ export interface Options {
|
|||||||
theme: string;
|
theme: string;
|
||||||
insertSpaces: boolean;
|
insertSpaces: boolean;
|
||||||
fontSize: number;
|
fontSize: number;
|
||||||
|
vim: boolean;
|
||||||
}
|
}
|
||||||
|
@ -21,12 +21,14 @@ export function OptionsModal(props: IProps): React.ReactElement {
|
|||||||
const [theme, setTheme] = useState(props.options.theme);
|
const [theme, setTheme] = useState(props.options.theme);
|
||||||
const [insertSpaces, setInsertSpaces] = useState(props.options.insertSpaces);
|
const [insertSpaces, setInsertSpaces] = useState(props.options.insertSpaces);
|
||||||
const [fontSize, setFontSize] = useState(props.options.fontSize);
|
const [fontSize, setFontSize] = useState(props.options.fontSize);
|
||||||
|
const [vim, setVim] = useState(props.options.vim);
|
||||||
|
|
||||||
function save(): void {
|
function save(): void {
|
||||||
props.save({
|
props.save({
|
||||||
theme: theme,
|
theme,
|
||||||
insertSpaces: insertSpaces,
|
insertSpaces,
|
||||||
fontSize: fontSize,
|
fontSize,
|
||||||
|
vim,
|
||||||
});
|
});
|
||||||
props.onClose();
|
props.onClose();
|
||||||
}
|
}
|
||||||
@ -54,6 +56,12 @@ export function OptionsModal(props: IProps): React.ReactElement {
|
|||||||
<Typography>Use whitespace over tabs: </Typography>
|
<Typography>Use whitespace over tabs: </Typography>
|
||||||
<Switch onChange={(event) => setInsertSpaces(event.target.checked)} checked={insertSpaces} />
|
<Switch onChange={(event) => setInsertSpaces(event.target.checked)} checked={insertSpaces} />
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
|
<Box display="flex" flexDirection="row" alignItems="center">
|
||||||
|
<Typography>Enable vim mode: </Typography>
|
||||||
|
<Switch onChange={(event) => setVim(event.target.checked)} checked={vim} />
|
||||||
|
</Box>
|
||||||
|
|
||||||
<Box display="flex" flexDirection="row" alignItems="center">
|
<Box display="flex" flexDirection="row" alignItems="center">
|
||||||
<TextField type="number" label="Font size" value={fontSize} onChange={onFontChange} />
|
<TextField type="number" label="Font size" value={fontSize} onChange={onFontChange} />
|
||||||
</Box>
|
</Box>
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
import React, { useState, useEffect, useRef, useMemo } from "react";
|
import React, { useState, useEffect, useRef, useMemo } from "react";
|
||||||
import Editor, { Monaco } from "@monaco-editor/react";
|
import Editor, { Monaco } from "@monaco-editor/react";
|
||||||
import * as monaco from "monaco-editor";
|
import * as monaco from "monaco-editor";
|
||||||
|
|
||||||
type IStandaloneCodeEditor = monaco.editor.IStandaloneCodeEditor;
|
type IStandaloneCodeEditor = monaco.editor.IStandaloneCodeEditor;
|
||||||
type ITextModel = monaco.editor.ITextModel;
|
type ITextModel = monaco.editor.ITextModel;
|
||||||
import { OptionsModal } from "./OptionsModal";
|
import { OptionsModal } from "./OptionsModal";
|
||||||
@ -16,7 +17,7 @@ import { TextFile } from "../../TextFile";
|
|||||||
import { calculateRamUsage, checkInfiniteLoop } from "../../Script/RamCalculations";
|
import { calculateRamUsage, checkInfiniteLoop } from "../../Script/RamCalculations";
|
||||||
import { RamCalculationErrorCode } from "../../Script/RamCalculationErrorCodes";
|
import { RamCalculationErrorCode } from "../../Script/RamCalculationErrorCodes";
|
||||||
import { numeralWrapper } from "../../ui/numeralFormat";
|
import { numeralWrapper } from "../../ui/numeralFormat";
|
||||||
import { DragDropContext, Droppable, Draggable } from 'react-beautiful-dnd';
|
import { DragDropContext, Droppable, Draggable } from "react-beautiful-dnd";
|
||||||
|
|
||||||
import { NetscriptFunctions } from "../../NetscriptFunctions";
|
import { NetscriptFunctions } from "../../NetscriptFunctions";
|
||||||
import { WorkerScript } from "../../Netscript/WorkerScript";
|
import { WorkerScript } from "../../Netscript/WorkerScript";
|
||||||
@ -37,13 +38,13 @@ 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;
|
filename: string;
|
||||||
code: string;
|
code: string;
|
||||||
hostname: string;
|
hostname: string;
|
||||||
player: IPlayer;
|
player: IPlayer;
|
||||||
router: IRouter;
|
router: IRouter;
|
||||||
|
vim?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: try to removve global symbols
|
// TODO: try to removve global symbols
|
||||||
@ -75,7 +76,6 @@ export function SetupTextEditor(): void {
|
|||||||
symbols = symbols.filter((symbol: string) => !exclude.includes(symbol)).sort();
|
symbols = symbols.filter((symbol: string) => !exclude.includes(symbol)).sort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Holds all the data for a open script
|
// Holds all the data for a open script
|
||||||
class OpenScript {
|
class OpenScript {
|
||||||
fileName: string;
|
fileName: string;
|
||||||
@ -97,13 +97,20 @@ class OpenScript {
|
|||||||
export function Root(props: IProps): React.ReactElement {
|
export function Root(props: IProps): React.ReactElement {
|
||||||
const editorRef = useRef<IStandaloneCodeEditor | null>(null);
|
const editorRef = useRef<IStandaloneCodeEditor | null>(null);
|
||||||
const monacoRef = useRef<Monaco | null>(null);
|
const monacoRef = useRef<Monaco | null>(null);
|
||||||
|
const vimStatusRef = useRef<HTMLElement>(null);
|
||||||
|
const [vimEditor, setVimEditor] = useState<any>(null);
|
||||||
|
const [editor, setEditor] = useState<IStandaloneCodeEditor | null>(null);
|
||||||
|
|
||||||
const [openScripts, setOpenScripts] = useState<OpenScript[]>(
|
const [openScripts, setOpenScripts] = useState<OpenScript[]>(
|
||||||
window.localStorage.getItem('scriptEditorOpenScripts') !== null ? JSON.parse(window.localStorage.getItem('scriptEditorOpenScripts')!) : []
|
window.localStorage.getItem("scriptEditorOpenScripts") !== null
|
||||||
|
? JSON.parse(window.localStorage.getItem("scriptEditorOpenScripts")!)
|
||||||
|
: [],
|
||||||
);
|
);
|
||||||
|
|
||||||
const [currentScript, setCurrentScript] = useState<OpenScript | null>(
|
const [currentScript, setCurrentScript] = useState<OpenScript | null>(
|
||||||
window.localStorage.getItem('scriptEditorCurrentScript') !== null ? JSON.parse(window.localStorage.getItem('scriptEditorCurrentScript')!) : null
|
window.localStorage.getItem("scriptEditorCurrentScript") !== null
|
||||||
|
? JSON.parse(window.localStorage.getItem("scriptEditorCurrentScript")!)
|
||||||
|
: null,
|
||||||
);
|
);
|
||||||
|
|
||||||
const [ram, setRAM] = useState("RAM: ???");
|
const [ram, setRAM] = useState("RAM: ???");
|
||||||
@ -115,21 +122,28 @@ export function Root(props: IProps): React.ReactElement {
|
|||||||
theme: Settings.MonacoTheme,
|
theme: Settings.MonacoTheme,
|
||||||
insertSpaces: Settings.MonacoInsertSpaces,
|
insertSpaces: Settings.MonacoInsertSpaces,
|
||||||
fontSize: Settings.MonacoFontSize,
|
fontSize: Settings.MonacoFontSize,
|
||||||
|
vim: props.vim || Settings.MonacoVim,
|
||||||
});
|
});
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// Save currentScript
|
// Save currentScript
|
||||||
window.localStorage.setItem('scriptEditorCurrentScript', JSON.stringify(currentScript, (key, value) => {
|
window.localStorage.setItem(
|
||||||
if (key == 'model') return undefined;
|
"scriptEditorCurrentScript",
|
||||||
|
JSON.stringify(currentScript, (key, value) => {
|
||||||
|
if (key == "model") return undefined;
|
||||||
return value;
|
return value;
|
||||||
}));
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
// Save openScripts
|
// Save openScripts
|
||||||
window.localStorage.setItem('scriptEditorOpenScripts', JSON.stringify(openScripts, (key, value) => {
|
window.localStorage.setItem(
|
||||||
if (key == 'model') return undefined;
|
"scriptEditorOpenScripts",
|
||||||
|
JSON.stringify(openScripts, (key, value) => {
|
||||||
|
if (key == "model") return undefined;
|
||||||
return value;
|
return value;
|
||||||
}))
|
}),
|
||||||
}, [currentScript, openScripts])
|
);
|
||||||
|
}, [currentScript, openScripts]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (currentScript !== null) {
|
if (currentScript !== null) {
|
||||||
@ -157,6 +171,35 @@ export function Root(props: IProps): React.ReactElement {
|
|||||||
return () => document.removeEventListener("keydown", maybeSave);
|
return () => document.removeEventListener("keydown", maybeSave);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
// setup monaco-vim
|
||||||
|
if (options.vim && editor && !vimEditor) {
|
||||||
|
try {
|
||||||
|
// This library is not typed
|
||||||
|
// @ts-expect-error
|
||||||
|
window.require(["monaco-vim"], function (MonacoVim: any) {
|
||||||
|
setVimEditor(MonacoVim.initVimMode(editor, vimStatusRef.current));
|
||||||
|
MonacoVim.VimMode.Vim.defineEx("write", "w", function () {
|
||||||
|
// your own implementation on what you want to do when :w is pressed
|
||||||
|
save();
|
||||||
|
});
|
||||||
|
MonacoVim.VimMode.Vim.defineEx("quit", "q", function () {
|
||||||
|
save();
|
||||||
|
});
|
||||||
|
editor.focus();
|
||||||
|
});
|
||||||
|
} catch {}
|
||||||
|
} else if (!options.vim) {
|
||||||
|
// Whem vim mode is disabled
|
||||||
|
vimEditor?.dispose();
|
||||||
|
setVimEditor(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
vimEditor?.dispose();
|
||||||
|
};
|
||||||
|
}, [options, editorRef, editor, vimEditor]);
|
||||||
|
|
||||||
// Generates a new model for the script
|
// Generates a new model for the script
|
||||||
function regenerateModel(script: OpenScript): void {
|
function regenerateModel(script: OpenScript): void {
|
||||||
if (monacoRef.current !== null) {
|
if (monacoRef.current !== null) {
|
||||||
@ -253,9 +296,12 @@ export function Root(props: IProps): React.ReactElement {
|
|||||||
loadThemes(monaco);
|
loadThemes(monaco);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// When the editor is mounted
|
// When the editor is mounted
|
||||||
function onMount(editor: IStandaloneCodeEditor, monaco: Monaco): void {
|
function onMount(editor: IStandaloneCodeEditor, monaco: Monaco): void {
|
||||||
|
// Required when switching between site navigation (e.g. from Script Editor -> Terminal and back)
|
||||||
|
// the `useEffect()` for vim mode is called before editor is mounted.
|
||||||
|
setEditor(editor);
|
||||||
|
|
||||||
editorRef.current = editor;
|
editorRef.current = editor;
|
||||||
monacoRef.current = monaco;
|
monacoRef.current = monaco;
|
||||||
|
|
||||||
@ -263,10 +309,16 @@ export function Root(props: IProps): React.ReactElement {
|
|||||||
|
|
||||||
if (props.filename) {
|
if (props.filename) {
|
||||||
// Check if file is already opened
|
// Check if file is already opened
|
||||||
const openScriptIndex = openScripts.findIndex(script => script.fileName === props.filename && script.hostname === props.hostname);
|
const openScriptIndex = openScripts.findIndex(
|
||||||
|
(script) => script.fileName === props.filename && script.hostname === props.hostname,
|
||||||
|
);
|
||||||
if (openScriptIndex !== -1) {
|
if (openScriptIndex !== -1) {
|
||||||
// Script is already opened
|
// Script is already opened
|
||||||
if (openScripts[openScriptIndex].model === undefined || openScripts[openScriptIndex].model === null || openScripts[openScriptIndex].model.isDisposed()) {
|
if (
|
||||||
|
openScripts[openScriptIndex].model === undefined ||
|
||||||
|
openScripts[openScriptIndex].model === null ||
|
||||||
|
openScripts[openScriptIndex].model.isDisposed()
|
||||||
|
) {
|
||||||
regenerateModel(openScripts[openScriptIndex]);
|
regenerateModel(openScripts[openScriptIndex]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -277,8 +329,14 @@ export function Root(props: IProps): React.ReactElement {
|
|||||||
updateRAM(openScripts[openScriptIndex].code);
|
updateRAM(openScripts[openScriptIndex].code);
|
||||||
} else {
|
} else {
|
||||||
// Open script
|
// Open script
|
||||||
const newScript = new OpenScript(props.filename, props.code, props.hostname, new monacoRef.current.Position(0, 0), monacoRef.current.editor.createModel(props.code, 'javascript'));
|
const newScript = new OpenScript(
|
||||||
setOpenScripts(oldArray => [...oldArray, newScript]);
|
props.filename,
|
||||||
|
props.code,
|
||||||
|
props.hostname,
|
||||||
|
new monacoRef.current.Position(0, 0),
|
||||||
|
monacoRef.current.editor.createModel(props.code, "javascript"),
|
||||||
|
);
|
||||||
|
setOpenScripts((oldArray) => [...oldArray, newScript]);
|
||||||
setCurrentScript({ ...newScript });
|
setCurrentScript({ ...newScript });
|
||||||
editorRef.current.setModel(newScript.model);
|
editorRef.current.setModel(newScript.model);
|
||||||
updateRAM(newScript.code);
|
updateRAM(newScript.code);
|
||||||
@ -331,9 +389,11 @@ export function Root(props: IProps): React.ReactElement {
|
|||||||
if (editorRef.current !== null) {
|
if (editorRef.current !== null) {
|
||||||
const newPos = editorRef.current.getPosition();
|
const newPos = editorRef.current.getPosition();
|
||||||
if (newPos === null) return;
|
if (newPos === null) return;
|
||||||
setCurrentScript(oldScript => ({ ...oldScript!, code: newCode, lastPosition: newPos! }))
|
setCurrentScript((oldScript) => ({ ...oldScript!, code: newCode, lastPosition: newPos! }));
|
||||||
if (currentScript !== null) {
|
if (currentScript !== null) {
|
||||||
const curIndex = openScripts.findIndex(script => script.fileName === currentScript.fileName && script.hostname === currentScript.hostname);
|
const curIndex = openScripts.findIndex(
|
||||||
|
(script) => script.fileName === currentScript.fileName && script.hostname === currentScript.hostname,
|
||||||
|
);
|
||||||
const newArr = [...openScripts];
|
const newArr = [...openScripts];
|
||||||
const tempScript = currentScript;
|
const tempScript = currentScript;
|
||||||
tempScript.code = newCode;
|
tempScript.code = newCode;
|
||||||
@ -480,7 +540,7 @@ export function Root(props: IProps): React.ReactElement {
|
|||||||
function onDragEnd(result: any): void {
|
function onDragEnd(result: any): void {
|
||||||
// Dropped outside of the list
|
// Dropped outside of the list
|
||||||
if (!result.destination) {
|
if (!result.destination) {
|
||||||
result
|
result;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -492,7 +552,9 @@ export function Root(props: IProps): React.ReactElement {
|
|||||||
function onTabClick(index: number): void {
|
function onTabClick(index: number): void {
|
||||||
if (currentScript !== null) {
|
if (currentScript !== null) {
|
||||||
// Save currentScript to openScripts
|
// Save currentScript to openScripts
|
||||||
const curIndex = openScripts.findIndex(script => script.fileName === currentScript.fileName && script.hostname === currentScript.hostname);
|
const curIndex = openScripts.findIndex(
|
||||||
|
(script) => script.fileName === currentScript.fileName && script.hostname === currentScript.hostname,
|
||||||
|
);
|
||||||
openScripts[curIndex] = currentScript;
|
openScripts[curIndex] = currentScript;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -514,29 +576,36 @@ export function Root(props: IProps): React.ReactElement {
|
|||||||
async function onTabClose(index: number): Promise<void> {
|
async function onTabClose(index: number): Promise<void> {
|
||||||
// See if the script on the server is up to date
|
// See if the script on the server is up to date
|
||||||
const closingScript = openScripts[index];
|
const closingScript = openScripts[index];
|
||||||
const savedOpenScripts: Array<OpenScript> = JSON.parse(window.localStorage.getItem('scriptEditorOpenScripts')!);
|
const savedOpenScripts: Array<OpenScript> = JSON.parse(window.localStorage.getItem("scriptEditorOpenScripts")!);
|
||||||
const savedScriptIndex = savedOpenScripts.findIndex(script => script.fileName === closingScript.fileName && script.hostname === closingScript.hostname);
|
const savedScriptIndex = savedOpenScripts.findIndex(
|
||||||
let savedScriptCode = '';
|
(script) => script.fileName === closingScript.fileName && script.hostname === closingScript.hostname,
|
||||||
|
);
|
||||||
|
let savedScriptCode = "";
|
||||||
if (savedScriptIndex !== -1) {
|
if (savedScriptIndex !== -1) {
|
||||||
savedScriptCode = savedOpenScripts[savedScriptIndex].code;
|
savedScriptCode = savedOpenScripts[savedScriptIndex].code;
|
||||||
}
|
}
|
||||||
|
|
||||||
const serverScriptIndex = GetServer(closingScript.hostname)?.scripts.findIndex(script => script.filename === closingScript.fileName);
|
const serverScriptIndex = GetServer(closingScript.hostname)?.scripts.findIndex(
|
||||||
if (serverScriptIndex === -1 || savedScriptCode !== GetServer(closingScript.hostname)?.scripts[serverScriptIndex as number].code) {
|
(script) => script.filename === closingScript.fileName,
|
||||||
|
);
|
||||||
|
if (
|
||||||
|
serverScriptIndex === -1 ||
|
||||||
|
savedScriptCode !== GetServer(closingScript.hostname)?.scripts[serverScriptIndex as number].code
|
||||||
|
) {
|
||||||
PromptEvent.emit({
|
PromptEvent.emit({
|
||||||
txt: 'Do you want to save changes to ' + closingScript.fileName + '?',
|
txt: "Do you want to save changes to " + closingScript.fileName + "?",
|
||||||
resolve: (result: boolean) => {
|
resolve: (result: boolean) => {
|
||||||
if (result) {
|
if (result) {
|
||||||
// Save changes
|
// Save changes
|
||||||
closingScript.code = savedScriptCode;
|
closingScript.code = savedScriptCode;
|
||||||
saveScript(closingScript);
|
saveScript(closingScript);
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (openScripts.length > 1) {
|
if (openScripts.length > 1) {
|
||||||
setOpenScripts(oldScripts => oldScripts.filter((value, i) => i !== index));
|
setOpenScripts((oldScripts) => oldScripts.filter((value, i) => i !== index));
|
||||||
|
|
||||||
let indexOffset = -1;
|
let indexOffset = -1;
|
||||||
if (openScripts[index + indexOffset] === undefined) {
|
if (openScripts[index + indexOffset] === undefined) {
|
||||||
@ -546,13 +615,17 @@ export function Root(props: IProps): React.ReactElement {
|
|||||||
// Change current script if we closed it
|
// Change current script if we closed it
|
||||||
setCurrentScript(openScripts[index + indexOffset]);
|
setCurrentScript(openScripts[index + indexOffset]);
|
||||||
if (editorRef.current !== null) {
|
if (editorRef.current !== null) {
|
||||||
if (openScripts[index + indexOffset].model === undefined || openScripts[index + indexOffset].model === null || openScripts[index + indexOffset].model.isDisposed()) {
|
if (
|
||||||
|
openScripts[index + indexOffset].model === undefined ||
|
||||||
|
openScripts[index + indexOffset].model === null ||
|
||||||
|
openScripts[index + indexOffset].model.isDisposed()
|
||||||
|
) {
|
||||||
regenerateModel(openScripts[index + indexOffset]);
|
regenerateModel(openScripts[index + indexOffset]);
|
||||||
}
|
}
|
||||||
|
|
||||||
editorRef.current.setModel(openScripts[index + indexOffset].model);
|
editorRef.current.setModel(openScripts[index + indexOffset].model);
|
||||||
editorRef.current.setPosition(openScripts[index + indexOffset].lastPosition);
|
editorRef.current.setPosition(openScripts[index + indexOffset].lastPosition);
|
||||||
editorRef.current.revealLineInCenter(openScripts[index + indexOffset].lastPosition.lineNumber)
|
editorRef.current.revealLineInCenter(openScripts[index + indexOffset].lastPosition.lineNumber);
|
||||||
editorRef.current.focus();
|
editorRef.current.focus();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -562,14 +635,17 @@ export function Root(props: IProps): React.ReactElement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 370px 71%, 725px 85.1%, 1085px 90%, 1300px 91.7%
|
// TODO: Make this responsive to window resizes
|
||||||
// fuck around in desmos until you find a function
|
// Toolbars are roughly 108px + vim bar 34px
|
||||||
const p = 11000 / -window.innerHeight + 100;
|
// Get percentage of space that toolbars represent and the rest should be the
|
||||||
|
// editor
|
||||||
|
const editorHeight = 100 - ((108 + (options.vim ? 34 : 0)) / window.innerHeight) * 100;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div style={{ display: currentScript !== null ? 'block' : 'none', height: '100%', width: '100%' }}>
|
<div style={{ display: currentScript !== null ? "block" : "none", height: "100%", width: "100%" }}>
|
||||||
<DragDropContext onDragEnd={onDragEnd}>
|
<DragDropContext onDragEnd={onDragEnd}>
|
||||||
<Droppable droppableId='tabs' direction='horizontal'>
|
<Droppable droppableId="tabs" direction="horizontal">
|
||||||
{(provided, snapshot) => (
|
{(provided, snapshot) => (
|
||||||
<Box
|
<Box
|
||||||
maxWidth="1640px"
|
maxWidth="1640px"
|
||||||
@ -579,10 +655,18 @@ export function Root(props: IProps): React.ReactElement {
|
|||||||
whiteSpace="nowrap"
|
whiteSpace="nowrap"
|
||||||
ref={provided.innerRef}
|
ref={provided.innerRef}
|
||||||
{...provided.droppableProps}
|
{...provided.droppableProps}
|
||||||
style={{ backgroundColor: snapshot.isDraggingOver ? '#1F2022' : Settings.theme.backgroundprimary, overflowX: 'scroll' }}
|
style={{
|
||||||
|
backgroundColor: snapshot.isDraggingOver ? "#1F2022" : Settings.theme.backgroundprimary,
|
||||||
|
overflowX: "scroll",
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
{openScripts.map(({ fileName, hostname }, index) => (
|
{openScripts.map(({ fileName, hostname }, index) => (
|
||||||
<Draggable key={fileName + hostname} draggableId={fileName + hostname} index={index} disableInteractiveElementBlocking={true}>
|
<Draggable
|
||||||
|
key={fileName + hostname}
|
||||||
|
draggableId={fileName + hostname}
|
||||||
|
index={index}
|
||||||
|
disableInteractiveElementBlocking={true}
|
||||||
|
>
|
||||||
{(provided) => (
|
{(provided) => (
|
||||||
<div
|
<div
|
||||||
ref={provided.innerRef}
|
ref={provided.innerRef}
|
||||||
@ -590,22 +674,33 @@ export function Root(props: IProps): React.ReactElement {
|
|||||||
{...provided.dragHandleProps}
|
{...provided.dragHandleProps}
|
||||||
style={{
|
style={{
|
||||||
...provided.draggableProps.style,
|
...provided.draggableProps.style,
|
||||||
marginRight: '5px',
|
marginRight: "5px",
|
||||||
flexShrink: 0
|
flexShrink: 0,
|
||||||
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Button
|
<Button
|
||||||
id={"tabButton" + fileName + hostname}
|
id={"tabButton" + fileName + hostname}
|
||||||
onClick={() => onTabClick(index)}
|
onClick={() => onTabClick(index)}
|
||||||
style={{ background: currentScript?.fileName === openScripts[index].fileName ? Settings.theme.secondarydark : '' }}
|
style={{
|
||||||
|
background:
|
||||||
|
currentScript?.fileName === openScripts[index].fileName
|
||||||
|
? Settings.theme.secondarydark
|
||||||
|
: "",
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
{hostname}:~/{fileName}
|
{hostname}:~/{fileName}
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
id={"tabCloseButton" + fileName + hostname}
|
id={"tabCloseButton" + fileName + hostname}
|
||||||
onClick={() => onTabClose(index)}
|
onClick={() => onTabClose(index)}
|
||||||
style={{ maxWidth: "20px", minWidth: "20px", background: currentScript?.fileName === openScripts[index].fileName ? Settings.theme.secondarydark : '' }}
|
style={{
|
||||||
|
maxWidth: "20px",
|
||||||
|
minWidth: "20px",
|
||||||
|
background:
|
||||||
|
currentScript?.fileName === openScripts[index].fileName
|
||||||
|
? Settings.theme.secondarydark
|
||||||
|
: "",
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
x
|
x
|
||||||
</Button>
|
</Button>
|
||||||
@ -618,18 +713,28 @@ export function Root(props: IProps): React.ReactElement {
|
|||||||
)}
|
)}
|
||||||
</Droppable>
|
</Droppable>
|
||||||
</DragDropContext>
|
</DragDropContext>
|
||||||
<div style={{ paddingBottom: '5px' }} />
|
<div style={{ paddingBottom: "5px" }} />
|
||||||
<Editor
|
<Editor
|
||||||
beforeMount={beforeMount}
|
beforeMount={beforeMount}
|
||||||
onMount={onMount}
|
onMount={onMount}
|
||||||
loading={<Typography>Loading script editor!</Typography>}
|
loading={<Typography>Loading script editor!</Typography>}
|
||||||
height={p + "%"}
|
height={`${editorHeight}%`}
|
||||||
defaultLanguage="javascript"
|
defaultLanguage="javascript"
|
||||||
defaultValue={''}
|
defaultValue={""}
|
||||||
onChange={updateCode}
|
onChange={updateCode}
|
||||||
theme={options.theme}
|
theme={options.theme}
|
||||||
options={{ ...options, glyphMargin: true }}
|
options={{ ...options, glyphMargin: true }}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<Box
|
||||||
|
ref={vimStatusRef}
|
||||||
|
className="monaco-editor"
|
||||||
|
display="flex"
|
||||||
|
flexDirection="row"
|
||||||
|
sx={{ p: 1 }}
|
||||||
|
alignItems="center"
|
||||||
|
></Box>
|
||||||
|
|
||||||
<Box display="flex" flexDirection="row" sx={{ m: 1 }} alignItems="center">
|
<Box display="flex" flexDirection="row" sx={{ m: 1 }} alignItems="center">
|
||||||
<Button onClick={beautify}>Beautify</Button>
|
<Button onClick={beautify}>Beautify</Button>
|
||||||
<Typography color={updatingRam ? "secondary" : "primary"} sx={{ mx: 1 }}>
|
<Typography color={updatingRam ? "secondary" : "primary"} sx={{ mx: 1 }}>
|
||||||
@ -661,18 +766,31 @@ export function Root(props: IProps): React.ReactElement {
|
|||||||
theme: Settings.MonacoTheme,
|
theme: Settings.MonacoTheme,
|
||||||
insertSpaces: Settings.MonacoInsertSpaces,
|
insertSpaces: Settings.MonacoInsertSpaces,
|
||||||
fontSize: Settings.MonacoFontSize,
|
fontSize: Settings.MonacoFontSize,
|
||||||
|
vim: Settings.MonacoVim,
|
||||||
}}
|
}}
|
||||||
save={(options: Options) => {
|
save={(options: Options) => {
|
||||||
setOptions(options);
|
setOptions(options);
|
||||||
Settings.MonacoTheme = options.theme;
|
Settings.MonacoTheme = options.theme;
|
||||||
Settings.MonacoInsertSpaces = options.insertSpaces;
|
Settings.MonacoInsertSpaces = options.insertSpaces;
|
||||||
Settings.MonacoFontSize = options.fontSize;
|
Settings.MonacoFontSize = options.fontSize;
|
||||||
|
Settings.MonacoVim = options.vim;
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div style={{ display: currentScript !== null ? 'none' : 'flex', height: '100%', width: '100%', justifyContent: 'center', alignItems: 'center' }}>
|
<div
|
||||||
<p style={{ color: Settings.theme.primary, fontSize: '20px', textAlign: 'center' }}><h1>No open files</h1><h5>Use "nano [File Name]" in the terminal to open files</h5></p>
|
style={{
|
||||||
|
display: currentScript !== null ? "none" : "flex",
|
||||||
|
height: "100%",
|
||||||
|
width: "100%",
|
||||||
|
justifyContent: "center",
|
||||||
|
alignItems: "center",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<p style={{ color: Settings.theme.primary, fontSize: "20px", textAlign: "center" }}>
|
||||||
|
<h1>No open files</h1>
|
||||||
|
<h5>Use "nano [File Name]" in the terminal to open files</h5>
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
@ -134,6 +134,8 @@ interface ISettings extends IDefaultSettings {
|
|||||||
MonacoInsertSpaces: boolean;
|
MonacoInsertSpaces: boolean;
|
||||||
|
|
||||||
MonacoFontSize: number;
|
MonacoFontSize: number;
|
||||||
|
|
||||||
|
MonacoVim: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const defaultSettings: IDefaultSettings = {
|
export const defaultSettings: IDefaultSettings = {
|
||||||
@ -193,6 +195,7 @@ export const Settings: ISettings & ISelfInitializer & ISelfLoading = {
|
|||||||
MonacoTheme: "monokai",
|
MonacoTheme: "monokai",
|
||||||
MonacoInsertSpaces: false,
|
MonacoInsertSpaces: false,
|
||||||
MonacoFontSize: 20,
|
MonacoFontSize: 20,
|
||||||
|
MonacoVim: false,
|
||||||
|
|
||||||
theme: { ...defaultTheme },
|
theme: { ...defaultTheme },
|
||||||
init() {
|
init() {
|
||||||
|
@ -21,12 +21,13 @@
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
var require = { paths: { vs: "dist/ext/monaco-editor/min/vs" } };
|
var require = { paths: { vs: "dist/ext/monaco-editor/min/vs", "monaco-vim": "dist/ext/monaco-vim" } };
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script src="dist/ext/monaco-editor/min/vs/loader.js"></script>
|
<script src="dist/ext/monaco-editor/min/vs/loader.js"></script>
|
||||||
<script src="dist/ext/monaco-editor/min/vs/editor/editor.main.nls.js"></script>
|
<script src="dist/ext/monaco-editor/min/vs/editor/editor.main.nls.js"></script>
|
||||||
<script src="dist/ext/monaco-editor/min/vs/editor/editor.main.js"></script>
|
<script src="dist/ext/monaco-editor/min/vs/editor/editor.main.js"></script>
|
||||||
|
<script src="dist/ext/monaco-vim.js"></script>
|
||||||
|
|
||||||
<!-- Google Analytics -->
|
<!-- Google Analytics -->
|
||||||
<script>
|
<script>
|
||||||
|
Loading…
Reference in New Issue
Block a user