diff --git a/frontend/components/Layouts.js b/frontend/components/Layouts.js
new file mode 100644
index 0000000..8916575
--- /dev/null
+++ b/frontend/components/Layouts.js
@@ -0,0 +1,32 @@
+import React from "react";
+import { EventEmitter } from "../utils/EventEmitter";
+import Split from "react-split";
+
+const Layouts = (props) => {
+ const { splitType, children } = props;
+ return (
+ <>
+ EventEmitter.dispatch("resize")}
+ >
+ {children}
+
+ >
+ );
+};
+
+export default Layouts;
diff --git a/frontend/components/RijuTerminal.js b/frontend/components/RijuTerminal.js
index f24a08a..b5f18fc 100644
--- a/frontend/components/RijuTerminal.js
+++ b/frontend/components/RijuTerminal.js
@@ -19,6 +19,9 @@ function RijuTerminal() {
term.loadAddon(fitAddon);
window.addEventListener("resize", () => fitAddon.fit());
+ EventEmitter.subscribe("resize", () => {
+ fitAddon.fit();
+ });
EventEmitter.subscribe("terminal", (payload) => {
if (!payload) return;
const { type, data } = payload;
@@ -40,7 +43,14 @@ function RijuTerminal() {
}, []);
return (
-
+
);
}
diff --git a/frontend/pages/editor/[lang].js b/frontend/pages/editor/[lang].js
index 6d407d7..56f3a8e 100644
--- a/frontend/pages/editor/[lang].js
+++ b/frontend/pages/editor/[lang].js
@@ -1,13 +1,30 @@
import MonacoEditor, { useMonaco } from "@monaco-editor/react";
-import { Circle, Code as Format, Home, PlayArrow } from "@mui/icons-material";
+import {
+ Circle,
+ Code as Format,
+ Home,
+ HorizontalSplit,
+ PlayArrow,
+ VerticalSplit,
+} from "@mui/icons-material";
import { LoadingButton } from "@mui/lab";
-import { Box, Button, Chip, Divider, Typography } from "@mui/material";
+import {
+ Box,
+ Button,
+ Chip,
+ Divider,
+ Stack,
+ ToggleButton,
+ ToggleButtonGroup,
+ Typography,
+} from "@mui/material";
import ansi from "ansicolor";
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";
ansi.rgb = {
@@ -27,12 +44,14 @@ 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);
const [isFormatting, setFormatting] = useState(false);
const [isLspStarted, setLspStarted] = useState(false);
const [isLspRequested, setIsLspRequested] = useState(false);
+ const [splitType, setSplitType] = useState("horizontal");
const monaco = useMonaco();
const [status, setStatus] = useState("connecting");
@@ -233,8 +252,6 @@ const CodeRunner = (props) => {
case "lsp":
setLspStarted(false);
setIsLspRequested(false);
- // lspButton.classList.add("is-light");
- // lspButtonState.innerText = "CRASHED";
break;
case "terminal":
sendToTerminal(
@@ -307,13 +324,42 @@ const CodeRunner = (props) => {
showValue();
},
});
- // editor.getModel().onDidChangeContent(() => recordActivity());
- // window.addEventListener("resize", () => editor.layout());
editor.getModel().setValue(config.template + "\n");
monaco.editor.setModelLanguage(
editor.getModel(),
config.monacoLang || "plaintext"
);
+ // 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);
}
@@ -338,6 +384,17 @@ const CodeRunner = (props) => {
}
};
+ const handleLayout = (event, value) => {
+ const e = document.querySelector(".split .gutter");
+ e.classList.replace(`gutter-${splitType}`, `gutter-${value}`);
+ const es = document.querySelectorAll(".split .panel");
+ for (const e of es) {
+ e.removeAttribute("style");
+ e.removeAttribute("style");
+ }
+ setSplitType(value);
+ };
+
return (
<>
@@ -352,25 +409,20 @@ const CodeRunner = (props) => {
content="minimum-scale=1, initial-scale=1, width=device-width"
/>
-
- t.zIndex.appBar,
}}
>
-
+
-
+
{config.name}
{
}}
label={status}
/>
-
+
{
>
Autocomplete
+
+
+
+
+
+
+
+
+
{
>
Run
-
-
-
-
-
+
+
+ {
onMount={editorDidMount}
/>
-
+
-
-
+
+
>
);
};
diff --git a/frontend/styles/Home.module.css b/frontend/styles/Home.module.css
deleted file mode 100644
index 35454bb..0000000
--- a/frontend/styles/Home.module.css
+++ /dev/null
@@ -1,121 +0,0 @@
-.container {
- min-height: 100vh;
- padding: 0 0.5rem;
- display: flex;
- flex-direction: column;
- justify-content: center;
- align-items: center;
- height: 100vh;
-}
-
-.main {
- padding: 5rem 0;
- flex: 1;
- display: flex;
- flex-direction: column;
- justify-content: center;
- align-items: center;
-}
-
-.footer {
- width: 100%;
- height: 100px;
- border-top: 1px solid #eaeaea;
- display: flex;
- justify-content: center;
- align-items: center;
-}
-
-.footer a {
- display: flex;
- justify-content: center;
- align-items: center;
- flex-grow: 1;
-}
-
-.title a {
- color: #0070f3;
- text-decoration: none;
-}
-
-.title a:hover,
-.title a:focus,
-.title a:active {
- text-decoration: underline;
-}
-
-.title {
- margin: 0;
- line-height: 1.15;
- font-size: 4rem;
-}
-
-.title,
-.description {
- text-align: center;
-}
-
-.description {
- line-height: 1.5;
- font-size: 1.5rem;
-}
-
-.code {
- background: #fafafa;
- border-radius: 5px;
- padding: 0.75rem;
- font-size: 1.1rem;
- font-family: Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono,
- Bitstream Vera Sans Mono, Courier New, monospace;
-}
-
-.grid {
- display: flex;
- align-items: center;
- justify-content: center;
- flex-wrap: wrap;
- max-width: 800px;
- margin-top: 3rem;
-}
-
-.card {
- margin: 1rem;
- padding: 1.5rem;
- text-align: left;
- color: inherit;
- text-decoration: none;
- border: 1px solid #eaeaea;
- border-radius: 10px;
- transition: color 0.15s ease, border-color 0.15s ease;
- width: 45%;
-}
-
-.card:hover,
-.card:focus,
-.card:active {
- color: #0070f3;
- border-color: #0070f3;
-}
-
-.card h2 {
- margin: 0 0 1rem 0;
- font-size: 1.5rem;
-}
-
-.card p {
- margin: 0;
- font-size: 1.25rem;
- line-height: 1.5;
-}
-
-.logo {
- height: 1em;
- margin-left: 0.5rem;
-}
-
-@media (max-width: 600px) {
- .grid {
- width: 100%;
- flex-direction: column;
- }
-}
diff --git a/frontend/styles/globals.css b/frontend/styles/globals.css
index 6363925..ee624d6 100644
--- a/frontend/styles/globals.css
+++ b/frontend/styles/globals.css
@@ -20,6 +20,43 @@ a {
}
.rijuEdutor {
- overflow: hidden;
- height: calc(100% - 8px);
+ height: 100%;
+ width: 100%;
+}
+
+/* Split pane */
+
+.split {
+ overflow: auto;
+}
+.split .panel {
+ overflow: auto;
+}
+.split .editor {
+ overflow: hidden;
+}
+.split .gutter {
+ background-color: #eee;
+ opacity: 1;
+ z-index: 1;
+ background-repeat: no-repeat;
+ background-position: 50%;
+}
+
+/* .split .gutter:hover {
+ opacity: 1;
+ -webkit-transition: all 2s ease;
+ transition: all 2s ease;
+} */
+
+.split .gutter.gutter-vertical {
+ background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAFAQMAAABo7865AAAABlBMVEVHcEzMzMzyAv2sAAAAAXRSTlMAQObYZgAAABBJREFUeF5jOAMEEAIEEFwAn3kMwcB6I2AAAAAASUVORK5CYII=");
+ cursor: row-resize;
+ width: 100% !important;
+}
+
+.split .gutter.gutter-horizontal {
+ background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAeCAYAAADkftS9AAAAIklEQVQoU2M4c+bMfxAGAgYYmwGrIIiDjrELjpo5aiZeMwF+yNnOs5KSvgAAAABJRU5ErkJggg==");
+ cursor: col-resize;
+ height: 100% !important;
}
diff --git a/package.json b/package.json
index c8651d0..7ff3d84 100644
--- a/package.json
+++ b/package.json
@@ -51,6 +51,7 @@
"prettier": "^2.3.1",
"react": "17.0.2",
"react-dom": "17.0.2",
+ "react-split": "^2.0.13",
"regenerator-runtime": "^0.13.7",
"setimmediate": "^1.0.5",
"strip-ansi": "^6.0.0",
diff --git a/yarn.lock b/yarn.lock
index b54e3de..e56c12c 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -4787,7 +4787,7 @@ promise-inflight@^1.0.1:
resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3"
integrity sha1-mEcocL8igTL8vdhoEputEsPAKeM=
-prop-types@15.7.2, prop-types@^15.6.2, prop-types@^15.7.2:
+prop-types@15.7.2, prop-types@^15.5.7, prop-types@^15.6.2, prop-types@^15.7.2:
version "15.7.2"
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5"
integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==
@@ -4952,6 +4952,14 @@ react-refresh@0.8.3:
resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.8.3.tgz#721d4657672d400c5e3c75d063c4a85fb2d5d68f"
integrity sha512-X8jZHc7nCMjaCqoU+V2I0cOhNW+QMBwSUkeXnTi8IPe6zaRWfn60ZzvFDZqWPfmSJfjub7dDW1SP0jaHWLu/hg==
+react-split@^2.0.13:
+ version "2.0.13"
+ resolved "https://registry.yarnpkg.com/react-split/-/react-split-2.0.13.tgz#8d55fcb17edfd6cd2fb0203ab8324c02ec39a81a"
+ integrity sha512-suq/UH4epMu2aF4NBh+imlpUvntsIvU3li9EBBLdxqNtYEg+nY7TGl8Ij65mD1qYyhs3dQhA1Pv3rLXd1s5/lQ==
+ dependencies:
+ prop-types "^15.5.7"
+ split.js "^1.6.0"
+
react-transition-group@^4.4.2:
version "4.4.2"
resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-4.4.2.tgz#8b59a56f09ced7b55cbd53c36768b922890d5470"
@@ -5432,6 +5440,11 @@ split-string@^3.0.1, split-string@^3.0.2:
dependencies:
extend-shallow "^3.0.0"
+split.js@^1.6.0:
+ version "1.6.4"
+ resolved "https://registry.yarnpkg.com/split.js/-/split.js-1.6.4.tgz#13d47cba53382adef230a53294ce5dacb2a2f2e1"
+ integrity sha512-kYmQZprRJrF1IOjg/E+gdBEsKFv5kbgUE6RJVJZvrIzTOK/IHzKSqIeiJnWs7IP5D9TnpTQ2CbanuDuIWcyDUQ==
+
ssri@^6.0.1:
version "6.0.2"
resolved "https://registry.yarnpkg.com/ssri/-/ssri-6.0.2.tgz#157939134f20464e7301ddba3e90ffa8f7728ac5"