| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105 |
- import * as vscode from 'vscode';
- import { createDiagnostics } from './diagnostics';
- import { LanguageClient, LanguageClientOptions, ServerOptions, TransportKind } from 'vscode-languageclient/node';
- const KEYWORDS = new Set([
- 'AND', 'ARRAY', 'BEGIN', 'CASE', 'CONST', 'DIV', 'DO', 'DOWNTO',
- 'ELSE', 'END', 'FILE', 'FOR', 'FUNCTION', 'GOTO', 'IF', 'IN',
- 'LABEL', 'MOD', 'NIL', 'NOT', 'OF', 'OR', 'PACKED', 'PROCEDURE',
- 'PROGRAM', 'RECORD', 'REPEAT', 'SET', 'THEN', 'TO', 'TYPE', 'UNIT',
- 'UNTIL', 'USES', 'VAR', 'WHILE', 'WITH', 'FORWARD'
- ]);
- let applyingEdit = false;
- function isIdentifierCharacter(ch: string | undefined): boolean {
- return !!ch && /[A-Za-z0-9_]/.test(ch);
- }
- export function activate(context: vscode.ExtensionContext): void {
- createDiagnostics(context);
- const serverModule = context.asAbsolutePath('out/server.js');
- const serverOptions: ServerOptions = {
- run: { module: serverModule, transport: TransportKind.ipc },
- debug: { module: serverModule, transport: TransportKind.ipc }
- };
- const cfg = vscode.workspace.getConfiguration('modula2');
- const clientOptions: LanguageClientOptions = {
- documentSelector: [
- { scheme: 'file', language: 'pascal' }
- ],
- synchronize: { configurationSection: 'modula2' },
- initializationOptions: {
- pascalDialect: cfg.get<string>('pascal.dialect', 'freepascal'),
- pascalValidators: cfg.get<object>('pascal.validators', {}),
- format: {
- indentSize: cfg.get<number>('pascal.format.indentSize', 2),
- useTabs: cfg.get<boolean>('pascal.format.useTabs', false),
- keywordCase: cfg.get<string>('pascal.format.keywordCase', 'upper'),
- spaceAroundOperators: cfg.get<boolean>('pascal.format.spaceAroundOperators', true),
- spaceAfterComma: cfg.get<boolean>('pascal.format.spaceAfterComma', true),
- spaceBeforeColon: cfg.get<boolean>('pascal.format.spaceBeforeColon', false),
- spaceAroundRange: cfg.get<boolean>('pascal.format.spaceAroundRange', true),
- emptyLineLimit: cfg.get<number>('pascal.format.emptyLineLimit', 1),
- trimTrailingWhitespace: cfg.get<boolean>('pascal.format.trimTrailingWhitespace', true),
- insertFinalNewline: cfg.get<boolean>('pascal.format.insertFinalNewline', true)
- }
- }
- };
- const client = new LanguageClient('pascalCocoR', 'Pascal Coco/R Language Server', serverOptions, clientOptions);
- context.subscriptions.push(client);
- void client.start();
- context.subscriptions.push(vscode.workspace.onDidChangeTextDocument(async event => {
- if (applyingEdit || event.document.languageId !== 'pascal' ||
- !vscode.workspace.getConfiguration('modula2').get<boolean>('pascal.uppercaseKeywords', true)) {
- return;
- }
- const editor = vscode.window.activeTextEditor;
- if (!editor || editor.document.uri.toString() !== event.document.uri.toString()) {
- return;
- }
- for (const change of event.contentChanges) {
- const position = change.range.start.translate(0, change.text.length);
- const line = event.document.lineAt(position.line).text;
- let start = position.character;
- while (start > 0 && isIdentifierCharacter(line[start - 1])) {
- start--;
- }
- let end = position.character;
- while (end < line.length && isIdentifierCharacter(line[end])) {
- end++;
- }
- // Do not modify a token while it is still being typed.
- // This is what prevents "beginning" from becoming "BEGINning".
- if (end >= line.length || isIdentifierCharacter(line[end])) {
- continue;
- }
- const token = line.slice(start, end);
- const upper = token.toUpperCase();
- if (!KEYWORDS.has(upper) || token === upper) {
- continue;
- }
- applyingEdit = true;
- try {
- await editor.edit(builder => {
- builder.replace(
- new vscode.Range(position.line, start, position.line, end),
- upper
- );
- });
- } finally {
- applyingEdit = false;
- }
- }
- }));
- }
- export function deactivate(): void {}
|