From 43bc2f24e54e440fd7f10fdbbde5b6374312a8d6 Mon Sep 17 00:00:00 2001 From: inaseem Date: Tue, 5 Oct 2021 14:37:38 +0530 Subject: [PATCH] Moved the Editor to separate component --- frontend/components/RijuEditor.js | 111 ++++++++++++++++++++++ frontend/pages/_app.js | 2 +- frontend/pages/editor/[lang].js | 150 +++++------------------------- package.json | 1 + yarn.lock | 5 + 5 files changed, 141 insertions(+), 128 deletions(-) create mode 100644 frontend/components/RijuEditor.js diff --git a/frontend/components/RijuEditor.js b/frontend/components/RijuEditor.js new file mode 100644 index 0000000..b0f5467 --- /dev/null +++ b/frontend/components/RijuEditor.js @@ -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 ( + <> + { + editorRef.current = editor; + monacoRef.current = monaco; + if (onEditorMount) onEditorMount(editor, monaco); + }} + /> + + ); +}; + +export default RijuEditor; diff --git a/frontend/pages/_app.js b/frontend/pages/_app.js index 44c3a09..9a2c5be 100644 --- a/frontend/pages/_app.js +++ b/frontend/pages/_app.js @@ -18,7 +18,7 @@ Router.events.on("routeChangeComplete", () => { }); Router.events.on("routeChangeError", () => { console.log("routeChangeError"); - NProgress.done(); + // NProgress.done(); }); function MyApp({ Component, pageProps }) { diff --git a/frontend/pages/editor/[lang].js b/frontend/pages/editor/[lang].js index a8ab2f2..6428cd2 100644 --- a/frontend/pages/editor/[lang].js +++ b/frontend/pages/editor/[lang].js @@ -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) => { - diff --git a/package.json b/package.json index 7ff3d84..9fac69b 100644 --- a/package.json +++ b/package.json @@ -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", diff --git a/yarn.lock b/yarn.lock index e56c12c..d8a87d4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -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"