Permalink
Please sign in to comment.
Browse files
Merge pull request #49 from legien/master
Head command, plus fix for cat
- Loading branch information...
Showing
with
404 additions
and 29 deletions.
- +2 −0 bin/head.js
- +2 −1 commands.json
- +5 −1 dist/commands/cat.js
- +90 −0 dist/commands/head.js
- +3 −0 dist/help/head.js
- +4 −1 packages/cat/dist/commands/cat.js
- +32 −0 packages/head/README.md/template.README.md
- +2 −0 packages/head/bin/head.js
- +50 −0 packages/head/bin/parser.js
- +44 −0 packages/head/package.json
- +30 −26 src/commands/cat.js
- +94 −0 src/commands/head.js
- +1 −0 src/help.js
- +7 −0 src/help/head.js
- +38 −0 test/head.js
2
bin/head.js
| @@ -0,0 +1,2 @@ | ||
| +#!/usr/bin/env node | ||
| +require('./parser')(process.argv, 'head'); |
3
commands.json
6
dist/commands/cat.js
90
dist/commands/head.js
| @@ -0,0 +1,90 @@ | ||
| +'use strict'; | ||
| + | ||
| +var interfacer = require('./../util/interfacer'); | ||
| +var fs = require('fs'); | ||
| +var fsAutocomplete = require('vorpal-autocomplete-fs'); | ||
| + | ||
| +var head = { | ||
| + exec: function exec(args, options) { | ||
| + var self = this; | ||
| + options = options || {}; | ||
| + | ||
| + options.argsType = args.stdin === undefined ? 'files' : 'stdin'; | ||
| + options.n = options.n === undefined ? 10 : options.n; | ||
| + | ||
| + if (options.n < 1) { | ||
| + self.log('Option n must be a positive integer.'); | ||
| + return 1; | ||
| + } | ||
| + | ||
| + if (options.argsType === 'stdin') { | ||
| + self.log(head.readLines(args.stdin[0], options.n)); | ||
| + return 0; | ||
| + } | ||
| + | ||
| + var files = args.files || args; | ||
| + files = files === undefined ? [] : files; | ||
| + files = typeof files === 'string' ? String(files).split(' ') : files; | ||
| + files = files.filter(function (arg) { | ||
| + return String(arg).trim() !== ''; | ||
| + }); | ||
| + | ||
| + var stdout = ''; | ||
| + var writeHeaders = false; | ||
| + if (files.length > 1) { | ||
| + writeHeaders = true; | ||
| + } | ||
| + | ||
| + var content = []; | ||
| + for (var i = 0; i < files.length; i++) { | ||
| + try { | ||
| + content[i] = fs.readFileSync(files[i]).toString(); | ||
| + } catch (e) { | ||
| + self.log('head: ' + files[i] + ': No such file or directory'); | ||
| + return 1; | ||
| + } | ||
| + } | ||
| + | ||
| + for (var i = 0; i < files.length; i++) { | ||
| + if (writeHeaders) { | ||
| + stdout += (i > 0 ? '\n\n' : '') + '==> ' + files[i] + ' <==\n'; | ||
| + } | ||
| + | ||
| + stdout += head.readLines(content[i], options.n); | ||
| + } | ||
| + | ||
| + self.log(stdout); | ||
| + return 0; | ||
| + }, | ||
| + readLines: function readLines(content, numberOfLines) { | ||
| + var stdout = ''; | ||
| + var contentArray = content.split('\n'); | ||
| + var linesToRead = numberOfLines >= contentArray.length ? contentArray.length : numberOfLines; | ||
| + for (var i = 0; i < linesToRead; i++) { | ||
| + if (stdout === '') { | ||
| + stdout = contentArray[i]; | ||
| + continue; | ||
| + } | ||
| + | ||
| + stdout += '\n' + contentArray[i]; | ||
| + } | ||
| + | ||
| + return stdout; | ||
| + } | ||
| +}; | ||
| + | ||
| +module.exports = function (vorpal) { | ||
| + if (vorpal === undefined) { | ||
| + return head; | ||
| + } | ||
| + vorpal.api.head = head; | ||
| + vorpal.command('head [files...]').option('-n [number]', 'The first number of lines will be copied to stdout.').autocomplete(fsAutocomplete()).action(function (args, callback) { | ||
| + args.options = args.options || {}; | ||
| + return interfacer.call(this, { | ||
| + command: head, | ||
| + args: args, | ||
| + options: args.options, | ||
| + callback: callback | ||
| + }); | ||
| + }); | ||
| +}; |
3
dist/help/head.js
| @@ -0,0 +1,3 @@ | ||
| +"use strict"; | ||
| + | ||
| +module.exports = "\nUsage: head [OPTION] [files ...]\nShow first lines of file(s).\n\nReport head bugs to <https://github.com/dthree/cash>\nCash home page: <http://cash.js.org/>\n"; |
5
packages/cat/dist/commands/cat.js
32
packages/head/README.md/template.README.md
| @@ -0,0 +1,32 @@ | ||
| +# {package-name} | ||
| + | ||
| +--- | ||
| + | ||
| + | ||
| +This is a cross-platform, 100% ES6 implementation of the Unix `{command-name}` command. | ||
| + | ||
| +```bash | ||
| +npm install {package-name} -g | ||
| +``` | ||
| + | ||
| +This will install `{command-name}` globally in your system path. | ||
| + | ||
| +For help on the command, type: | ||
| + | ||
| +```bash | ||
| +> {command-name} --help | ||
| +``` | ||
| + | ||
| +## More | ||
| + | ||
| +This module is part of [Cash](https://github.com/dthree/cash), a project providing cross-platform implementations of all major Unix-based commands in pure Javascript. | ||
| + | ||
| + | ||
| +## Related | ||
| + | ||
| +{related} | ||
| + | ||
| + | ||
| +## License | ||
| + | ||
| +MIT © [David Caccavella](https://github.com/dthree) |
2
packages/head/bin/head.js
| @@ -0,0 +1,2 @@ | ||
| +#!/usr/bin/env node | ||
| +require('./parser')(process.argv, 'head'); |
50
packages/head/bin/parser.js
| @@ -0,0 +1,50 @@ | ||
| +'use strict'; | ||
| + | ||
| +module.exports = function (args, command) { | ||
| + args.splice(0, 2); | ||
| + var pipes = (args.indexOf('|') > -1); | ||
| + if (args.length === 0) { | ||
| + // If we don't have to parse arguments, do | ||
| + // the quickest load: just the raw js file | ||
| + // of the command and nothing else. | ||
| + var cmd = require('./../dist/commands/' + command)(); | ||
| + cmd.exec.call(console, {options: {}}, {}); | ||
| + } else if (pipes === false) { | ||
| + // If we need to parse args for this | ||
| + // command only, pull up vorpal and just load | ||
| + // that one command. | ||
| + var vorpal = require('vorpal')(); | ||
| + vorpal.api = {}; | ||
| + require('./../dist/commands/' + command)(vorpal); | ||
| + args = args.join(' '); | ||
| + | ||
| + // If we passed in a help request, load in | ||
| + // the help file. | ||
| + if (args.indexOf('help') > -1 || args.indexOf('?') > -1) { | ||
| + let help; | ||
| + try { | ||
| + help = require('./../dist/help/' + command + '.js'); | ||
| + help = String(help).replace(/^\n|\n$/g, ''); | ||
| + } catch (e) {} | ||
| + let cmdObj = vorpal.find(command); | ||
| + if (cmdObj && help) { | ||
| + cmdObj.help(function (argus, cb) { | ||
| + cb(help); | ||
| + }) | ||
| + } | ||
| + } | ||
| + vorpal.exec(command + ' ' + args); | ||
| + } else { | ||
| + // If we get into piping other commands, | ||
| + // we need to go full bore and load the | ||
| + // entire cash library. | ||
| + // I guess we could technically parse all | ||
| + // of the passed args, look for applicable | ||
| + // commands and only load those, but that's | ||
| + // some messy work for something that might | ||
| + // not matter. If you're reading this and | ||
| + // have deemed it matters, do a PR. | ||
| + var cash = require('./../dist/index'); | ||
| + cash.vorpal.exec(command + ' ' + args.join(' ')); | ||
| + } | ||
| +}; |
44
packages/head/package.json
| @@ -0,0 +1,44 @@ | ||
| +{ | ||
| + "name": "", | ||
| + "version": "0.0.1", | ||
| + "description": "", | ||
| + "main": "", | ||
| + "scripts": {}, | ||
| + "repository": { | ||
| + "type": "git", | ||
| + "url": "git+https://github.com/dthree/cash.git" | ||
| + }, | ||
| + "keywords": [ | ||
| + "cash", | ||
| + "terminal", | ||
| + "emulator", | ||
| + "cygwin", | ||
| + "cli", | ||
| + "windows", | ||
| + "linux", | ||
| + "unix", | ||
| + "posix", | ||
| + "bash", | ||
| + "tty", | ||
| + "util", | ||
| + "vorpal", | ||
| + "vorpal.js" | ||
| + ], | ||
| + "author": "dthree", | ||
| + "license": "MIT", | ||
| + "bugs": { | ||
| + "url": "https://github.com/dthree/cash/issues" | ||
| + }, | ||
| + "homepage": "https://github.com/dthree/cash#readme", | ||
| + "devDependencies": {}, | ||
| + "bin": {}, | ||
| + "dependencies": {}, | ||
| + "engines": { | ||
| + "node": ">= 4", | ||
| + "iojs": ">= 1.0.0" | ||
| + }, | ||
| + "files": [ | ||
| + "dist", | ||
| + "bin" | ||
| + ] | ||
| +} |
56
src/commands/cat.js
94
src/commands/head.js
| @@ -0,0 +1,94 @@ | ||
| +'use strict'; | ||
| + | ||
| +const interfacer = require('./../util/interfacer'); | ||
| +const fs = require('fs'); | ||
| +const fsAutocomplete = require('vorpal-autocomplete-fs'); | ||
| + | ||
| +const head = { | ||
| + | ||
| + exec(args, options) { | ||
| + const self = this; | ||
| + options = options || {}; | ||
| + | ||
| + options.argsType = args.stdin === undefined ? 'files' : 'stdin'; | ||
| + options.n = options.n === undefined ? 10 : options.n; | ||
| + | ||
| + if (options.n < 1) { | ||
| + self.log('Option n must be a positive integer.'); | ||
| + return 1; | ||
| + } | ||
| + | ||
| + if (options.argsType === 'stdin') { | ||
| + self.log(head.readLines(args.stdin[0], options.n)); | ||
| + return 0; | ||
| + } | ||
| + | ||
| + let files = args.files || args; | ||
| + files = (files === undefined) ? [] : files; | ||
| + files = (typeof files === 'string') ? String(files).split(' ') : files; | ||
| + files = files.filter(arg => String(arg).trim() !== ''); | ||
| + | ||
| + let stdout = ''; | ||
| + let writeHeaders = false; | ||
| + if (files.length > 1) { | ||
| + writeHeaders = true; | ||
| + } | ||
| + | ||
| + const content = []; | ||
| + for (let i = 0; i < files.length; i++) { | ||
| + try { | ||
| + content[i] = fs.readFileSync(files[i]).toString(); | ||
| + } catch (e) { | ||
| + self.log(`head: ${files[i]}: No such file or directory`); | ||
| + return 1; | ||
| + } | ||
| + } | ||
| + | ||
| + for (let i = 0; i < files.length; i++) { | ||
| + if (writeHeaders) { | ||
| + stdout += `${i > 0 ? '\n\n' : ''}==> ${files[i]} <==\n`; | ||
| + } | ||
| + | ||
| + stdout += head.readLines(content[i], options.n); | ||
| + } | ||
| + | ||
| + self.log(stdout); | ||
| + return 0; | ||
| + }, | ||
| + | ||
| + readLines(content, numberOfLines) { | ||
| + let stdout = ''; | ||
| + const contentArray = content.split('\n'); | ||
| + const linesToRead = numberOfLines >= contentArray.length ? contentArray.length : numberOfLines; | ||
| + for (let i = 0; i < linesToRead; i++) { | ||
| + if (stdout === '') { | ||
| + stdout = contentArray[i]; | ||
| + continue; | ||
| + } | ||
| + | ||
| + stdout += `\n${contentArray[i]}`; | ||
| + } | ||
| + | ||
| + return stdout; | ||
| + } | ||
| +}; | ||
| + | ||
| +module.exports = function (vorpal) { | ||
| + if (vorpal === undefined) { | ||
| + return head; | ||
| + } | ||
| + vorpal.api.head = head; | ||
| + vorpal | ||
| + .command('head [files...]') | ||
| + .option('-n [number]', 'The first number of lines will be copied to stdout.') | ||
| + .autocomplete(fsAutocomplete()) | ||
| + .action(function (args, callback) { | ||
| + args.options = args.options || {}; | ||
| + return interfacer.call(this, { | ||
| + command: head, | ||
| + args, | ||
| + options: args.options, | ||
| + callback | ||
| + }); | ||
| + }); | ||
| +}; |
1
src/help.js
7
src/help/head.js
| @@ -0,0 +1,7 @@ | ||
| +module.exports = ` | ||
| +Usage: head [OPTION] [files ...] | ||
| +Show first lines of file(s). | ||
| + | ||
| +Report head bugs to <https://github.com/dthree/cash> | ||
| +Cash home page: <http://cash.js.org/> | ||
| +`; |
38
test/head.js
| @@ -0,0 +1,38 @@ | ||
| +'use strict'; | ||
| + | ||
| +require('assert'); | ||
| +require('mocha'); | ||
| +const should = require('should'); | ||
| +const cash = require('../dist/index.js'); | ||
| +const $ = require('shelljs'); | ||
| +require('shelljs/global'); | ||
| + | ||
| +describe('head', function () { | ||
| + before(function () { | ||
| + 'line1\nline2\nline3\nline4\nline5\nline6\nline7\nline8\nline9\nline10\nline11'.to('eleven.test'); | ||
| + 'line1\nline2\nline3\nline4\nline5\nline6\nline7\nline8\nline9\nline10'.to('ten.test'); | ||
| + }); | ||
| + | ||
| + after(function () { | ||
| + $.rm(['eleven.test', 'ten.test']); | ||
| + }); | ||
| + | ||
| + it('should exist and be a function', function () { | ||
| + should.exist(cash.head); | ||
| + }); | ||
| + | ||
| + it('should give back ten lines when called without options', function () { | ||
| + const result = cash.head('eleven.test'); | ||
| + result.should.be.equal('line1\nline2\nline3\nline4\nline5\nline6\nline7\nline8\nline9\nline10\n'); | ||
| + }); | ||
| + | ||
| + it('should give back five lines when called with option n set to 5', function () { | ||
| + const result = cash.head('eleven.test', {n: 5}); | ||
| + result.should.be.equal('line1\nline2\nline3\nline4\nline5\n'); | ||
| + }); | ||
| + | ||
| + it('should write header when used with more than one file', function () { | ||
| + const result = cash.head(['eleven.test', 'ten.test'], {n: 2}); | ||
| + result.should.be.equal('==> eleven.test <==\nline1\nline2\n\n==> ten.test <==\nline1\nline2\n'); | ||
| + }); | ||
| +}); |
0 comments on commit
b9f9ee9