1'use strict'; 2 3const fs = require('fs'); 4const path = require('path'); 5 6// Create an object of all benchmark scripts 7const benchmarks = {}; 8fs.readdirSync(__dirname) 9 .filter((name) => { 10 return name !== 'fixtures' && 11 fs.statSync(path.resolve(__dirname, name)).isDirectory(); 12 }) 13 .forEach((category) => { 14 benchmarks[category] = fs.readdirSync(path.resolve(__dirname, category)) 15 .filter((filename) => filename[0] !== '.' && filename[0] !== '_'); 16 }); 17 18function CLI(usage, settings) { 19 if (process.argv.length < 3) { 20 this.abort(usage); // Abort will exit the process 21 } 22 23 this.usage = usage; 24 this.optional = {}; 25 this.items = []; 26 this.test = false; 27 28 for (const argName of settings.arrayArgs) { 29 this.optional[argName] = []; 30 } 31 32 let currentOptional = null; 33 let mode = 'both'; // Possible states are: [both, option, item] 34 35 for (const arg of process.argv.slice(2)) { 36 if (arg === '--') { 37 // Only items can follow -- 38 mode = 'item'; 39 } else if (mode === 'both' && arg[0] === '-') { 40 // Optional arguments declaration 41 42 if (arg[1] === '-') { 43 currentOptional = arg.slice(2); 44 } else { 45 currentOptional = arg.slice(1); 46 } 47 48 if (settings.boolArgs && settings.boolArgs.includes(currentOptional)) { 49 this.optional[currentOptional] = true; 50 mode = 'both'; 51 } else { 52 // Expect the next value to be option related (either -- or the value) 53 mode = 'option'; 54 } 55 } else if (mode === 'option') { 56 // Optional arguments value 57 58 if (settings.arrayArgs.includes(currentOptional)) { 59 this.optional[currentOptional].push(arg); 60 } else { 61 this.optional[currentOptional] = arg; 62 } 63 64 // The next value can be either an option or an item 65 mode = 'both'; 66 } else if (arg === 'test') { 67 this.test = true; 68 } else if (['both', 'item'].includes(mode)) { 69 // item arguments 70 this.items.push(arg); 71 72 // The next value must be an item 73 mode = 'item'; 74 } else { 75 // Bad case, abort 76 this.abort(usage); 77 } 78 } 79} 80module.exports = CLI; 81 82CLI.prototype.abort = function(msg) { 83 console.error(msg); 84 process.exit(1); 85}; 86 87CLI.prototype.benchmarks = function() { 88 const paths = []; 89 90 if (this.items.includes('all')) { 91 this.items = Object.keys(benchmarks); 92 } 93 94 for (const category of this.items) { 95 if (benchmarks[category] === undefined) { 96 console.error(`The "${category}" category does not exist.`); 97 process.exit(1); 98 } 99 for (const scripts of benchmarks[category]) { 100 if (this.shouldSkip(scripts)) continue; 101 102 paths.push(path.join(category, scripts)); 103 } 104 } 105 106 return paths; 107}; 108 109CLI.prototype.shouldSkip = function(scripts) { 110 const filters = this.optional.filter || []; 111 const excludes = this.optional.exclude || []; 112 let skip = filters.length > 0; 113 114 for (const filter of filters) { 115 if (scripts.lastIndexOf(filter) !== -1) { 116 skip = false; 117 } 118 } 119 120 for (const exclude of excludes) { 121 if (scripts.lastIndexOf(exclude) !== -1) { 122 skip = true; 123 } 124 } 125 126 return skip; 127}; 128