Moved the Editor to separate component
This commit is contained in:
parent
40cd66eae0
commit
43bc2f24e5
|
@ -0,0 +1,111 @@
|
||||||
|
import MonacoEditor from "@monaco-editor/react";
|
||||||
|
import {
|
||||||
|
createConnection,
|
||||||
|
MonacoLanguageClient,
|
||||||
|
MonacoServices,
|
||||||
|
Services,
|
||||||
|
} from "monaco-languageclient";
|
||||||
|
import React from "react";
|
||||||
|
import { createMessageConnection } from "vscode-jsonrpc";
|
||||||
|
import RijuMessageReader from "../services/RijuMessageReader";
|
||||||
|
import RijuMessageWriter from "../services/RijuMessageWriter";
|
||||||
|
import { EventEmitter } from "../utils/EventEmitter";
|
||||||
|
|
||||||
|
let clientDisposable = null;
|
||||||
|
let servicesDisposable = null;
|
||||||
|
|
||||||
|
const RijuEditor = (props) => {
|
||||||
|
const { onEditorValueChange, config, splitType, onEditorMount } = props;
|
||||||
|
const editorRef = React.useRef();
|
||||||
|
const monacoRef = React.useRef();
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
EventEmitter.subscribe("lspStarted", (data) => {
|
||||||
|
const { message, socket } = data;
|
||||||
|
initLSP(socket, message, monacoRef.current, editorRef.current);
|
||||||
|
});
|
||||||
|
EventEmitter.subscribe("lspStopped", () => {
|
||||||
|
if (clientDisposable) {
|
||||||
|
clientDisposable.dispose();
|
||||||
|
clientDisposable = null;
|
||||||
|
}
|
||||||
|
if (servicesDisposable) {
|
||||||
|
servicesDisposable.dispose();
|
||||||
|
servicesDisposable = null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const initLSP = (socket, message, monaco, editor) => {
|
||||||
|
const services = MonacoServices.create(editor, {
|
||||||
|
rootUri: `file://${message.root}`,
|
||||||
|
});
|
||||||
|
servicesDisposable = Services.install(services);
|
||||||
|
const newURI = `file://${message.root}/${config.main}`;
|
||||||
|
const oldModel = editor.getModel();
|
||||||
|
if (oldModel.uri.toString() !== newURI) {
|
||||||
|
// This code is likely to be buggy as it will probably
|
||||||
|
// never run and has thus never been tested.
|
||||||
|
editor.setModel(
|
||||||
|
monaco.editor.createModel(
|
||||||
|
oldModel.getValue(),
|
||||||
|
undefined,
|
||||||
|
monaco.Uri.parse(newURI)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
oldModel.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
const connection = createMessageConnection(
|
||||||
|
new RijuMessageReader(socket),
|
||||||
|
new RijuMessageWriter(socket, config)
|
||||||
|
);
|
||||||
|
const client = new MonacoLanguageClient({
|
||||||
|
name: "Riju",
|
||||||
|
clientOptions: {
|
||||||
|
documentSelector: [{ pattern: "**" }],
|
||||||
|
middleware: {
|
||||||
|
workspace: {
|
||||||
|
configuration: (params, token, configuration) => {
|
||||||
|
return Array(configuration(params, token).length).fill(
|
||||||
|
config.lsp.config !== undefined ? config.lsp.config : {}
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
initializationOptions: config.lsp.init || {},
|
||||||
|
},
|
||||||
|
connectionProvider: {
|
||||||
|
get: (errorHandler, closeHandler) =>
|
||||||
|
Promise.resolve(
|
||||||
|
createConnection(connection, errorHandler, closeHandler)
|
||||||
|
),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
clientDisposable = client.start();
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<MonacoEditor
|
||||||
|
wrapperClassName={"rijuEditor"}
|
||||||
|
onChange={onEditorValueChange}
|
||||||
|
language={config.monacoLang || "plaintext"}
|
||||||
|
value={config.template + "\n"}
|
||||||
|
options={{
|
||||||
|
minimap: { enabled: splitType == "horizontal" ? false : true },
|
||||||
|
scrollbar: { verticalScrollbarSize: 0 },
|
||||||
|
fontLigatures: true,
|
||||||
|
fontFamily: "Fira Code",
|
||||||
|
}}
|
||||||
|
onMount={(editor, monaco) => {
|
||||||
|
editorRef.current = editor;
|
||||||
|
monacoRef.current = monaco;
|
||||||
|
if (onEditorMount) onEditorMount(editor, monaco);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default RijuEditor;
|
|
@ -18,7 +18,7 @@ Router.events.on("routeChangeComplete", () => {
|
||||||
});
|
});
|
||||||
Router.events.on("routeChangeError", () => {
|
Router.events.on("routeChangeError", () => {
|
||||||
console.log("routeChangeError");
|
console.log("routeChangeError");
|
||||||
NProgress.done();
|
// NProgress.done();
|
||||||
});
|
});
|
||||||
|
|
||||||
function MyApp({ Component, pageProps }) {
|
function MyApp({ Component, pageProps }) {
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
import MonacoEditor, { useMonaco } from "@monaco-editor/react";
|
|
||||||
import {
|
import {
|
||||||
Circle,
|
Circle,
|
||||||
Code as Format,
|
Code as Format,
|
||||||
|
@ -22,7 +21,6 @@ import dynamic from "next/dynamic";
|
||||||
import Head from "next/head";
|
import Head from "next/head";
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import React, { useEffect, useRef, useState } from "react";
|
import React, { useEffect, useRef, useState } from "react";
|
||||||
import { createMessageConnection } from "vscode-jsonrpc";
|
|
||||||
import Layouts from "../../components/Layouts";
|
import Layouts from "../../components/Layouts";
|
||||||
import langs from "../../static/langs.json";
|
import langs from "../../static/langs.json";
|
||||||
import { EventEmitter } from "../../utils/EventEmitter";
|
import { EventEmitter } from "../../utils/EventEmitter";
|
||||||
|
@ -32,10 +30,11 @@ ansi.rgb = {
|
||||||
const RijuTerminal = dynamic(() => import("../../components/RijuTerminal"), {
|
const RijuTerminal = dynamic(() => import("../../components/RijuTerminal"), {
|
||||||
ssr: false,
|
ssr: false,
|
||||||
});
|
});
|
||||||
|
const RijuEditor = dynamic(() => import("../../components/RijuEditor"), {
|
||||||
|
ssr: false,
|
||||||
|
});
|
||||||
|
|
||||||
const DEBUG = true;
|
const DEBUG = true;
|
||||||
let clientDisposable = null;
|
|
||||||
let servicesDisposable = null;
|
|
||||||
let serviceLogBuffers = {};
|
let serviceLogBuffers = {};
|
||||||
let serviceLogLines = {};
|
let serviceLogLines = {};
|
||||||
|
|
||||||
|
@ -43,7 +42,6 @@ const CodeRunner = (props) => {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { langConfig } = props;
|
const { langConfig } = props;
|
||||||
const editorRef = useRef(null);
|
const editorRef = useRef(null);
|
||||||
const paneRef = useRef(null);
|
|
||||||
const [config, setConfig] = useState(langConfig);
|
const [config, setConfig] = useState(langConfig);
|
||||||
const [mounted, setMounted] = useState(false);
|
const [mounted, setMounted] = useState(false);
|
||||||
const [isRunning, setRunning] = useState(false);
|
const [isRunning, setRunning] = useState(false);
|
||||||
|
@ -51,7 +49,7 @@ const CodeRunner = (props) => {
|
||||||
const [isLspStarted, setLspStarted] = useState(false);
|
const [isLspStarted, setLspStarted] = useState(false);
|
||||||
const [isLspRequested, setIsLspRequested] = useState(false);
|
const [isLspRequested, setIsLspRequested] = useState(false);
|
||||||
const [splitType, setSplitType] = useState("horizontal");
|
const [splitType, setSplitType] = useState("horizontal");
|
||||||
const monaco = useMonaco();
|
|
||||||
const [status, setStatus] = useState("connecting");
|
const [status, setStatus] = useState("connecting");
|
||||||
|
|
||||||
function sendToTerminal(type, data) {
|
function sendToTerminal(type, data) {
|
||||||
|
@ -59,6 +57,8 @@ const CodeRunner = (props) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
function connect() {
|
function connect() {
|
||||||
|
serviceLogBuffers = {};
|
||||||
|
serviceLogLines = {};
|
||||||
setStatus("connecting");
|
setStatus("connecting");
|
||||||
const socket = new WebSocket(
|
const socket = new WebSocket(
|
||||||
// (document.location.protocol === "http:" ? "ws://" : "wss://") +
|
// (document.location.protocol === "http:" ? "ws://" : "wss://") +
|
||||||
|
@ -126,14 +126,7 @@ const CodeRunner = (props) => {
|
||||||
case "lspStopped":
|
case "lspStopped":
|
||||||
setIsLspRequested(false);
|
setIsLspRequested(false);
|
||||||
setLspStarted(false);
|
setLspStarted(false);
|
||||||
if (clientDisposable) {
|
EventEmitter.dispatch("lspStopped");
|
||||||
clientDisposable.dispose();
|
|
||||||
clientDisposable = null;
|
|
||||||
}
|
|
||||||
if (servicesDisposable) {
|
|
||||||
servicesDisposable.dispose();
|
|
||||||
servicesDisposable = null;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case "lspStarted":
|
case "lspStarted":
|
||||||
setLspStarted(true);
|
setLspStarted(true);
|
||||||
|
@ -143,68 +136,10 @@ const CodeRunner = (props) => {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log("Started", message.root, config.main);
|
EventEmitter.dispatch("lspStarted", { message, socket });
|
||||||
// EventEmitter.dispatch("lspStarted", message);
|
|
||||||
const {
|
|
||||||
createConnection,
|
|
||||||
MonacoLanguageClient,
|
|
||||||
MonacoServices,
|
|
||||||
Services,
|
|
||||||
} = await import("monaco-languageclient");
|
|
||||||
const services = MonacoServices.create(editorRef.current, {
|
|
||||||
rootUri: `file://${message.root}`,
|
|
||||||
});
|
|
||||||
servicesDisposable = Services.install(services);
|
|
||||||
const newURI = `file://${message.root}/${config.main}`;
|
|
||||||
const oldModel = editorRef.current.getModel();
|
|
||||||
console.log("Check 4", oldModel.uri, newURI);
|
|
||||||
if (oldModel.uri.toString() !== newURI) {
|
|
||||||
// This code is likely to be buggy as it will probably
|
|
||||||
// never run and has thus never been tested.
|
|
||||||
editorRef.current.setModel(
|
|
||||||
monaco.editor.createModel(
|
|
||||||
oldModel.getValue(),
|
|
||||||
undefined,
|
|
||||||
monaco.Uri.parse(newURI)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
oldModel.dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
const RijuMessageReader = (
|
setTimeout(() => {}, 3000);
|
||||||
await import("../../services/RijuMessageReader")
|
|
||||||
).default;
|
|
||||||
const RijuMessageWriter = (
|
|
||||||
await import("../../services/RijuMessageWriter")
|
|
||||||
).default;
|
|
||||||
|
|
||||||
const connection = createMessageConnection(
|
|
||||||
new RijuMessageReader(socket),
|
|
||||||
new RijuMessageWriter(socket, config)
|
|
||||||
);
|
|
||||||
const client = new MonacoLanguageClient({
|
|
||||||
name: "Riju",
|
|
||||||
clientOptions: {
|
|
||||||
documentSelector: [{ pattern: "**" }],
|
|
||||||
middleware: {
|
|
||||||
workspace: {
|
|
||||||
configuration: (params, token, configuration) => {
|
|
||||||
return Array(configuration(params, token).length).fill(
|
|
||||||
config.lsp.config !== undefined ? config.lsp.config : {}
|
|
||||||
);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
initializationOptions: config.lsp.init || {},
|
|
||||||
},
|
|
||||||
connectionProvider: {
|
|
||||||
get: (errorHandler, closeHandler) =>
|
|
||||||
Promise.resolve(
|
|
||||||
createConnection(connection, errorHandler, closeHandler)
|
|
||||||
),
|
|
||||||
},
|
|
||||||
});
|
|
||||||
clientDisposable = client.start();
|
|
||||||
return;
|
return;
|
||||||
case "lspOutput":
|
case "lspOutput":
|
||||||
// Should be handled by RijuMessageReader
|
// Should be handled by RijuMessageReader
|
||||||
|
@ -251,6 +186,7 @@ const CodeRunner = (props) => {
|
||||||
case "lsp":
|
case "lsp":
|
||||||
setLspStarted(false);
|
setLspStarted(false);
|
||||||
setIsLspRequested(false);
|
setIsLspRequested(false);
|
||||||
|
EventEmitter.dispatch("lspStopped");
|
||||||
break;
|
break;
|
||||||
case "terminal":
|
case "terminal":
|
||||||
sendToTerminal(
|
sendToTerminal(
|
||||||
|
@ -260,6 +196,12 @@ const CodeRunner = (props) => {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
case "langConfig":
|
||||||
|
console.log("Lang Config", message);
|
||||||
|
// We could use this message instead of hardcoding the
|
||||||
|
// language config into the HTML page returned from the
|
||||||
|
// server, but for now we just ignore it.
|
||||||
|
return;
|
||||||
default:
|
default:
|
||||||
console.error("Unexpected message from server:", message);
|
console.error("Unexpected message from server:", message);
|
||||||
}
|
}
|
||||||
|
@ -270,14 +212,7 @@ const CodeRunner = (props) => {
|
||||||
} else {
|
} else {
|
||||||
console.error("Connection died");
|
console.error("Connection died");
|
||||||
}
|
}
|
||||||
if (clientDisposable) {
|
EventEmitter.dispatch("lspStopped");
|
||||||
clientDisposable.dispose();
|
|
||||||
clientDisposable = null;
|
|
||||||
}
|
|
||||||
if (servicesDisposable) {
|
|
||||||
servicesDisposable.dispose();
|
|
||||||
servicesDisposable = null;
|
|
||||||
}
|
|
||||||
setRunning(false);
|
setRunning(false);
|
||||||
setLspStarted(false);
|
setLspStarted(false);
|
||||||
setIsLspRequested(false);
|
setIsLspRequested(false);
|
||||||
|
@ -313,7 +248,6 @@ const CodeRunner = (props) => {
|
||||||
|
|
||||||
function editorDidMount(editor, monaco) {
|
function editorDidMount(editor, monaco) {
|
||||||
editorRef.current = editor;
|
editorRef.current = editor;
|
||||||
|
|
||||||
editor.addAction({
|
editor.addAction({
|
||||||
id: "runCode",
|
id: "runCode",
|
||||||
label: "Run",
|
label: "Run",
|
||||||
|
@ -323,37 +257,6 @@ const CodeRunner = (props) => {
|
||||||
showValue();
|
showValue();
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
// Below code is just for adding an empty line in editor
|
|
||||||
monaco.languages.registerCodeLensProvider(
|
|
||||||
config.monacoLang || "plaintext",
|
|
||||||
{
|
|
||||||
provideCodeLenses: function (model, token) {
|
|
||||||
return {
|
|
||||||
lenses: [
|
|
||||||
{
|
|
||||||
range: {
|
|
||||||
startLineNumber: 1,
|
|
||||||
startColumn: 1,
|
|
||||||
endLineNumber: 2,
|
|
||||||
endColumn: 1,
|
|
||||||
},
|
|
||||||
id: "Format",
|
|
||||||
command: {
|
|
||||||
// id: commandId,
|
|
||||||
// title: "Format",
|
|
||||||
title: "",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
dispose: () => {},
|
|
||||||
};
|
|
||||||
},
|
|
||||||
resolveCodeLens: function (model, codeLens, token) {
|
|
||||||
return codeLens;
|
|
||||||
},
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
setMounted(true);
|
setMounted(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -415,7 +318,7 @@ const CodeRunner = (props) => {
|
||||||
sx={{
|
sx={{
|
||||||
boxShadow: `0 2px 4px rgb(0 0 0 / 10%)`,
|
boxShadow: `0 2px 4px rgb(0 0 0 / 10%)`,
|
||||||
zIndex: (t) => t.zIndex.appBar,
|
zIndex: (t) => t.zIndex.appBar,
|
||||||
height: "48px",
|
minHeight: "48px",
|
||||||
p: "0 24px",
|
p: "0 24px",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
@ -524,18 +427,11 @@ const CodeRunner = (props) => {
|
||||||
</Stack>
|
</Stack>
|
||||||
<Layouts splitType={splitType}>
|
<Layouts splitType={splitType}>
|
||||||
<Box className="panel editor">
|
<Box className="panel editor">
|
||||||
<MonacoEditor
|
<RijuEditor
|
||||||
wrapperClassName={"rijuEditor"}
|
onEditorValueChange={handleChange}
|
||||||
onChange={handleChange}
|
config={config}
|
||||||
language={config.monacoLang || "plaintext"}
|
splitType={splitType}
|
||||||
value={config.template + "\n"}
|
onEditorMount={editorDidMount}
|
||||||
options={{
|
|
||||||
minimap: { enabled: splitType == "horizontal" ? false : true },
|
|
||||||
scrollbar: { verticalScrollbarSize: 0 },
|
|
||||||
fontLigatures: true,
|
|
||||||
fontFamily: "Fira Code",
|
|
||||||
}}
|
|
||||||
onMount={editorDidMount}
|
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
<Box className="panel" sx={{ bgcolor: "#292D3E", p: 2 }}>
|
<Box className="panel" sx={{ bgcolor: "#292D3E", p: 2 }}>
|
||||||
|
|
|
@ -41,6 +41,7 @@
|
||||||
"historic-readline": "^1.0.8",
|
"historic-readline": "^1.0.8",
|
||||||
"jsonschema": "^1.4.0",
|
"jsonschema": "^1.4.0",
|
||||||
"lodash": "^4.17.20",
|
"lodash": "^4.17.20",
|
||||||
|
"monaco-editor": "^0.28.1",
|
||||||
"monaco-editor-webpack-plugin": "^4.1.2",
|
"monaco-editor-webpack-plugin": "^4.1.2",
|
||||||
"monaco-languageclient": "0.13.0",
|
"monaco-languageclient": "0.13.0",
|
||||||
"next": "11.0.1",
|
"next": "11.0.1",
|
||||||
|
|
|
@ -4181,6 +4181,11 @@ monaco-editor-webpack-plugin@^4.1.2:
|
||||||
dependencies:
|
dependencies:
|
||||||
loader-utils "^2.0.0"
|
loader-utils "^2.0.0"
|
||||||
|
|
||||||
|
monaco-editor@^0.28.1:
|
||||||
|
version "0.28.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/monaco-editor/-/monaco-editor-0.28.1.tgz#732788ff2172d59e6d436b206da8cac715413940"
|
||||||
|
integrity sha512-P1vPqxB4B1ZFzTeR1ScggSp9/5NoQrLCq88fnlNUsuRAP1usEBN4TIpI2lw0AYIZNVIanHk0qwjze2uJwGOHUw==
|
||||||
|
|
||||||
monaco-languageclient@0.13.0:
|
monaco-languageclient@0.13.0:
|
||||||
version "0.13.0"
|
version "0.13.0"
|
||||||
resolved "https://registry.yarnpkg.com/monaco-languageclient/-/monaco-languageclient-0.13.0.tgz#59b68b42fb7633171502d6557f597c2752f6c266"
|
resolved "https://registry.yarnpkg.com/monaco-languageclient/-/monaco-languageclient-0.13.0.tgz#59b68b42fb7633171502d6557f597c2752f6c266"
|
||||||
|
|
Loading…
Reference in New Issue