diff --git a/README.md b/README.md index 0f4e646..4a64329 100644 --- a/README.md +++ b/README.md @@ -318,6 +318,9 @@ introduced between each file). ### head([{'-n', \},] file [, file ...]) ### head([{'-n', \},] file_array) +Available options: + ++ `-n `: Show the first `` 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 `` if `-n` is -specified) +Read the start of a file. ### tail([{'-n', \},] file [, file ...]) ### tail([{'-n', \},] file_array) +Available options: + ++ `-n `: Show the last `` 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 `` if `-n` is -specified) +Read the end of a file. ### ShellString.prototype.to(file) diff --git a/src/common.js b/src/common.js index 3986d42..a154431 100644 --- a/src/common.js +++ b/src/common.js @@ -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') diff --git a/src/cp.js b/src/cp.js index d124c48..133fe08 100644 --- a/src/cp.js +++ b/src/cp.js @@ -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; diff --git a/src/find.js b/src/find.js index 4069525..a13e23e 100644 --- a/src/find.js +++ b/src/find.js @@ -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)); }); } diff --git a/src/grep.js b/src/grep.js index 3a3f5ca..09787e6 100644 --- a/src/grep.js +++ b/src/grep.js @@ -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); diff --git a/src/head.js b/src/head.js index 305f927..baf7972 100644 --- a/src/head.js +++ b/src/head.js @@ -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', \},] file [, file ...]) //@ ### head([{'-n', \},] file_array) +//@ Available options: +//@ +//@ + `-n `: Show the first `` 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 `` 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); diff --git a/src/ln.js b/src/ln.js index cdf15ca..6b11fc4 100644 --- a/src/ln.js +++ b/src/ln.js @@ -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 and/or '); } diff --git a/src/ls.js b/src/ls.js index fc4c767..d39506a 100644 --- a/src/ls.js +++ b/src/ls.js @@ -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) diff --git a/src/mkdir.js b/src/mkdir.js index 5c51afd..7a8479c 100644 --- a/src/mkdir.js +++ b/src/mkdir.js @@ -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'); diff --git a/src/mv.js b/src/mv.js index 6c42a59..48f8451 100644 --- a/src/mv.js +++ b/src/mv.js @@ -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 and/or '); diff --git a/src/rm.js b/src/rm.js index ff43e99..b4929c4 100644 --- a/src/rm.js +++ b/src/rm.js @@ -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'); diff --git a/src/sed.js b/src/sed.js index 5a12217..7a55bc2 100644 --- a/src/sed.js +++ b/src/sed.js @@ -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); diff --git a/src/sort.js b/src/sort.js index 2b111c4..a67742d 100644 --- a/src/sort.js +++ b/src/sort.js @@ -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); diff --git a/src/tail.js b/src/tail.js index d0fd897..e6a5948 100644 --- a/src/tail.js +++ b/src/tail.js @@ -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', \},] file [, file ...]) //@ ### tail([{'-n', \},] file_array) +//@ Available options: +//@ +//@ + `-n `: Show the last `` 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 `` 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); diff --git a/src/test.js b/src/test.js index d4d8428..6cb4f8a 100644 --- a/src/test.js +++ b/src/test.js @@ -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) { diff --git a/src/touch.js b/src/touch.js index a84a5a8..0eab448 100644 --- a/src/touch.js +++ b/src/touch.js @@ -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') diff --git a/src/uniq.js b/src/uniq.js index 65bb51e..930c6b9 100644 --- a/src/uniq.js +++ b/src/uniq.js @@ -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);