refactor: move option parsing into common.wrap() (#479)

* refactor: move option parsing into common.wrap()

* docs: update README
This commit is contained in:
Nate Fischer 2016-07-24 17:52:51 -07:00 committed by Ari Porad
parent 880d732611
commit e438e61f45
17 changed files with 144 additions and 105 deletions

View File

@ -318,6 +318,9 @@ introduced between each file).
### head([{'-n', \<num\>},] file [, file ...])
### head([{'-n', \<num\>},] file_array)
Available options:
+ `-n <num>`: Show the first `<num>` lines of the files
Examples:
@ -327,12 +330,14 @@ var str = head('file1', 'file2');
var str = head(['file1', 'file2']); // same as above
```
Output the first 10 lines of a file (or the first `<num>` if `-n` is
specified)
Read the start of a file.
### tail([{'-n', \<num\>},] file [, file ...])
### tail([{'-n', \<num\>},] file_array)
Available options:
+ `-n <num>`: Show the last `<num>` lines of the files
Examples:
@ -342,8 +347,7 @@ var str = tail('file1', 'file2');
var str = tail(['file1', 'file2']); // same as above
```
Output the last 10 lines of a file (or the last `<num>` if `-n` is
specified)
Read the end of a file.
### ShellString.prototype.to(file)

View File

