UNPKG

file-prompt

Version:

An interactive prompt for selecting files from a directory.

264 lines (239 loc) 5.59 kB
/** * Map To Object * Creates an object out of a keys and values array pair * * @param {array} keys - Array of key values to use as properties * @param {array} values - Array of values to assign to the properties * @returns {object} A newly mapped object */ function mapToObject (keys, values) { let data = {}; keys.forEach((key, i) => { data[key] = values[i]; }); return data; } /** * Query * @class * @classdesc It represents search input for a menu option and has a static * method to take input with several comma or space separated * subqueries and turn that into an array of queries. */ export default class Query { query = null; data = {}; /** * Create From * Returns a list of separate queries * * @method * @static * @param {string} query - Raw query string * @returns {array} Array of sub queries */ static createFrom (query) { // Separates the query into all groupings of strings, numbers, ranges // sequences etc... then map them into query instances for testing. try { return query.split(/,| /g) .filter((subQuery) => { // No blanks. if (subQuery === '') { return false; } return true; }) // Map them sub queries .map((subQuery) => { return new Query(subQuery); }); } catch (e) { return []; } } /** * Extract Numbers * Returns an array of all the numbers in the given str * * @method * @public * @param {string} str - Original input string * @returns {array|object} Found numbers */ static extractNumbers (str) { return str.match(/[\d]+/g).map((numStr) => { return Number(numStr); }); } /** * Is Valid * Determines if a str is empty or not * * @method * @public * @param {string} str - Str to check validity of * @returns {boolean} True if query is a valid string */ static isValid (str) { return typeof str === 'string' && str.trim().length > 0; } /** * Constructor * Initializes the query interface * * @method * @public * @constructor * @param {string} query - The raw query string to parse & test with */ constructor (query) { this.rawQueryString = query; if (Query.isValid(query)) { this.query = String(query) .trim() .toLowerCase(); this.data = this.parse(); } } /** * Extract Numbers * An instance method to forward to the static method * * @method * @public * @returns {array} Array of Number() formatted numbers */ extractNumbers () { return Query.extractNumbers(this.query); } /** * Is * Determines if str matches the query * * @method * @public * @param {string} str - Input string to test against * @returns {boolean} If query is the option name */ is (str) { return str.toLowerCase() === this.query; } /** * Is Asterik * If user has input an asterik to select all options * * @method * @public * @returns {boolean} If query is a range */ isAsterik () { return this.query.length <= 2 && (/\*$/).test(this.query); } /** * Is Integer * Determiens if query is a integer or not * * @method * @public * @returns {boolean} If str is an integer */ isInteger () { return Number.isInteger(Number(this.query)); } /** * Is Start Of * Determines if option name startsWith the query * * @param {string} str - String to test against * @returns {boolean} If query starts with the str */ isStartOf (str) { return str.toLowerCase().startsWith(this.data.value); } /** * Is Integer * Determiens if query is a insteger or not * * @method * @public * @returns {boolean} If query is a range */ isRange () { return (/[\d]+[\s]*-[\s]*[\d]/g).test(this.query); } /** * Is Valid * Determines if a str is empty or not * * @method * @public * @returns {boolean} True if query is a valid string */ isValid () { return Query.isValid(this.query); } /** * Parse * Determine what type of query we are dealing with and what to do * * @method * @public * @returns {object} An action this query should take */ parse () { let data = { action: 'select', }, query = this.query; // If this is a query to remove something, mark that and remove the // negative sign if (this.query.slice(0, 1) === '-') { data.action = 'unselect'; query = this.query.slice(1); } // It's a range of integers so you know... do that. if (this.isRange()) { data.type = 'range'; data.value = mapToObject(['min', 'max'], Query.extractNumbers(query)); } // It's an integer so lets check for menu option ids else if (this.isInteger()) { data.type = 'id'; data.value = Number(query); } else if (this.isAsterik()) { data.type = 'all'; } // Guess you're a string then huh? else { data.type = 'string'; data.value = query; } data.query = this.rawQueryString; return data; } /** * Raw Query * Returns a copy of the raw query string * * @method * @public * @returns {string} Raw query string */ rawQuery () { return String(this.rawQueryString); } /** * To String * Returns the query string * * @method * @public * @returns {string} Original query string */ toString () { return this.query; } }