blob: 514a90fd4086fce0d4d6767c63623937e6f3460a [file] [log] [blame]
var common = require('./common');
var fs = require('fs');
// parse out the number prefix of a line
function parseNumber (str) {
var match = str.match(/^\s*(\d*)\s*(.*)$/);
return {num: Number(match[1]), value: match[2]};
}
// compare two strings case-insensitively, but examine case for strings that are
// case-insensitive equivalent
function unixCmp(a, b) {
var aLower = a.toLowerCase();
var bLower = b.toLowerCase();
return (aLower === bLower ?
-1 * a.localeCompare(b) : // unix sort treats case opposite how javascript does
aLower.localeCompare(bLower));
}
// compare two strings in the fashion that unix sort's -n option works
function numericalCmp(a, b) {
var objA = parseNumber(a);
var objB = parseNumber(b);
if (objA.hasOwnProperty('num') && objB.hasOwnProperty('num')) {
return ((objA.num !== objB.num) ?
(objA.num - objB.num) :
unixCmp(objA.value, objB.value));
} else {
return unixCmp(objA.value, objB.value);
}
}
//@
//@ ### sort([options,] file [, file ...])
//@ ### sort([options,] file_array)
//@ Available options:
//@
//@ + `-r`: Reverse the result of comparisons
//@ + `-n`: Compare according to numerical value
//@
//@ Examples:
//@
//@ ```javascript
//@ sort('foo.txt', 'bar.txt');
//@ sort('-r', 'foo.txt');
//@ ```
//@
//@ Return the contents of the files, sorted line-by-line. Sorting multiple
//@ files mixes their content, just like unix sort does.
function _sort(options, files) {
options = common.parseOptions(options, {
'r': 'reverse',
'n': 'numerical'
});
// Check if this is coming from a pipe
var pipe = common.readFromPipe(this);
if (!files && !pipe)
common.error('no files given');
files = [].slice.call(arguments, 1);
if (pipe)
files.unshift('-');
var lines = [];
files.forEach(function(file) {
if (!fs.existsSync(file) && file !== '-') {
// exit upon any sort of error
common.error('no such file or directory: ' + file);
}
var contents = file === '-' ? pipe : fs.readFileSync(file, 'utf8');
lines = lines.concat(contents.trimRight().split(/\r*\n/));
});
var sorted;
sorted = lines.sort(options.numerical ? numericalCmp : unixCmp);
if (options.reverse)
sorted = sorted.reverse();
return new common.ShellString(sorted.join('\n')+'\n', common.state.error, common.state.errorCode);
}
module.exports = _sort;