Blame view

node_modules/shelljs/src/sort.js 2.49 KB
aaac7fed   liuqimichale   add
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
  var common = require('./common');
  var fs = require('fs');
  
  common.register('sort', _sort, {
    canReceivePipe: true,
    cmdOptions: {
      'r': 'reverse',
      'n': 'numerical',
    },
  });
  
  // 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) {
    // Check if this is coming from a pipe
    var pipe = common.readFromPipe();
  
    if (!files && !pipe) common.error('no files given');
  
    files = [].slice.call(arguments, 1);
  
    if (pipe) {
      files.unshift('-');
    }
  
    var lines = [];
    files.forEach(function (file) {
      if (file !== '-') {
        if (!fs.existsSync(file)) {
          common.error('no such file or directory: ' + file, { continue: true });
          return;
        } else if (fs.statSync(file).isDirectory()) {
          common.error('read failed: ' + file + ': Is a directory', {
            continue: true,
          });
          return;
        }
      }
  
      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 sorted.join('\n') + '\n';
  }
  
  module.exports = _sort;