(configText, shouldLogWarnings)
| 65 | // - shouldLogWarnings: if true, logs to the console when part of the user's config is invalid. |
| 66 | // Returns { keyToRegistryEntry, keyToMappedKey, validationErrors }. |
| 67 | parse(configText, shouldLogWarnings) { |
| 68 | let keyToRegistryEntry = {}; |
| 69 | let mapKeyRegistry = {}; |
| 70 | let errors = []; |
| 71 | const configLines = parseLines(configText); |
| 72 | const commandsByName = Utils.keyBy(allCommands, "name"); |
| 73 | |
| 74 | const validModifiers = ["a", "c", "m", "s"]; |
| 75 | const validateParsedKey = function (key) { |
| 76 | if (!key?.match(modifiedKey)) return; |
| 77 | // Check that the modifier is valid and not capitalized. |
| 78 | const mod = key.split("-")[0].slice(1); |
| 79 | if (!validModifiers.includes(mod)) { |
| 80 | return `${key} has an invalid modifier; valid modifiers are ${validModifiers}`; |
| 81 | } |
| 82 | }; |
| 83 | const validateUrl = function (str) { |
| 84 | try { |
| 85 | new URL(str); |
| 86 | return true; |
| 87 | } catch { |
| 88 | return false; |
| 89 | } |
| 90 | }; |
| 91 | |
| 92 | for (const line of configLines) { |
| 93 | const tokens = line.split(/\s+/); |
| 94 | const action = tokens[0].toLowerCase(); |
| 95 | switch (action) { |
| 96 | case "map": { |
| 97 | if (tokens.length < 3) { |
| 98 | errors.push(`"map requires at least 2 arguments on line ${line}`); |
| 99 | continue; |
| 100 | } |
| 101 | const [_, key, command] = tokens; |
| 102 | let optionString; |
| 103 | const optionsStart = nthRegexIndex(line, /\s+/, 3); |
| 104 | if (optionsStart == -1) { |
| 105 | optionString = ""; |
| 106 | } else { |
| 107 | optionString = line.slice(optionsStart).trim(); |
| 108 | } |
| 109 | const commandInfo = commandsByName[command]; |
| 110 | if (!commandInfo) { |
| 111 | errors.push(`"${command}" is not a valid command in the line: ${line}`); |
| 112 | continue; |
| 113 | } |
| 114 | const keySequence = this.parseKeySequence(key); |
| 115 | const keyErrors = keySequence.map((k) => validateParsedKey(k)).filter((e) => e); |
| 116 | if (keyErrors.length > 0) { |
| 117 | errors = errors.concat(keyErrors); |
| 118 | continue; |
| 119 | } |
| 120 | const options = this.parseCommandOptions(optionString); |
| 121 | const allowedOptions = Object.keys(commandInfo.options || {}); |
| 122 | if (!commandInfo.noRepeat) { |
| 123 | allowedOptions.push("count"); |
| 124 | } |
nothing calls this directly
no test coverage detected