forked from streetsidesoftware/vscode-spell-checker
-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.ts
176 lines (147 loc) · 4.88 KB
/
main.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
import {
CodeActionKind,
createConnection,
Diagnostic,
DidChangeConfigurationNotification,
ExecuteCommandParams,
InitializeParams,
InitializeResult,
ProposedFeatures,
TextDocuments,
TextDocumentSyncKind,
} from "vscode-languageserver/node";
import * as fs from 'fs';
import * as readline from 'readline';
import { TextDocument } from "vscode-languageserver-textdocument";
import { getDefaultSettings, constructSettingsForText } from "cspell-lib";
import * as Validator from './validator.mjs';
import { createOnCodeActionHandler } from "./codeActions.mts";
// Retrieve the arguments array, excluding the first two elements
const args = process.argv.slice(2);
let dictionaryPath: string | null = null;
export let userWords: Array<string> = [];
// Iterate over the arguments to find '--dictionary'
for (let i = 0; i < args.length; i++) {
if (args[i] === '--dictionary' && args[i + 1]) {
// The next element should be the path to the file
try {
dictionaryPath = args[i + 1];
let stream = fs.createReadStream(dictionaryPath);
const rl = readline.createInterface({
input: stream,
crlfDelay: Infinity // Recognizes all instances of CR LF as a single line break
});
for await (const line of rl) {
userWords.push(line);
}
break;
} catch (err) {
console.error(`An error occurred while processing the file: ${err}`);
}
}
}
if (dictionaryPath) {
console.log(`Dictionary path: ${dictionaryPath}`);
} else {
console.log('No dictionary path provided');
}
// Create a connection for the server, using Node's IPC as a transport.
// Also include all preview / proposed LSP features.
const connection = createConnection(ProposedFeatures.all);
// Create a simple text document manager.
const documents = new TextDocuments(TextDocument);
let hasConfigurationCapability = false;
let hasWorkspaceFolderCapability = false;
connection.onInitialize((_: InitializeParams) => {
const result: InitializeResult = {
capabilities: {
textDocumentSync: {
openClose: true,
change: TextDocumentSyncKind.Incremental,
willSave: true,
save: { includeText: true },
},
codeActionProvider: {
codeActionKinds: [CodeActionKind.QuickFix],
},
executeCommandProvider: {
commands: ['AddToDictionary']
}
},
};
return result;
});
connection.onInitialized(() => {
if (hasConfigurationCapability) {
// Register for all configuration changes.
connection.client.register(
DidChangeConfigurationNotification.type,
undefined,
);
}
if (hasWorkspaceFolderCapability) {
connection.workspace.onDidChangeWorkspaceFolders((_event) => {
connection.console.log("Workspace folder change event received.");
});
}
});
// connection.onDidChangeConfiguration((change) => {
// connection.languages.diagnostics.refresh();
// });
// Utility function to create a simple code action
function createCodeAction(title, kind, diagnostics, textEdit) {
return {
title,
kind,
diagnostics,
edit: {
changes: {
[textEdit.uri]: [textEdit]
}
}
};
}
connection.onCodeAction(createOnCodeActionHandler(documents));
// The content of a text document has changed. This event is emitted
// when the text document first opened or when its content has changed.
documents.onDidChangeContent((change) => {
validateTextDocument(change.document);
});
async function validateTextDocument(
textDocument: TextDocument,
): Promise<void> {
// TODO: add settings cache
const settings = constructSettingsForText(await getDefaultSettings(), textDocument.getText(), textDocument.languageId);
settings.userWords = [...userWords];
const diagnostics: Diagnostic[] = await Validator.validateTextDocument(textDocument, settings);
// Send the computed diagnostics to the editor.
connection.sendDiagnostics({ uri: textDocument.uri, diagnostics });
}
connection.onExecuteCommand(async (params: ExecuteCommandParams) => {
const { command, arguments: args } = params;
if (command == "AddToDictionary") {
const diagnosticInfo = args![0];
const { uri, range } = diagnosticInfo;
const document = documents.get(uri!);
if (!document) {
return { error: `Could not get document for ${uri}` };
}
const word = document.getText(range);
if (word) {
// Add the word to the custom dictionary
userWords.push(word);
// Add to fictionary file
if (dictionaryPath) {
fs.appendFile(dictionaryPath, word + "\n", () => { });
}
await validateTextDocument(document);
return { result: `Added "${word}" to the dictionary.` };
}
return { error: 'Could not extract the word from the message.' };
}
});
// Make the text document manager listen on the connection
// for open, change and close text document events
documents.listen(connection);
// Listen on the connection
connection.listen();