on master help sign in
142 lines 3.4 kB history raw
1const {
2 sendNotification,
3 sendNotificationWithAction,
4} = require("notifications");
5const {
6 getHLS,
7} = require("download");
8const {
9 getHLSConfig,
10} = require("configuration");
11const {
12 getFileName, createEnv, getEnv
13} = require("utils");
15exports.activate = function () {
16 nova.commands.register("stop", (_workspace) => {
17 stopServer();
18 });
19 nova.commands.register("restart", (_workspace) => {
20 startServer();
21 });
22 nova.commands.register("clear-cache", (_workspace) => {
23 nova.fs.rmdir(nova.extension.globalStoragePath);
24 startServer();
25 });
26 nova.commands.register("format", formatFile);
27 // startServer();
28};
29exports.deactivate = function () {
30 // Clean up state before the extension is deactivated
31 if (lspClient) {
32 lspClient.stop();
33 lspClient = null;
34 }
35};
37function formatFile(editor) {
38 // If there is no URI, there's not much we can do ;(
39 if (editor.document.uri) {
40 const name = getFileName(editor.document.uri);
41 let valid = true;
42 const removeNotification = sendNotificationWithAction(
43 "Formatting " + name,
44 "Waiting for Haskell Language Server to format " + name,
45 "Cancel",
46 () => {
47 valid = false;
48 },
49 );
50 editor.onDidChange(() => {
51 removeNotification();
52 valid = false;
53 });
54 const req = {
55 textDocument: {
56 uri: editor.document.uri,
57 },
58 options: {
59 tabSize: editor.tabLength,
60 insertSpaces: true,
61 },
62 };
63 lspClient.sendRequest("textDocument/formatting", req).then((edits) => {
64 editor.edit((edit) => {
65 if (valid) {
66 const range = new Range(0, editor.document.length);
67 const documentText = editor.document.getTextInRange(range);
68 const newText = applyAllLSPEdits(edits, documentText);
69 if (valid) {
70 edit.replace(range, newText);
71 }
72 }
73 removeNotification();
74 });
75 });
76 }
79function applyAllLSPEdits(edits, text) {
80 let i = 0;
81 let line = 0;
82 let out = "";
84 function goToLine(l) {
85 while (line < l) {
86 if (text.slice(i, i + 2) === "\r\n") {
87 line += 1;
88 i += 1;
89 } else if (text[i] === "\n" || text[i] === "\r") {
90 line += 1;
91 }
92 i += 1;
93 }
94 }
95 let edit;
96 for (edit of edits) {
97 const prev = i;
98 goToLine(edit.range.start.line);
99 i += edit.range.start.character;
100 out += text.slice(prev, i);
101 goToLine(edit.range.end.line);
102 i += edit.range.end.character;
103 out += edit.newText;
104 console.log(out);
105 }
106 out += text.slice(i);
107 return out;
109let lspClient = null;
110async function startServer() {
111 await createEnv()
112 stopServer();
113 const path = await getServerPath();
114 const env = await getEnv()
115 const serverOptions = {
116 path, env,
117 args: ["lsp", "--cwd", nova.workspace.path],
118 };
119 const clientOptions = {
120 syntaxes: ["haskell"],
121 initializationOptions: getHLSConfig(),
122 };
123 lspClient = new LanguageClient(
124 "haskell-language-server",
125 nova.extension.name,
126 serverOptions,
127 clientOptions,
128 );
129 sendNotification("Starting Haskell Language Server", "");
130 lspClient.start();
133function stopServer() {
134 if (lspClient) {
135 sendNotification("Stopping Haskell Language Server", "");
136 lspClient.stop();
137 lspClient = null;
138 }
140function getServerPath() {
141 return getHLS();