@cspell/cspell-tools
Version:
Tools to assist with the development of cSpell
109 lines • 3.2 kB
JavaScript
// cspell:ignore gimuxy
export const regExMatchRegExParts = /^\s*\/([\s\S]*?)\/([gimuxy]*)\s*$/;
export function stringToRegExp(pattern, defaultFlags = '', forceFlags = '') {
if (pattern instanceof RegExp) {
return pattern;
}
try {
const [, pat, flag] = [
...(pattern.match(regExMatchRegExParts) || ['', pattern.trim(), defaultFlags]),
forceFlags,
];
if (pat) {
const regPattern = flag.includes('x') ? removeVerboseFromRegExp(pat) : pat;
// Make sure the flags are unique.
const flags = [...new Set(forceFlags + flag)].join('').replaceAll(/[^gimuy]/g, '');
const regex = new RegExp(regPattern, flags);
return regex;
}
}
catch {
/* empty */
}
return undefined;
}
const SPACES = {
' ': true,
'\n': true,
'\r': true,
'\t': true,
};
/**
* Remove all whitespace and comments from a regexp string. The format follows Pythons Verbose.
* Note: this is a best attempt. Special cases for comments: `#` and spaces should be proceeded with a `\`
*
* All space must be proceeded by a `\` or in a character class `[]`
*
* @param pattern - the pattern to clean
*/
function removeVerboseFromRegExp(pattern) {
function escape(acc) {
const char = pattern[acc.idx];
if (char !== '\\')
return undefined;
const next = pattern[++acc.idx];
acc.idx++;
if (next === '#') {
acc.result += '#';
return acc;
}
if (!(next in SPACES)) {
acc.result += '\\' + next;
return acc;
}
acc.result += next;
if (next === '\r' && pattern[acc.idx] === '\n') {
acc.result += '\n';
acc.idx++;
}
return acc;
}
function braces(acc) {
const char = pattern[acc.idx];
if (char !== '[')
return undefined;
acc.result += char;
acc.idx++;
let escCount = 0;
while (acc.idx < pattern.length) {
const char = pattern[acc.idx];
acc.result += char;
acc.idx++;
if (char === ']' && !(escCount & 1))
break;
escCount = char === '\\' ? escCount + 1 : 0;
}
return acc;
}
function spaces(acc) {
const char = pattern[acc.idx];
if (!(char in SPACES))
return undefined;
acc.idx++;
return acc;
}
function comments(acc) {
const char = pattern[acc.idx];
if (char !== '#')
return undefined;
while (acc.idx < pattern.length && pattern[acc.idx] !== '\n') {
acc.idx++;
}
return acc;
}
function copy(acc) {
const char = pattern[acc.idx++];
acc.result += char;
return acc;
}
const reducers = [escape, braces, spaces, comments, copy];
const result = { idx: 0, result: '' };
while (result.idx < pattern.length) {
for (const r of reducers) {
if (r(result))
break;
}
}
return result.result;
}
//# sourceMappingURL=textRegex.js.map