on master help sign in
.
commite9d579a1c1f54c6a78abb4ad75803730cd166a0f authoriko <ilyakooo0@gmail.com> dateSat 19 Feb 2022, 16:31 (5 years ago)
11 files changed+1647
Haskell Language Server.novaextension/.gitignore+1 Haskell Language Server.novaextension/.nova/waypoints.json+1 Haskell Language Server.novaextension/CHANGELOG.md+3 Haskell Language Server.novaextension/README.md+72 Haskell Language Server.novaextension/Scripts/configuration.js+61 Haskell Language Server.novaextension/Scripts/download.js+158 Haskell Language Server.novaextension/Scripts/main.js+143 Haskell Language Server.novaextension/Scripts/notifications.js+36 Haskell Language Server.novaextension/Scripts/utils.js+51 Haskell Language Server.novaextension/Syntaxes/Haskell.xml+821 Haskell Language Server.novaextension/extension.json+300
Haskell Language Server.novaextension/.gitignorenew file+1
@@ -0,0 +1 @@
1+.DS_Store
Haskell Language Server.novaextension/.nova/waypoints.jsonnew file+1
@@ -0,0 +1 @@
1+{"activeJourney":"2022/02/18 07:57","journeys":[{"identifier":"1645171063348_43","name":"2022/02/18 07:57","path":false,"line":false,"updatedAt":1645172096799,"children":[{"identifier":"1645171063356_35","name":"Syntaxes/Haskell.xml","path":"Syntaxes/Haskell.xml","line":false,"updatedAt":1645172096799,"comment":false,"children":[{"identifier":"1645171063356_45","name":"<collection name=\"pattern-match\">","path":"Syntaxes/Haskell.xml","line":101,"updatedAt":1645172096799,"comment":false,"children":[]}]}]}]}
Haskell Language Server.novaextension/CHANGELOG.mdnew file+3
@@ -0,0 +1,3 @@
1+## Version 1.0
2+
3+Initial release
Haskell Language Server.novaextension/README.mdnew file+72
@@ -0,0 +1,72 @@
1+<!--
2+๐Ÿ‘‹ Hello! As Nova users browse the extensions library, a good README can help them understand what your extension does, how it works, and what setup or configuration it may require.
3+
4+Not every extension will need every item described below. Use your best judgement when deciding which parts to keep to provide the best experience for your new users.
5+
6+๐Ÿ’ก Quick Tip!ย As you edit this README template, you can preview your changes by selecting **Extensions โ†’ Activate Project as Extension**, opening the Extension Library, and selecting "Haskell Language Server" in the sidebar.
7+
8+Let's get started!
9+-->
10+
11+<!--
12+๐ŸŽˆ Include a brief description of the features your extension provides. For example:
13+-->
14+
15+**Haskell Language Server** provides deep integration with **An Important Language**, including the most important feature, something that's really helpful, and _a little-known secret!_
16+
17+<!--
18+๐ŸŽˆ It can also be helpful to include a screenshot or GIF showing your extension in action:
19+-->
20+
21+![](https://nova.app/images/en/dark/editor.png)
22+
23+## Requirements
24+
25+<!--
26+๐ŸŽˆ If your extension depends on external processes or tools that users will need to have, it's helpful to list those and provide links to their installers:
27+-->
28+
29+Haskell Language Server requires some additional tools to be installed on your Mac:
30+
31+- [Node.js 8.2.0](https://nodejs.org) and NPM 5.2.0 or newer
32+
33+<!--
34+โœจ Providing tips, tricks, or other guides for installing or configuring external dependencies can go a long way toward helping your users have a good setup experience:
35+-->
36+
37+> To install the current stable version of Node, click the "Recommended for Most Users" button to begin the download. When that completes, double-click the **.pkg** installer to begin installation.
38+
39+## Usage
40+
41+<!--
42+๐ŸŽˆ If your extension provides features that are invoked manually, consider describing those options for users:
43+-->
44+
45+To run Haskell Language Server:
46+
47+- Select the **Editor โ†’ Haskell Language Server** menu item; or
48+- Open the command palette and type `Haskell Language Server`
49+
50+<!--
51+๐ŸŽˆ Alternatively, if your extension runs automatically (as in the case of a validator), consider showing users what they can expect to see:
52+-->
53+
54+Haskell Language Server runs any time you open a local project, automatically lints all open files, then reports errors and warnings in Nova's **Issues** sidebar and the editor gutter:
55+
56+![](https://nova.app/images/en/dark/tools/sidebars.png)
57+
58+### Configuration
59+
60+<!--
61+๐ŸŽˆ If your extension offers global- or workspace-scoped preferences, consider pointing users toward those settings. For example:
62+-->
63+
64+To configure global preferences, open **Extensions โ†’ Extension Library...** then select Haskell Language Server's **Preferences** tab.
65+
66+You can also configure preferences on a per-project basis in **Project โ†’ Project Settings...**
67+
68+<!--
69+๐Ÿ‘‹ That's it! Happy developing!
70+
71+P.S. If you'd like, you can remove these comments before submitting your extension ๐Ÿ˜‰
72+-->
Haskell Language Server.novaextension/Scripts/configuration.jsnew file+61
@@ -0,0 +1,61 @@
1+exports.getHLSConfig = () => readAllConfigs(HLSKeys);
2+
3+// X must be an object. It is modified in place and returned.
4+// The second is also an object and is merged into the left one.
5+function merge(x, y) {
6+ for (key in y) {
7+ if (typeof y[key] == "object" && x[key] && typeof x[key] == "object") {
8+ x[key] = merge(x[key], y[key]);
9+ } else {
10+ x[key] = y[key];
11+ }
12+ }
13+ return x;
14+}
15+
16+function objectifyString(s, v) {
17+ let previous = v;
18+ for (key of s.split(".").reverse()) {
19+ const next = {};
20+ next[key] = previous;
21+ previous = next;
22+ }
23+ return previous;
24+}
25+
26+function readOneConfig(key) {
27+ return objectifyString(key, nova.workspace.config.get(key));
28+}
29+
30+function readAllConfigs(keys) {
31+ return keys.map(readOneConfig).reduce(merge, {});
32+}
33+const HLSKeys = [
34+ "haskell.formattingProvider",
35+ "haskell.checkProject",
36+ "haskell.maxCompletions",
37+ "haskell.plugin.importLens.codeActionsOn",
38+ "haskell.plugin.importLens.codeLensOn",
39+ "haskell.plugin.hlint.codeActionsOn",
40+ "haskell.plugin.hlint.diagnosticsOn",
41+ "haskell.plugin.hlint.config.flags",
42+ "haskell.plugin.eval.globalOn",
43+ "haskell.plugin.moduleName.globalOn",
44+ "haskell.plugin.splice.globalOn",
45+ "haskell.plugin.haddockComments.globalOn",
46+ "haskell.plugin.class.globalOn",
47+ "haskell.plugin.retrie.globalOn",
48+ "haskell.plugin.tactics.globalOn",
49+ "haskell.plugin.tactics.config.auto_gas",
50+ "haskell.plugin.tactics.config.hole_severity",
51+ "haskell.plugin.tactics.config.max_use_ctor_actions",
52+ "haskell.plugin.tactics.config.timeout_duration",
53+ "haskell.plugin.tactics.config.proofstate_styling",
54+ "haskell.plugin.pragmas.codeActionsOn",
55+ "haskell.plugin.pragmas.completionOn",
56+ "haskell.plugin.ghcide-completions.config.autoExtendOn",
57+ "haskell.plugin.ghcide-completions.config.snippetsOn",
58+ "haskell.plugin.ghcide-type-lenses.globalOn",
59+ "haskell.plugin.ghcide-type-lenses.config.mode",
60+ "haskell.plugin.refineImports.globalOn",
61+];
Haskell Language Server.novaextension/Scripts/download.jsnew file+158
@@ -0,0 +1,158 @@
1+const {
2+ sendNotification,
3+ sendPermanentNotification,
4+} = require("notifications");
5+const {
6+ readStream,
7+ getStorage,
8+} = require("utils");
9+
10+exports.getHLS = getHLS;
11+
12+let assets = null;
13+async function getHLSAssets() {
14+ if (!assets) {
15+ const response = await fetch(
16+ "https://api.github.com/repos/haskell/haskell-language-server/releases",
17+ );
18+ if (!response.ok) {
19+ console.error(response.statusText);
20+ return null;
21+ }
22+ const respObj = await response.json();
23+ const pairs = respObj[0].assets.flatMap((asset) => {
24+ const match = asset.name.match("haskell-language-server-macOS-(.*)\.gz");
25+ if (match) {
26+ return [
27+ [match[1], asset.browser_download_url],
28+ ];
29+ } else if (asset.name === "haskell-language-server-wrapper-macOS.gz") {
30+ return [
31+ ["wrapper", asset.browser_download_url],
32+ ];
33+ } else {
34+ return [];
35+ }
36+ });
37+ assets = Object.fromEntries(pairs);
38+ }
39+ return assets;
40+}
41+async function downloadTool(name) {
42+ notifyToolDownloading(name);
43+ const storagePath = getStorageForTool(name);
44+ console.log("Downloading " + storagePath);
45+ const urls = await getHLSAssets();
46+ const response = await fetch(urls[name]);
47+ if (!response.ok) {
48+ console.error(response.statusText);
49+ return null;
50+ }
51+ const p = new Promise((resolve, _reject) => {
52+ const gzip = new Process("/usr/bin/gzip", {
53+ args: ["-d"],
54+ });
55+ response.body.pipeTo(gzip.stdin);
56+ const file = nova.fs.open(storagePath, "x+b");
57+ const outReader = gzip.stdout.getReader();
58+ outReader.read().then(function processChunk({
59+ done,
60+ value,
61+ }) {
62+ if (done) {
63+ file.close;
64+ console.log("Downloaded " + storagePath);
65+ const chmod = new Process("/bin/chmod", {
66+ args: ["+x", storagePath],
67+ });
68+ chmod.onDidExit((exitCode) => {
69+ console.log(exitCode);
70+ resolve(storagePath);
71+ });
72+ chmod.start();
73+ } else {
74+ file.write(value);
75+ outReader.read().then(processChunk);
76+ }
77+ });
78+ console.log("unzipping");
79+ gzip.start();
80+ });
81+ return await p;
82+}
83+async function getTool(name) {
84+ const path = getStorageForTool(name);
85+ if (nova.fs.access(path, nova.fs.X_OK)) {
86+ console.log("Exists: " + path);
87+ return path;
88+ } else {
89+ console.log("Doesn't exists: " + path);
90+ nova.fs.remove(path);
91+ return await downloadTool(name);
92+ }
93+}
94+async function getGHCVersion() {
95+ const wrapper = await getTool("wrapper");
96+ sendNotification("Woking out the GHC version of the project", "");
97+ const process = new Process(wrapper, {
98+ cwd: nova.workspace.path,
99+ args: ["--project-ghc-version"],
100+ });
101+ const promise = new Promise((resolve, _reject) => {
102+ process.onDidExit((exitCode) => {
103+ if (exitCode == 0) {
104+ readStream(process.stdout).then((x) => {
105+ const version = x.trim();
106+ sendNotification("Detected GHC " + version, "");
107+ resolve(version);
108+ });
109+ } else {
110+ readStream(process.stderr).then((x) => {
111+ const rRes = x.match(/Cradle requires (.+) but couldn't find it/);
112+ if (rRes) {
113+ let tool;
114+ switch (rRes[1]) {
115+ case "stack":
116+ tool = "Stack";
117+ break;
118+ case "cabal":
119+ tool = "Cabal";
120+ break;
121+ case "ghc":
122+ tool = "GHC";
123+ break;
124+ default:
125+ tool = rRes[1];
126+ break;
127+ }
128+ sendPermanentNotification(
129+ tool + " not installed!",
130+ "Please install " + tool +
131+ " and restart Haskell Language Server.",
132+ );
133+ } else {
134+ sendPermanentNotification("Couldn't detect GHC version", x);
135+ }
136+ });
137+ }
138+ });
139+ });
140+ process.start();
141+ return promise;
142+}
143+async function getHLS() {
144+ const version = await getGHCVersion();
145+ return await getTool(version);
146+}
147+
148+function getStorageForTool(name) {
149+ return getStorage() + "/" + getToolName(name);
150+}
151+
152+function getToolName(name) {
153+ return "haskell-language-server-" + name;
154+}
155+
156+function notifyToolDownloading(name) {
157+ sendNotification("Downloading tool", "Downloading " + getToolName(name));
158+}
Haskell Language Server.novaextension/Scripts/main.jsnew file+143
@@ -0,0 +1,143 @@
1+const {
2+ sendNotification,
3+ sendNotificationWithAction,
4+} = require("notifications");
5+const {
6+ getHLS,
7+} = require("download");
8+const {
9+ getHLSConfig,
10+} = require("configuration");
11+const {
12+ getFileName,
13+} = require("utils");
14+exports.activate = function () {
15+ nova.commands.register("stop", (_workspace) => {
16+ stopServer();
17+ });
18+ nova.commands.register("restart", (_workspace) => {
19+ startServer();
20+ });
21+ nova.commands.register("clear-cache", (_workspace) => {
22+ nova.fs.rmdir(nova.extension.globalStoragePath);
23+ startServer();
24+ });
25+ nova.commands.register("format", formatFile);
26+ // startServer();
27+};
28+exports.deactivate = function () {
29+ // Clean up state before the extension is deactivated
30+ if (lspClient) {
31+ lspClient.stop();
32+ lspClient = null;
33+ }
34+};
35+
36+function formatFile(editor) {
37+ // If there is no URI, there's not much we can do ;(
38+ if (editor.document.uri) {
39+ const name = getFileName(editor.document.uri);
40+ let valid = true;
41+ const removeNotification = sendNotificationWithAction(
42+ "Formatting " + name,
43+ "Waiting for Haskell Language Server to format " + name,
44+ "Cancel",
45+ () => {
46+ valid = false;
47+ },
48+ );
49+ editor.onDidChange(() => {
50+ removeNotification();
51+ valid = false;
52+ });
53+ const req = {
54+ textDocument: {
55+ uri: editor.document.uri,
56+ },
57+ options: {
58+ tabSize: editor.tabLength,
59+ insertSpaces: true,
60+ },
61+ };
62+ lspClient.sendRequest("textDocument/formatting", req).then((edits) => {
63+ editor.edit((edit) => {
64+ if (valid) {
65+ const range = new Range(0, editor.document.length);
66+ const documentText = editor.document.getTextInRange(range);
67+ const newText = applyAllLSPEdits(edits, documentText);
68+ if (valid) {
69+ edit.replace(range, newText);
70+ }
71+ }
72+ removeNotification();
73+ });
74+ });
75+ }
76+}
77+
78+function applyAllLSPEdits(edits, text) {
79+ let i = 0;
80+ let line = 0;
81+ let out = "";
82+
83+ function goToLine(l) {
84+ while (line < l) {
85+ if (text.slice(i, i + 2) === "\r\n") {
86+ line += 1;
87+ i += 1;
88+ } else if (text[i] === "\n" || text[i] === "\r") {
89+ line += 1;
90+ }
91+ i += 1;
92+ }
93+ }
94+ let edit;
95+ for (edit of edits) {
96+ const prev = i;
97+ goToLine(edit.range.start.line);
98+ i += edit.range.start.character;
99+ out += text.slice(prev, i);
100+ goToLine(edit.range.end.line);
101+ i += edit.range.end.character;
102+ out += edit.newText;
103+ console.log(out);
104+ }
105+ out += text.slice(i);
106+ return out;
107+}
108+let lspClient = null;
109+async function startServer() {
110+ stopServer();
111+ const path = await getServerPath();
112+ const serverOptions = {
113+ path: path,
114+ args: ["lsp", "--cwd", nova.workspace.path],
115+ };
116+ const clientOptions = {
117+ syntaxes: ["haskell"],
118+ initializationOptions: getHLSConfig(),
119+ };
120+ lspClient = new LanguageClient(
121+ "haskell-language-server",
122+ nova.extension.name,
123+ serverOptions,
124+ clientOptions,
125+ );
126+ sendNotification("Starting Haskell Language Server", "");
127+ lspClient.start();
128+}
129+
130+function stopServer() {
131+ if (lspClient) {
132+ sendNotification("Stopping Haskell Language Server", "");
133+ lspClient.stop();
134+ lspClient = null;
135+ }
136+}
137+function getServerPath() {
138+ return getHLS();
139+}
140+
141+// function getLogPath() {
142+// return getStorage() + "/haskell-language-server.log";
143+// }
Haskell Language Server.novaextension/Scripts/notifications.jsnew file+36
@@ -0,0 +1,36 @@
1+function sendNotification(title, body) {
2+ const request = new NotificationRequest();
3+ request.title = title;
4+ request.body = body;
5+ nova.notifications.add(request);
6+}
7+
8+function sendPermanentNotification(title, body) {
9+ const request = new NotificationRequest();
10+ request.title = title;
11+ request.body = body;
12+ request.actions = ["OK"];
13+ nova.notifications.add(request);
14+}
15+
16+function sendNotificationWithAction(title, body, actionName, action) {
17+ const now = Date.now().toString();
18+ const request = new NotificationRequest(now);
19+ request.title = title;
20+ request.body = body;
21+ request.actions = [actionName];
22+ nova.notifications.add(request).then((x) => {
23+ if (x) {
24+ action();
25+ }
26+ });
27+ return () => {
28+ nova.notifications.cancel(now);
29+ };
30+}
31+
32+module.exports = {
33+ sendNotification,
34+ sendPermanentNotification,
35+ sendNotificationWithAction,
36+};
Haskell Language Server.novaextension/Scripts/utils.jsnew file+51
@@ -0,0 +1,51 @@
1+function readStream(readableStream) {
2+ return new Promise((resolve, _reject) => {
3+ const reader = readableStream.getReader();
4+ let out = "";
5+ reader.read().then(function processChunk({
6+ done,
7+ value,
8+ }) {
9+ if (done) {
10+ resolve(out);
11+ } else {
12+ out += arrayBufferToString(value);
13+ reader.read().then(processChunk);
14+ }
15+ });
16+ });
17+}
18+
19+function arrayBufferToString(buffer) {
20+ const arr = new Uint8Array(buffer);
21+ const str = String.fromCharCode.apply(String, arr);
22+ if (/[\u0080-\uffff]/.test(str)) {
23+ throw new Error("this string seems to contain (still encoded) multibytes");
24+ }
25+ return str;
26+}
27+
28+function getStorage() {
29+ try {
30+ nova.fs.mkdir(nova.extension.globalStoragePath);
31+ } catch (e) {
32+ console.error(e);
33+ }
34+ return nova.extension.globalStoragePath;
35+}
36+
37+function getFileName(path) {
38+ return path.replace(/^.*[\\\/]/, "");
39+}
40+
41+function trace(x) {
42+ console.log(JSON.stringify(x));
43+ return x;
44+}
45+
46+function traceRaw(x) {
47+ console.log(x);
48+ return x;
49+}
50+
51+module.exports = { readStream, getStorage, getFileName, trace, traceRaw };
Haskell Language Server.novaextension/Syntaxes/Haskell.xmlnew file+821
@@ -0,0 +1,821 @@
1+<?xml version="1.0" encoding="UTF-8"?>
2+<syntax name="haskell">
3+ <meta>
4+ <name>Haskell</name>
5+ <type>compiled</type>
6+ <preferred-file-extension>hs</preferred-file-extension>
7+ </meta>
8+
9+ <detectors>
10+ <extension priority="1.0">hs</extension>
11+ </detectors>
12+
13+ <comments>
14+ <single>
15+ <expression>--</expression>
16+ </single>
17+ <multiline>
18+ <starts-with>
19+ <expression>{-</expression>
20+ </starts-with>
21+ <ends-with>
22+ <expression>-}</expression>
23+ </ends-with>
24+ </multiline>
25+ </comments>
26+
27+ <brackets>
28+ <pair open="{" close="}" />
29+ <pair open="[" close="]" />
30+ <pair open="(" close=")" />
31+ </brackets>
32+
33+ <surrounding-pairs>
34+ <pair open="[" close="]" />
35+ <pair open="(" close=")" />
36+ <pair open="&apos;" close="&apos;" />
37+ <pair open="&quot;" close="&quot;" />
38+ <pair open="`" close="`" />
39+ </surrounding-pairs>
40+
41+ <indentation>
42+ <increase>
43+ <expression>
44+ (case|class|do|let|where).*
45+ </expression>
46+ </increase>
47+ <decrease>
48+ <expression>^\\s*(end|done|with|in|else)\\b|^\\s*;;</expression>
49+ </decrease>
50+ </indentation>
51+
52+
53+ <scopes>
54+ <include syntax="self" collection="comments" />
55+ <include syntax="self" collection="module" />
56+ <include syntax="self" collection="import" />
57+ <include syntax="self" collection="type-family-definition" />
58+ <include syntax="self" collection="pattern-definition" />
59+ <include syntax="self" collection="type-definition" />
60+ <!-- <include syntax="self" collection="type-annotation" /> -->
61+ <include syntax="self" collection="data-definition" />
62+ <include syntax="self" collection="GADT-definition" />
63+ <include syntax="self" collection="instance" />
64+ <include syntax="self" collection="typeclass" />
65+ <include syntax="self" collection="definition" />
66+ </scopes>
67+
68+ <template-scopes>
69+ <include syntax="self" collection="Quote" />
70+ <include syntax="self" collection="comments" />
71+ </template-scopes>
72+
73+ <collections>
74+
75+
76+ <collection name="operators">
77+ <scope name="keyword.modifier">
78+ <expression>(!|#|\$|%|&amp;|โ‹†|\+|\.|/|&lt;|=|&gt;|\?|@|\\|\^|\||-|~|:)+</expression>
79+ </scope>
80+ </collection>
81+
82+ <collection name="expressions">
83+ <include syntax="self" collection="do-bind" />
84+ <include syntax="self" collection="literal" />
85+ <include syntax="self" collection="operators" />
86+ <include syntax="self" collection="list" />
87+ <include syntax="self" collection="lambda-case" />
88+ <include syntax="self" collection="lambda-head" />
89+ <include syntax="self" collection="type-applications" />
90+ <include syntax="self" collection="case-expression" />
91+ <include syntax="self" collection="qvarid" />
92+ <include syntax="self" collection="bind-arrow" />
93+ <include syntax="self" collection="tuple" />
94+
95+
96+
97+ <!-- Needed for do binds -->
98+ <!-- <include syntax="self" collection="pattern-match" /> -->
99+ </collection>
100+
101+ <collection name="pattern-match">
102+ <include syntax="self" collection="literal" />
103+ <include syntax="self" collection="view-pattern" />
104+ <include syntax="self" collection="tuple-match" />
105+<!-- <include syntax="self" collection="at-pattern" /> -->
106+ <include syntax="self" collection="varid" />
107+ <include syntax="self" collection="qconid" />
108+ <include syntax="self" collection="record-match" />
109+ <include syntax="self" collection="list-pattern" />
110+ </collection>
111+
112+ <collection name="type-applications">
113+ <scope name="type-applications">
114+ <starts-with>
115+ <expression>(\s@)\(</expression>
116+ <capture number="1" name="haskell.keyword.operator.typeapplication" />
117+ </starts-with>
118+ <ends-with>
119+ <expression>)</expression>
120+ </ends-with>
121+ <subscopes>
122+ <include syntax="self" collection="type" />
123+ </subscopes>
124+ </scope>
125+ <scope name="type-applications-single">
126+ <expression>(@)(\w+)</expression>
127+ <capture number="1" name="haskell.keyword.operator.typeapplication" />
128+ <capture number="2" name="haskell.identifier.type" />
129+ </scope>
130+ </collection>
131+
132+ <collection name="Quote">
133+ <scope name="haskell.quasiquote.string-template">
134+ <starts-with>
135+ <expression>\[((?:\w|')+)\|</expression>
136+ <capture number="1" name="haskell.identifier.constant" />
137+ </starts-with>
138+ <ends-with>
139+ <expression>\|\]</expression>
140+ </ends-with>
141+ <subscopes>
142+ <scope name="haskell.quasiquote.string-template.value">
143+ <expression>.+?</expression>
144+ </scope>
145+ </subscopes>
146+ </scope>
147+ </collection>
148+
149+ <collection name="record-match">
150+ <include syntax="self" collection="qconid" />
151+ <include syntax="self" collection="record-fields-match" />
152+ <include syntax="self" collection="record-fields-match-all" />
153+ </collection>
154+
155+
156+ <collection name="record-fields-match">
157+ <scope name="record-fields-match">
158+ <symbol type="expression" />
159+ <starts-with>
160+ <expression>(\{)</expression>
161+ <capture number="1" name="haskell.pattern.record.bracket" />
162+ </starts-with>
163+ <ends-with>
164+ <expression>(\})</expression>
165+ <capture number="1" name="haskell.pattern.record.bracket" />
166+ </ends-with>
167+ <subscopes>
168+ <include syntax="self" collection="pattern-match" />
169+ <include syntax="self" collection="varid" />
170+ <scope name="record-sep">
171+ <expression>=</expression>
172+ </scope>
173+ <scope name="record-sep">
174+ <expression>,</expression>
175+ </scope>
176+ </subscopes>
177+ </scope>
178+ </collection>
179+
180+ <collection name="record-fields-match-wildcard">
181+ <scope name="record-fields-match-all">
182+ <starts-with>
183+ <expression>(\{)</expression>
184+ <capture number="1" name="haskell.pattern.record.bracket" />
185+ </starts-with>
186+ <ends-with>
187+ <expression>(\})</expression>
188+ <capture number="1" name="haskell.pattern.record.bracket" />
189+ </ends-with>
190+ <subscopes>
191+ <scope name="haskell.pattern.record.wildcard">
192+ <expression>\.\.</expression>
193+ </scope>
194+ </subscopes>
195+ </scope>
196+ </collection>
197+
198+ <collection name="bind-arrow">
199+ <scope name="haskell.operator.bind-arrow">
200+ <expression>&lt;-</expression>
201+ </scope>
202+ </collection>
203+
204+
205+ <collection name="list">
206+ <symbol type="expression" />
207+ <scope name="haskell.list">
208+ <starts-with>
209+ <expression>(\[)</expression>
210+ <capture number="1" name="haskell.list.bracket" />
211+ </starts-with>
212+ <ends-with>
213+ <expression>(\])</expression>
214+ <capture number="1" name="haskell.list.bracket" />
215+ </ends-with>
216+ <subscopes>
217+ <include syntax="self" collection="expressions" />
218+ </subscopes>
219+ </scope>
220+ </collection>
221+
222+ <collection name="list-pattern">
223+ <symbol type="expression" />
224+ <scope name="haskell.pattern.list">
225+ <starts-with>
226+ <expression>(\[)</expression>
227+ <capture number="1" name="haskell.pattern.list.bracket" />
228+ </starts-with>
229+ <ends-with>
230+ <expression>(\])</expression>
231+ <capture number="1" name="haskell.pattern.list.bracket" />
232+ </ends-with>
233+ <subscopes>
234+ <include syntax="self" collection="pattern-match" />
235+ </subscopes>
236+ </scope>
237+ </collection>
238+
239+
240+ <collection name="view-pattern">
241+ <scope name="haskell.pattern.view">
242+ <symbol type="expression" />
243+ <starts-with>
244+ <expression>(\()</expression>
245+ <capture number="1" name="haskell.pattern.view.bracket" />
246+ </starts-with>
247+ <ends-with>
248+ <expression>(\))</expression>
249+ <capture number="1" name="haskell.pattern.view.bracket" />
250+ </ends-with>
251+ <subscopes anchored="true">
252+ <include syntax="self" collection="expressions" />
253+ <scope name="haskell.pattern.view.operator.arrow">
254+ <expression>-&gt;</expression>
255+ </scope>
256+ <include syntax="self" collection="pattern-match" />
257+ </subscopes>
258+ </scope>
259+ </collection>
260+
261+ <collection name="tuple-match">
262+ <symbol type="expression" />
263+ <scope name="haskell.pattern.tuple">
264+ <starts-with>
265+ <expression>(\()</expression>
266+ <capture number="1" name="haskell.pattern.tuple.bracket" />
267+ </starts-with>
268+ <ends-with>
269+ <expression>(\))</expression>
270+ <capture number="1" name="haskell.pattern.tuple.bracket" />
271+ </ends-with>
272+ <subscopes>
273+ <include syntax="self" collection="pattern-match" />
274+ </subscopes>
275+ </scope>
276+ </collection>
277+
278+ <collection name="case-expression">
279+ <scope name="haskell.case">
280+ <starts-with>
281+ <expression>(case)</expression>
282+ <capture number="1" name="haskell.case.keyword.condition" />
283+ </starts-with>
284+ <ends-with>
285+ <expression>(of)</expression>
286+ <capture number="1" name="haskell.case.keyword.condition" />
287+ </ends-with>
288+ <subscopes>
289+ <include syntax="self" collection="expressions" />
290+ </subscopes>
291+ </scope>
292+ </collection>
293+
294+ <collection name="tuple">
295+ <symbol type="expression" />
296+ <scope name="haskell.tuple">
297+ <starts-with>
298+ <expression>(\()</expression>
299+ <capture number="1" name="haskell.tuple.bracket" />
300+ </starts-with>
301+ <ends-with>
302+ <expression>(\))</expression>
303+ <capture number="1" name="haskell.tuple.bracket" />
304+ </ends-with>
305+ <subscopes>
306+ <include syntax="self" collection="expressions" />
307+ </subscopes>
308+ </scope>
309+ </collection>
310+
311+ <collection name="typeclass">
312+ <symbol type="interface" />
313+ <scope name="haskell.definition.class">
314+ <starts-with>
315+ <expression>^(\h*)(class)($|\h)</expression>
316+ <capture number="2" name="haskell.keyword.construct.class" />
317+ </starts-with>
318+ <ends-with>
319+ <template>^(?!\s+\1\S)(?!\s*$)</template>
320+ </ends-with>
321+ <subscopes>
322+ <scope name="haskell.keyword.construct.where">
323+ <expression>where</expression>
324+ </scope>
325+ <include syntax="self" collection="type" />
326+ <include syntax="self" collection="type-definition" />
327+ <!-- <include syntax="self" collection="type-annotation" /> -->
328+ <include syntax="self" collection="definition" />
329+ </subscopes>
330+ </scope>
331+ </collection>
332+
333+ <collection name="instance">
334+ <scope name="haskell.instance">
335+ <symbol type="category" />
336+ <starts-with>
337+ <expression>^(\h*)(instance)($|\h)</expression>
338+ <capture number="2" name="haskell.keyword.construct.instance" />
339+ </starts-with>
340+ <ends-with>
341+ <template>^(?!\s+\1\S)(?!\s*$)</template>
342+ </ends-with>
343+ <subscopes>
344+ <scope name="haskell.keyword.construct.where">
345+ <expression>where</expression>
346+ </scope>
347+ <include syntax="self" collection="type" />
348+ <include syntax="self" collection="type-definition" />
349+ <include syntax="self" collection="type-annotation" />
350+ <include syntax="self" collection="definition" />
351+ </subscopes>
352+ </scope>
353+ </collection>
354+
355+ <collection name="type-family-definition">
356+ <scope name="haskell.definition.type.type-family">
357+ <symbol type="type" />
358+ <starts-with>
359+ <expression>^(\h*)(type\h+family)\h+`?(\w(\w|')*)`?($|\h)</expression>
360+ <capture number="2" name="haskell.keyword.construct.type-family" />
361+ </starts-with>
362+ <ends-with>
363+ <template>^(?!\s+\1\S)(?!\s*$)</template>
364+ </ends-with>
365+ <subscopes>
366+ <scope name="haskell.keyword.construct.where">
367+ <expression>where</expression>
368+ </scope>
369+ <include syntax="self" collection="type" />
370+ </subscopes>
371+ </scope>
372+ </collection>
373+
374+ <collection name="definition">
375+ <scope name="haskell.definition.type.function">
376+ <symbol type="function">
377+ <display-name>
378+ <component selector="haskell.definition.type.function" />
379+ </display-name>
380+
381+ </symbol>
382+ <starts-with>
383+ <expression>^(?=(\h*)(default\h+)?`?(\w(\w|')*)`?($|\h))</expression>
384+ <capture number="2" name="haskell.keyword.construct.default" />
385+ <capture number="3" name="haskell.identifier.function" />
386+ </starts-with>
387+ <ends-with>
388+ <template>^(?!\1\3\s)(?!\s+\1\S)(?!\s*$)</template>
389+ </ends-with>
390+ <subscopes>
391+ <include syntax="self" collection="type-annotation" />
392+ <include syntax="self" collection="implementation" />
393+ </subscopes>
394+ </scope>
395+ </collection>
396+
397+ <collection name="do-bind">
398+ <scope name="do-bind">
399+ <starts-with>
400+ <expression>^(?=(\h*).+&lt;-($|\h))</expression>
401+ </starts-with>
402+ <ends-with>
403+ <template>^(?!\0)(?!\s+\1\S)(?!\s*$)</template>
404+ </ends-with>
405+ <subscopes anchored="true">
406+ <include syntax="self" collection="pattern-match" />
407+ <scope name="bind-arrow">
408+ <expression>&lt;-</expression>
409+ </scope>
410+ <include syntax="self" collection="expressions" repeat="true" />
411+ </subscopes>
412+ </scope>
413+ </collection>
414+
415+ <collection name="implementation">
416+ <scope name="haskell.definition.type.function">
417+ <local scope="within-construct" />
418+ <starts-with>
419+ <expression>^(\h*)(default\h+)?`?(\w(\w|')*)`?($|\h)</expression>
420+ <capture number="2" name="haskell.keyword.construct.default" />
421+ <capture number="3" name="haskell.identifier.function" />
422+ </starts-with>
423+ <ends-with>
424+ <template>^(?!\1\3\s)(?!\s+\1\S)(?!\s*$)</template>
425+ </ends-with>
426+ <subscopes>
427+ <include syntax="self" collection="where-clause" />
428+ <include syntax="self" collection="expressions" />
429+ </subscopes>
430+ </scope>
431+ </collection>
432+
433+ <collection name="type-annotation">
434+ <scope name="haskell.definition.type.function">
435+ <starts-with>
436+ <expression>^(\h*)`?(\w(\w|')*)`?\h*::($|\h)</expression>
437+ <capture number="2" name="haskell.identifier.function" />
438+ </starts-with>
439+ <ends-with>
440+ <template>^(?!\s+\1\S)(?!\s*$)</template>
441+ </ends-with>
442+ <subscopes>
443+ <include syntax="self" collection="type" />
444+ </subscopes>
445+ </scope>
446+ </collection>
447+
448+ <collection name="type-definition">
449+ <scope name="haskell.definition.type">
450+ <starts-with>
451+ <expression>^(\h*)(type)\h+(\w(\w|')*)</expression>
452+ <capture number="2" name="haskell.keyword.construct.type" />
453+ <capture number="3" name="haskell.identifier.type" />
454+ </starts-with>
455+ <ends-with>
456+ <template>^(?!\s+\1\S)(?!\s*$)</template>
457+ </ends-with>
458+ <subscopes>
459+ <include syntax="self" collection="type" />
460+ </subscopes>
461+ </scope>
462+ </collection>
463+
464+ <collection name="GADT-definition">
465+ <scope name="haskell.definition.struct.GADT">
466+ <starts-with>
467+ <expression>^(\h*)(data)\h+(\w(\w|')*)</expression>
468+ <capture number="2" name="haskell.keyword.construct.data.GADT" />
469+ </starts-with>
470+ <ends-with>
471+ <template>^(?!\s+\1\S)(?!\s*$)</template>
472+ </ends-with>
473+ <subscopes>
474+ <include syntax="self" collection="gadt-constructor" />
475+ <include syntax="self" collection="type" />
476+ <include syntax="self" collection="record-definition" />
477+ <include syntax="self" collection="record-definition-field-name" />
478+ </subscopes>
479+ </scope>
480+ </collection>
481+
482+ <collection name="gadt-constructor">
483+ <scope name="identifier.type.struct.GADT.constructor">
484+ <expression>^\h+[A-Z](\w|')*</expression>
485+ </scope>
486+ </collection>
487+
488+ <collection name="data-definition">
489+ <scope name="haskell.definition.struct.data">
490+ <starts-with>
491+ <expression>^(\h*)(data|newtype)\h+(\w(\w|')*)</expression>
492+ <capture number="2" name="haskell.keyword.construct.data.newtype" />
493+ <capture number="3" name="haskell.identifier.type" />
494+ </starts-with>
495+ <ends-with>
496+ <template>^(?!\s+\1\S)(?!\s*$)</template>
497+ </ends-with>
498+ <subscopes>
499+ <include syntax="self" collection="record-definition" />
500+ <include syntax="self" collection="data-constructor" />
501+ <include syntax="self" collection="type" />
502+ </subscopes>
503+ </scope>
504+ </collection>
505+
506+ <collection name="data-constructor">
507+ <scope name="haskell.identifier.type.struct.data.constructor">
508+ <expression>=\h+[A-Z](\w|')*</expression>
509+ </scope>
510+ <scope name="haskell.identifier.type.struct.data.constructor">
511+ <expression>\|\h+[A-Z](\w|')*</expression>
512+ </scope>
513+ </collection>
514+
515+ <collection name="record-definition">
516+ <scope name="haskell.record">
517+ <starts-with>
518+ <expression>(\{)</expression>
519+ <capture number="1" name="haskell.record.bracket" />
520+ </starts-with>
521+ <ends-with>
522+ <expression>(\})</expression>
523+ <capture number="1" name="haskell.record.bracket" />
524+ </ends-with>
525+ <subscopes>
526+ <include syntax="self" collection="record-definition-field-name" />
527+ <include syntax="self" collection="type" />
528+ </subscopes>
529+ </scope>
530+ </collection>
531+
532+ <collection name="record-definition-field-name">
533+ <scope name="haskell.record.definition.property">
534+ <expression>\w(\w|')*\h*::</expression>
535+ </scope>
536+ </collection>
537+
538+ <collection name="type">
539+ <include syntax="self" collection="type-list" />
540+ <scope name="haskell.identifier.type">
541+ <expression>([A-Z](\w|')*\.)*[A-Z](\w|')*</expression>
542+ </scope>
543+ <scope name="haskell.keyword.construct.forall">
544+ <expression>forall</expression>
545+ </scope>
546+ <scope name="haskell.identifier.type.variable">
547+ <expression>\w(\w|')*</expression>
548+ </scope>
549+ <scope name="haskell.keyword.construct.function-arrow">
550+ <expression>-&gt;</expression>
551+ </scope>
552+ <scope name="haskell.keyword.construct.fat-arrow">
553+ <expression>=&gt;</expression>
554+ </scope>
555+ </collection>
556+
557+ <collection name="pattern-definition">
558+ <scope name="haskell.pattern">
559+ <starts-with>
560+ <expression>^(\h*)(pattern)\h+(\w(\w|')*)</expression>
561+ <capture number="2" name="haskell.keyword.construct.pattern" />
562+ <capture number="3" name="haskell.identifier.decorator.pattern" />
563+ </starts-with>
564+ <ends-with>
565+ <template>^(?!\s+\1\S)(?!\s*$)</template>
566+ </ends-with>
567+ <subscopes>
568+ <scope name="haskell.keyword.construct.where">
569+ <expression>where</expression>
570+ </scope>
571+ <include syntax="self" collection="expressions" />
572+ </subscopes>
573+ </scope>
574+ </collection>
575+
576+ <collection name="type-list">
577+ <scope name="haskell.type-list">
578+ <starts-with>
579+ <expression>('\[)</expression>
580+ <capture number="1" name="haskell.type-list.bracket" />
581+ </starts-with>
582+ <ends-with>
583+ <expression>(\])</expression>
584+ <capture number="1" name="haskell.type-list.bracket" />
585+ </ends-with>
586+ <subscopes>
587+ <include syntax="self" collection="type" />
588+ </subscopes>
589+ </scope>
590+ </collection>
591+
592+ <collection name="lambda-head">
593+ <scope name="haskell.lambda">
594+ <starts-with>
595+ <expression>(\\)</expression>
596+ <capture number="1" name="haskell.keyword.construct.lambda" />
597+ </starts-with>
598+ <ends-with>
599+ <expression>(-&gt;)</expression>
600+ <capture number="1" name="haskell.keyword.construct.lambda" />
601+ </ends-with>
602+ <subscopes>
603+ <include syntax="self" collection="pattern-match" />
604+ </subscopes>
605+ </scope>
606+ </collection>
607+
608+ <collection name="lambda-case">
609+ <scope name="haskell.keyword.condition.lambda-case">
610+ <expression>\\case</expression>
611+ </scope>
612+ </collection>
613+
614+ <collection name="where-clause">
615+ <scope name="haskell.construct.where">
616+ <local scope="within-parent" />
617+ <starts-with>
618+ <expression>^(\h*)(where)</expression>
619+ <capture number="2" name="haskell.construct.keyword.where" />
620+ </starts-with>
621+ <ends-with>
622+ <template>^(?!\1\s*\S)(?!s*$)</template>
623+ </ends-with>
624+ <subscopes>
625+ <include syntax="self" collection="definition" />
626+ </subscopes>
627+ </scope>
628+ </collection>
629+
630+
631+ <collection name="qvarid">
632+ <scope name="haskell.identifier.function">
633+ <expression>([A-Z](\w|')*\.)*\w(\w|')*</expression>
634+ </scope>
635+ </collection>
636+
637+ <collection name="varid">
638+ <scope name="haskell.identifier.variable">
639+ <expression>\w(\w|')*</expression>
640+ </scope>
641+ </collection>
642+
643+ <collection name="qconid">
644+ <scope name="haskell.identifier.type.struct.constructor">
645+ <expression>([A-Z](\w|')*\.)*[A-Z](\w|')*</expression>
646+ </scope>
647+ </collection>
648+
649+ <collection name="qconsym">
650+ <scope name="haskell.identifier.decorator.pattern">
651+ <expression>([A-Z](\w|')*\.):(\w|')*</expression>
652+ </scope>
653+ </collection>
654+
655+ <collection name="literal">
656+ <include syntax="self" collection="number" />
657+ <include syntax="self" collection="strings" />
658+ </collection>
659+
660+
661+ <collection name="strings">
662+ <scope name="haskell.string.double-quoted">
663+ <starts-with>
664+ <expression>"</expression>
665+ </starts-with>
666+ <ends-with>
667+ <expression>"</expression>
668+ </ends-with>
669+ <subscopes>
670+ <scope name="haskell.string.escape-sequences">
671+ <expression>\\.</expression>
672+ </scope>
673+ </subscopes>
674+ </scope>
675+ <scope name="haskell.string.single-quoted">
676+ <expression>'([^'\\]|\\.)'</expression>
677+ </scope>
678+ </collection>
679+
680+
681+ <collection name="number">
682+ <scope name="haskell.value.number">
683+ <expression>(0x|0o|0O|0X)?\d+(\d|_)*(\.[\d|_]+)?((e|E)(\+|-)?\d+)?</expression>
684+ </scope>
685+ </collection>
686+
687+
688+ <collection name="module">
689+ <scope name="haskell.definition.module.package">
690+ <starts-with>
691+ <expression>^(module)\s+(\w|\.)+</expression>
692+ <capture number="1" name="haskell.construct.keyword.module" />
693+ <capture number="2" name="haskell.definition.module.package" />
694+ </starts-with>
695+ <ends-with>
696+ <expression>(where)</expression>
697+ <capture number="1" name="haskell.construct.keyword.module" />
698+ </ends-with>
699+ <subscopes export-symbols="true">
700+ <scope name="identifier.constant">
701+ <expression>(\w|')+</expression>
702+ </scope>
703+ </subscopes>
704+ </scope>
705+ </collection>
706+
707+ <collection name="import">
708+ <scope name="haskell.construct.keyword.import">
709+ <expression>^import\s</expression>
710+ </scope>
711+ <scope name="haskell.construct.keyword.qualified">
712+ <expression>qualified</expression>
713+ </scope>
714+ <scope name="haskell.construct.keyword.as">
715+ <expression>as</expression>
716+ </scope>
717+ <scope name="haskell.identifier.module.package">
718+ <expression>([A-Z](\w|')*\.)*[A-Z](\w|')*</expression>
719+ </scope>
720+ <include syntax="self" collection="import-list" />
721+ </collection>
722+
723+ <collection name="import-list">
724+ <scope name="import-list">
725+ <starts-with>
726+ <expression>(\()</expression>
727+ <capture number="1" name="haskell.import-list.bracket" />
728+ </starts-with>
729+ <ends-with>
730+ <expression>(\))</expression>
731+ <capture number="1" name="haskell.import-list.bracket" />
732+ </ends-with>
733+ <subscopes>
734+ <scope name="identifier.decorator">
735+ <expression>([A-Z](\w|')*\.)*\w(\w|')*</expression>
736+ </scope>
737+ </subscopes>
738+ </scope>
739+ </collection>
740+
741+ <!-- <collection name="special">
742+ <scope>
743+ <expression>(;|,)</expression>
744+ </scope>
745+ </collection> -->
746+
747+
748+ <collection name="reservedop">
749+ <scope name="keyword.operator">
750+ <expression>(\.\.|:|::|=|\\|\||&lt;-|-&gt;|@|~|=>)</expression>
751+ </scope>
752+ </collection>
753+
754+ <collection name="keywords">
755+ <scope name="haskell.keyword.modifier">
756+ <symbol type="keyword" />
757+ <strings>
758+ <string>do</string>
759+ <string>in</string>
760+ <string>infix</string>
761+ <string>infixl</string>
762+ <string>infixr</string>
763+ <string>where</string>
764+ <string>let</string>
765+ </strings>
766+ </scope>
767+ <scope name="haskell.keyword.condition">
768+ <symbol type="keyword" />
769+ <strings>
770+ <string>of</string>
771+ <string>case</string>
772+ <string>else</string>
773+ <string>if</string>
774+ <string>then</string>
775+ </strings>
776+ </scope>
777+ <scope name="haskell.keyword.keyword.construct">
778+ <symbol type="keyword" />
779+ <strings>
780+ <string>instance</string>
781+ <string>newtype</string>
782+ <string>module</string>
783+ <string>type</string>
784+ <string>class</string>
785+ <string>data</string>
786+ <string>default</string>
787+ <string>deriving</string>
788+ <string>foreign</string>
789+ </strings>
790+ </scope>
791+ <scope name="haskell.keyword.self">
792+ <symbol type="keyword" />
793+ <strings>
794+ <string>undefined</string>
795+ <string>_</string>
796+ </strings>
797+ </scope>
798+ </collection>
799+
800+ <collection name="comments">
801+ <scope name="haskell.comment.single" spell-check="true">
802+ <starts-with>
803+ <expression>--</expression>
804+ </starts-with>
805+ <ends-with>
806+ <expression>$</expression>
807+ </ends-with>
808+ </scope>
809+ <scope name="haskell.comment.block" spell-check="true">
810+ <starts-with>
811+ <expression>{-</expression>
812+ </starts-with>
813+ <ends-with>
814+ <expression>-}</expression>
815+ </ends-with>
816+ </scope>
817+ </collection>
818+
819+
820+ </collections>
821+</syntax>
Haskell Language Server.novaextension/extension.jsonnew file+300
@@ -0,0 +1,300 @@
1+{
2+ "identifier": "iko.soy.HaskellLanguageServer",
3+ "name": "Haskell Language Server",
4+ "organization": "iko",
5+ "description": "Lorem ipsum, dolor sit amet.",
6+ "version": "1.0",
7+ "categories": ["languages", "formatters"],
8+ "main": "main.js",
9+ "entitlements": {
10+ "process": true,
11+ "filesystem": "readwrite",
12+ "requests": true
13+ },
14+ "configWorkspace": [{
15+ "key": "haskell-language-server-path",
16+ "title": "Haskell Language Server path",
17+ "description": "If you want to use a custom HLS build for this project, then specify the path to it here.",
18+ "type": "path",
19+ "placeholder": "/usr/local/bin/example"
20+ }, {
21+ "type": "section",
22+ "title": "Haskell Language Server settings",
23+ "children": [{
24+ "key": "haskell.formattingProvider",
25+ "title": "Code formatter",
26+ "type": "enum",
27+ "values": [
28+ "brittany",
29+ "floskell",
30+ "fourmolu",
31+ "ormolu",
32+ "stylish-haskell",
33+ "none"
34+ ],
35+ "default": "ormolu",
36+ "description": "The formatter to use when formatting a document or range. Ensure the plugin is enabled."
37+ }, {
38+ "key": "haskell.checkProject",
39+ "title": "Check whole project",
40+ "type": "boolean",
41+ "default": false,
42+ "description": "Whether to typecheck the entire project on load. It could drive to bad perfomance in large projects."
43+ }, {
44+ "key": "haskell.maxCompletions",
45+ "type": "number",
46+ "title": "Maximum number of completions",
47+ "description": "Maximum number of completions sent to the editor.",
48+ "default": 40
49+ }, {
50+ "type": "section",
51+ "title": "Plugin settings",
52+ "children": [{
53+ "type": "section",
54+ "title": "Import lens",
55+ "description": "Not currently implemented in Nova",
56+ "children": [{
57+ "key": "haskell.plugin.importLens.codeActionsOn",
58+ "title": "Enable code actions",
59+ "type": "boolean",
60+ "default": true,
61+ "description": "Enables explicit imports code actions"
62+ }, {
63+ "key": "haskell.plugin.importLens.codeLensOn",
64+ "title": "Enable code lens",
65+ "type": "boolean",
66+ "default": true,
67+ "description": "Enables explicit imports code lenses"
68+ }]
69+ }, {
70+ "title": "HLint",
71+ "type": "section",
72+ "children": [{
73+ "key": "haskell.plugin.hlint.codeActionsOn",
74+ "title": "Enable code actions",
75+ "type": "boolean",
76+ "default": true,
77+ "description": "Enables hlint code actions (apply hints)"
78+ }, {
79+ "key": "haskell.plugin.hlint.diagnosticsOn",
80+ "title": "Enable diagnostics",
81+ "type": "boolean",
82+ "default": true,
83+ "description": "Enables hlint diagnostics"
84+ }, {
85+ "title": "Configuration",
86+ "type": "section",
87+ "children": [{
88+ "key": "haskell.plugin.hlint.config.flags",
89+ "title": "Flags",
90+ "description": "Flags used by hlint",
91+ "default": [],
92+ "type": "stringArray"
93+ }]
94+ }]
95+ }, {
96+ "title": "Eval",
97+ "type": "section",
98+ "children": [{
99+ "key": "haskell.plugin.eval.globalOn",
100+ "title": "Enable",
101+ "type": "boolean",
102+ "default": true,
103+ "description": "Enables eval plugin"
104+ }]
105+ }, {
106+ "title": "Module name",
107+ "type": "section",
108+ "children": [{
109+ "key": "haskell.plugin.moduleName.globalOn",
110+ "title": "Enable",
111+ "type": "boolean",
112+ "default": true,
113+ "description": "Enables module name plugin"
114+ }]
115+ }, {
116+ "title": "Splice",
117+ "type": "section",
118+ "children": [{
119+ "key": "haskell.plugin.splice.globalOn",
120+ "title": "Enable",
121+ "type": "boolean",
122+ "default": true,
123+ "description": "Enables splice plugin (expand template haskell definitions)"
124+ }]
125+ }, {
126+ "title": "Haddock comments",
127+ "type": "section",
128+ "children": [{
129+ "key": "haskell.plugin.haddockComments.globalOn",
130+ "title": "Enable",
131+ "type": "boolean",
132+ "default": true,
133+ "description": "Enables haddock comments plugin"
134+ }]
135+ }, {
136+ "title": "Class",
137+ "type": "section",
138+ "children": [{
139+ "key": "haskell.plugin.class.globalOn",
140+ "title": "Enable",
141+ "type": "boolean",
142+ "default": true,
143+ "description": "Enables type class plugin"
144+ }]
145+ }, {
146+ "title": "Retrie",
147+ "type": "section",
148+ "children": [{
149+ "key": "haskell.plugin.retrie.globalOn",
150+ "title": "Enable",
151+ "type": "boolean",
152+ "default": true,
153+ "description": "Enables retrie plugin"
154+ }]
155+ }, {
156+ "title": "Wingman",
157+ "type": "section",
158+ "children": [{
159+ "key": "haskell.plugin.tactics.globalOn",
160+ "title": "Enable",
161+ "type": "boolean",
162+ "default": true,
163+ "description": "Enables Wingman (tactics) plugin"
164+ }, {
165+ "title": "Configuration",
166+ "type": "section",
167+ "children": [{
168+ "key": "haskell.plugin.tactics.config.auto_gas",
169+ "title": "Gas",
170+ "description": "The depth of the search tree when performing \"Attempt to fill hole\". Bigger values will be able to derive more solutions, but will take exponentially more time.",
171+ "default": 4,
172+ "type": "number"
173+ }, {
174+ "key": "haskell.plugin.tactics.config.hole_severity",
175+ "title": "Hole severity",
176+ "description": "The severity to use when showing hole diagnostics.",
177+ "values": [
178+ 1,
179+ 2,
180+ 3,
181+ 4,
182+ null
183+ ],
184+ "default": null,
185+ "type": "enum"
186+ }, {
187+ "key": "haskell.plugin.tactics.config.max_use_ctor_actions",
188+ "title": "Max number of constructors",
189+ "type": "number",
190+ "default": 5,
191+ "description": "Maximum number of `Use constructor <x>` code actions that can appear"
192+ }, {
193+ "key": "haskell.plugin.tactics.config.timeout_duration",
194+ "title": "Timeout",
195+ "description": "The timeout for Wingman actions, in seconds",
196+ "default": 2,
197+ "type": "number"
198+ }, {
199+ "key": "haskell.plugin.tactics.config.proofstate_styling",
200+ "title": "Proof states",
201+ "description": "Should Wingman emit styling markup when showing metaprogram proof states?",
202+ "default": true,
203+ "type": "boolean"
204+ }]
205+ }]
206+ }, {
207+ "title": "Pragmas",
208+ "type": "section",
209+ "children": [{
210+ "key": "haskell.plugin.pragmas.codeActionsOn",
211+ "title": "Enable code actions",
212+ "type": "boolean",
213+ "default": true,
214+ "description": "Enables pragmas code actions"
215+ }, {
216+ "key": "haskell.plugin.pragmas.completionOn",
217+ "title": "Enable completions",
218+ "type": "boolean",
219+ "default": true,
220+ "description": "Enables pragmas completions"
221+ }]
222+ }, {
223+ "title": "Completions",
224+ "type": "section",
225+ "children": [{
226+ "title": "Configuration",
227+ "type": "section",
228+ "children": [{
229+ "key": "haskell.plugin.ghcide-completions.config.autoExtendOn",
230+ "title": "Extend with out-of-scope identifiers",
231+ "description": "Extends the import list automatically when completing a out-of-scope identifier",
232+ "default": true,
233+ "type": "boolean"
234+ }, {
235+ "key": "haskell.plugin.ghcide-completions.config.snippetsOn",
236+ "title": "Insert snippets",
237+ "description": "Inserts snippets when using code completions",
238+ "default": true,
239+ "type": "boolean"
240+ }]
241+ }]
242+ }, {
243+ "description": "Not currently implemented in Nova",
244+ "type": "section",
245+ "children": [{
246+ "key": "haskell.plugin.ghcide-type-lenses.globalOn",
247+ "title": "Enable",
248+ "type": "boolean",
249+ "default": true,
250+ "description": "Enables type lenses plugin"
251+ }, {
252+ "title": "Configuration",
253+ "type": "section",
254+ "children": [{
255+ "key": "haskell.plugin.ghcide-type-lenses.config.mode",
256+ "title": "Mode",
257+ "type": "enum",
258+ "default": true,
259+ "description": "Control how type lenses are shown",
260+ "values": ["always", "exported", "diagnostics"]
261+ }]
262+ }]
263+ }, {
264+ "title": "Refine imports",
265+ "type": "section",
266+ "children": [{
267+ "key": "haskell.plugin.refineImports.globalOn",
268+ "title": "Enable",
269+ "type": "boolean",
270+ "default": true,
271+ "description": "Enables refine imports plugin"
272+ }]
273+ }]
274+ }]
275+ }],
276+ "activationEvents": ["onLanguage:haskell", "onLanguage:hs"],
277+ "commands": {
278+ "editor": [{
279+ "title": "Format file with Haskell Language Server",
280+ "command": "format",
281+ "when": "editorSyntax == 'haskell' && editorHasFocus",
282+ "filters": {
283+ "syntaxes": ["haskell"]
284+ }
285+ }],
286+ "extensions": [{
287+ "title": "Stop",
288+ "paletteTitle": "Stop Haskell Language Server",
289+ "command": "stop"
290+ }, {
291+ "title": "Restart",
292+ "paletteTitle": "Restart Haskell Language Server",
293+ "command": "restart"
294+ }, {
295+ "title": "Clear cached versions",
296+ "paletteTitle": "Clear cached versions of Haskell Language Server",
297+ "command": "clear-cache"
298+ }]
299+ }
300+}