UNPKG

hana-cli

Version:
125 lines (105 loc) 4.49 kB
// @ts-check /** * @module commandSuggestions * Utility for suggesting similar commands when user enters an invalid command */ import didYouMean, { ReturnTypeEnums, ThresholdTypeEnums } from 'didyoumean2' import { commandMap } from '../bin/commandMap.js' /** * Get unique command names (excluding duplicates/aliases) * @returns {string[]} Array of unique command names */ function getUniqueCommands() { const seen = new Set() const uniqueCommands = [] for (const [command, file] of Object.entries(commandMap)) { // Take the first occurrence of each file (usually the main command name) if (!seen.has(file)) { seen.add(file) uniqueCommands.push(command) } } return uniqueCommands.sort() } /** * Find similar commands based on user input * @param {string} input - The invalid command entered by the user * @param {number} [threshold=0.4] - Similarity threshold (0-1), lower = more strict * @param {number} [maxSuggestions=3] - Maximum number of suggestions to return * @returns {string[]} Array of suggested command names */ export function getSimilarCommands(input, threshold = 0.4, maxSuggestions = 3) { if (!input || typeof input !== 'string') { return [] } // Get all available commands (both main commands and aliases) const allCommands = Object.keys(commandMap) // Get suggestions using didyoumean2 // @ts-ignore - TypeScript has trouble with the options object type const suggestions = didYouMean(input, allCommands, { threshold: threshold, thresholdType: ThresholdTypeEnums.SIMILARITY, returnType: ReturnTypeEnums.ALL_CLOSEST_MATCHES, caseSensitive: false, trimSpaces: true }) // Return up to maxSuggestions (didyoumean2 returns string[] with ALL_CLOSEST_MATCHES) return suggestions.slice(0, maxSuggestions) } /** * Get a formatted suggestion message for display to user * @param {string} invalidCommand - The invalid command entered * @param {object} bundle - The i18n text bundle for translations * @returns {string} Formatted message with suggestions, or empty string if no suggestions */ export function getSuggestionMessage(invalidCommand, bundle) { const suggestions = getSimilarCommands(invalidCommand) if (suggestions.length === 0) { return '' } if (suggestions.length === 1) { return bundle.getText("didYouMeanSingle", [suggestions[0]]) } return bundle.getText("didYouMeanMultiple", [suggestions.join('\n ')]) } /** * Find similar option names based on user input * @param {string} input - The invalid option entered by the user * @param {string[]} availableOptions - List of valid option names to match against * @param {number} [threshold=0.4] - Similarity threshold (0-1), lower = more strict * @param {number} [maxSuggestions=3] - Maximum number of suggestions to return * @returns {string[]} Array of suggested option names */ export function getSimilarOptions(input, availableOptions, threshold = 0.4, maxSuggestions = 3) { if (!input || typeof input !== 'string' || !availableOptions || availableOptions.length === 0) { return [] } // Get suggestions using didyoumean2 // @ts-ignore - TypeScript has trouble with the options object type const suggestions = didYouMean(input, availableOptions, { threshold: threshold, thresholdType: ThresholdTypeEnums.SIMILARITY, returnType: ReturnTypeEnums.ALL_CLOSEST_MATCHES, caseSensitive: false, trimSpaces: true }) // Return up to maxSuggestions return suggestions.slice(0, maxSuggestions) } /** * Get a formatted suggestion message for an invalid option * @param {string} invalidOption - The invalid option name * @param {string[]} availableOptions - List of valid option names * @param {object} bundle - The i18n text bundle for translations * @returns {string} Formatted message with suggestions, or empty string if no suggestions */ export function getOptionSuggestionMessage(invalidOption, availableOptions, bundle) { const suggestions = getSimilarOptions(invalidOption, availableOptions) if (suggestions.length === 0) { return '' } if (suggestions.length === 1) { return bundle.getText("didYouMeanOption", [suggestions[0]]) } return bundle.getText("didYouMeanMultipleOptions", [suggestions.join('\n ')]) }