Utility Methods
This commit is contained in:
parent
bdd72b0037
commit
b8e194e743
1 changed files with 204 additions and 147 deletions
|
@ -25,6 +25,7 @@ var
|
|||
mask: '*',
|
||||
limit: [],
|
||||
limitMessage: 'Input another, please.${( [)limit(])}',
|
||||
defaultInput: '',
|
||||
trueValue: [],
|
||||
falseValue: [],
|
||||
caseSensitive: false,
|
||||
|
@ -32,7 +33,9 @@ var
|
|||
encoding: 'utf8',
|
||||
bufferSize: 1024,
|
||||
print: void 0,
|
||||
history: true
|
||||
history: true,
|
||||
cd: false,
|
||||
phContent: void 0
|
||||
},
|
||||
|
||||
fdR = 'none', fdW, ttyR, isRawMode = false,
|
||||
|
@ -448,15 +451,16 @@ function margeOptions() {
|
|||
if (!optionsPart.hasOwnProperty(optionName)) { return; }
|
||||
value = optionsPart[optionName];
|
||||
switch (optionName) {
|
||||
// _readlineSync defaultOptions
|
||||
// _readlineSync <- * * -> defaultOptions
|
||||
// ================ string
|
||||
case 'mask': // * *
|
||||
case 'limitMessage': // *
|
||||
case 'defaultInput': // *
|
||||
case 'encoding': // * *
|
||||
/* jshint eqnull:true */
|
||||
value = value != null ? value + '' : '';
|
||||
/* jshint eqnull:false */
|
||||
if (value && optionName === 'mask' || optionName === 'encoding')
|
||||
if (value && optionName !== 'limitMessage')
|
||||
{ value = value.replace(/[\r\n]/g, ''); }
|
||||
options[optionName] = value;
|
||||
break;
|
||||
|
@ -472,6 +476,7 @@ function margeOptions() {
|
|||
case 'caseSensitive': // * *
|
||||
case 'keepWhitespace': // * *
|
||||
case 'history': // *
|
||||
case 'cd': // *
|
||||
options[optionName] = !!value;
|
||||
break;
|
||||
// ================ array
|
||||
|
@ -488,6 +493,7 @@ function margeOptions() {
|
|||
break;
|
||||
// ================ function
|
||||
case 'print': // * *
|
||||
case 'phContent': // *
|
||||
options[optionName] = typeof value === 'function' ? value : void 0;
|
||||
break;
|
||||
// ================ other
|
||||
|
@ -539,7 +545,7 @@ function array2charlist(array, caseSensitive, collectSymbols) {
|
|||
{ return chars.concat((value + '').split('')); }, [])
|
||||
.reduce(function(groups, curChar) {
|
||||
var curGroupClass, curCharCode;
|
||||
if (!caseSensitive) { curChar = curChar.toUpperCase(); }
|
||||
if (!caseSensitive) { curChar = curChar.toLowerCase(); }
|
||||
curGroupClass = /^\d$/.test(curChar) ? 1 :
|
||||
/^[A-Z]$/.test(curChar) ? 2 : /^[a-z]$/.test(curChar) ? 3 : 0;
|
||||
if (collectSymbols && curGroupClass === 0) {
|
||||
|
@ -567,22 +573,30 @@ function joinChunks(chunks, suppressed)
|
|||
{ return chunks.join(chunks.length > 2 ? ', ' : suppressed ? ' / ' : '/'); }
|
||||
|
||||
function getPhContent(param, options) {
|
||||
var text, values, resCharlist = {}, arg;
|
||||
var text, values, resCharlist = {}, path, arg;
|
||||
if (options.phContent) {
|
||||
text = options.phContent(param, options);
|
||||
}
|
||||
if (typeof text !== 'string') {
|
||||
switch (param) {
|
||||
case 'hideEchoBack':
|
||||
case 'mask':
|
||||
case 'defaultInput':
|
||||
case 'caseSensitive':
|
||||
case 'keepWhitespace':
|
||||
case 'encoding':
|
||||
case 'bufferSize':
|
||||
case 'history':
|
||||
text = options.hasOwnProperty(param) ? options[param] + '' : '';
|
||||
break;
|
||||
case 'prompt':
|
||||
case 'query':
|
||||
case 'display':
|
||||
text = options.displaySrc + '';
|
||||
case 'cd':
|
||||
text = !options.hasOwnProperty(param) ? '' :
|
||||
typeof options[param] === 'boolean' ? (options[param] ? 'on' : 'off') :
|
||||
options[param] + '';
|
||||
break;
|
||||
// case 'prompt':
|
||||
// case 'query':
|
||||
// case 'display':
|
||||
// text = options.hasOwnProperty('displaySrc') ? options.displaySrc + '' : '';
|
||||
// break;
|
||||
case 'limit':
|
||||
case 'trueValue':
|
||||
case 'falseValue':
|
||||
|
@ -600,7 +614,8 @@ function getPhContent(param, options) {
|
|||
break;
|
||||
case 'limitCount':
|
||||
case 'limitCountNotZero':
|
||||
text = options[options.hasOwnProperty('limitSrc') ? 'limitSrc' : 'limit'].length;
|
||||
text = options[options.hasOwnProperty('limitSrc') ?
|
||||
'limitSrc' : 'limit'].length;
|
||||
text = text || param !== 'limitCountNotZero' ? text + '' : '';
|
||||
break;
|
||||
case 'lastInput':
|
||||
|
@ -608,14 +623,31 @@ function getPhContent(param, options) {
|
|||
break;
|
||||
case 'cwd':
|
||||
case 'CWD':
|
||||
case 'cwdHome':
|
||||
text = process.cwd();
|
||||
if (param === 'CWD') { text = require('path').basename(text); }
|
||||
else if (param === 'cwdHome') {
|
||||
path = (IS_WIN ? ((process.env.HOMEDRIVE || '') +
|
||||
(process.env.HOMEPATH || '')).toLowerCase() :
|
||||
process.env.HOME || '').replace(/[\/\\]+$/, '');
|
||||
if (path && (IS_WIN ? text.toLowerCase() : text).indexOf(path) === 0)
|
||||
{ text = '~' + text.substr(path.length); }
|
||||
}
|
||||
break;
|
||||
case 'date':
|
||||
case 'time':
|
||||
case 'localeDate':
|
||||
case 'localeTime':
|
||||
text = (new Date())['to' +
|
||||
param.replace(/^./, function(str) { return str.toUpperCase(); }) +
|
||||
'String']();
|
||||
break;
|
||||
default: // with arg
|
||||
if (typeof(arg = (param.match(/^history_m(\d+)$/) || [])[1]) === 'string') {
|
||||
text = inputHistory[inputHistory.length - arg] || '';
|
||||
}
|
||||
}
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
|
@ -630,7 +662,7 @@ function getPhCharlist(param) {
|
|||
return text;
|
||||
}
|
||||
|
||||
function readlineWithOptions(options, preCheck) {
|
||||
function getValidLine(options, preCheck) {
|
||||
var res, forceNext, resCheck, limitMessage,
|
||||
matches, histInput;
|
||||
function _getPhContent(param) { return getPhContent(param, options); }
|
||||
|
@ -706,11 +738,11 @@ exports.setDefault = function(options) {
|
|||
exports.prompt = function(options) {
|
||||
var readOptions = margeOptions(true, options);
|
||||
readOptions.display = readOptions.prompt;
|
||||
return readlineWithOptions(readOptions);
|
||||
return getValidLine(readOptions);
|
||||
};
|
||||
|
||||
exports.question = function(query, options) {
|
||||
return readlineWithOptions(margeOptions(margeOptions(true, options), {
|
||||
return getValidLine(margeOptions(margeOptions(true, options), {
|
||||
display: query
|
||||
}));
|
||||
};
|
||||
|
@ -767,6 +799,7 @@ exports.questionEMail = function(query, options) {
|
|||
}, options, {
|
||||
// -------- forced
|
||||
keepWhitespace: false,
|
||||
cd: false
|
||||
}));
|
||||
};
|
||||
|
||||
|
@ -780,159 +813,183 @@ exports.questionNewPassword = function(query, options) {
|
|||
trueValue: null,
|
||||
falseValue: null,
|
||||
caseSensitive: true
|
||||
}, options),
|
||||
// forced: limit
|
||||
// added: charlist, min, max, confirm
|
||||
charlist, min, max, confirm, resCharlist, res1, res2, limit1, limitMessage1;
|
||||
|
||||
function phSpecial(param) {
|
||||
}, options, {
|
||||
// -------- forced
|
||||
history: false,
|
||||
cd: false,
|
||||
// limit (by charlist etc.),
|
||||
phContent: function(param) {
|
||||
return param === 'charlist' ? resCharlist.text :
|
||||
param === 'length' ? min + '...' + max : null;
|
||||
}
|
||||
}),
|
||||
// added: charlist, min, max, confirm
|
||||
charlist, min, max, confirm, limit, resCharlist, limitMessage, res1, res2;
|
||||
|
||||
// bug? `eqnull:true` doesn't work
|
||||
/* jshint ignore:start */
|
||||
if (query == null) { query = 'Input new password :'; }
|
||||
/* jshint ignore:end */
|
||||
|
||||
charlist = options && options.charlist ? options.charlist + '' : '${!-~}';
|
||||
charlist = replacePlaceholder(charlist, getPhCharlist);
|
||||
charlist = replacePlaceholder(
|
||||
options && options.charlist ? options.charlist + '' : '${!-~}', getPhCharlist);
|
||||
if (options) { min = options.min; max = options.max; }
|
||||
if (isNaN(min = parseInt(min, 10)) || typeof min !== 'number') { min = 12; }
|
||||
if (isNaN(max = parseInt(max, 10)) || typeof max !== 'number') { max = 24; }
|
||||
limit = new RegExp('^[' + charlist.replace(/[^A-Za-z0-9_ ]/g, '\\$&') +
|
||||
']{' + min + ',' + max + '}$');
|
||||
resCharlist = array2charlist([charlist], readOptions.caseSensitive, true);
|
||||
resCharlist.text = joinChunks(resCharlist.values, resCharlist.suppressed);
|
||||
|
||||
/* jshint eqnull:true */
|
||||
confirm = options && options.confirm != null ? options.confirm :
|
||||
'Reinput same one to confirm it :';
|
||||
/* jshint eqnull:false */
|
||||
|
||||
limit1 = new RegExp('^[' + charlist.replace(/[^A-Za-z0-9_ ]/g, '\\$&') +
|
||||
']{' + min + ',' + max + '}$');
|
||||
|
||||
if (readOptions.limitMessage) {
|
||||
resCharlist = array2charlist([charlist], readOptions.caseSensitive, true);
|
||||
resCharlist.text = joinChunks(resCharlist.values, resCharlist.suppressed);
|
||||
// getPhContent is called by readlineWithOptions
|
||||
limitMessage1 = replacePlaceholder(readOptions.limitMessage, phSpecial);
|
||||
}
|
||||
/* jshint eqnull:true */
|
||||
if (query == null) { query = 'Input new password :'; }
|
||||
/* jshint eqnull:false */
|
||||
|
||||
limitMessage = readOptions.limitMessage;
|
||||
while (!res2) {
|
||||
readOptions.limit = limit1;
|
||||
readOptions.limitMessage = limitMessage1;
|
||||
readOptions.limit = limit;
|
||||
readOptions.limitMessage = limitMessage;
|
||||
res1 = exports.question(query, readOptions);
|
||||
|
||||
readOptions.limit = [res1, ''];
|
||||
readOptions.limitMessage = 'Two passwords don\'t match.' +
|
||||
' Hit only Enter key if you want to retry from first password.';
|
||||
// getPhContent is called by readlineWithOptions
|
||||
res2 = exports.question(replacePlaceholder(confirm, phSpecial), readOptions);
|
||||
res2 = exports.question(confirm, readOptions);
|
||||
}
|
||||
|
||||
return res1;
|
||||
};
|
||||
|
||||
function _questionParse(query, options, fncParse) {
|
||||
function _questionNum(query, options, parser) {
|
||||
var validValue;
|
||||
function getValidValue(value) {
|
||||
validValue = fncParse(value);
|
||||
validValue = parser(value);
|
||||
return !isNaN(validValue) && typeof validValue === 'number';
|
||||
}
|
||||
exports.question(query, margeOptions(options, {
|
||||
exports.question(query, margeOptions({
|
||||
// -------- default
|
||||
limitMessage: 'Input valid number, please.'
|
||||
}, options, {
|
||||
// -------- forced
|
||||
limit: getValidValue
|
||||
limit: getValidValue,
|
||||
cd: false
|
||||
// trueValue, falseValue are don't work.
|
||||
}));
|
||||
return validValue;
|
||||
}
|
||||
exports.questionInt = function(query, options) {
|
||||
return _questionParse(query, options, function(value) { return parseInt(value, 10); });
|
||||
return _questionNum(query, options, function(value) { return parseInt(value, 10); });
|
||||
};
|
||||
exports.questionFloat = function(query, options) {
|
||||
return _questionNum(query, options, parseFloat);
|
||||
};
|
||||
exports.questionFloat = function(query, options)
|
||||
{ return _questionParse(query, options, parseFloat); };
|
||||
|
||||
exports.questionPath = function(query, options) {
|
||||
var fs = require('fs'), validPath;
|
||||
function getValidPath(value) {
|
||||
var readOptions = margeOptions({
|
||||
// -------- default
|
||||
limitMessage: 'Input valid path, please.${( Min:)minSize}${( Max:)maxSize}',
|
||||
history: true,
|
||||
cd: true
|
||||
}, options, {
|
||||
// -------- forced
|
||||
keepWhitespace: false,
|
||||
limit: function(value) {
|
||||
var stat;
|
||||
if (!fs.existsSync(value)) { return; }
|
||||
validPath = fs.realpathSync(value);
|
||||
if (options.minSize || options.maxSize || options.isFile || options.isDirectory) {
|
||||
if (options) {
|
||||
if (options.minSize || options.maxSize ||
|
||||
options.isFile || options.isDirectory) {
|
||||
stat = fs.statSync(validPath);
|
||||
if (options.minSize && stat.size < +options.minSize ||
|
||||
options.maxSize && stat.size > +options.maxSize ||
|
||||
options.isFile && !stat.isFile() ||
|
||||
options.isDirectory && !stat.isDirectory()) { return false; }
|
||||
options.isDirectory && !stat.isDirectory()) { return; }
|
||||
}
|
||||
if (typeof options.validate === 'function' && !options.validate(validPath))
|
||||
{ return false; }
|
||||
return true;
|
||||
{ return; }
|
||||
}
|
||||
exports.question(query, margeOptions(options, {
|
||||
// -------- forced
|
||||
limit: getValidPath
|
||||
return true;
|
||||
},
|
||||
// trueValue, falseValue are don't work.
|
||||
}));
|
||||
phContent: function(param) {
|
||||
return param !== 'minSize' && param !== 'maxSize' ? null :
|
||||
options && options.hasOwnProperty(param) ? options[param] + '' : '';
|
||||
}
|
||||
}),
|
||||
// added: minSize, maxSize, isFile, isDirectory, validate
|
||||
validPath;
|
||||
|
||||
/* jshint eqnull:true */
|
||||
if (query == null) { query = 'Input path (you can "cd" and "pwd") :'; }
|
||||
/* jshint eqnull:false */
|
||||
|
||||
exports.question(query, readOptions);
|
||||
return validPath;
|
||||
};
|
||||
|
||||
exports.promptCWD = function(options) {
|
||||
var readOptions = margeOptions({
|
||||
exports.promptSimShell = function(options) {
|
||||
return exports.prompt(margeOptions({
|
||||
// -------- default
|
||||
prompt: '[${cwd}]$ '
|
||||
}, options);
|
||||
return exports.prompt(readOptions);
|
||||
history: true
|
||||
}, options, {
|
||||
// -------- forced
|
||||
prompt: (function() {
|
||||
return IS_WIN ?
|
||||
'${cwd}>' :
|
||||
// 'user@host:cwd$ '
|
||||
(process.env.USER || '') +
|
||||
(process.env.HOSTNAME ?
|
||||
'@' + process.env.HOSTNAME.replace(/\..*$/, '') : '') +
|
||||
':${cwdHome}$ ';
|
||||
})()
|
||||
}));
|
||||
};
|
||||
|
||||
function _keyInYN(query, options, limit) {
|
||||
var readOptions = margeOptions(options, {
|
||||
// -------- forced
|
||||
hideEchoBack: false,
|
||||
limit: limit,
|
||||
trueValue: 'y',
|
||||
falseValue: 'n',
|
||||
caseSensitive: false
|
||||
}), res;
|
||||
|
||||
exports.keyInYN = function(query, options) {
|
||||
var res;
|
||||
/* jshint eqnull:true */
|
||||
if (query == null) { query = 'Are you sure? :'; }
|
||||
/* jshint eqnull:false */
|
||||
if ((query += '') && options.guide !== false)
|
||||
{ query = query.replace(/\s*:?\s*$/, '') + ' [Y/N] :'; }
|
||||
|
||||
res = exports.keyIn(query, readOptions);
|
||||
if ((!options || options.guide !== false) && (query += ''))
|
||||
{ query = query.replace(/\s*:?\s*$/, '') + ' [y/n] :'; }
|
||||
res = exports.keyIn(query, margeOptions(options, {
|
||||
// -------- forced
|
||||
hideEchoBack: false,
|
||||
limit: options && options.strict ? 'yn' : null,
|
||||
trueValue: 'y',
|
||||
falseValue: 'n',
|
||||
caseSensitive: false
|
||||
}));
|
||||
return typeof res === 'boolean' ? res : '';
|
||||
}
|
||||
exports.keyInYN = function(query, options) { return _keyInYN(query, options); };
|
||||
exports.keyInYNStrict = function(query, options)
|
||||
{ return _keyInYN(query, options, 'yn'); };
|
||||
};
|
||||
|
||||
exports.keyInPause = function(query, options) {
|
||||
var readOptions = margeOptions(options, {
|
||||
// -------- forced
|
||||
hideEchoBack: true,
|
||||
mask: ''
|
||||
});
|
||||
|
||||
/* jshint eqnull:true */
|
||||
if (query == null) { query = 'Continue...'; }
|
||||
/* jshint eqnull:false */
|
||||
if ((query += '') && options.guide !== false)
|
||||
if ((!options || options.guide !== false) && (query += ''))
|
||||
{ query = query.replace(/\s+$/, '') + ' (Hit any key)'; }
|
||||
|
||||
exports.keyIn(query, readOptions);
|
||||
exports.keyIn(query, margeOptions(options, {
|
||||
// -------- forced
|
||||
hideEchoBack: true,
|
||||
mask: ''
|
||||
}));
|
||||
return;
|
||||
};
|
||||
|
||||
exports.keyInSelect = function(query, items, options) {
|
||||
var readOptions = margeOptions({
|
||||
// -------- default
|
||||
hideEchoBack: false,
|
||||
hideEchoBack: false
|
||||
}, options, {
|
||||
// -------- forced
|
||||
trueValue: null,
|
||||
falseValue: null,
|
||||
caseSensitive: false
|
||||
}), keylist = '', key2i = {}, charCode = 49 /* '1' */, display = '\n';
|
||||
// limit (by items)
|
||||
}),
|
||||
keylist = '', key2i = {}, charCode = 49 /* '1' */, display = '\n';
|
||||
if (!Array.isArray(items) || items.length > 35)
|
||||
{ throw '`items` must be Array (max length: 35).'; }
|
||||
|
||||
|
@ -941,9 +998,9 @@ exports.keyInSelect = function(query, items, options) {
|
|||
keylist += key;
|
||||
key2i[key] = i;
|
||||
display += '[' + key + '] ' + item.trim() + '\n';
|
||||
charCode = charCode === 57 /* '9' */ ? 65 /* 'A' */ : charCode + 1;
|
||||
charCode = charCode === 57 /* '9' */ ? 97 /* 'a' */ : charCode + 1;
|
||||
});
|
||||
if (options.cancel !== false) {
|
||||
if (!options || options.cancel !== false) {
|
||||
keylist += '0';
|
||||
key2i['0'] = -1;
|
||||
display += '[' + '0' + '] CANCEL\n';
|
||||
|
@ -955,12 +1012,12 @@ exports.keyInSelect = function(query, items, options) {
|
|||
if (query == null) { query = 'Choose one from list :'; }
|
||||
/* jshint eqnull:false */
|
||||
if ((query += '')) {
|
||||
if (options.guide !== false)
|
||||
if (!options || options.guide !== false)
|
||||
{ query = query.replace(/\s*:?\s*$/, '') + ' [${limit}] :'; }
|
||||
display += query;
|
||||
}
|
||||
|
||||
return key2i[exports.keyIn(display, readOptions).toUpperCase()];
|
||||
return key2i[exports.keyIn(display, readOptions).toLowerCase()];
|
||||
};
|
||||
|
||||
// ======== DEPRECATED ========
|
||||
|
|
Loading…
Reference in a new issue