Skip to content

Commit e66fcd4

Browse files
committed
feat: First pass on mss editor with monaco editor and connection via lsp
1 parent d32750c commit e66fcd4

File tree

6 files changed

+251
-1
lines changed

6 files changed

+251
-1
lines changed

.env

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
NEXT_PUBLIC_API_BASE_URL=http://localhost:8080
2+
NEXT_PUBLIC_API_LANGUAGE_SERVER=http://localhost:5001

package.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,9 @@
1515
"@emotion/react": "11",
1616
"@emotion/styled": "11",
1717
"@jlguenego/lexer": "^1.5.0",
18+
"@monaco-editor/react": "^4.7.0",
1819
"framer-motion": "6",
20+
"monaco-editor": "^0.52.2",
1921
"next": "12.2.5",
2022
"prismjs": "^1.29.0",
2123
"react": "18.2.0",
@@ -32,12 +34,15 @@
3234
"@types/prismjs": "^1.26.0",
3335
"@types/react": "18.0.18",
3436
"@types/react-dom": "18.0.6",
37+
"@types/ws": "^8.18.1",
3538
"eslint": "8.23.0",
3639
"eslint-config-next": "12.2.5",
3740
"jest": "^29.1.1",
3841
"jest-environment-jsdom": "^29.1.1",
3942
"prettier": "2.8.8",
4043
"prettier-plugin-organize-imports": "^3.2.4",
41-
"typescript": "4.8.2"
44+
"typescript": "4.8.2",
45+
"vscode-languageserver-protocol": "^3.17.5",
46+
"vscode-languageserver-types": "^3.17.5"
4247
}
4348
}

src/api/LanguageServerAPI.ts

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
import {
2+
CompletionParams,
3+
DidOpenTextDocumentNotification,
4+
DidOpenTextDocumentParams,
5+
Position,
6+
} from "vscode-languageserver-protocol";
7+
8+
export class LanguageServerAPI {
9+
private url: string;
10+
private webSocket: WebSocket;
11+
private fileUri: string = "file:///C:/Users/nickp/Downloads/test.py";
12+
private languageId: string = "python";
13+
14+
public constructor(url: string) {
15+
this.url = url;
16+
17+
this.webSocket = new WebSocket(url);
18+
this.webSocket.onopen = (event) => {
19+
console.log("WebSocket connection opened:", event);
20+
21+
const params: DidOpenTextDocumentParams = {
22+
textDocument: {
23+
uri: this.fileUri,
24+
languageId: this.languageId,
25+
version: 1,
26+
text: `print('Hello, world!')\n"test".`,
27+
},
28+
};
29+
this.webSocket.send(
30+
JSON.stringify({
31+
jsonrpc: "2.0",
32+
method: DidOpenTextDocumentNotification.method,
33+
params: params,
34+
})
35+
);
36+
// const params2: CompletionParams = {
37+
// textDocument: {
38+
// uri: this.fileUri,
39+
// },
40+
// position: {
41+
// line: 1,
42+
// character: 8,
43+
// },
44+
// };
45+
// this.webSocket.send(
46+
// JSON.stringify({
47+
// jsonrpc: "2.0",
48+
// method: "textDocument/completion",
49+
// params: params2,
50+
// })
51+
// );
52+
};
53+
this.webSocket.onmessage = (event) => {
54+
console.log("Message received:", JSON.parse(event.data));
55+
};
56+
this.webSocket.onclose = (event) => {
57+
console.log("WebSocket connection closed:", event);
58+
};
59+
this.webSocket.onerror = (error) => {
60+
console.error("WebSocket error:", error);
61+
};
62+
}
63+
64+
public getCompletion(position: Position): Promise<any> {
65+
return new Promise((resolve, reject) => {
66+
const handleMessage = (event: MessageEvent) => {
67+
const response = JSON.parse(event.data);
68+
69+
if (response.result && response.result.items) {
70+
this.webSocket.removeEventListener("message", handleMessage);
71+
console.log("Completion items received:", response.result.items);
72+
resolve(response.result.items);
73+
} else if (response.error) {
74+
this.webSocket.removeEventListener("message", handleMessage);
75+
console.error("Error in completion response:", response.error);
76+
reject(response.error);
77+
}
78+
};
79+
80+
this.webSocket.addEventListener("message", handleMessage);
81+
82+
const params: CompletionParams = {
83+
textDocument: {
84+
uri: this.fileUri,
85+
},
86+
position: {
87+
line: position.line - 1,
88+
89+
character: position.character,
90+
},
91+
};
92+
this.webSocket.send(
93+
JSON.stringify({
94+
jsonrpc: "2.0",
95+
id: Date.now(),
96+
method: "textDocument/completion",
97+
params: params,
98+
})
99+
);
100+
console.log("sent completion request", params);
101+
});
102+
// return new Promise((resolve, reject) => {
103+
// const params: CompletionParams = {
104+
// textDocument: {
105+
// uri: this.fileUri,
106+
// },
107+
// position: position,
108+
// };
109+
// this.webSocket.send(
110+
// JSON.stringify({
111+
// jsonrpc: "2.0",
112+
// method: "textDocument/completion",
113+
// params: params,
114+
// })
115+
// );
116+
// console.log("sent completion request", params);
117+
// this.webSocket.addEventListener("message", (event) => {
118+
// console.log("AAAAAAAAAAAAAAAAAAAAAA Message received:", event.data);
119+
// const response = JSON.parse(event.data);
120+
// if (response.method === CompletionRequest.method) {
121+
// console.log("Completion response:", response);
122+
// resolve(response);
123+
// }
124+
// });
125+
// });
126+
}
127+
}
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
import Editor, { useMonaco } from "@monaco-editor/react";
2+
import { CancellationToken, editor, languages, Position } from "monaco-editor";
3+
import { useEffect, useState } from "react";
4+
import { LanguageServerAPI } from "../../api/LanguageServerAPI";
5+
import ITextModel = editor.ITextModel;
6+
import CompletionContext = languages.CompletionContext;
7+
8+
const languageId: string = "test";
9+
10+
export const MetaSolverStrategyEditor = () => {
11+
const monaco = useMonaco();
12+
const [webServerApi, setWebServerApi] = useState<LanguageServerAPI | null>(
13+
null
14+
);
15+
16+
useEffect(() => {
17+
if (monaco) {
18+
console.log("here is the monaco instance:", monaco);
19+
// Initialize the LanguageServerAPI with the WebSocket URL
20+
const webSocketUrl = "ws://localhost:5001/";
21+
const api = new LanguageServerAPI(webSocketUrl);
22+
setWebServerApi(api);
23+
}
24+
}, [monaco]);
25+
26+
useEffect(() => {
27+
if (!monaco) return;
28+
29+
// Register the language server
30+
monaco.languages.register({ id: languageId });
31+
monaco.languages.registerCompletionItemProvider(languageId, {
32+
provideCompletionItems: async (
33+
model: ITextModel,
34+
position: Position,
35+
context: CompletionContext,
36+
token: CancellationToken
37+
) => {
38+
const completion = await webServerApi?.getCompletion({
39+
line: position.lineNumber,
40+
character: position.column,
41+
});
42+
console.log("result", completion);
43+
const word = model.getWordUntilPosition(position);
44+
const range = {
45+
startLineNumber: position.lineNumber,
46+
endLineNumber: position.lineNumber,
47+
startColumn: word.startColumn,
48+
endColumn: word.endColumn,
49+
};
50+
console.log("completions!");
51+
return {
52+
suggestions: completion,
53+
};
54+
},
55+
});
56+
}, [webServerApi]);
57+
58+
return (
59+
<Editor
60+
height="50vh"
61+
defaultValue={`print('Hello, world!')\n"test".`}
62+
defaultLanguage={languageId}
63+
language={languageId}
64+
/>
65+
);
66+
};

