cspell
Version:
A Spelling Checker for Code!
116 lines (96 loc) • 3.75 kB
text/typescript
import { Sequence } from 'gensequence';
import * as Text from '../util/text';
import { CSpellUserSettings } from './CSpellSettingsDef';
import { mergeInDocSettings } from './CSpellSettingsServer';
// cspell:ignore gimuy
const regExMatchRegEx = /\/.*\/[gimuy]*/;
const regExInFileSetting = /(?:spell-?checker|cSpell)::?\s*(.*)/gi;
export type CSpellUserSettingsKeys = keyof CSpellUserSettings;
export function getInDocumentSettings(text: string): CSpellUserSettings {
const settings = getPossibleInDocSettings(text)
.map(a => {
return a;
})
.map(a => a[1] || '')
.concatMap(a => parseSettingMatch(a))
.reduce((s, setting) => {
return mergeInDocSettings(s, setting);
}, { id: 'in-doc-settings' } as CSpellUserSettings);
return settings;
}
function parseSettingMatch(possibleSetting: string): CSpellUserSettings[] {
const settingParsers: [RegExp, (m: string) => CSpellUserSettings][] = [
[ /^(?:enable|disable)(?:allow)?CompoundWords/i, parseCompoundWords ],
[ /^words?\s/i , parseWords ],
[ /^ignore(?:words?)?\s/i, parseIgnoreWords ],
[ /^ignore_?Reg_?Exp\s+.+$/i, parseIgnoreRegExp ],
[ /^include_?Reg_?Exp\s+.+$/i, parseIncludeRegExp ],
[ /^(?:local|language)/i, parseLocal ],
];
return settingParsers
.filter(([regex]) => regex.test(possibleSetting))
.map(([, fn]) => fn)
.map(fn => fn(possibleSetting));
}
function parseCompoundWords(match: string): CSpellUserSettings {
const allowCompoundWords = (/enable/i).test(match);
return { id: 'in-doc-allowCompoundWords', allowCompoundWords };
}
function parseWords(match: string): CSpellUserSettings {
const words = match.split(/[,\s]+/g).slice(1);
return { id: 'in-doc-words', words };
}
function parseLocal(match: string): CSpellUserSettings {
const parts = match.trim().split(/\s+/);
const language = parts.slice(1).join(' ');
return language ? { id: 'in-doc-local', language } : {};
}
function parseIgnoreWords(match: string): CSpellUserSettings {
const wordsSetting = parseWords(match);
return { id: 'in-doc-ignore', ignoreWords: wordsSetting.words };
}
function parseRegEx(match: string): string[] {
const patterns = [ match.replace(/^[^\s]+\s+/, '') ]
.map(a => {
const m = a.match(regExMatchRegEx);
if (m && m[0]) {
return m[0];
}
return a.replace(/((?:[^\s]|\\ )+).*/, '$1');
});
return patterns;
}
function parseIgnoreRegExp(match: string): CSpellUserSettings {
const ignoreRegExpList = parseRegEx(match);
return { id: 'in-doc-ignoreRegExp', ignoreRegExpList };
}
function parseIncludeRegExp(match: string): CSpellUserSettings {
const includeRegExpList = parseRegEx(match);
return { id: 'in-doc-includeRegExp', includeRegExpList };
}
function getPossibleInDocSettings(text: string): Sequence<RegExpExecArray> {
return Text.match(regExInFileSetting, text);
}
function getWordsFromDocument(text: string): string[] {
const { words = [] } = getInDocumentSettings(text);
return words;
}
export function getIgnoreWordsFromDocument(text: string): string[] {
const { ignoreWords = [] } = getInDocumentSettings(text);
return ignoreWords;
}
export function getIgnoreRegExpFromDocument(text: string): (string|RegExp)[] {
const { ignoreRegExpList = [] } = getInDocumentSettings(text);
return ignoreRegExpList;
}
/**
* These internal functions are used exposed for unit testing.
*/
export const internal = {
getPossibleInDocSettings,
getWordsFromDocument,
parseWords,
parseCompoundWords,
parseIgnoreRegExp,
parseIgnoreWords,
};