diff --git a/src/app/(main)/play/page.tsx b/src/app/(main)/play/page.tsx new file mode 100644 index 0000000..6533533 --- /dev/null +++ b/src/app/(main)/play/page.tsx @@ -0,0 +1,148 @@ +"use client"; + +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from "@/components/ui/select"; +import { + SUPPORTED_THEMES, + highlightMonacoEditor, +} from "@/constants/editor/themes"; +import { Palette } from "lucide-react"; +import * as monaco from "monaco-editor"; +import { files } from "@/constants/editor/files"; +import { useEffect, useRef, useState } from "react"; +import { Editor, loader } from "@monaco-editor/react"; +import { MonacoLanguageClient } from "monaco-languageclient"; +import { connectToLSP, LSP_SUPPORTED_LANGUAGES } from "@/lib/lsp"; +import { Tabs, TabsList, TabsTrigger } from "@/components/ui/tabs"; +import { ScrollArea, ScrollBar } from "@/components/ui/scroll-area"; +import { COriginal, CplusplusOriginal, JavaOriginal } from "devicons-react"; + +loader.config({ monaco }); + +function moveCursorToLastLine(editor: monaco.editor.IStandaloneCodeEditor) { + const model = editor.getModel(); + if (model) { + const lineCount = model.getLineCount(); + const lastLineLength = model.getLineLength(lineCount); + editor.setPosition({ + lineNumber: lineCount, + column: lastLineLength + 1, + }); + editor.focus(); + } +} + +export default function PlayPage() { + const [language, setLanguage] = useState("c"); + const [theme, setTheme] = useState("vitesse-dark"); + const file = files[language]; + const editorRef = useRef(null); + const languageClientRef = useRef(null); + + useEffect(() => { + if (editorRef.current) { + moveCursorToLastLine(editorRef.current); + if (languageClientRef.current) { + languageClientRef.current.stop(); + languageClientRef.current = null; + } + if (language in LSP_SUPPORTED_LANGUAGES) { + connectToLSP(language).then((languageClient) => { + languageClientRef.current = languageClient; + }); + } + } + }, [language]); + + return ( +
+
+ + + + setLanguage("c")} + disabled={language === "c"} + > + + setLanguage("cpp")} + disabled={language === "cpp"} + > + + setLanguage("java")} + disabled={language === "java"} + > + + + + + + +
+ { + editorRef.current = editor; + moveCursorToLastLine(editor); + if (language in LSP_SUPPORTED_LANGUAGES) { + connectToLSP(language).then((languageClient) => { + languageClientRef.current = languageClient; + }); + } + }} + /> +
+ ); +} diff --git a/src/app/playground/page.tsx b/src/app/playground/page.tsx index 05b9550..3c0ef47 100644 --- a/src/app/playground/page.tsx +++ b/src/app/playground/page.tsx @@ -110,14 +110,13 @@ export default function PlaygroundPage() { const result = await runCode(code, language); - // 根据编译结果显示不同的信息 const statusMessage = result.success ? "Compilation successful" : "Compilation failed"; const fullMessage = `${statusMessage}\n\n${result.output}`; const highlighted = await codeToHtml(fullMessage, { - lang: "log", // 或者根据你的需求选择合适的语言 + lang: "log", theme: "one-dark-pro", }); diff --git a/src/constants/editor/files.ts b/src/constants/editor/files.ts new file mode 100644 index 0000000..f62d948 --- /dev/null +++ b/src/constants/editor/files.ts @@ -0,0 +1,31 @@ +export const files: { + [key: string]: { name: string; language: string; value: string }; +} = { + c: { + name: "main.c", + language: "c", + value: `#include +int main() { + printf("Hello, World!"); + return 0; +}`, + }, + cpp: { + name: "main.cpp", + language: "cpp", + value: `#include +int main() { + std::cout << "Hello, World!"; + return 0; +}`, + }, + java: { + name: "Main.java", + language: "java", + value: `public class Main { + public static void main(String[] args) { + System.out.println("Hello, World!"); + } +}`, + }, +}; diff --git a/src/lib/lsp.ts b/src/lib/lsp.ts index d6d22c6..ee23f0a 100644 --- a/src/lib/lsp.ts +++ b/src/lib/lsp.ts @@ -92,3 +92,37 @@ export async function connectToLanguageServer( }; }); } + +export async function connectToLSP( + language: string +): Promise { + return new Promise((resolve, reject) => { + let url: string; + if (language in LSP_SUPPORTED_LANGUAGES) { + const { hostname, port, path } = LSP_SUPPORTED_LANGUAGES[language]; + url = createUrl(hostname, port, path); + } else { + reject("Unsupported language"); + return; + } + + const webSocket = new WebSocket(url); + + webSocket.onopen = () => { + const socket = toSocket(webSocket); + const reader = new WebSocketMessageReader(socket); + const writer = new WebSocketMessageWriter(socket); + const languageClient = createLanguageClient({ reader, writer }); + languageClient.start(); + resolve(languageClient); + }; + + webSocket.onclose = () => { + reject("WebSocket connection closed unexpectedly"); + }; + + webSocket.onerror = (error) => { + reject(`WebSocket connection error: ${error}`); + }; + }); +}