on master help sign in
Added env generators
commit2eda210e16827eecbdc8451f563334c7ac834ec0 authoriko <ilyakooo0@gmail.com> dateSun 20 Mar 2022, 12:49 (5 years ago) parent3eb1500
4 files changed+114−30
Haskell Language Server.novaextension/Scripts/download.js+11−23 Haskell Language Server.novaextension/Scripts/main.js+5−6 Haskell Language Server.novaextension/Scripts/utils.js+90−1 Haskell Language Server.novaextension/extension.json+8
Haskell Language Server.novaextension/Scripts/download.js+11−23
@@ -5,6 +5,8 @@ const {
55const {
66 readStream,
77 getStorage,
8+ call,
9+ hasCustomEnv
810} = require("utils");
911
1012exports.getHLS = getHLS;
@@ -147,8 +149,12 @@ async function getHLS() {
147149 return explicitPath
148150 }
149151
150− const version = await getGHCVersion();
151152 const localHLSPath = await which("haskell-language-server").catch((_) => null)
153+ if (hasCustomEnv() && localHLSPath) {
154+ return localHLSPath
155+ }
156+
157+ const version = await getGHCVersion();
152158 if (localHLSPath) {
153159 sendNotification("Found HLS", "Found haskell-language-server in PATH. Checking if it is the right version.")
154160 const v = await getHLSVersion(localHLSPath)
@@ -175,35 +181,17 @@ function notifyToolDownloading(name) {
175181}
176182
177183function getHLSVersion(path) {
178− return call(new Process(path, {
184+ return call(path, {
179185 args: ["--version"],
180− }))
186+ })
181187 .then((x) => x.match(/\(GHC: (\S+)\)/)[1].trim())
182188 .catch((err) => sendPermanentNotification("HLS version check failed", err))
183189}
184190
185191function which(name) {
186− return call(new Process("/usr/bin/which", {
192+ return call("/usr/bin/which", {
187193 args: [name],
188194 shell: true,
189− })).then((p) => p.trim())
195+ }).then((p) => p.trim())
190196}
191197
192−function call(process) {
193− const promise = new Promise((resolve, reject) => {
194− process.onDidExit((exitCode) => {
195− console.log(exitCode)
196− if (exitCode == 0) {
197− readStream(process.stdout).then((x) => {
198− resolve(x);
199− });
200− } else {
201− readStream(process.stderr).then((x) => {
202− reject(x)
203− });
204− }
205− });
206− })
207− process.start()
208− return promise
209−}
Haskell Language Server.novaextension/Scripts/main.js+5−6
@@ -9,8 +9,9 @@ const {
99 getHLSConfig,
1010} = require("configuration");
1111const {
12− getFileName,
12+ getFileName, createEnv, getEnv
1313} = require("utils");
14+
1415exports.activate = function () {
1516 nova.commands.register("stop", (_workspace) => {
1617 stopServer();
@@ -107,10 +108,12 @@ function applyAllLSPEdits(edits, text) {
107108}
108109let lspClient = null;
109110async function startServer() {
111+ await createEnv()
110112 stopServer();
111113 const path = await getServerPath();
114+ const env = await getEnv()
112115 const serverOptions = {
113− path: path,
116+ path, env,
114117 args: ["lsp", "--cwd", nova.workspace.path],
115118 };
116119 const clientOptions = {
@@ -137,7 +140,3 @@ function stopServer() {
137140function getServerPath() {
138141 return getHLS();
139142}
140−
141−// function getLogPath() {
142−// return getStorage() + "/haskell-language-server.log";
143−// }
Haskell Language Server.novaextension/Scripts/utils.js+90−1
@@ -1,3 +1,8 @@
1+const {
2+ sendNotification,
3+ sendPermanentNotification,
4+} = require("notifications");
5+
16function readStream(readableStream) {
27 return new Promise((resolve, _reject) => {
38 const reader = readableStream.getReader();
@@ -48,4 +53,88 @@ function traceRaw(x) {
4853 return x;
4954}
5055
51−module.exports = { readStream, getStorage, getFileName, trace, traceRaw };
56+async function call(path, args) {
57+ const env = await getEnv()
58+ const process = new Process(path, {...args, ...{env}});
59+ const promise = new Promise((resolve, reject) => {
60+ process.onDidExit((exitCode) => {
61+ console.log(exitCode)
62+ if (exitCode == 0) {
63+ readStream(process.stdout).then((x) => {
64+ resolve(x);
65+ });
66+ } else {
67+ readStream(process.stderr).then((x) => {
68+ reject(x)
69+ });
70+ }
71+ });
72+ })
73+ process.start()
74+ return promise
75+}
76+
77+
78+function parseEnvs(x) {
79+ const env = {}
80+ for (line of x.split("\n")) {
81+ const res = line.match(/(.*?)=(.*)/)
82+ if (res) {
83+ env[res[1]] = res[2]
84+ }
85+ }
86+
87+ console.log(JSON.stringify(env))
88+
89+ return env
90+}
91+
92+let envCache = null
93+
94+async function createEnv() {
95+ const generator = nova.workspace.config.get("env-generator")
96+ if (generator) {
97+ const [prog, ...args] = generator.split(/\s+/)
98+ sendNotification("Generating environment", "Executing " + generator + ".")
99+ const process = new Process(prog, {
100+ shell: true,
101+ args,
102+ cwd: nova.workspace.path
103+ });
104+ const promise = new Promise((resolve, reject) => {
105+ process.onDidExit((exitCode) => {
106+ console.log(exitCode)
107+ if (exitCode == 0) {
108+ readStream(process.stdout).then((x) => {
109+ resolve(x);
110+ });
111+ } else {
112+ readStream(process.stderr).then((x) => {
113+ reject(x)
114+ });
115+ }
116+ });
117+ })
118+ process.start()
119+
120+ const envStr = await promise
121+ .catch((err) => sendPermanentNotification("Generating environment failed", err))
122+ envCache = parseEnvs(envStr)
123+ }
124+}
125+
126+async function getEnv() {
127+ console.log(JSON.stringify(envCache))
128+ if (!envCache) {
129+ await createEnv()
130+ }
131+ return envCache
132+}
133+
134+
135+function hasCustomEnv() {
136+ return (nova.workspace.config.get("env-generator") !== null)
137+}
138+
139+module.exports = { readStream, getStorage, getFileName, trace, traceRaw, call, createEnv, hasCustomEnv, getEnv };
140+
Haskell Language Server.novaextension/extension.json+8
@@ -20,6 +20,14 @@
2020 "type": "path",
2121 "placeholder": "/usr/local/bin/example"
2222 },
23+ {
24+ "key": "env-generator",
25+ "title": "Environment generator",
26+ "description": "You can specify a shell command which will be used to generate the environment, in which the extension will be executes. This is useful if you want to utilize `nix-shell`, `direnv` or any similar command.\n\nExpects the command to have the same stdout as the `env` command.",
27+ "type": "enum",
28+ "allowsCustom": true,
29+ "values": ["nix-shell --run env", "direnv exec env"]
30+ },
2331 {
2432 "type": "section",
2533 "title": "Haskell Language Server settings",