UNPKG

2.56 kBJavaScriptView Raw
1var common = require('./common');
2var fs = require('fs');
3
4common.register('sort', _sort, {
5 canReceivePipe: true,
6 cmdOptions: {
7 'r': 'reverse',
8 'n': 'numerical',
9 },
10});
11
12// parse out the number prefix of a line
13function parseNumber(str) {
14 var match = str.match(/^\s*(\d*)\s*(.*)$/);
15 return { num: Number(match[1]), value: match[2] };
16}
17
18// compare two strings case-insensitively, but examine case for strings that are
19// case-insensitive equivalent
20function unixCmp(a, b) {
21 var aLower = a.toLowerCase();
22 var bLower = b.toLowerCase();
23 return (aLower === bLower ?
24 -1 * a.localeCompare(b) : // unix sort treats case opposite how javascript does
25 aLower.localeCompare(bLower));
26}
27
28// compare two strings in the fashion that unix sort's -n option works
29function numericalCmp(a, b) {
30 var objA = parseNumber(a);
31 var objB = parseNumber(b);
32 if (objA.hasOwnProperty('num') && objB.hasOwnProperty('num')) {
33 return ((objA.num !== objB.num) ?
34 (objA.num - objB.num) :
35 unixCmp(objA.value, objB.value));
36 } else {
37 return unixCmp(objA.value, objB.value);
38 }
39}
40
41//@
42//@ ### sort([options,] file [, file ...])
43//@ ### sort([options,] file_array)
44//@
45//@ Available options:
46//@
47//@ + `-r`: Reverse the results
48//@ + `-n`: Compare according to numerical value
49//@
50//@ Examples:
51//@
52//@ ```javascript
53//@ sort('foo.txt', 'bar.txt');
54//@ sort('-r', 'foo.txt');
55//@ ```
56//@
57//@ Return the contents of the `file`s, sorted line-by-line. Sorting multiple
58//@ files mixes their content (just as unix `sort` does).
59function _sort(options, files) {
60 // Check if this is coming from a pipe
61 var pipe = common.readFromPipe();
62
63 if (!files && !pipe) common.error('no files given');
64
65 files = [].slice.call(arguments, 1);
66
67 if (pipe) {
68 files.unshift('-');
69 }
70
71 var lines = files.reduce(function (accum, file) {
72 if (file !== '-') {
73 if (!fs.existsSync(file)) {
74 common.error('no such file or directory: ' + file, { continue: true });
75 return accum;
76 } else if (common.statFollowLinks(file).isDirectory()) {
77 common.error('read failed: ' + file + ': Is a directory', {
78 continue: true,
79 });
80 return accum;
81 }
82 }
83
84 var contents = file === '-' ? pipe : fs.readFileSync(file, 'utf8');
85 return accum.concat(contents.trimRight().split('\n'));
86 }, []);
87
88 var sorted = lines.sort(options.numerical ? numericalCmp : unixCmp);
89
90 if (options.reverse) {
91 sorted = sorted.reverse();
92 }
93
94 return sorted.join('\n') + '\n';
95}
96
97module.exports = _sort;