@ -315,9 +315,16 @@ function wrap(cmd, fn, options) {
// Perform glob-expansion on all arguments after globStart, but preserve
// the arguments before it (like regexes for sed and grep)
if (!config.noglob && typeof options.globStart === 'number')
if (!config.noglob && typeof options.globStart === 'number') {
args = args.slice(0, options.globStart).concat(expand(args.slice(options.globStart)));
}
try {
// parse options if options are provided
if (typeof options.cmdOptions === 'object') {
args[0] = parseOptions(args[0], options.cmdOptions);
}
retValue = fn.apply(this, args);
} catch (e) {
if (e.msg === 'earlyExit')

View File

@ -3,7 +3,15 @@ var path = require('path');
var common = require('./common');
var os = require('os');
common.register('cp', _cp, {globStart: 1});
common.register('cp', _cp, {globStart: 1, cmdOptions: {
'f': '!no_force',
'n': 'no_force',
'R': 'recursive',
'r': 'recursive',
'L': 'followsymlink',
'P': 'noFollowsymlink',
}
});
// Buffered file copy, synchronous
// (Using readFileSync() + writeFileSync() could easily cause a memory overflow
@ -173,15 +181,6 @@ function cpcheckcycle(sourceDir, srcFile) {
//@
//@ Copies files.
function _cp(options, sources, dest) {
options = common.parseOptions(options, {
'f': '!no_force',
'n': 'no_force',
'R': 'recursive',
'r': 'recursive',
'L': 'followsymlink',
'P': 'noFollowsymlink',
});
// If we're missing -R, it actually implies -L (unless -P is explicit)
if (options.followsymlink)
options.noFollowsymlink = false;

View File

@ -42,7 +42,7 @@ function _find(options, paths) {
pushFile(file);
if (fs.statSync(file).isDirectory()) {
_ls('-RA', file).forEach(function(subfile) {
_ls({recursive: true, all: true}, file).forEach(function(subfile) {
pushFile(path.join(file, subfile));
});
}

View File

@ -1,7 +1,14 @@
var common = require('./common');
var fs = require('fs');
common.register('grep', _grep, {globStart: 2, canReceivePipe: true}); // don't glob-expand the regex
common.register('grep', _grep, {
globStart: 2, // don't glob-expand the regex
canReceivePipe: true,
cmdOptions: {
'v': 'inverse',
'l': 'nameOnly',
},
});
//@
//@ ### grep([options,] regex_filter, file [, file ...])
@ -21,11 +28,6 @@ common.register('grep', _grep, {globStart: 2, canReceivePipe: true}); // don't g
//@ Reads input string from given files and returns a string containing all lines of the
//@ file that match the given `regex_filter`.
function _grep(options, regex, files) {
options = common.parseOptions(options, {
'v': 'inverse',
'l': 'nameOnly'
});
// Check if this is coming from a pipe
var pipe = common.readFromPipe(this);

View File

@ -1,7 +1,13 @@
var common = require('./common');
var fs = require('fs');
common.register('head', _head, {globStart: 1, canReceivePipe: true});
common.register('head', _head, {
globStart: 1,
canReceivePipe: true,
cmdOptions: {
'n': 'numLines',
},
});
// This reads n or more lines, or the entire file, whichever is less.
function readSomeLines(file, numLines) {
@ -33,6 +39,9 @@ function readSomeLines(file, numLines) {
//@
//@ ### head([{'-n', \<num\>},] file [, file ...])
//@ ### head([{'-n', \<num\>},] file_array)
//@ Available options:
//@
//@ + `-n <num>`: Show the first `<num>` lines of the files
//@
//@ Examples:
//@
@ -42,12 +51,8 @@ function readSomeLines(file, numLines) {
//@ var str = head(['file1', 'file2']); // same as above
//@ ```
//@
//@ Output the first 10 lines of a file (or the first `<num>` if `-n` is
//@ specified)
//@ Read the start of a file.
function _head(options, files) {
options = common.parseOptions(options, {
'n': 'numLines'
});
var head = [];
var pipe = common.readFromPipe(this);

View File

@ -2,7 +2,13 @@ var fs = require('fs');
var path = require('path');
var common = require('./common');
common.register('ln', _ln, {globStart: 1});
common.register('ln', _ln, {
globStart: 1,
cmdOptions: {
's': 'symlink',
'f': 'force',
},
});
//@
//@ ### ln([options,] source, dest)
@ -20,11 +26,6 @@ common.register('ln', _ln, {globStart: 1});
//@
//@ Links source to dest. Use -f to force the link, should dest already exist.
function _ln(options, source, dest) {
options = common.parseOptions(options, {
's': 'symlink',
'f': 'force'
});
if (!source || !dest) {
common.error('Missing <source> and/or <dest>');
}

View File

@ -5,7 +5,17 @@ var glob = require('glob');
var globPatternRecursive = path.sep + '**' + path.sep + '*';
common.register('ls', _ls, {globStart: 1});
common.register('ls', _ls, {
globStart: 1,
cmdOptions: {
'R': 'recursive',
'A': 'all',
'a': 'all_deprecated',
'd': 'directory',
'l': 'long',
},
});
//@
//@ ### ls([options,] [path, ...])
@ -31,14 +41,6 @@ common.register('ls', _ls, {globStart: 1});
//@
//@ Returns array of files in the given path, or in current directory if no path provided.
function _ls(options, paths) {
options = common.parseOptions(options, {
'R': 'recursive',
'A': 'all',
'a': 'all_deprecated',
'd': 'directory',
'l': 'long'
});
if (options.all_deprecated) {
// We won't support the -a option as it's hard to image why it's useful
// (it includes '.' and '..' in addition to '.*' files)

View File

@ -2,7 +2,12 @@ var common = require('./common');
var fs = require('fs');
var path = require('path');
common.register('mkdir', _mkdir, {globStart: 1});
common.register('mkdir', _mkdir, {
globStart: 1,
cmdOptions: {
'p': 'fullpath',
},
});
// Recursively creates 'dir'
function mkdirSyncRecursive(dir) {
@ -44,9 +49,6 @@ function mkdirSyncRecursive(dir) {
//@
//@ Creates directories.
function _mkdir(options, dirs) {
options = common.parseOptions(options, {
'p': 'fullpath'
});
if (!dirs)
common.error('no paths given');

View File

@ -4,7 +4,13 @@ var common = require('./common');
var cp = require('./cp');
var rm = require('./rm');
common.register('mv', _mv, {globStart: 1});
common.register('mv', _mv, {
globStart: 1,
cmdOptions: {
'f': '!no_force',
'n': 'no_force',
},
});
//@
//@ ### mv([options ,] source [, source ...], dest')
@ -24,11 +30,6 @@ common.register('mv', _mv, {globStart: 1});
//@
//@ Moves files.
function _mv(options, sources, dest) {
options = common.parseOptions(options, {
'f': '!no_force',
'n': 'no_force'
});
// Get sources, dest
if (arguments.length < 3) {
common.error('missing <source> and/or <dest>');

View File

@ -1,7 +1,14 @@
var common = require('./common');
var fs = require('fs');
common.register('rm', _rm, {globStart: 1});
common.register('rm', _rm, {
globStart: 1,
cmdOptions: {
'f': 'force',
'r': 'recursive',
'R': 'recursive',
},
});
// Recursively removes 'dir'
// Adapted from https://github.com/ryanmcgrath/wrench-js
@ -97,11 +104,6 @@ function isWriteable(file) {
//@
//@ Removes files.
function _rm(options, files) {
options = common.parseOptions(options, {
'f': 'force',
'r': 'recursive',
'R': 'recursive'
});
if (!files)
common.error('no paths given');

View File

@ -1,7 +1,13 @@
var common = require('./common');
var fs = require('fs');
common.register('sed', _sed, {globStart: 3, canReceivePipe: true}); // don't glob-expand regexes
common.register('sed', _sed, {
globStart: 3, // don't glob-expand regexes
canReceivePipe: true,
cmdOptions: {
'i': 'inplace',
},
});
//@
//@ ### sed([options,] search_regex, replacement, file [, file ...])
@ -20,10 +26,6 @@ common.register('sed', _sed, {globStart: 3, canReceivePipe: true}); // don't glo
//@ Reads an input string from `files` and performs a JavaScript `replace()` on the input
//@ using the given search regex and replacement string or function. Returns the new string after replacement.
function _sed(options, regex, replacement, files) {
options = common.parseOptions(options, {
'i': 'inplace'
});
// Check if this is coming from a pipe
var pipe = common.readFromPipe(this);

View File

@ -1,7 +1,15 @@
var common = require('./common');
var fs = require('fs');
common.register('sort', _sort, {globStart: 1, canReceivePipe: true});
common.register('sort', _sort, {
globStart: 1,
canReceivePipe: true,
cmdOptions: {
'r': 'reverse',
'n': 'numerical',
}
});
// parse out the number prefix of a line
function parseNumber (str) {
@ -50,11 +58,6 @@ function numericalCmp(a, b) {
//@ 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);

View File

@ -1,11 +1,20 @@
var common = require('./common');
var fs = require('fs');
common.register('tail', _tail, {globStart: 1, canReceivePipe: true});
common.register('tail', _tail, {
globStart: 1,
canReceivePipe: true,
cmdOptions: {
'n': 'numLines',
},
});
//@
//@ ### tail([{'-n', \<num\>},] file [, file ...])
//@ ### tail([{'-n', \<num\>},] file_array)
//@ Available options:
//@
//@ + `-n <num>`: Show the last `<num>` lines of the files
//@
//@ Examples:
//@
@ -15,12 +24,8 @@ common.register('tail', _tail, {globStart: 1, canReceivePipe: true});
//@ var str = tail(['file1', 'file2']); // same as above
//@ ```
//@
//@ Output the last 10 lines of a file (or the last `<num>` if `-n` is
//@ specified)
//@ Read the end of a file.
function _tail(options, files) {
options = common.parseOptions(options, {
'n': 'numLines'
});
var tail = [];
var pipe = common.readFromPipe(this);

View File

@ -1,7 +1,20 @@
var common = require('./common');
var fs = require('fs');
common.register('test', _test);
common.register('test', _test, {
cmdOptions: {
'b': 'block',
'c': 'character',
'd': 'directory',
'e': 'exists',
'f': 'file',
'L': 'link',
'p': 'pipe',
'S': 'socket',
},
});
//@
//@ ### test(expression)
@ -28,18 +41,6 @@ function _test(options, path) {
if (!path)
common.error('no path given');
// hack - only works with unary primaries
options = common.parseOptions(options, {
'b': 'block',
'c': 'character',
'd': 'directory',
'e': 'exists',
'f': 'file',
'L': 'link',
'p': 'pipe',
'S': 'socket'
});
var canInterpret = false;
for (var key in options)
if (options[key] === true) {

View File

@ -1,7 +1,16 @@
var common = require('./common');
var fs = require('fs');
common.register('touch', _touch, {globStart: 1});
common.register('touch', _touch, {
globStart: 1,
cmdOptions: {
'a': 'atime_only',
'c': 'no_create',
'd': 'date',
'm': 'mtime_only',
'r': 'reference',
},
});
//@
//@ ### touch([options,] file [, file ...])
@ -26,14 +35,6 @@ common.register('touch', _touch, {globStart: 1});
//@ A FILE argument that does not exist is created empty, unless -c is supplied.
//@ This is a partial implementation of *[touch(1)](http://linux.die.net/man/1/touch)*.
function _touch(opts, files) {
opts = common.parseOptions(opts, {
'a': 'atime_only',
'c': 'no_create',
'd': 'date',
'm': 'mtime_only',
'r': 'reference',
});
if (!files)
common.error('no files given');
else if (typeof files === 'string')

View File

@ -10,7 +10,15 @@ function lpad(c, str){
return res;
}
common.register('uniq', _uniq, {globStart: 1, canReceivePipe: true});
common.register('uniq', _uniq, {
globStart: 1,
canReceivePipe: true,
cmdOptions: {
'i': 'ignoreCase',
'c': 'count',
'd': 'duplicates',
},
});
//@
//@ ### uniq([options,] [input, [output]])
@ -30,12 +38,6 @@ common.register('uniq', _uniq, {globStart: 1, canReceivePipe: true});
//@
//@ Filter adjacent matching lines from input
function _uniq(options, input, output) {
options = common.parseOptions(options, {
'i': 'ignoreCase',
'c': 'count',
'd': 'duplicates'
});
// Check if this is coming from a pipe
var pipe = common.readFromPipe(this);