Skip to content

Commit

Permalink
feat: Support UTF-16 words lists (#2549)
Browse files Browse the repository at this point in the history
  • Loading branch information
Jason3S committed Feb 27, 2023
1 parent c6c4a0e commit 3222dcc
Show file tree
Hide file tree
Showing 8 changed files with 73 additions and 8 deletions.
12 changes: 12 additions & 0 deletions packages/client/src/settings/CSpellSettings.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,18 @@ import * as CSS from './CSpellSettings';
import { readSettings, writeSettings } from './CSpellSettings';
import { createDictionaryTargetForFile } from './DictionaryTarget';

import { replaceDocText } from './replaceDocText';
import { vscodeFs } from './fs';

jest.mock('./replaceDocText');

const mock_replaceDocText = jest.mocked(replaceDocText);

mock_replaceDocText.mockImplementation(async (doc, text) => {
await vscodeFs.writeFile(doc.uri, text);
return true;
});

describe('Validate CSpellSettings functions', () => {
const filenameSampleCSpellFile = getUriToSample('cSpell.json');

Expand Down
12 changes: 12 additions & 0 deletions packages/client/src/settings/DictionaryTarget.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,18 @@ import { DictionaryTarget } from './DictionaryTarget';
import { configTargetToDictionaryTarget } from './DictionaryTargetHelper';
import { createConfigFile } from './settings';

import { vscodeFs } from './fs';
import { replaceDocText } from './replaceDocText';

jest.mock('./replaceDocText');

const mock_replaceDocText = jest.mocked(replaceDocText);

mock_replaceDocText.mockImplementation(async (doc, text) => {
await vscodeFs.writeFile(doc.uri, text);
return true;
});

describe('Validate DictionaryTarget', () => {
interface TestUpdating {
createFn: (tempDir: Uri) => Promise<TargetAndReader>;
Expand Down
28 changes: 20 additions & 8 deletions packages/client/src/settings/DictionaryTarget.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { isErrnoException } from 'common-utils/index.js';
import { uriToName } from 'common-utils/uriHelper.js';
import * as fs from 'fs-extra';
import * as path from 'path';
import { format } from 'util';
import { Uri } from 'vscode';
import { Uri, window, workspace } from 'vscode';
import { Utils as UriUtils } from 'vscode-uri';
import { ConfigRepository, createCSpellConfigRepository } from './configRepository';
import { addWordsFn, removeWordsFn, updaterAddWords, updaterRemoveWords } from './configUpdaters';
import { vscodeFs as fs } from './fs';
import { replaceDocText } from './replaceDocText';

const regBlockUpdateDictionaryFormat = /(\.((gz|jsonc?|yaml|yml|c?js)$|trie\b)|^$|[/\\]$)/i;

Expand Down Expand Up @@ -80,17 +81,28 @@ async function addWordsToCustomDictionary(words: string[], dict: CustomDictDef):
}

async function updateWordInCustomDictionary(updateFn: (words: string[]) => string[], dict: CustomDictDef): Promise<void> {
const fsPath = dict.uri.fsPath;
if (regBlockUpdateDictionaryFormat.test(fsPath)) {
if (regBlockUpdateDictionaryFormat.test(dict.uri.path)) {
return Promise.reject(new Error(`Failed to add words to dictionary "${dict.name}", unsupported format: "${dict.uri.fsPath}".`));
}
try {
const data = await fs.readFile(fsPath, 'utf8').catch(() => '');
await ensureFileExists(dict.uri);
const doc = await workspace.openTextDocument(dict.uri);
const data = doc.getText();
const lines = updateFn(data.split(/\r?\n/g).filter((a) => !!a));
await fs.mkdirp(path.dirname(fsPath));
await fs.writeFile(fsPath, lines.join('\n').trim().concat('\n'));
const text = lines.join('\n').trim() + '\n';
const success = await replaceDocText(doc, text);
if (!success) {
await window.showInformationMessage(`Unable to add words to dictionary "${dict.name}"`);
}
} catch (e) {
const errMsg = isErrnoException(e) ? e.message : format(e);
return Promise.reject(new Error(`Failed to add words to dictionary "${dict.name}", ${errMsg}`));
}
}

async function ensureFileExists(uri: Uri): Promise<void> {
if (await fs.fileExists(uri)) return;

await fs.createDirectory(UriUtils.dirname(uri));
await fs.writeFile(uri, '');
}
11 changes: 11 additions & 0 deletions packages/client/src/settings/replaceDocText.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { Range, TextDocument, TextEdit, workspace, WorkspaceEdit } from 'vscode';

export async function replaceDocText(doc: TextDocument, text: string): Promise<boolean> {
const wsEdit = new WorkspaceEdit();
const range = new Range(doc.positionAt(0), doc.positionAt(doc.getText().length));
const teReplaceDoc = TextEdit.replace(range, text);
wsEdit.set(doc.uri, [teReplaceDoc]);
const success = await workspace.applyEdit(wsEdit);
success && (await doc.save());
return success;
}
8 changes: 8 additions & 0 deletions samples/utf16/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Test UTF16 word lists.

mywordd
otherword

mywordbe

mywordle
10 changes: 10 additions & 0 deletions samples/utf16/cspell.config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
dictionaryDefinitions:
- name: words16le
path: ./words16le.dic
addWords: true
- name: words16be
path: ./words/words16be.dic
addWords: true
dictionaries:
- words16be
- words16le
Binary file added samples/utf16/words/words16be.dic
Binary file not shown.
Binary file added samples/utf16/words16le.dic
Binary file not shown.

0 comments on commit 3222dcc

Please sign in to comment.