Moved the Editor to separate component

This commit is contained in:
inaseem 2021-10-05 14:37:38 +05:30
parent 40cd66eae0
commit 43bc2f24e5
5 changed files with 141 additions and 128 deletions

View File

@ -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;

View File

@ -18,7 +18,7 @@ Router.events.on("routeChangeComplete", () => {
});
Router.events.on("routeChangeError", () => {
console.log("routeChangeError");
NProgress.done();
// NProgress.done();
});
function MyApp({ Component, pageProps }) {

View File

@ -1,4 +1,3 @@
import MonacoEditor, { useMonaco } from "@monaco-editor/react";
import {
Circle,
Code as Format,
@ -22,7 +21,6 @@ import dynamic from "next/dynamic";
import Head from "next/head";
import { useRouter } from "next/router";
import React, { useEffect, useRef, useState } from "react";
import { createMessageConnection } from "vscode-jsonrpc";
import Layouts from "../../components/Layouts";
import langs from "../../static/langs.json";
import { EventEmitter } from "../../utils/EventEmitter";
@ -32,10 +30,11 @@ ansi.rgb = {
const RijuTerminal = dynamic(() => import("../../components/RijuTerminal"), {
ssr: false,
});
const RijuEditor = dynamic(() => import("../../components/RijuEditor"), {
ssr: false,
});
const DEBUG = true;
let clientDisposable = null;
let servicesDisposable = null;
let serviceLogBuffers = {};
let serviceLogLines = {};
@ -43,7 +42,6 @@ const CodeRunner = (props) => {
const router = useRouter();
const { langConfig } = props;
const editorRef = useRef(null);
const paneRef = useRef(null);
const [config, setConfig] = useState(langConfig);
const [mounted, setMounted] = useState(false);
const [isRunning, setRunning] = useState(false);
@ -51,7 +49,7 @@ const CodeRunner = (props) => {
const [isLspStarted, setLspStarted] = useState(false);
const [isLspRequested, setIsLspRequested] = useState(false);
const [splitType, setSplitType] = useState("horizontal");
const monaco = useMonaco();
const [status, setStatus] = useState("connecting");
function sendToTerminal(type, data) {
@ -59,6 +57,8 @@ const CodeRunner = (props) => {
}
function connect() {
serviceLogBuffers = {};
serviceLogLines = {};
setStatus("connecting");
const socket = new WebSocket(
// (document.location.protocol === "http:" ? "ws://" : "wss://") +
@ -126,14 +126,7 @@ const CodeRunner = (props) => {
case "lspStopped":
setIsLspRequested(false);
setLspStarted(false);
if (clientDisposable) {
clientDisposable.dispose();
clientDisposable = null;
}
if (servicesDisposable) {
servicesDisposable.dispose();
servicesDisposable = null;
}
EventEmitter.dispatch("lspStopped");
break;
case "lspStarted":
setLspStarted(true);
@ -143,68 +136,10 @@ const CodeRunner = (props) => {
return;
}
console.log("Started", message.root, config.main);
// 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();
}
EventEmitter.dispatch("lspStarted", { message, socket });
const RijuMessageReader = (
await import("../../services/RijuMessageReader")
).default;
const RijuMessageWriter = (
await import("../../services/RijuMessageWriter")
).default;
setTimeout(() => {}, 3000);
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;
case "lspOutput":
// Should be handled by RijuMessageReader
@ -251,6 +186,7 @@ const CodeRunner = (props) => {
case "lsp":
setLspStarted(false);
setIsLspRequested(false);
EventEmitter.dispatch("lspStopped");
break;
case "terminal":
sendToTerminal(
@ -260,6 +196,12 @@ const CodeRunner = (props) => {
break;
}
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:
console.error("Unexpected message from server:", message);
}
@ -270,14 +212,7 @@ const CodeRunner = (props) => {
} else {
console.error("Connection died");
}
if (clientDisposable) {
clientDisposable.dispose();
clientDisposable = null;
}
if (servicesDisposable) {
servicesDisposable.dispose();
servicesDisposable = null;
}
EventEmitter.dispatch("lspStopped");
setRunning(false);
setLspStarted(false);
setIsLspRequested(false);
@ -313,7 +248,6 @@ const CodeRunner = (props) => {
function editorDidMount(editor, monaco) {
editorRef.current = editor;
editor.addAction({
id: "runCode",
label: "Run",
@ -323,37 +257,6 @@ const CodeRunner = (props) => {
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);
}
@ -415,7 +318,7 @@ const CodeRunner = (props) => {
sx={{
boxShadow: `0 2px 4px rgb(0 0 0 / 10%)`,
zIndex: (t) => t.zIndex.appBar,
height: "48px",
minHeight: "48px",
p: "0 24px",
}}
>
@ -524,18 +427,11 @@ const CodeRunner = (props) => {
</Stack>
<Layouts splitType={splitType}>
<Box className="panel editor">
<MonacoEditor
wrapperClassName={"rijuEditor"}
onChange={handleChange}
language={config.monacoLang || "plaintext"}
value={config.template + "\n"}
options={{
minimap: { enabled: splitType == "horizontal" ? false : true },
scrollbar: { verticalScrollbarSize: 0 },
fontLigatures: true,
fontFamily: "Fira Code",
}}
onMount={editorDidMount}
<RijuEditor
onEditorValueChange={handleChange}
config={config}
splitType={splitType}
onEditorMount={editorDidMount}
/>
</Box>
<Box className="panel" sx={{ bgcolor: "#292D3E", p: 2 }}>

View File

@ -41,6 +41,7 @@
"historic-readline": "^1.0.8",
"jsonschema": "^1.4.0",
"lodash": "^4.17.20",
"monaco-editor": "^0.28.1",
"monaco-editor-webpack-plugin": "^4.1.2",
"monaco-languageclient": "0.13.0",
"next": "11.0.1",

View File

@ -4181,6 +4181,11 @@ monaco-editor-webpack-plugin@^4.1.2:
dependencies:
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:
version "0.13.0"
resolved "https://registry.yarnpkg.com/monaco-languageclient/-/monaco-languageclient-0.13.0.tgz#59b68b42fb7633171502d6557f597c2752f6c266"