UNPKG

@eagleoutice/flowr-dev

Version:

Static Dataflow Analyzer and Program Slicer for the R Programming Language

141 lines 4.63 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.startAndEndsWith = startAndEndsWith; exports.isSubsequence = isSubsequence; exports.matchByPrefixOrSubsequence = matchByPrefixOrSubsequence; exports.withoutWhitespace = withoutWhitespace; exports.longestCommonPrefix = longestCommonPrefix; exports.joinWithLast = joinWithLast; exports.isUrl = isUrl; exports.fileUrlToPath = fileUrlToPath; exports.isAbsolutePath = isAbsolutePath; exports.dropRawStringSurround = dropRawStringSurround; const path_1 = __importDefault(require("path")); const url_1 = require("url"); /** * Check if the given string starts and ends with the given letter */ function startAndEndsWith(str, letter) { return str.startsWith(letter) && str.endsWith(letter); } /** * Whether every character of `needle` appears in `hay` in order (a subsequence / fuzzy match). */ function isSubsequence(needle, hay) { if (needle.length === 0) { return true; } let i = 0; for (const c of hay) { if (c === needle[i] && ++i === needle.length) { return true; } } return false; } /** * The `candidates` that start with `needle`, or -- if none do -- those that contain it as a * {@link isSubsequence|subsequence} (case-insensitive). `needle` itself is never returned. */ function matchByPrefixOrSubsequence(candidates, needle) { const prefixed = candidates.filter(c => c.startsWith(needle) && c !== needle); if (prefixed.length > 0) { return prefixed; } const lower = needle.toLowerCase(); return candidates.filter(c => c !== needle && isSubsequence(lower, c.toLowerCase())); } /** * Removes all whitespace in the given string */ function withoutWhitespace(output) { return output.replace(/\s/g, ''); } /** * Find the longest common prefix in an array of strings */ function longestCommonPrefix(strings) { if (strings.length === 0) { return ''; } let prefix = strings[0]; for (const str of strings) { if (prefix.length === 0) { break; } let i = 0; while (i < prefix.length && prefix[i] === str[i]) { i++; } if (i !== prefix.length) { prefix = prefix.slice(0, i); } } return prefix; } /** * Join a list of strings, but with special handling for the last element/scenarios in which the array contains exactly two elements. * The goal is to create (partial) sentences like `a, b, and c` or `a and b`. */ function joinWithLast(strs, { join = ', ', last = ', and ', joinTwo = ' and ' } = {}) { if (strs.length <= 1) { return strs.join(''); } else if (strs.length === 2) { return strs.join(joinTwo); } return strs.slice(0, -1).join(join) + last + strs[strs.length - 1]; } const UrlPattern = /^(https?|ftps?|s3|gs):\/\//i; /** Check if the given string looks like a remote URL (http/https/ftp/ftps/s3/gs). */ function isUrl(p) { return UrlPattern.test(p); } /** * If `s` is a `file://` URI, return the local filesystem path it refers to. * Returns `undefined` for any other string. */ function fileUrlToPath(s) { if (!s.startsWith('file://')) { return undefined; } try { return (0, url_1.fileURLToPath)(s); } catch { return undefined; } } /** * Check if the given path is an absolute path. */ function isAbsolutePath(p, regex) { return regex?.test(p) || p.startsWith('/') || p.startsWith('\\') || /[a-zA-Z]:[\\/]/.test(p) || // Windows absolute path path_1.default.normalize(p + '/') === path_1.default.normalize(path_1.default.resolve(p) + '/'); } const CorrespondingClose = { '(': ')', '[': ']', '{': '}' }; /** collect '-' at the start until '[' or '(' is reached, then drop the same from the end if present otherwise return the value as is */ function dropRawStringSurround(value) { const dashCount = value.match(/^-*/)?.[0].length ?? 0; const open = value[dashCount]; if (open === '[' || open === '(' || open === '{') { // if the value starts with a dash and then a bracket, we drop the dashes at the end const end = value.endsWith(CorrespondingClose[open] + '-'.repeat(dashCount)) ? dashCount : undefined; if (end !== undefined) { return value.slice(dashCount + 1, -end - 1); } else { return value; } } return value; } //# sourceMappingURL=strings.js.map