src/pages/index.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import {
1010
import type { NextPage } from "next";
1111
import Head from "next/head";
1212
import { baseUrl } from "../api/ToolboxAPI";
13+
import { MetaSolverStrategyEditor } from "../components/editors/MetaSolverStrategyEditor";
1314
import { DemonstratorChooser } from "../components/landing-page/DemonstratorChooser";
1415
import { ProblemChooser } from "../components/landing-page/ProblemChooser";
1516
import { Layout } from "../components/layout/Layout";
@@ -23,6 +24,7 @@ const Home: NextPage = () => {
2324
<link rel="icon" href="/favicon.ico" />
2425
{/* TODO: replace favicon */}
2526
</Head>
27+
<MetaSolverStrategyEditor />
2628
<Text color="text" align="justify" as="b">
2729
Welcome to the ProvideQ Toolbox!
2830
</Text>

yarn.lock

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1530,6 +1530,20 @@
15301530
"@jridgewell/resolve-uri" "3.1.0"
15311531
"@jridgewell/sourcemap-codec" "1.4.14"
15321532

1533+
"@monaco-editor/loader@^1.5.0":
1534+
version "1.5.0"
1535+
resolved "https://registry.yarnpkg.com/@monaco-editor/loader/-/loader-1.5.0.tgz#dcdbc7fe7e905690fb449bed1c251769f325c55d"
1536+
integrity sha512-hKoGSM+7aAc7eRTRjpqAZucPmoNOC4UUbknb/VNoTkEIkCPhqV8LfbsgM1webRM7S/z21eHEx9Fkwx8Z/C/+Xw==
1537+
dependencies:
1538+
state-local "^1.0.6"
1539+
1540+
"@monaco-editor/react@^4.7.0":
1541+
version "4.7.0"
1542+
resolved "https://registry.yarnpkg.com/@monaco-editor/react/-/react-4.7.0.tgz#35a1ec01bfe729f38bfc025df7b7bac145602a60"
1543+
integrity sha512-cyzXQCtO47ydzxpQtCGSQGOC8Gk3ZUeBXFAxD+CWXYFo5OqZyZUonFl0DwUlTyAfRHntBfw2p3w4s9R6oe1eCA==
1544+
dependencies:
1545+
"@monaco-editor/loader" "^1.5.0"
1546+
15331547
"@motionone/animation@^10.12.0":
15341548
version "10.15.1"
15351549
resolved "https://registry.yarnpkg.com/@motionone/animation/-/animation-10.15.1.tgz#4a85596c31cbc5100ae8eb8b34c459fb0ccf6807"
@@ -2228,6 +2242,13 @@
22282242
resolved "https://registry.yarnpkg.com/@types/tough-cookie/-/tough-cookie-4.0.2.tgz#6286b4c7228d58ab7866d19716f3696e03a09397"
22292243
integrity sha512-Q5vtl1W5ue16D+nIaW8JWebSSraJVlK+EthKn7e7UcD4KWsaSJ8BqGPXNaPghgtcn/fhvrN17Tv8ksUsQpiplw==
22302244

2245+
"@types/ws@^8.18.1":
2246+
version "8.18.1"
2247+
resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.18.1.tgz#48464e4bf2ddfd17db13d845467f6070ffea4aa9"
2248+
integrity sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==
2249+
dependencies:
2250+
"@types/node" "*"
2251+
22312252
"@types/yargs-parser@*":
22322253
version "21.0.0"
22332254
resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.0.tgz#0c60e537fa790f5f9472ed2776c2b71ec117351b"
@@ -4724,6 +4745,11 @@ minimist@^1.2.0, minimist@^1.2.6:
47244745
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c"
47254746
integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==
47264747

4748+
monaco-editor@^0.52.2:
4749+
version "0.52.2"
4750+
resolved "https://registry.yarnpkg.com/monaco-editor/-/monaco-editor-0.52.2.tgz#53c75a6fcc6802684e99fd1b2700299857002205"
4751+
integrity sha512-GEQWEZmfkOGLdd3XK8ryrfWz3AIP8YymVXiPHEdewrUq7mh0qrKrfHLNCXcbB6sTnMLnOZ3ztSiKcciFUkIJwQ==
4752+
47274753
47284754
version "2.1.2"
47294755
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
@@ -5410,6 +5436,11 @@ stack-utils@^2.0.3:
54105436
dependencies:
54115437
escape-string-regexp "^2.0.0"
54125438

5439+
state-local@^1.0.6:
5440+
version "1.0.7"
5441+
resolved "https://registry.yarnpkg.com/state-local/-/state-local-1.0.7.tgz#da50211d07f05748d53009bee46307a37db386d5"
5442+
integrity sha512-HTEHMNieakEnoe33shBYcZ7NX83ACUjCu8c40iOGEZsngj9zRnkqS9j1pqQPXwobB0ZcVTk27REb7COQ0UR59w==
5443+
54135444
stop-iteration-iterator@^1.0.0:
54145445
version "1.0.0"
54155446
resolved "https://registry.yarnpkg.com/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz#6a60be0b4ee757d1ed5254858ec66b10c49285e4"
@@ -5751,6 +5782,24 @@ v8-to-istanbul@^9.0.1:
57515782
"@types/istanbul-lib-coverage" "^2.0.1"
57525783
convert-source-map "^1.6.0"
57535784

5785+
5786+
version "8.2.0"
5787+
resolved "https://registry.yarnpkg.com/vscode-jsonrpc/-/vscode-jsonrpc-8.2.0.tgz#f43dfa35fb51e763d17cd94dcca0c9458f35abf9"
5788+
integrity sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA==
5789+
5790+
vscode-languageserver-protocol@^3.17.5:
5791+
version "3.17.5"
5792+
resolved "https://registry.yarnpkg.com/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.5.tgz#864a8b8f390835572f4e13bd9f8313d0e3ac4bea"
5793+
integrity sha512-mb1bvRJN8SVznADSGWM9u/b07H7Ecg0I3OgXDuLdn307rl/J3A9YD6/eYOssqhecL27hK1IPZAsaqh00i/Jljg==
5794+
dependencies:
5795+
vscode-jsonrpc "8.2.0"
5796+
vscode-languageserver-types "3.17.5"
5797+
5798+
[email protected], vscode-languageserver-types@^3.17.5:
5799+
version "3.17.5"
5800+
resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.17.5.tgz#3273676f0cf2eab40b3f44d085acbb7f08a39d8a"
5801+
integrity sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==
5802+
57545803
w3c-xmlserializer@^4.0.0:
57555804
version "4.0.0"
57565805
resolved "https://registry.yarnpkg.com/w3c-xmlserializer/-/w3c-xmlserializer-4.0.0.tgz#aebdc84920d806222936e3cdce408e32488a3073"

0 commit comments

Comments
 (0)