Skip to content
Browse files

init

  • Loading branch information...
0 parents commit a8d0eab2c6168d44fff29a38305bbdbe35959b83 @dthree committed
Showing with 9,653 additions and 0 deletions.
  1. +3 −0 .babelrc
  2. +1 −0 .eslintignore
  3. +31 −0 .gitignore
  4. +55 −0 .istanbul.yml
  5. +9 −0 .travis.yml
  6. +22 −0 LICENSE
  7. +193 −0 README.md
  8. +21 −0 appveyor.yml
  9. +2 −0 bin/alias.js
  10. +7 −0 bin/cash.js
  11. +2 −0 bin/cat.js
  12. +2 −0 bin/cd.js
  13. +2 −0 bin/cp.js
  14. +2 −0 bin/echo.js
  15. +2 −0 bin/grep.js
  16. +2 −0 bin/kill.js
  17. +2 −0 bin/less.js
  18. +2 −0 bin/ls.js
  19. +2 −0 bin/mkdir.js
  20. +2 −0 bin/mv.js
  21. +50 −0 bin/parser.js
  22. +2 −0 bin/pwd.js
  23. +2 −0 bin/rm.js
  24. +2 −0 bin/sort.js
  25. +2 −0 bin/touch.js
  26. +2 −0 bin/unalias.js
  27. +171 −0 commands.json
  28. +109 −0 dist/commands/alias.js
  29. +98 −0 dist/commands/boilerplate.js
  30. +116 −0 dist/commands/cat.js
  31. +55 −0 dist/commands/cd.js
  32. +207 −0 dist/commands/cp.js
  33. +78 −0 dist/commands/echo.js
  34. +3 −0 dist/commands/grep.js
  35. +97 −0 dist/commands/kill.js
  36. +3 −0 dist/commands/less.js
  37. +353 −0 dist/commands/ls.js
  38. +86 −0 dist/commands/mkdir.js
  39. +105 −0 dist/commands/mv.js
  40. +28 −0 dist/commands/pwd.js
  41. +171 −0 dist/commands/rm.js
  42. +269 −0 dist/commands/sort.js
  43. +151 −0 dist/commands/touch.js
  44. +100 −0 dist/commands/unalias.js
  45. +33 −0 dist/delimiter.js
  46. +35 −0 dist/help.js
  47. +3 −0 dist/help/alias.js
  48. +3 −0 dist/help/cat.js
  49. +3 −0 dist/help/cd.js
  50. +3 −0 dist/help/cp.js
  51. +3 −0 dist/help/echo.js
  52. +3 −0 dist/help/grep.js
  53. +3 −0 dist/help/kill.js
  54. +3 −0 dist/help/ls.js
  55. +3 −0 dist/help/mkdir.js
  56. +3 −0 dist/help/mv.js
  57. +3 −0 dist/help/pwd.js
  58. +3 −0 dist/help/rm.js
  59. +3 −0 dist/help/sort.js
  60. +3 −0 dist/help/touch.js
  61. +3 −0 dist/help/unalias.js
  62. +185 −0 dist/index.js
  63. +747 −0 dist/lib/sugar.js
  64. +34 −0 dist/util/colorFile.js
  65. +58 −0 dist/util/columnify.js
  66. +30 −0 dist/util/converter.date.js
  67. +19 −0 dist/util/converter.path.js
  68. +39 −0 dist/util/converter.permissions.js
  69. +29 −0 dist/util/expand.js
  70. +50 −0 dist/util/fetch.js
  71. +17 −0 dist/util/fileFromPath.js
  72. +47 −0 dist/util/intercept.js
  73. +45 −0 dist/util/interfacer.js
  74. +20 −0 dist/util/lpad.js
  75. +22 −0 dist/util/pad.js
  76. +14 −0 dist/util/stripAnsi.js
  77. +30 −0 dist/util/unlinkSync.js
  78. +41 −0 dist/util/walkDir.js
  79. +24 −0 dist/util/walkDirRecursive.js
  80. +120 −0 dist/windows.js
  81. +127 −0 gulpfile.js
  82. +103 −0 package.json
  83. +47 −0 packages/cat/README.md
  84. +2 −0 packages/cat/bin/cat.js
  85. +50 −0 packages/cat/bin/parser.js
  86. +116 −0 packages/cat/dist/commands/cat.js
  87. +3 −0 packages/cat/dist/help/cat.js
  88. +29 −0 packages/cat/dist/util/expand.js
  89. +50 −0 packages/cat/dist/util/fetch.js
  90. +45 −0 packages/cat/dist/util/interfacer.js
  91. +20 −0 packages/cat/dist/util/lpad.js
  92. +14 −0 packages/cat/dist/util/stripAnsi.js
  93. +51 −0 packages/cat/package.json
  94. +47 −0 packages/cp/README.md
  95. +2 −0 packages/cp/bin/cp.js
  96. +50 −0 packages/cp/bin/parser.js
  97. +207 −0 packages/cp/dist/commands/cp.js
  98. +3 −0 packages/cp/dist/help/cp.js
  99. +29 −0 packages/cp/dist/util/expand.js
  100. +45 −0 packages/cp/dist/util/interfacer.js
  101. +51 −0 packages/cp/package.json
  102. +47 −0 packages/kill/README.md
  103. +2 −0 packages/kill/bin/kill.js
  104. +50 −0 packages/kill/bin/parser.js
  105. +97 −0 packages/kill/dist/commands/kill.js
  106. +3 −0 packages/kill/dist/help/kill.js
  107. +45 −0 packages/kill/dist/util/interfacer.js
  108. +50 −0 packages/kill/package.json
  109. +47 −0 packages/ls/README.md
  110. +2 −0 packages/ls/bin/ls.js
  111. +50 −0 packages/ls/bin/parser.js
  112. +353 −0 packages/ls/dist/commands/ls.js
  113. +3 −0 packages/ls/dist/help/ls.js
  114. +34 −0 packages/ls/dist/util/colorFile.js
  115. +58 −0 packages/ls/dist/util/columnify.js
  116. +30 −0 packages/ls/dist/util/converter.date.js
  117. +39 −0 packages/ls/dist/util/converter.permissions.js
  118. +17 −0 packages/ls/dist/util/fileFromPath.js
  119. +45 −0 packages/ls/dist/util/interfacer.js
  120. +20 −0 packages/ls/dist/util/lpad.js
  121. +22 −0 packages/ls/dist/util/pad.js
  122. +14 −0 packages/ls/dist/util/stripAnsi.js
  123. +41 −0 packages/ls/dist/util/walkDir.js
  124. +24 −0 packages/ls/dist/util/walkDirRecursive.js
  125. +52 −0 packages/ls/package.json
  126. +47 −0 packages/mkdir/README.md
  127. +2 −0 packages/mkdir/bin/mkdir.js
  128. +50 −0 packages/mkdir/bin/parser.js
  129. +86 −0 packages/mkdir/dist/commands/mkdir.js
  130. +3 −0 packages/mkdir/dist/help/mkdir.js
  131. +45 −0 packages/mkdir/dist/util/interfacer.js
  132. +49 −0 packages/mkdir/package.json
  133. +47 −0 packages/mv/README.md
  134. +2 −0 packages/mv/bin/mv.js
  135. +50 −0 packages/mv/bin/parser.js
  136. +105 −0 packages/mv/dist/commands/mv.js
  137. +3 −0 packages/mv/dist/help/mv.js
  138. +29 −0 packages/mv/dist/util/expand.js
  139. +45 −0 packages/mv/dist/util/interfacer.js
  140. +51 −0 packages/mv/package.json
  141. +47 −0 packages/pwd/README.md
  142. +50 −0 packages/pwd/bin/parser.js
  143. +2 −0 packages/pwd/bin/pwd.js
  144. +28 −0 packages/pwd/dist/commands/pwd.js
  145. +3 −0 packages/pwd/dist/help/pwd.js
  146. +45 −0 packages/pwd/dist/util/interfacer.js
  147. +48 −0 packages/pwd/package.json
  148. +47 −0 packages/rm/README.md
  149. +50 −0 packages/rm/bin/parser.js
  150. +2 −0 packages/rm/bin/rm.js
  151. +171 −0 packages/rm/dist/commands/rm.js
  152. +3 −0 packages/rm/dist/help/rm.js
  153. +29 −0 packages/rm/dist/util/expand.js
  154. +45 −0 packages/rm/dist/util/interfacer.js
  155. +30 −0 packages/rm/dist/util/unlinkSync.js
  156. +50 −0 packages/rm/package.json
  157. +47 −0 packages/sort/README.md
  158. +50 −0 packages/sort/bin/parser.js
  159. +2 −0 packages/sort/bin/sort.js
  160. +269 −0 packages/sort/dist/commands/sort.js
  161. +3 −0 packages/sort/dist/help/sort.js
  162. +29 −0 packages/sort/dist/util/expand.js
  163. +50 −0 packages/sort/dist/util/fetch.js
  164. +45 −0 packages/sort/dist/util/interfacer.js
  165. +14 −0 packages/sort/dist/util/stripAnsi.js
  166. +51 −0 packages/sort/package.json
  167. +32 −0 packages/template.README.md
  168. +44 −0 packages/template.package.json
  169. +47 −0 packages/touch/README.md
  170. +50 −0 packages/touch/bin/parser.js
  171. +2 −0 packages/touch/bin/touch.js
  172. +151 −0 packages/touch/dist/commands/touch.js
  173. +3 −0 packages/touch/dist/help/touch.js
  174. +747 −0 packages/touch/dist/lib/sugar.js
  175. +45 −0 packages/touch/dist/util/interfacer.js
  176. +51 −0 packages/touch/package.json
  177. +113 −0 src/commands/alias.js
Sorry, we could not display the entire diff because it was too big.
3 .babelrc
@@ -0,0 +1,3 @@
+{
+ "presets": ["es2015"]
+}
1 .eslintignore
@@ -0,0 +1 @@
+src/lib/sugar.js
31 .gitignore
@@ -0,0 +1,31 @@
+*.log
+
+# Runtime data
+pids
+*.pid
+*.seed
+
+*sublime*
+
+# Directory for instrumented libs generated by jscoverage/JSCover
+lib-cov
+
+# Coverage directory used by tools like istanbul
+coverage
+
+# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
+.grunt
+
+# node-waf configuration
+.lock-wscript
+
+# Compiled binary addons (http://nodejs.org/api/addons.html)
+build/Release
+
+# Dependency directory
+# https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git
+node_modules
+
+.cmd_history
+.cmd_history/*
+.cmd_history/cmd_historycash
55 .istanbul.yml
@@ -0,0 +1,55 @@
+verbose: false
+instrumentation:
+ root: .
+ extensions:
+ - .js
+ default-excludes: true
+ excludes: ['./dist/lib/sugar.js']
+ embed-source: false
+ variable: __coverage__
+ compact: true
+ preserve-comments: false
+ complete-copy: false
+ save-baseline: false
+ baseline-file: ./coverage/coverage-baseline.json
+ include-all-sources: false
+ include-pid: false
+ es-modules: false
+reporting:
+ print: summary
+ reports:
+ - lcov
+ dir: ./coverage
+ watermarks:
+ statements: [50, 80]
+ lines: [50, 80]
+ functions: [50, 80]
+ branches: [50, 80]
+ report-config:
+ clover: {file: clover.xml}
+ cobertura: {file: cobertura-coverage.xml}
+ json: {file: coverage-final.json}
+ json-summary: {file: coverage-summary.json}
+ lcovonly: {file: lcov.info}
+ teamcity: {file: null, blockName: Code Coverage Summary}
+ text: {file: null, maxCols: 0}
+ text-lcov: {file: lcov.info}
+ text-summary: {file: null}
+hooks:
+ hook-run-in-context: false
+ post-require-hook: null
+ handle-sigint: false
+check:
+ global:
+ statements: 0
+ lines: 0
+ branches: 0
+ functions: 0
+ excludes: []
+ each:
+ statements: 0
+ lines: 0
+ branches: 0
+ functions: 0
+ excludes: []
+
9 .travis.yml
@@ -0,0 +1,9 @@
+sudo: false
+language: node_js
+node_js:
+ - "5"
+ - "4"
+after_success: "cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js"
+branches:
+ only:
+ - master
22 LICENSE
@@ -0,0 +1,22 @@
+(The MIT License)
+
+Copyright (c) 2015 DC <threedeecee@gmail.com>
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+'Software'), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
193 README.md
@@ -0,0 +1,193 @@
+<h1 align="center">
+ <img width="312" src="http://i.imgur.com/tKrIdAI.jpg" alt="Cash">
+ <!--<img width="256" src="http://i.imgur.com/oIN1WsM.jpg" alt="Cash">-->
+</h1>
+
+
+> Cross-platform Linux commands in pure ES6
+
+[![Build Status](https://travis-ci.org/vorpaljs/cash.svg)](https://travis-ci.org/vorpaljs/cash/)
+[![Windows Build Status](https://ci.appveyor.com/api/projects/status/286om4y0wbxs69fy?svg=true)](https://ci.appveyor.com/project/dthree/cash)
+[![Coverage Status](https://coveralls.io/repos/vorpaljs/cash/badge.svg?branch=master&service=github)](https://coveralls.io/github/vorpaljs/cash?branch=master)
+<a href="https://gitter.im/dthree/cash?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge">
+ <img src="https://img.shields.io/badge/gitter-join%20chat-brightgreen.svg" alt="Gitter" />
+</a>
+[![XO code style](https://img.shields.io/badge/code_style-XO-5ed9c7.svg)](https://github.com/sindresorhus/xo)
+
+Cash is a cross-platform implementation of Unix shell commands written in pure ES6.
+
+*Huh?* Okay - think [Cygwin](https://en.wikipedia.org/wiki/Cygwin), except:
+
+- No DLLs
+- Terminal-agnostic
+- 1/15th of the size
+- No native compiling
+- Just:
+
+```bash
+> npm install cash -g
+> cash
+$
+```
+
+<p align="center">
+ <img src="http://i.giphy.com/xT0BKNwUPFhFj2glry.gif" alt="Cash" />
+</p>
+
+
+### Woah.
+
+Yeah. But it gets better.
+
+Let's mix some Windows & Unix commands together:
+
+```bash
+$ ipconfig | grep IPv4 | sort
+IPv4 Address. . . . . . . . . . . : 10.10.40.50
+IPv4 Address. . . . . . . . . . . : 192.168.100.11
+$
+```
+
+[Learn more](https://github.com/dthree/cash/wiki/Usage-|-Interactive)
+
+
+### But I don't want to type "cash"
+
+No problem. Let's make all commands global on your system:
+
+```bash
+> npm install cash-global -g
+> ls -lah
+```
+
+[Learn more](https://github.com/dthree/cash/wiki/Usage-|-Global)
+
+
+### Nice, but I only want certain commands
+
+You're covered!
+
+```bash
+> npm install cash-ls -g
+> npm install cash-grep -g
+```
+
+[Learn more](https://github.com/dthree/cash/wiki/Usage-|-Global#installing-individual-commands)
+
+
+### Wow. But I want this programmatically!
+
+Again, you're in business:
+
+```js
+const $ = require('cash');
+const out = $.ls('.', {l: true});
+```
+
+Not terse enough? How about this:
+
+```js
+const out = $('ls -lah');
+```
+
+[Learn more](https://github.com/dthree/cash/wiki/Usage-|-Programmatic)
+
+
+### Isn't this impossible to do in Node?
+
+It was, before [Vorpal](https://github.com/dthree/vorpal).
+
+Made with ❤ by [dthree](https://github.com/dthree).
+
+Love it? Cash is brand new! Give it a :star: or a tweet to help spread the word!
+
+
+## Contents
+
+- [Introduction](#introduction)
+- [Supported commands](#supported-commands)
+- [Contributing](#contributing)
+- [FAQ](#faq)
+- [License](#license)
+
+- [Wiki](https://github.com/dthree/cash/wiki)
+
+## Introduction
+
+Cash is a project working on a cross-platform implementation of the most used Unix-based commands in pure Javascript and with no external dependencies.
+
+The goal of Cash is to open up these commands to the massive Javascript community for the first time, and to provide a cleaner, simpler and flexible alternative to applications like Cygwin for those wanting the Linux feel on Windows.
+
+Cash was built with strict attention to nearly exact implementations and excellent test coverage of over 200 unit tests.
+
+
+## Supported commands
+
+The following commands are currently implemented:
+
+- alias
+- cat
+- cd
+- cp
+- echo
+- grep
+- kill
+- less
+- ls
+- mkdir
+- mv
+- pwd
+- rm
+- sort
+- touch
+- unalias
+
+Want more commands?
+
+- [Vote on the next commands](https://github.com/dthree/cash/wiki/Roadmap)
+- [Help spread the word:](http://bit.ly/1LBEJ5s) More knowledge of Cash equals more contributors
+- [Contribute](#contributing)
+
+
+## Contributing
+
+- [Editing commands](contributing.md)
+- [Adding new commands](contributing.md)
+
+I am currently looking for someone with experience in building Windows installers (`.msi`) to bundle Cash and its individual components into a self-contained wrapper. I you would like to help with this, send me a ping.
+
+
+## FAQ
+
+
+#### Why Cash?
+
+In its very essence, Cash replaces the Windows CLI prompt (`>`) with the Unix one (`$`), the dollar symbol.
+
+Cash was most fitting in this sense:
+
+> Ask and ye shall receive
+
+```
+> cash
+$
+````
+
+Cash is also a play on the word `bash`, and is actually[\[1\]](https://xkcd.com/906) a recursive acronym for Cash Shell.
+
+Shout out to [@aseemk](https://github.com/aseemk) for donating the name.
+
+
+#### Doesn't Shell.js do this?
+
+No.
+
+For those who don't know, [Shell.js](https://github.com/shelljs/shelljs) is an awesome Node app that implements Unix shell commands programatically in Javascript. Check it out - really. While Shell.js was tremendously helpful in figuring out how to accomplish Cash, the two do not really conflict.
+
+Shell.js *gives the feel of and approximates* Unix commands in a code environment, but does not aim to precisely implement it.
+By example, Shell.js' `ls` command supports two arguments and returns an array. Cash supports seventeen arguments and strives to mirror the exact funcionality and output of the POSIX-compliant `ls` command.
+
+
+## License
+
+MIT © [David Caccavella](https://github.com/dthree)
21 appveyor.yml
@@ -0,0 +1,21 @@
+environment:
+ matrix:
+ - nodejs_version: '5'
+ - nodejs_version: '4'
+install:
+ - ps: Install-Product node $env:nodejs_version
+ - set CI=true
+ - set CASH_APPVEYOR=true
+ - npm install -g npm@latest || (timeout 30 && npm install -g npm@latest)
+ - set PATH=%APPDATA%\npm;%PATH%
+ - npm install || (timeout 30 && npm install)
+matrix:
+ fast_finish: true
+build: off
+version: '{build}'
+shallow_clone: true
+clone_depth: 1
+test_script:
+ - node --version
+ - npm --version
+ - npm run test-win || (timeout 30 && npm run test-win)
2 bin/alias.js
@@ -0,0 +1,2 @@
+#!/usr/bin/env node
+require('./parser')(process.argv, 'alias');
7 bin/cash.js
@@ -0,0 +1,7 @@
+#!/usr/bin/env node
+'use strict';
+var cash = require('../dist/index');
+var delimiter = require('./../dist/delimiter')
+delimiter.refresh(cash.vorpal, function () {
+ cash.show();
+});
2 bin/cat.js
@@ -0,0 +1,2 @@
+#!/usr/bin/env node
+require('./parser')(process.argv, 'cat');
2 bin/cd.js
@@ -0,0 +1,2 @@
+#!/usr/bin/env node
+require('./parser')(process.argv, 'cd');
2 bin/cp.js
@@ -0,0 +1,2 @@
+#!/usr/bin/env node
+require('./parser')(process.argv, 'cp');
2 bin/echo.js
@@ -0,0 +1,2 @@
+#!/usr/bin/env node
+require('./parser')(process.argv, 'echo');
2 bin/grep.js
@@ -0,0 +1,2 @@
+#!/usr/bin/env node
+require('./parser')(process.argv, 'grep');
2 bin/kill.js
@@ -0,0 +1,2 @@
+#!/usr/bin/env node
+require('./parser')(process.argv, 'kill');
2 bin/less.js
@@ -0,0 +1,2 @@
+#!/usr/bin/env node
+require('./parser')(process.argv, 'less');
2 bin/ls.js
@@ -0,0 +1,2 @@
+#!/usr/bin/env node
+require('./parser')(process.argv, 'ls');
2 bin/mkdir.js
@@ -0,0 +1,2 @@
+#!/usr/bin/env node
+require('./parser')(process.argv, 'mkdir');
2 bin/mv.js
@@ -0,0 +1,2 @@
+#!/usr/bin/env node
+require('./parser')(process.argv, 'mv');
50 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(' '));
+ }
+};
2 bin/pwd.js
@@ -0,0 +1,2 @@
+#!/usr/bin/env node
+require('./parser')(process.argv, 'pwd');
2 bin/rm.js
@@ -0,0 +1,2 @@
+#!/usr/bin/env node
+require('./parser')(process.argv, 'rm');
2 bin/sort.js
@@ -0,0 +1,2 @@
+#!/usr/bin/env node
+require('./parser')(process.argv, 'sort');
2 bin/touch.js
@@ -0,0 +1,2 @@
+#!/usr/bin/env node
+require('./parser')(process.argv, 'touch');
2 bin/unalias.js
@@ -0,0 +1,2 @@
+#!/usr/bin/env node
+require('./parser')(process.argv, 'unalias');
171 commands.json
@@ -0,0 +1,171 @@
+{
+ "commands": [
+ "alias",
+ "cd",
+ "cp",
+ "echo",
+ "kill",
+ "ls",
+ "mkdir",
+ "mv",
+ "pwd",
+ "sort",
+ "touch",
+ "cat",
+ "less",
+ "grep",
+ "rm",
+ "unalias"
+ ],
+ "globalExclusions": [
+ "alias",
+ "cd",
+ "echo",
+ "less",
+ "sort",
+ "unalias"
+ ],
+ "importedCommands": [
+ "less",
+ "grep"
+ ],
+ "windowsCommands": [
+ "attrib",
+ "assoc",
+ "cacls",
+ "chcp",
+ "copy",
+ "del",
+ "dir",
+ "driverquery",
+ "erase",
+ "git",
+ "icacls",
+ "ipconfig",
+ "md",
+ "mklink",
+ "move",
+ "net",
+ "npm",
+ "openfiles",
+ "path",
+ "rd",
+ "recover",
+ "ren",
+ "replace",
+ "robocopy",
+ "route",
+ "sc",
+ "schtasks",
+ "setlocal",
+ "start",
+ "subst",
+ "systeminfo",
+ "tasklist",
+ "taskkill",
+ "tree",
+ "ver",
+ "vol",
+ "xcopy"
+ ],
+ "dependencies": {
+ "./dist/delimiter.js": ["username", "./dist/util/converter.path.js"],
+ "./dist/util/colorFile.js": ["./dist/util/stripAnsi.js"],
+ "./dist/util/columnify.js": ["./dist/util/stripAnsi.js", "./dist/util/pad.js"],
+ "./dist/util/converter.path.js": [],
+ "./dist/util/converter.permissions.js": [],
+ "./dist/util/converter.date.js": [],
+ "./dist/util/expand.js": ["glob"],
+ "./dist/util/fetch.js": ["./dist/util/expand.js"],
+ "./dist/util/fileFromPath.js": [],
+ "./dist/util/interfacer.js": [],
+ "./dist/util/lpad.js": ["./dist/util/stripAnsi.js"],
+ "./dist/util/pad.js": ["./dist/util/stripAnsi.js"],
+ "./dist/util/stripAnsi.js": [],
+ "./dist/util/walkDir.js": [],
+ "./dist/util/walkDirRecursive.js": [],
+ "./dist/util/unlinkSync.js": []
+ },
+ "packages": {
+ "cat": {
+ "dependencies": ["lodash", "vorpal-autocomplete-fs", "glob"],
+ "files": [
+ "./dist/util/fetch.js",
+ "./dist/util/interfacer.js",
+ "./dist/util/lpad.js",
+ "./dist/util/stripAnsi.js",
+ "./dist/util/expand.js"
+ ]
+ },
+ "cp": {
+ "dependencies": ["lodash", "vorpal-autocomplete-fs", "glob"],
+ "files": [
+ "./dist/util/expand.js",
+ "./dist/util/interfacer.js"
+ ]
+ },
+ "kill": {
+ "dependencies": ["fkill", "lodash"],
+ "files": [
+ "./dist/util/interfacer.js"
+ ]
+ },
+ "ls": {
+ "dependencies": ["lodash", "chalk", "filesize", "vorpal-autocomplete-fs"],
+ "files": [
+ "./dist/util/colorFile.js",
+ "./dist/util/columnify.js",
+ "./dist/util/converter.date.js",
+ "./dist/util/fileFromPath.js",
+ "./dist/util/interfacer.js",
+ "./dist/util/pad.js",
+ "./dist/util/lpad.js",
+ "./dist/util/converter.permissions.js",
+ "./dist/util/stripAnsi.js",
+ "./dist/util/walkDir.js",
+ "./dist/util/walkDirRecursive.js"
+ ]
+ },
+ "mkdir": {
+ "dependencies": ["vorpal-autocomplete-fs"],
+ "files": ["./dist/util/interfacer.js"]
+ },
+ "mv": {
+ "dependencies": ["lodash", "vorpal-autocomplete-fs", "glob"],
+ "files": [
+ "./dist/util/expand.js",
+ "./dist/util/interfacer.js"
+ ]
+ },
+ "pwd": {
+ "dependencies": [],
+ "files": [
+ "./dist/util/interfacer.js"
+ ]
+ },
+ "sort": {
+ "dependencies": ["lodash", "vorpal-autocomplete-fs", "glob"],
+ "files": [
+ "./dist/util/fetch.js",
+ "./dist/util/interfacer.js",
+ "./dist/util/stripAnsi.js",
+ "./dist/util/expand.js"
+ ]
+ },
+ "touch": {
+ "dependencies": ["lodash", "fs-extra", "vorpal-autocomplete-fs"],
+ "files": [
+ "./dist/util/interfacer.js",
+ "./dist/lib/sugar.js"
+ ]
+ },
+ "rm": {
+ "dependencies": ["vorpal-autocomplete-fs", "glob"],
+ "files": [
+ "./dist/util/expand.js",
+ "./dist/util/interfacer.js",
+ "./dist/util/unlinkSync.js"
+ ]
+ }
+ }
+}
109 dist/commands/alias.js
@@ -0,0 +1,109 @@
+'use strict';
+
+var _ = require('lodash');
+
+var interfacer = require('./../util/interfacer');
+
+var alias = {
+ exec: function exec(args, options) {
+ args = args || [];
+ options = options || {};
+ var vorpal = options.vorpal;
+
+ if (!vorpal) {
+ throw new Error('Alias is not programatically supported.');
+ }
+
+ vorpal._aliases = vorpal._aliases || [];
+
+ if (args.length < 1) {
+ options.p = true;
+ }
+
+ if (_.isString(args)) {
+ args = [args];
+ }
+
+ // Parse incoming args. Accept either:
+ // alias foo=bar, or
+ // alias foo 'bar and so on'.
+ var key = args.join(' ');
+ var value = undefined;
+ if (String(key).indexOf('=') > -1) {
+ var parts = String(key).trim().split('=');
+ key = parts[0];
+ value = parts[1] || value;
+ } else {
+ var parts = String(key).trim().split(' ');
+ key = parts.shift();
+ value = parts.join(' ');
+ }
+
+ // Remove wrapped quotes from value.
+ if (value !== undefined) {
+ value = String(value).replace(/^[\"|\']|[\"|\']$/g, '');
+ }
+
+ // Pull list of aliases
+ var all = undefined;
+ try {
+ all = JSON.parse(vorpal.localStorage.getItem('aliases') || []);
+ } catch (e) {
+ all = [];
+ vorpal.localStorage.removeItem('aliases');
+ }
+
+ if (options.p) {
+ for (var i = 0; i < all.length; ++i) {
+ var item = vorpal.localStorage.getItem('alias|' + all[i]);
+ if (item !== undefined && item !== null) {
+ this.log('alias ' + all[i] + '=\'' + item + '\'');
+ }
+ }
+ } else {
+ if (value) {
+ vorpal.localStorage.setItem('alias|' + key, value);
+ _.remove(all, function (val) {
+ return val === key;
+ });
+ all.push(key);
+ } else {
+ var item = vorpal.localStorage.getItem('alias|' + key);
+ if (item !== undefined && item !== null) {
+ this.log('alias ' + key + '=\'' + item + '\'');
+ } else {
+ this.log('-cash: alias: ' + key + ': not found');
+ }
+ }
+
+ var aliases = {};
+ for (var i = 0; i < all.length; ++i) {
+ var item = vorpal.localStorage.getItem('alias|' + all[i]);
+ if (item !== undefined && item !== null) {
+ aliases[all[i]] = item;
+ }
+ }
+ vorpal._aliases = aliases;
+ }
+
+ vorpal.localStorage.setItem('aliases', JSON.stringify(all));
+ return 0;
+ }
+};
+
+module.exports = function (vorpal) {
+ if (vorpal === undefined) {
+ return alias;
+ }
+ vorpal.api.alias = alias;
+ vorpal.command('alias [name...]').option('-p', 'print all defined aliases in a reusable format').action(function (args, callback) {
+ args.options = args.options || {};
+ args.options.vorpal = vorpal;
+ return interfacer.call(this, {
+ command: alias,
+ args: args.name,
+ options: args.options,
+ callback: callback
+ });
+ });
+};
98 dist/commands/boilerplate.js
@@ -0,0 +1,98 @@
+'use strict';
+
+var interfacer = require('./../util/interfacer');
+
+/**
+ * This is a boilerplate for implementing a new command.
+ * Delete all of these comments / instructions before finishing.
+ */
+
+/**
+ * 0. Replace all instances of `cmdName` with
+ * the exact name of the command being implemented.
+ */
+
+var cmdName = {
+
+ /**
+ * The cmdName.exec method is exposed by Cash
+ * as the only public interfacer to your command.
+ */
+
+ exec: function exec(args, options) {
+ options = options || {};
+
+ /**
+ * 1. Validate arg input to include every
+ * possible form of input, such as:
+ *
+ * a. as a string:
+ * cash.foo('bar and so on', {option: true});
+ *
+ * b. as an array:
+ * cash.foo(['bar', 'and', 'so', 'on'], {option: true});
+ *
+ * c. as interpeted through Vorpal:
+ * cash('foo bar and so on --option');
+ */
+
+ /**
+ * 2. For errors, use `this.log` to print the
+ * error message to the user, and only return
+ * the error code (1, 2, etc.)
+ *
+ * if (args.length < 1) {
+ * this.log('foo: cannot bar: requires at least one file name');
+ * return 1;
+ * }
+ */
+
+ /**
+ * 3. For all other stdout to the user, use `this.log`.
+ * For large jobs that should stream logging a
+ * bit at a time, use multiple `this.log` statements
+ * and cash will handle the heavy lifting of piping
+ * and returning the final assembled output to the
+ * user in the case of programmatically executed
+ * commands.
+ */
+
+ /**
+ * 4. When complete with no errors, return 0;
+ *
+ * return 0;
+ */
+ }
+};
+
+module.exports = function (vorpal) {
+ /**
+ * When do a raw execution of the command
+ * without options, Vorpal is not used. In this
+ * case, the raw command is returned.
+ */
+ if (vorpal === undefined) {
+ return cmdName;
+ }
+ vorpal.api.cmdName = cmdName;
+ /**
+ * Registers the command in Vorpal.
+ * Command strings, options and their
+ * descriptions should exactly emulate
+ * existing commands.
+ */
+ vorpal.command('cmdName [files...]').option('-o, --option', 'option description').action(function (args, callback) {
+ args.options = args.options || {};
+ /**
+ * The interfacer method does a
+ * lot of heavy lifting on interfacing with
+ * the command properly.
+ */
+ return interfacer.call(this, {
+ command: cmdName,
+ args: args.files, // only pass in what you need from Vorpal
+ options: args.options, // split the options into their own arg
+ callback: callback
+ });
+ });
+};
116 dist/commands/cat.js
@@ -0,0 +1,116 @@
+'use strict';
+
+var _ = require('lodash');
+var fsAutocomplete = require('vorpal-autocomplete-fs');
+
+var fetch = require('./../util/fetch');
+var interfacer = require('./../util/interfacer');
+var lpad = require('./../util/lpad');
+var strip = require('./../util/stripAnsi');
+
+var cat = {
+ exec: function exec(args, options) {
+ var self = this;
+
+ // Input normalization
+ if (args === undefined) {
+ args = {
+ files: []
+ };
+ } else if (_.isString(args)) {
+ args = {
+ files: [args]
+ };
+ } else if (_.isArray(args)) {
+ args = {
+ files: args
+ };
+ }
+
+ options = options || {};
+
+ // -A handler
+ if (options.showall) {
+ options.shownonprinting = true;
+ options.showends = true;
+ options.showtabs = true;
+ }
+
+ // -e handler
+ if (options.e) {
+ options.shownonprinting = true;
+ options.showends = true;
+ }
+
+ // -t handler
+ if (options.t) {
+ options.shownonprinting = true;
+ options.showtabs = true;
+ }
+
+ var stdout = '';
+ try {
+ var stdin = fetch(args.files, args.stdin, {
+ onDirectory: function onDirectory(name) {
+ return 'cat: ' + name + ': Is a directory';
+ },
+ onInvalidFile: function onInvalidFile(name) {
+ return 'cat: ' + name + ': No such file or directory';
+ }
+ });
+ var ctr = 0;
+ for (var i = 0; i < stdin.length; ++i) {
+ // If -s, squeeze double blank lines to a
+ // single line.
+ if (options.squeezeblank) {
+ stdin[i] = stdin[i].replace(/\n\n\s*\n/g, '\n\n');
+ }
+ if (options.showtabs) {
+ stdin[i] = stdin[i].replace(/\t/g, '^I');
+ }
+ // Get rid of trailing line break because
+ // node logging does it anyway.
+ stdin[i] = stdin[i].replace(/\s$/, '');
+ var parts = String(stdin[i]).split('\n');
+ for (var j = 0; j < parts.length; ++j) {
+ var blank = strip(parts[j]).trim() === '';
+ // If -b, number every non-blank line
+ // If -n, number every line
+ var numbered = !blank && options.numbernonblank || options.number && !options.numbernonblank;
+ if (numbered) {
+ ctr++;
+ }
+ var numStr = numbered ? lpad(String(ctr), 6, ' ') + ' ' : '';
+ // If -E, append a $ to each line end.
+ var dollarStr = options.showends ? '$' : '';
+ var line = numStr + parts[j] + dollarStr;
+ self.log(line);
+ stdout += line + '\n';
+ }
+ }
+ return 0;
+ } catch (e) {
+ /* istanbul ignore next */
+ self.log(e.stack);
+ /* istanbul ignore next */
+ return 1;
+ }
+ }
+};
+
+module.exports = function (vorpal) {
+ if (vorpal === undefined) {
+ return cat;
+ }
+ vorpal.api.cat = cat;
+ vorpal.command('cat [files...]').option('-A, --show-all', 'equivalent to -vET').option('-b, --number-nonblank', 'number nonempty output lines, overrides -n').option('-e', 'equivalent to -vE').option('-E, --show-ends', 'display $ at end of each line').option('-n, --number', 'number all output lines').option('-s, --squeeze-blank', 'suppress repeated empty output lines').option('-t', 'equivalent to -vT').option('-T, --show-tabs', 'display TAB characters as ^I').option('-v, --show-nonprinting', 'use ^ and M- notation, except for LFD and TAB') // this doesn't work yet...
+ .autocomplete(fsAutocomplete()).action(function (args, cb) {
+ args.options = args.options || {};
+ return interfacer.call(this, {
+ command: cat,
+ args: args,
+ options: args.options,
+ callback: cb
+ });
+ });
+};
55 dist/commands/cd.js
@@ -0,0 +1,55 @@
+'use strict';
+
+var fsAutocomplete = require('vorpal-autocomplete-fs');
+var delimiter = require('./../delimiter');
+
+var interfacer = require('./../util/interfacer');
+
+var cd = {
+ exec: function exec(dir, options) {
+ var self = this;
+ var vpl = options.vorpal;
+ options = options || {};
+
+ dir = !dir ? delimiter.getHomeDir() : dir;
+ try {
+ process.chdir(dir);
+ if (vpl) {
+ delimiter.refresh(vpl);
+ }
+ return 0;
+ } catch (e) {
+ return cd.error.call(self, e, dir);
+ }
+ },
+ error: function error(e, dir) {
+ var status = undefined;
+ var stdout = undefined;
+ if (e.code === 'ENOENT' && e.syscall === 'uv_chdir') {
+ status = 1;
+ stdout = '-bash: cd: ' + dir + ': No such file or directory';
+ } else {
+ status = 2;
+ stdout = e.stack;
+ }
+ this.log(stdout);
+ return status;
+ }
+};
+
+module.exports = function (vorpal) {
+ if (vorpal === undefined) {
+ return cd;
+ }
+ vorpal.api.cd = cd;
+ vorpal.command('cd [dir]').autocomplete(fsAutocomplete({ directory: true })).action(function (args, callback) {
+ args.options = args.options || {};
+ args.options.vorpal = vorpal;
+ return interfacer.call(this, {
+ command: cd,
+ args: args.dir,
+ options: args.options,
+ callback: callback
+ });
+ });
+};
207 dist/commands/cp.js
@@ -0,0 +1,207 @@
+'use strict';
+
+var _ = require('lodash');
+var fs = require('fs');
+var fsAutocomplete = require('vorpal-autocomplete-fs');
+var path = require('path');
+var os = require('os');
+
+var expand = require('./../util/expand');
+var interfacer = require('./../util/interfacer');
+
+var cp = {
+ exec: function exec(args, options) {
+ var self = this;
+ options = options || {};
+
+ args = args === undefined ? [] : args;
+ args = _.isArray(args) ? args : args.split(' ');
+ args = _.filter(args, function (arg) {
+ return String(arg).trim() !== '';
+ });
+
+ options.noclobber = options.force === true ? false : options.noclobber;
+ options.recursive = options.R === true ? true : options.recursive;
+
+ if (args.length < 1) {
+ this.log('cp: missing file operand\nTry \'cp --help\' for more information.');
+ return 1;
+ }
+
+ if (args.length === 1) {
+ this.log('cp: missing destination file operand after ' + args[0] + '\nTry \'cp --help\' for more information.');
+ return 1;
+ }
+
+ args = expand(args);
+
+ var dest = args.pop();
+ var sources = args;
+
+ var exists = fs.existsSync(dest);
+ var stats = exists && fs.statSync(dest);
+
+ // Dest is not existing dir, but multiple sources given
+ if ((!exists || !stats.isDirectory()) && sources.length > 1) {
+ this.log('cp: target ' + dest + ' is not a directory');
+ return 1;
+ }
+
+ // Dest is an existing file, but no -f given
+ if (exists && stats.isFile() && options.noclobber) {
+ // just dont do anything
+ return 0;
+ }
+
+ if (options.recursive) {
+ sources.forEach(function (src, i) {
+ if (src[src.length - 1] === '/') {
+ sources[i] += '*';
+ } else if (fs.statSync(src).isDirectory() && !exists) {
+ sources[i] += '/*';
+ }
+ });
+ try {
+ fs.mkdirSync(dest, parseInt('0777', 8));
+ } catch (e) {
+ // like Unix's cp, keep going even if we can't create dest dir
+ }
+ }
+
+ sources = expand(sources);
+
+ sources.forEach(function (src) {
+ if (!fs.existsSync(src)) {
+ self.log('cp: cannot stat ' + src + ': No such file or directory');
+ return;
+ }
+
+ if (fs.statSync(src).isDirectory()) {
+ if (!options.recursive) {
+ self.log('cp: omitting directory ' + src);
+ } else {
+ // 'cp /a/source dest' should create 'source' in 'dest'
+ var newDest = path.join(dest, path.basename(src));
+ var checkDir = fs.statSync(src);
+ try {
+ fs.mkdirSync(newDest, checkDir.mode);
+ } catch (e) {
+ /* istanbul ignore if */
+ if (e.code !== 'EEXIST') {
+ throw new Error();
+ }
+ }
+ cpdirSyncRecursive.call(self, src, newDest, options);
+ }
+ return;
+ }
+
+ // If here, src is a file
+ // When copying to '/path/dir', iDest = '/path/dir/file1'
+ var iDest = dest;
+ if (fs.existsSync(dest) && fs.statSync(dest).isDirectory()) {
+ iDest = path.normalize(dest + '/' + path.basename(src));
+ }
+
+ if (fs.existsSync(iDest) && options.no_force) {
+ return;
+ }
+
+ copyFileSync.call(self, src, iDest);
+ });
+ }
+};
+
+function cpdirSyncRecursive(sourceDir, destDir, options) {
+ var self = this;
+ /* istanbul ignore if */
+ if (!options) {
+ options = {};
+ }
+ var checkDir = fs.statSync(sourceDir);
+ try {
+ fs.mkdirSync(destDir, checkDir.mode);
+ } catch (e) {
+ /* istanbul ignore if */
+ if (e.code !== 'EEXIST') {
+ throw e;
+ }
+ }
+ var files = fs.readdirSync(sourceDir);
+ for (var i = 0; i < files.length; i++) {
+ var srcFile = sourceDir + '/' + files[i];
+ var destFile = destDir + '/' + files[i];
+ var srcFileStat = fs.lstatSync(srcFile);
+ if (srcFileStat.isDirectory()) {
+ // recursion this thing right on back.
+ cpdirSyncRecursive.call(self, srcFile, destFile, options);
+ } else if (srcFileStat.isSymbolicLink()) {
+ var symlinkFull = fs.readlinkSync(srcFile);
+ fs.symlinkSync(symlinkFull, destFile, os.platform() === 'win32' ? 'junction' : null);
+ // At this point, we've hit a file actually worth copying... so copy it on over.
+ } else if (fs.existsSync(destFile) && options.noclobber) {
+ // be silent
+ } else {
+ copyFileSync.call(self, srcFile, destFile);
+ }
+ }
+}
+
+function copyFileSync(src, dest) {
+ /* istanbul ignore if */
+ if (!fs.existsSync(src)) {
+ this.log('cp: cannot stat ' + src + ': No such file or directory');
+ return;
+ }
+
+ var BUF_LENGTH = 64 * 1024;
+ var buf = new Buffer(BUF_LENGTH);
+ var bytesRead = BUF_LENGTH;
+ var pos = 0;
+ var fdr = null;
+ var fdw = null;
+
+ try {
+ fdr = fs.openSync(src, 'r');
+ } catch (e) {
+ /* istanbul ignore next */
+ this.log('cp: cannot open ' + src + ': ' + e.code);
+ /* istanbul ignore next */
+ return;
+ }
+
+ try {
+ fdw = fs.openSync(dest, 'w');
+ } catch (e) {
+ /* istanbul ignore next */
+ this.log('cp: cannot write to destination file ' + dest + ': ' + e.code);
+ /* istanbul ignore next */
+ return;
+ }
+
+ while (bytesRead === BUF_LENGTH) {
+ bytesRead = fs.readSync(fdr, buf, 0, BUF_LENGTH, pos);
+ fs.writeSync(fdw, buf, 0, bytesRead);
+ pos += bytesRead;
+ }
+
+ fs.closeSync(fdr);
+ fs.closeSync(fdw);
+ fs.chmodSync(dest, fs.statSync(src).mode);
+}
+
+module.exports = function (vorpal) {
+ if (vorpal === undefined) {
+ return cp;
+ }
+ vorpal.api.cp = cp;
+ vorpal.command('cp [args...]').option('-f, --force', 'do not prompt before overwriting').option('-n, --no-clobber', 'do not overwrite an existing file').option('-r, --recursive', 'copy directories recursively').option('-R', 'copy directories recursively').autocomplete(fsAutocomplete()).action(function (args, callback) {
+ args.options = args.options || {};
+ return interfacer.call(this, {
+ command: cp,
+ args: args.args,
+ options: args.options,
+ callback: callback
+ });
+ });
+};
78 dist/commands/echo.js
@@ -0,0 +1,78 @@
+'use strict';
+
+var _ = require('lodash');
+
+var interfacer = require('./../util/interfacer');
+
+var echo = {
+ exec: function exec(arg, options) {
+ var self = this;
+ options = options || {};
+
+ try {
+ var text = arg || '';
+ text = !_.isArray(text) ? [text] : text;
+ var result = text.join(' ');
+ var out = '';
+ if (options.e && !options.E) {
+ for (var i = 0; i < result.length; ++i) {
+ var nxt = result[i] + (result[i + 1] || '');
+ if (nxt === '\\b') {
+ out = out.slice(0, out.length - 1);
+ i++;
+ } else if (nxt === '\\c') {
+ break;
+ } else if (nxt === '\\n') {
+ out += '\n';
+ i++;
+ } else if (nxt === '\\r') {
+ out += '\r';
+ i++;
+ } else if (nxt === '\\t') {
+ out += ' ';
+ i++;
+ } else if (nxt === '\\\\') {
+ out += '\\';
+ i += 2;
+ } else {
+ out += result[i];
+ }
+ }
+ result = out;
+ }
+
+ // Bug: If nothing is passed, ensure we keep
+ // a blank line. Vorpal is designed to just
+ // eat blank lines, so we have a problem.
+ result = result === '' ? '' : result;
+
+ this.log(result);
+ return 0;
+ } catch (e) {
+ /* istanbul ignore next */
+ return echo.error.call(self, e);
+ }
+ },
+ error: function error(e) {
+ /* istanbul ignore next */
+ this.log(e.stack);
+ /* istanbul ignore next */
+ return 2;
+ }
+};
+
+module.exports = function (vorpal) {
+ if (vorpal === undefined) {
+ return echo;
+ }
+ vorpal.api.echo = echo;
+ vorpal.command('echo [arg...]').option('-e', 'enable interpretation of the following backslash escapes').option('-E', 'explicitly suppress interpretation of backslash escapes').action(function (args, callback) {
+ args.options = args.options || {};
+ return interfacer.call(this, {
+ command: echo,
+ args: args.arg,
+ options: args.options,
+ callback: callback
+ });
+ });
+};
3 dist/commands/grep.js
@@ -0,0 +1,3 @@
+'use strict';
+
+module.exports = require('vorpal-grep');
97 dist/commands/kill.js
@@ -0,0 +1,97 @@
+'use strict';
+
+var _ = require('lodash');
+var fkill = require('fkill');
+var os = require('os');
+
+var interfacer = require('./../util/interfacer');
+
+var usage = 'kill: usage: kill [-s sigspec | -n signum | -sigspec] pid | jobspec ... or kill -l [sigspec]';
+var windows = os.platform().indexOf('win') > -1;
+var signals = {
+ SIGKILL: 9,
+ SIGTERM: 15,
+ KILL: 9,
+ TERM: 15,
+ 9: 'KILL',
+ 15: 'TERM'
+};
+
+var kill = {
+ exec: function exec(args, options) {
+ options = options || {};
+
+ var procs = args;
+ procs = procs === undefined ? [] : procs;
+ procs = typeof procs === 'string' ? String(procs).split(' ') : procs;
+ procs = _.filter(procs, function (arg) {
+ return String(arg).trim() !== '';
+ });
+
+ function log(str) {
+ if (options.vorpal) {
+ options.vorpal.log(str);
+ } else {
+ /* istanbul ignore next */
+ console.log(str);
+ }
+ }
+
+ if (options.l !== undefined) {
+ if (options.l === true) {
+ this.log(' 9) SIGKILL 15) SIGTERM');
+ return 0;
+ }
+ if (signals[options.l]) {
+ this.log(signals[options.l]);
+ return 0;
+ }
+ this.log('-cash: kill: ' + options.l + ': invalid signal specification');
+ return 0;
+ }
+
+ if (procs.length < 1) {
+ this.log(usage);
+ return 0;
+ }
+
+ var forced = options['9'] === true || options.n === 9 || String(options.s).toLowerCase() === 'sigkill' || String(options.s).toLowerCase() === 'kill';
+ var opts = { force: forced };
+
+ var _loop = function _loop(i) {
+ var proc = procs[i];
+ proc = !isNaN(proc) ? parseFloat(proc) : proc;
+ proc = windows && isNaN(proc) && proc.indexOf('.') === -1 ? proc + '.exe' : proc;
+ fkill(proc, opts).then(function () {
+ // .. chill
+ }).catch(function (err) {
+ if (String(err.message).indexOf('failed') > -1) {
+ log('-cash: kill: (' + proc + ') - No such process');
+ }
+ });
+ };
+
+ for (var i = 0; i < procs.length; ++i) {
+ _loop(i);
+ }
+
+ return 0;
+ }
+};
+
+module.exports = function (vorpal) {
+ if (vorpal === undefined) {
+ return kill;
+ }
+ vorpal.api.kill = kill;
+ vorpal.command('kill [process...]').option('-9', 'sigkill').option('-s [sig]', 'sig is a signal name').option('-n [sig]', 'sig is a signal number').option('-l [sigspec]', 'list the signal names').action(function (args, callback) {
+ args.options = args.options || {};
+ args.options.vorpal = vorpal;
+ return interfacer.call(this, {
+ command: kill,
+ args: args.process,
+ options: args.options,
+ callback: callback
+ });
+ });
+};
3 dist/commands/less.js
@@ -0,0 +1,3 @@
+'use strict';
+
+module.exports = require('vorpal-less');
353 dist/commands/ls.js
@@ -0,0 +1,353 @@
+'use strict';
+
+var _ = require('lodash');
+var chalk = require('chalk');
+var filesize = require('filesize');
+var fs = require('fs');
+var fsAutocomplete = require('vorpal-autocomplete-fs');
+var os = require('os');
+
+var colorFile = require('./../util/colorFile');
+var columnify = require('./../util/columnify');
+var dateConverter = require('./../util/converter.date');
+var fileFromPath = require('./../util/fileFromPath');
+var interfacer = require('./../util/interfacer');
+var pad = require('./../util/pad');
+var lpad = require('./../util/lpad');
+var permissionsConverter = require('./../util/converter.permissions');
+var strip = require('./../util/stripAnsi');
+var walkDir = require('./../util/walkDir');
+var walkDirRecursive = require('./../util/walkDirRecursive');
+
+var pads = { pad: pad, lpad: lpad };
+
+var ls = {
+
+ /**
+ * Main command execution.
+ *
+ * @param {Object} args
+ * @return {Object} { status, stdout }
+ * @api public
+ */
+
+ exec: function exec(paths, options) {
+ var self = this;
+ paths = !_.isArray(paths) && _.isObject(paths) ? paths.paths : paths;
+ paths = paths || ['.'];
+ paths = _.isArray(paths) ? paths : [paths];
+ options = options || {};
+ try {
+ var results = [];
+ for (var i = 0; i < paths.length; ++i) {
+ if (options.recursive) {
+ var result = ls.execDirRecursive(paths[i], options);
+ results = results.concat(result);
+ } else {
+ var result = ls.execDir(paths[i], options);
+ results.push(result);
+ }
+ }
+ var stdout = ls.formatAll(results, options);
+ if (strip(stdout).trim() !== '') {
+ self.log(String(stdout).replace(/\\/g, '/'));
+ }
+ return 0;
+ } catch (e) {
+ /* istanbul ignore next */
+ return ls.error.call(self, e);
+ }
+ },
+
+
+ /**
+ * Returns ls stderr and response codes
+ * for errors.
+ *
+ * @param {Error} e
+ * @return {Object} { status, stdout }
+ * @api private
+ */
+
+ error: function error(e) {
+ /* istanbul ignore next */
+ var status = undefined;
+ /* istanbul ignore next */
+ var stdout = undefined;
+ /* istanbul ignore next */
+ if (e.code === 'ENOENT' && e.syscall === 'scandir') {
+ status = 1;
+ stdout = 'ls: cannot access: No such file or directory';
+ } else {
+ /* istanbul ignore next */
+ status = 2;
+ /* istanbul ignore next */
+ stdout = e.stack;
+ }
+ /* istanbul ignore next */
+ this.log(stdout);
+ /* istanbul ignore next */
+ return status;
+ },
+
+
+ /**
+ * Recursively executes `execDir`.
+ * For use with `ls -R`.
+ *
+ * @param {String} path
+ * @param {Object} options
+ * @return {String} results
+ * @api private
+ */
+
+ execDirRecursive: function execDirRecursive(path, options) {
+ var self = this;
+ var results = [];
+ walkDirRecursive(path, function (pth) {
+ var result = self.execDir(pth, options);
+ results.push(result);
+ });
+ return results;
+ },
+
+
+ /**
+ * Executes `ls` functionality
+ * for a given directory.
+ *
+ * @param {String} path
+ * @param {Object} options
+ * @return {String} results
+ * @api private
+ */
+
+ execDir: function execDir(path, options) {
+ var files = [];
+ var rawFiles = [];
+ var totalSize = 0;
+
+ function pushFile(file, data) {
+ rawFiles.push({
+ file: file,
+ data: data
+ });
+ }
+
+ // Add in implied current and parent dirs.
+ pushFile('.', fs.statSync('.'));
+ pushFile('..', fs.statSync('..'));
+
+ // Walk the passed in directory,
+ // pushing the results into `rawFiles`.
+ walkDir(path, pushFile);
+
+ // Sort alphabetically be default,
+ // unless -U is specified, in which case
+ // we don't sort.
+ if (!options.U) {
+ rawFiles = rawFiles.sort(function (a, b) {
+ // Sort by size.
+ if (options.S) {
+ // Hack for windows - a directory lising
+ // in linux says the size is 4096, and Windows
+ // it's 0, leading to inconsistent sorts based
+ // on size, and failing tests.
+ var win = os.platform() === 'win32';
+ a.data.size = win && a.data.isDirectory() && a.data.size === 0 ? 4096 : a.data.size;
+ b.data.size = win && b.data.isDirectory() && b.data.size === 0 ? 4096 : b.data.size;
+ return a.data.size > b.data.size ? -1 : a.data.size < b.data.size ? 1 : 0;
+ }
+ if (options.t) {
+ // Sort by date modified.
+ return a.data.mtime < b.data.mtime ? 1 : b.data.mtime < a.data.mtime ? -1 : 0;
+ }
+ // Sort alphabetically - default.
+ var aFileName = fileFromPath(a.file).trim().toLowerCase().replace(/\W/g, '');
+ var bFileName = fileFromPath(b.file).trim().toLowerCase().replace(/\W/g, '');
+ return aFileName > bFileName ? 1 : aFileName < bFileName ? -1 : 0;
+ });
+ }
+
+ // Reverse whatever sort the user specified.
+ if (options.reverse) {
+ rawFiles.reverse();
+ }
+
+ var _loop = function _loop(i) {
+ var file = rawFiles[i].file;
+ var data = rawFiles[i].data;
+ var fileShort = fileFromPath(file);
+ var dotted = fileShort && fileShort.charAt(0) === '.';
+ var implied = fileShort === '..' || fileShort === '.';
+ var type = data.isDirectory() ? 'd' : '-';
+ var permissions = permissionsConverter.modeToRWX(data.mode);
+ var hardLinks = data.nlink;
+ var size = options.humanreadable ? filesize(data.size, { unix: true }) : data.size;
+ var modified = dateConverter.unix(data.mtime);
+ var owner = data.uid;
+ var group = data.gid;
+ var inode = data.ino;
+
+ totalSize += data.size;
+
+ var fileName = fileShort;
+
+ // If --classify, add '/' to end of folders.
+ fileName = options.classify && data.isDirectory() ? fileName + '/' : fileName;
+
+ // If getting --directory, give full path.
+ fileName = options.directory && file === '.' ? path : fileName;
+
+ // Color the files based on $LS_COLORS
+ fileName = data.isFile() ? colorFile(fileName) : fileName;
+
+ // If not already colored and is executable,
+ // make it green
+ var colored = strip(fileName) !== fileName;
+ if (String(permissions).indexOf('x') > -1 && !colored && data.isFile()) {
+ fileName = chalk.green(fileName);
+ }
+
+ // If --quote-name, wrap in double quotes;
+ fileName = options.quotename ? '"' + fileName + '"' : fileName;
+
+ // Make directories cyan.
+ fileName = data.isDirectory() ? chalk.cyan(fileName) : fileName;
+
+ var include = function () {
+ var directory = options.directory;
+ var all = options.all;
+ var almostAll = options.almostall;
+ var result = false;
+ if (directory && file !== '.') {
+ result = false;
+ } else if (!dotted) {
+ result = true;
+ } else if (all) {
+ result = true;
+ } else if (!implied && almostAll) {
+ result = true;
+ } else if (directory && file === '.') {
+ result = true;
+ }
+ return result;
+ }();
+
+ var details = [type + permissions, hardLinks, owner, group, size, modified, fileName];
+
+ if (options.inode) {
+ details.unshift(inode);
+ }
+
+ var result = options.l && !options.x ? details : fileName;
+
+ if (include) {
+ files.push(result);
+ }
+ };
+
+ for (var i = 0; i < rawFiles.length; ++i) {
+ _loop(i);
+ }
+
+ var result = undefined;
+
+ // If we have the detail view, draw out
+ // all of the details of each file.
+ // Otherwise, just throw the file names
+ // into columns.
+ if (_.isArray(files[0])) {
+ var longest = {};
+ for (var i = 0; i < files.length; ++i) {
+ for (var j = 0; j < files[i].length; ++j) {
+ var len = String(files[i][j]).length;
+ longest[j] = longest[j] || 0;
+ longest[j] = len > longest[j] ? len : longest[j];
+ }
+ }
+
+ var newFiles = [];
+ for (var i = 0; i < files.length; ++i) {
+ var glob = '';
+ for (var j = 0; j < files[i].length; ++j) {
+ var padFn = j === files[i].length - 1 ? 'pad' : 'lpad';
+ if (j === files[i].length - 1) {
+ glob += String(files[i][j]);
+ } else {
+ glob += pads[padFn](String(files[i][j]), longest[j], ' ') + ' ';
+ }
+ }
+ newFiles.push(String(glob));
+ }
+ result = newFiles.join('\n');
+ } else if (options['1']) {
+ result = files.join('\n');
+ } else {
+ var opt = {};
+ if (options.width) {
+ opt.width = options.width;
+ }
+ result = columnify(files, opt);
+ }
+
+ return {
+ path: path,
+ size: options.humanreadable ? filesize(totalSize, { unix: true }) : totalSize,
+ results: result
+ };
+ },
+
+
+ /**
+ * Concatenates the results of multiple
+ * `execDir` functions into their proper
+ * form based on options provided.
+ *
+ * @param {String} results
+ * @param {Object} options
+ * @return {String} stdout
+ * @api private
+ */
+
+ formatAll: function formatAll(results, options) {
+ var stdout = '';
+ if (results.length > 1) {
+ for (var i = 0; i < results.length; ++i) {
+ stdout += results[i].path + ':\n';
+ if (options.l) {
+ stdout += 'total ' + results[i].size + '\n';
+ }
+ stdout += results[i].results;
+ if (i !== results.length - 1) {
+ stdout += '\n\n';
+ }
+ }
+ } else if (results.length === 1) {
+ if (options.l && !options.x) {
+ stdout += 'total ' + results[0].size + '\n';
+ }
+ stdout += results[0].results;
+ }
+ return stdout;
+ }
+};
+
+/**
+ * Expose as a Vorpal extension.
+ */
+
+module.exports = function (vorpal) {
+ if (vorpal === undefined) {
+ return ls;
+ }
+ vorpal.api.ls = ls;
+ vorpal.command('ls [paths...]').option('-a, --all', 'do not ignore entries starting with .').option('-A, --almost-all', 'do not list implied . and ..').option('-d, --directory', 'list directory entries instead of contents, and do not dereference symbolic links').option('-F, --classify', 'append indicator (one of */=>@|) to entries').option('-h, --human-readable', 'with -l, print sizes in human readable format (e.g., 1K 234M 2G)').option('-i, --inode', 'print the index number of each file').option('-l', 'use a long listing format').option('-Q, --quote-name', 'enclose entry names in double quotes').option('-r, --reverse', 'reverse order while sorting').option('-R, --recursive', 'list subdirectories recursively').option('-S', 'sort by file size').option('-t', 'sort by modification time, newest first').option('-U', 'do not sort; list entries in directory order').option('-w, --width [COLS]', 'assume screen width instead of current value').option('-x', 'list entries by lines instead of columns').option('-1', 'list one file per line').autocomplete(fsAutocomplete()).action(function (args, cb) {
+ return interfacer.call(this, {
+ command: ls,
+ args: args.paths,
+ options: args.options,
+ callback: cb
+ });
+ });
+};
86 dist/commands/mkdir.js
@@ -0,0 +1,86 @@
+'use strict';
+
+var fs = require('fs');
+var path = require('path');
+var fsAutocomplete = require('vorpal-autocomplete-fs');
+
+var interfacer = require('./../util/interfacer');
+
+var mkdir = {
+ exec: function exec(args, options) {
+ var self = this;
+ var dirs = args || [];
+ options = options || {};
+
+ if (typeof dirs === 'string') {
+ dirs = dirs.split(' ');
+ }
+
+ dirs = dirs.filter(function (str) {
+ return String(str).trim() !== '';
+ });
+
+ if (dirs.length < 1) {
+ this.log('mkdir: missing operand\nTry \'mkdir --help\' for more information.');
+ }
+
+ dirs.forEach(function (dir) {
+ if (fs.existsSync(dir)) {
+ if (!options.parents) {
+ self.log('mkdir: cannot create directory ' + dir + ': File exists');
+ }
+ return;
+ }
+
+ // Base dir does not exist, and no -p option given
+ var baseDir = path.dirname(dir);
+ if (!fs.existsSync(baseDir) && !options.parents) {
+ self.log('mkdir: cannot create directory ' + dir + ': No such file or directory');
+ return;
+ }
+
+ if (options.parents) {
+ mkdirSyncRecursive.call(self, dir, options);
+ } else {
+ fs.mkdirSync(dir, parseInt('0777', 8));
+ if (options.verbose) {
+ self.log('mkdir: created directory ' + dir);
+ }
+ }
+ });
+ return 0;
+ }
+};
+
+function mkdirSyncRecursive(dir, options) {
+ var baseDir = path.dirname(dir);
+ if (fs.existsSync(baseDir)) {
+ fs.mkdirSync(dir, parseInt('0777', 8));
+ if (options.verbose) {
+ this.log('mkdir: created directory ' + dir);
+ }
+ return;
+ }
+ mkdirSyncRecursive.call(this, baseDir, options);
+ fs.mkdirSync(dir, parseInt('0777', 8));
+ if (options.verbose) {
+ this.log('mkdir: created directory ' + dir);
+ }
+}
+
+module.exports = function (vorpal) {
+ if (vorpal === undefined) {
+ return mkdir;
+ }
+ vorpal.api.mkdir = mkdir;
+ vorpal.command('mkdir [directory...]').option('-p, --parents', 'no error if existing, make parent directories as needed').option('-v, --verbose', 'print a message for each created directory').autocomplete(fsAutocomplete({ directory: true })).action(function (args, callback) {
+ args.options = args.options || {};
+ args.options.vorpal = vorpal;
+ return interfacer.call(this, {
+ command: mkdir,
+ args: args.directory,
+ options: args.options,
+ callback: callback
+ });
+ });
+};
105 dist/commands/mv.js
@@ -0,0 +1,105 @@
+'use strict';
+
+var _ = require('lodash');
+var fs = require('fs');
+var fsAutocomplete = require('vorpal-autocomplete-fs');
+var path = require('path');
+
+var expand = require('./../util/expand');
+var interfacer = require('./../util/interfacer');
+
+var mv = {
+ exec: function exec(args, options) {
+ var self = this;
+ options = options || {};
+
+ args = args === undefined ? [] : args;
+ args = _.isArray(args) ? args : args.split(' ');
+ args = _.filter(args, function (arg) {
+ return String(arg).trim() !== '';
+ });
+
+ options.noclobber = options.force === true ? false : options.noclobber;
+
+ if (args.length < 1) {
+ this.log('mv: missing file operand\nTry \'mv --help\' for more information.');
+ return 1;
+ }
+
+ if (args.length === 1) {
+ this.log('mv: missing destination file operand after ' + args[0] + '\nTry \'mv --help\' for more information.');
+ return 1;
+ }
+
+ args = expand(args);
+
+ var dest = args.pop();
+ var sources = args;
+
+ var exists = fs.existsSync(dest);
+ var stats = exists && fs.statSync(dest);
+
+ // Dest is not existing dir, but multiple sources given
+ if ((!exists || !stats.isDirectory()) && sources.length > 1) {
+ this.log('mv: target ' + dest + ' is not a directory');
+ return 1;
+ }
+
+ // Dest is an existing file, but no -f given
+ if (exists && stats.isFile() && options.noclobber) {
+ // just dont do anything
+ return 0;
+ }
+
+ if (options.striptrailingslashes) {
+ sources = sources.map(function (src) {
+ return String(src).replace(/\/$/g, '');
+ });
+ }
+
+ sources.forEach(function (src) {
+ if (!fs.existsSync(src)) {
+ self.log('mv: cannot stat ' + src + ': No such file or directory');
+ return;
+ }
+
+ // When copying to '/path/dir', iDest = '/path/dir/file1'
+ var iDest = dest;
+ if (exists && stats.isDirectory()) {
+ iDest = path.normalize(dest + '/' + path.basename(src));
+ }
+
+ // If the file exists and we're not clobbering, skip.
+ if (fs.existsSync(iDest) && options.noclobber) {
+ return;
+ }
+
+ if (path.resolve(src) === path.dirname(path.resolve(iDest))) {
+ self.log('mv: ' + src + ' and ' + iDest + ' are the same file');
+ return;
+ }
+
+ fs.renameSync(src, iDest);
+ if (options.verbose === true) {
+ self.log(String(src + ' -> ' + iDest).replace(/\\/g, '/'));
+ }
+ });
+ }
+};
+
+module.exports = function (vorpal) {
+ if (vorpal === undefined) {
+ return mv;
+ }
+ vorpal.api.mv = mv;
+ vorpal.command('mv [args...]').option('-f, --force', 'do not prompt before overwriting').option('-n, --no-clobber', 'do not overwrite an existing file').option('--striptrailingslashes', 'remove any trailing slashes from each source') // vorpal bug, need to add dashes between words
+ .option('-v, --verbose', 'explain what is being done').autocomplete(fsAutocomplete()).action(function (args, callback) {
+ args.options = args.options || {};
+ return interfacer.call(this, {
+ command: mv,
+ args: args.args,
+ options: args.options,
+ callback: callback
+ });
+ });
+};
28 dist/commands/pwd.js
@@ -0,0 +1,28 @@
+'use strict';
+
+var path = require('path');
+
+var interfacer = require('./../util/interfacer');
+
+var pwd = {
+ exec: function exec() {
+ this.log(path.resolve(process.cwd()).replace(/\\/g, '/'));
+ return 0;
+ }
+};
+
+module.exports = function (vorpal) {
+ if (vorpal === undefined) {
+ return pwd;
+ }
+ vorpal.api.pwd = pwd;
+ vorpal.command('pwd [files...]').action(function (args, callback) {
+ args.options = args.options || {};
+ return interfacer.call(this, {
+ command: pwd,
+ args: args.files,
+ options: args.options,
+ callback: callback
+ });
+ });
+};
171 dist/commands/rm.js
@@ -0,0 +1,171 @@
+'use strict';
+
+var fs = require('fs');
+var fsAutocomplete = require('vorpal-autocomplete-fs');
+
+var expand = require('./../util/expand');
+var interfacer = require('./../util/interfacer');
+var unlinkSync = require('./../util/unlinkSync');
+
+var rm = {
+ exec: function exec(args, options) {
+ var self = this;
+ options = options || {};
+ options.recursive = options.R ? options.R : options.recursive;
+
+ var files = args;
+ files = files === undefined ? [] : files;
+ files = typeof files === 'string' ? [files] : files;
+
+ files = expand(files);
+
+ files.forEach(function (file) {
+ if (!fs.existsSync(file)) {
+ // Path does not exist, no force flag given
+ if (!options.force) {
+ self.log('rm: cannot remove ' + file + ': No such file or directory');
+ return 2;
+ }
+ /* istanbul ignore next */
+ return 0;
+ }
+
+ var stats = fs.lstatSync(file);
+ if (stats.isFile() || stats.isSymbolicLink()) {
+ if (options.force) {
+ unlinkSync(file);
+ return 0;
+ }
+
+ if (isWriteable(file)) {
+ unlinkSync(file);
+ } else {
+ /* istanbul ignore next */
+ self.log('rm: cannot remove ' + file + ': permission denied');
+ /* istanbul ignore next */
+ return 2;
+ }
+ return 0;
+ }
+
+ // Path is an existing directory, but no -r flag given
+ if (stats.isDirectory() && !options.recursive) {
+ self.log('rm: cannot remove: path is a directory');
+ return 2;
+ }
+
+ // Recursively remove existing directory
+ if (stats.isDirectory() && options.recursive) {
+ rmdirSyncRecursive.call(self, file, options.force, options.dir);
+ }
+ });
+ }
+};
+
+function rmdirSyncRecursive(dir, force, removeEmptyDir) {
+ var self = this;
+ var files = undefined;
+ files = fs.readdirSync(dir);
+
+ // Loop through and delete everything in the sub-tree after checking it
+ for (var i = 0; i < files.length; i++) {
+ var file = dir + '/' + files[i];
+ var currFile = fs.lstatSync(file);
+
+ if (currFile.isDirectory()) {
+ // Recursive function back to the beginning
+ rmdirSyncRecursive(file, force, removeEmptyDir);
+ } else if (currFile.isSymbolicLink()) {
+ // Unlink symlinks
+ /* istanbul ignore next */
+ if (force || isWriteable(file)) {
+ try {
+ unlinkSync(file);
+ } catch (e) {
+ self.log('rm: cannot remove ' + file + ': code ' + e.code);
+ return 2;
+ }
+ }
+ } else if (force || isWriteable(file)) {
+ // Assume it's a file.
+ try {
+ unlinkSync(file);
+ } catch (e) {
+ /* istanbul ignore next */
+ self.log('rm: cannot remove ' + file + ': code ' + e.code);
+ /* istanbul ignore next */
+ return 2;
+ }
+ }
+ }
+
+ // Now that we know everything in the sub-tree has been deleted,
+ // we can delete the main directory.
+ var result = undefined;
+ try {
+ // Retry on windows, sometimes it takes a little time before all the files in the directory are gone
+ var start = Date.now();
+ while (true) {
+ try {
+ result = fs.rmdirSync(dir);
+ /* istanbul ignore next */
+ if (fs.existsSync(dir)) {
+ throw new Error('EAGAIN');
+ }
+ break;
+ } catch (er) {
+ // In addition to error codes, also check if the directory still exists and loop again if true
+ /* istanbul ignore next */
+ if (process.platform === 'win32' && (er.code === 'ENOTEMPTY' || er.code === 'EBUSY' || er.code === 'EPERM' || er.code === 'EAGAIN')) {
+ if (Date.now() - start > 1000) {
+ throw er;
+ }
+ /* istanbul ignore next */
+ } else if (er.code === 'ENOENT') {
+ // Directory did not exist, deletion was successful
+ break;
+ /* istanbul ignore next */
+ } else {
+ throw er;
+ }
+ }
+ }
+ } catch (e) {
+ /* istanbul ignore next */
+ self.log('rm: cannot remove directory ' + dir + ': code ' + e.code);
+ /* istanbul ignore next */
+ return 2;
+ }
+ return result;
+}
+
+// Hack to determine if file has write permissions for current user
+// Avoids having to check user, group, etc, but it's probably slow.
+function isWriteable(file) {
+ var writePermission = true;
+ try {
+ var __fd = fs.openSync(file, 'a');
+ fs.closeSync(__fd);
+ } catch (e) {
+ /* istanbul ignore next */
+ writePermission = false;
+ }
+
+ return writePermission;
+}
+
+module.exports = function (vorpal) {
+ if (vorpal === undefined) {
+ return rm;
+ }
+ vorpal.api.rm = rm;
+ vorpal.command('rm [files...]').option('-f, --force', 'ignore nonexistent files and arguments, never prompt').option('-r, --recursive', 'remove directories and their contents recursively').option('-R', 'remove directories and their contents recursively').autocomplete(fsAutocomplete()).action(function (args, callback) {
+ args.options = args.options || {};
+ return interfacer.call(this, {
+ command: rm,
+ args: args.files,
+ options: args.options,
+ callback: callback
+ });
+ });
+};
269 dist/commands/sort.js
@@ -0,0 +1,269 @@
+'use strict';
+
+var _ = require('lodash');
+var fs = require('fs');
+var fsAutocomplete = require('vorpal-autocomplete-fs');
+
+var fetch = require('./../util/fetch');
+var interfacer = require('./../util/interfacer');
+var strip = require('./../util/stripAnsi');
+
+var sort = {
+
+ counter: 0,
+
+ stdin: '',
+
+ exec: function exec(args, options) {
+ var self = this;
+
+ // Hack to handle multiple calls
+ // due to fragmented stdin, such as
+ // by piping. In essence, we're waiting
+ // 100 milliseconds for all of the
+ // requests to come in, and then running
+ // sort. Only applies when sort is called
+ // through a piped command.
+ /* istanbul ignore next */
+ if (args && args.stdin && options.bypass !== true) {
+ sort.counter++;
+ sort.stdin += args.stdin + '\n';
+ if (sort.counter === 1) {
+ setTimeout(function () {
+ sort.counter = 0;
+ args.stdin = sort.stdin;
+ sort.stdin = '';
+ options.bypass = true;
+ sort.exec.call(self, args, options);
+ }, 100);
+ }
+ return;
+ }
+ sort.counter = 0;
+ sort.stdin = '';
+
+ // Input normalization
+ if (args === undefined) {
+ args = {
+ files: []
+ };
+ } else if (_.isString(args)) {
+ args = {
+ files: [args]
+ };
+ } else if (_.isArray(args)) {
+ args = {
+ files: args
+ };
+ }
+
+ options = options || {};
+
+ function log(stdout) {
+ if (options.output) {
+ if (options.output === true) {
+ self.log('sort: option \'--output\' requires an argument\nTry \'sort --help\' for more information.');
+ return 0;
+ }
+ try {
+ fs.writeFileSync(options.output, stdout);
+ return 0;
+ } catch (e) {
+ if (e.code === 'ENOENT') {
+ self.log('sort: open failed: ' + options.output + ': No such file or directory');
+ } else {
+ /* istanbul ignore next */
+ self.log('sort: open failed: ' + options.output + ': ' + e.code);
+ }
+ return 2;
+ }
+ } else {
+ self.log(stdout);
+ }
+ }
+
+ try {
+ var stdin = fetch(args.files, args.stdin, {
+ onDirectory: function onDirectory(name) {
+ /* istanbul ignore next */
+ return 'sort: read failed: ' + name + ': Is a directory';
+ },
+ onInvalidFile: function onInvalidFile(name) {
+ /* istanbul ignore next */
+ return 'sort: cannot read: ' + name + ': No such file or directory';
+ }
+ });
+
+ var combined = '';
+ for (var i = 0; i < stdin.length; ++i) {
+ // Get rid of trailing line break because
+ // node logging does it anyway.
+ combined += stdin[i];
+ }
+
+ combined = combined.replace(/\s$/, '');
+ var parts = String(combined).split('\n');
+
+ if (options.check) {
+ // Check if the thing was already sorted.
+ var original = String(combined).split('\n');
+ var disorder = undefined;
+ for (var i = 0; i < original.length; ++i) {
+ var a = original[i];
+ var b = original[i + 1];
+ if (a && b) {
+ if (!isNaN(a) && !isNaN(b) && parseFloat(a) > parseFloat(b)) {
+ /* istanbul ignore next */
+ disorder = true;
+ } else if (a > b) {
+ disorder = true;
+ }
+ if (disorder) {
+ // To do: right now, I don't say the file
+ // name of the bad sorted item - I have to
+ // figure this out as I join all the files
+ // together beforehand and lose track.
+ disorder = 'sort: -:' + (i + 2) + ': disorder: ' + b;
+ break;
+ }
+ }
+ }
+ if (disorder) {
+ log(disorder);
+ return;
+ }
+ }
+
+ parts = parts.sort(function (a, b) {
+ var aAlpha = strip(a).replace(/\W+/g, '');
+ var bAlpha = strip(b).replace(/\W+/g, '');
+ var aNumeric = strip(a).replace(/\D/g, '');
+ var bNumeric = strip(b).replace(/\D/g, '');
+ if (options.humannumericsort) {
+ var aHuman = parseHumanReadableNumbers(strip(a));
+ var bHuman = parseHumanReadableNumbers(strip(b));
+ if (aHuman.group < bHuman.group) {
+ return -1;
+ } else if (aHuman.group > bHuman.group) {
+ return 1;
+ } else if (aHuman.num < bHuman.num) {
+ return -1;
+ } else if (aHuman.num > bHuman.num) {
+ return 1;
+ }
+ return aAlpha.localeCompare(bAlpha);
+ } else if (options.monthsort) {
+ var aMonth = parseMonths(strip(a));
+ var bMonth = parseMonths(strip(b));
+ var result = aMonth - bMonth;
+ if (aMonth === bMonth) {
+ result = aAlpha.localeCompare(bAlpha);
+ }
+ return result;
+ } else if (options.numericsort) {
+ var result = aNumeric - bNumeric;
+ result = result === 0 ? aAlpha.localeCompare(bAlpha) : result;
+ return result;
+ }
+ return aAlpha.localeCompare(bAlpha);
+ });
+
+ if (options.randomsort) {
+ fisherYatesShuffle(parts);
+ }
+
+ if (options.reverse) {
+ parts.reverse();
+ }
+
+ var out = parts.join('\n');
+ if (String(out).trim() !== '') {
+ log(out);
+ }
+
+ return;
+ } catch (e) {
+ /* istanbul ignore next */
+ self.log(e.stack);
+ /* istanbul ignore next */
+ return;
+ }
+ }
+};
+
+// This shit is gnarly.
+// Per the coreutils sort.c:
+// <none/unknown> < K/k < M < G < T < P < E < Z < Y
+var humanOrdering = { '': 0, 'K': 1, 'k': 1, 'M': 2, 'G': 3, 'T': 4, 'P': 5, 'E': 6, 'Z': 7 };
+var humanReadableSort = new RegExp(/^([0-9]+)?[\.]?[0-9]+[K|k|M|G|T|P|E|Z|Y]/g);
+function parseHumanReadableNumbers(nbr) {
+ nbr = String(nbr).replace(/(\r\n|\n|\r)/gm, '');
+ if (String(nbr).match(humanReadableSort)) {
+ var num = parseFloat(String(nbr).replace(/[a-zA-Z]/g, '').trim());
+ var group = humanOrdering[String(nbr).replace(/[^a-zA-Z]/g, '').trim()] || 0;
+ return {
+ num: num,
+ group: group
+ };
+ }
+ var isNumber = String(nbr).match(/^[0-9]/);
+ var stripped = isNumber ? parseFloat(String(nbr).replace(/[^0-9.]/g, '')) : 'NaN';
+ var result = !isNaN(stripped) ? stripped : -99999999999;
+ return {
+ num: result,
+ group: 0
+ };
+}
+
+var monthOrdering = {
+ jan: 1,
+ feb: 2,
+ mar: 3,
+ apr: 4,
+ may: 5,
+ jun: 6,
+ jul: 7,
+ aug: 8,
+ sep: 9,
+ oct: 10,
+ nov: 11,
+ dec: 12
+};
+
+var months = new RegExp(/^(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)/i);
+function parseMonths(str) {
+ var match = String(str).match(months);
+ if (match) {
+ return monthOrdering[String(str.slice(0, 3).toLowerCase())];
+ }
+ return 0;
+}
+
+function fisherYatesShuffle(array) {
+ var m = array.length;
+ var t = undefined;
+ var i = undefined;
+ while (m) {
+ i = Math.floor(Math.random() * m--);
+ t = array[m];
+ array[m] = array[i];
+ array[i] = t;
+ }
+ return array;
+}
+
+module.exports = function (vorpal) {
+ if (vorpal === undefined) {
+ return sort;
+ }
+ vorpal.api.sort = sort;
+ vorpal.command('sort [files...]').option('-M, --month-sort', 'compare (unknown) < \'JAN\' < ... < \'DEC\'').option('-h, --human-numeric-sort', 'compare human readable numbers (e.g., 2K 1G)').option('-n, --numeric-sort', 'compare according to string numerical value').option('-R, --random-sort', 'sort by random hash of keys').option('-r, --reverse', 'reverse the result of comparisons').option('-c, --check', 'check for sorted input; do not sort').option('-o, --output [file]', 'write result to file instead of standard output').autocomplete(fsAutocomplete()).action(function (args, callback) {
+ args.options = args.options || {};
+ return interfacer.call(this, {
+ command: sort,
+ args: args,
+ options: args.options,
+ callback: callback
+ });
+ });
+};
151 dist/commands/touch.js
@@ -0,0 +1,151 @@
+'use strict';
+
+var _ = require('lodash');
+var fs = require('fs-extra');
+var fsAutocomplete = require('vorpal-autocomplete-fs');
+
+var interfacer = require('./../util/interfacer');
+require('./../lib/sugar');
+
+var touch = {
+
+ /**
+ * Main command execution.
+ *
+ * @param {Object} args
+ * @return {Object} { status, stdout }
+ * @api public
+ */
+
+ exec: function exec(files, options) {
+ var self = this;
+ files = files || ['.'];
+ files = !_.isArray(files) ? [files] : files;
+ options = options || {};
+
+ // If any version of --no-create is passed, change it to false.
+ options.create = options.create === true ? false : options.create;
+
+ // If --time is passed, ensure a valid param is called in
+ // and map it to -a or -m, as this is the equivalent of these.
+ // Throw an error if nothing valid passed.
+ if (options.time) {
+ var a = ['access', 'atime', 'use'];
+ var m = ['modify', 'mtime'];
+ var opt = a.indexOf(options.time) > -1 ? 'a' : m.indexOf(options.time) > -1 ? 'm' : undefined;
+ if (!opt) {
+ var error = 'touch: invalid argument "' + options.time + '" for "--time"\n' + 'Valid arguments are:\n' + ' - "atime", "access", "use"\n' + ' - "mtime", "modify"\n' + 'Try \'touch --help\' for more information.';
+ // I think this is the stupidest thing
+ // I've ever written.
+ try {
+ throw new Error(error);
+ } catch (e) {
+ return touch.error.call(self, e);
+ }
+ } else {
+ options[opt] = true;
+ }
+ }
+
+ try {
+ var err = false;
+ for (var i = 0; i < files.length; ++i) {
+ try {
+ touch.file(files[i], options);
+ } catch (e) {
+ err = e;
+ break;
+ }
+ }
+ if (err) {
+ return touch.error.call(self, err);
+ }
+ return 0;
+ } catch (e) {
+ return touch.error.call(self, e);
+ }
+ },
+
+ /**
+ * Returns touch stderr and response codes
+ * for errors.
+ *
+ * @param {Error} e
+ * @return {Object} { status, stdout }
+ * @api private
+ */
+
+ error: function error(e) {
+ this.log(e.message);
+ return 2;
+ },
+
+ /**
+ * Handler for a single file using touch.
+ *
+ * @param {String} path
+ * @param {Object} options
+ * @api private
+ */
+
+ file: function file(path, options) {
+ try {
+ try {
+ fs.lstatSync(path);
+ } catch (e) {
+ // If the file doesn't exist and
+ // the user doesn't want to create it,
+ // we have no purpose in life. Goodbye.
+ if (options.create === false) {
+ throw new Error(e);
+ } else {
+ fs.closeSync(fs.openSync(path, 'wx'));
+ }
+ }
+
+ var stat = fs.statSync(path);
+ var dateToSet = options.date ? Date.create(options.date) : new Date();
+
+ if (String(dateToSet) === 'Invalid Date') {
+ throw new Error('touch: invalid date format ' + options.date);
+ }
+
+ // If -m, keep access time current.
+ var atime = options.m === true ? new Date(stat.atime) : dateToSet;
+
+ // If -a, keep mod time to current.
+ var mtime = options.a === true ? new Date(stat.mtime) : dateToSet;
+
+ if (options.reference !== undefined) {
+ var reference = undefined;
+ try {
+ reference = fs.statSync(options.reference);
+ } catch (e) {
+ throw new Error('touch: failed to get attributes of ' + options.reference + ': No such file or directory');
+ }
+ atime = options.m === true ? atime : reference.atime;
+ mtime = options.a === true ? mtime : reference.mtime;
+ }
+
+ fs.utimesSync(path, atime, mtime);
+ fs.utimesSync(path, atime, mtime);
+ } catch (e) {
+ throw new Error(e);
+ }
+ }
+};
+
+module.exports = function (vorpal) {
+ if (vorpal === undefined) {
+ return touch;
+ }
+ vorpal.api.touch = touch;
+ vorpal.command('touch <files...>').option('-a', 'change only the access time').option('-c, --no-create', 'do not create any files').option('-d, --date [STRING]', 'parse STRING and use it instead of current time').option('-m', 'change only the modification time').option('-r, --reference [FILE]', 'use this file\'s times instead of current time').option('--time [WORD]', 'change the specified time: WORD is access, atime, or use: equivalent to -a WORD is modify or mtime: equivalent to -m').autocomplete(fsAutocomplete()).action(function (args, callback) {
+ return interfacer.call(this, {
+ command: touch,
+ args: args.files || [],
+ options: args.options,
+ callback: callback
+ });
+ });
+};
100 dist/commands/unalias.js
@@ -0,0 +1,100 @@
+'use strict';
+
+var _ = require('lodash');
+
+var interfacer = require('./../util/interfacer');
+
+var unalias = {
+ exec: function exec(args, options) {
+ var _this = this;
+
+ args = args;
+ options = options || {};
+ var vorpal = options.vorpal;
+
+ if (!vorpal) {
+ /* istanbul ignore next */
+ throw new Error('Unalias is not programatically supported.');
+ }
+
+ vorpal._aliases = vorpal._aliases || [];
+
+ if (_.isString(args)) {
+ args = String(args).split(' ');
+ args = args.filter(function (str) {
+ return String(str).trim() !== '';
+ });
+ }
+
+ // Validate no input with help.
+ if ((args === undefined || args.length < 1 || args === '') && !options.a) {
+ this.log('unalias: usage: unalias [-a] name [name ...]');
+ return 1;
+ }
+
+ // Pull list of aliases
+ var all = undefined;
+ try {
+ all = JSON.parse(vorpal.localStorage.getItem('aliases') || []);
+ } catch (e) {
+ /* istanbul ignore next */
+ all = [];
+ /* istanbul ignore next */
+ vorpal.localStorage.removeItem('aliases');
+ }
+
+ if (options.a) {
+ args = all;
+ }
+
+ // Remove each alias in the list.
+
+ var _loop = function _loop(i) {
+ var key = args[i];
+ var item = vorpal.localStorage.getItem('alias|' + key);
+ if (item !== undefined && item !== null) {
+ vorpal.localStorage.removeItem('alias|' + key);
+ } else {
+ _this.log('-cash: unalias: ' + key + ': not found');
+ }
+ all = all.filter(function (str) {
+ return !(str === key);
+ });
+ };
+
+ for (var i = 0; i < args.length; ++i) {
+ _loop(i);
+ }
+
+ // Rebuild alias lists.
+ var aliases = {};
+ /* istanbul ignore next */
+ for (var i = 0; i < all.length; ++i) {
+ var item = vorpal.localStorage.getItem('alias|' + all[i]);
+ if (item !== undefined && item !== null) {
+ aliases[all[i]] = item;
+ }
+ }
+ vorpal._aliases = aliases;
+
+ vorpal.localStorage.setItem('aliases', JSON.stringify(all));
+ return 0;
+ }
+};
+
+module.exports = function (vorpal) {
+ if (vorpal === undefined) {
+ return unalias;
+ }
+ vorpal.api.unalias = unalias;
+ vorpal.command('unalias [name...]').option('-a', 'remove all alias definitions').action(function (args, callback) {
+ args.options = args.options || {};
+ args.options.vorpal = vorpal;
+ return interfacer.call(this, {
+ command: unalias,
+ args: args.name,
+ options: args.options,
+ callback: callback
+ });
+ });
+};
33 dist/delimiter.js
@@ -0,0 +1,33 @@
+'use strict';
+
+var os = require('os');
+var username = require('username');
+
+var pathConverter = require('./util/converter.path');
+
+module.exports = {
+ refresh: function refresh(vorpal, cb) {
+ cb = cb || function () {};
+ var self = this;
+ username(function (err, username) {
+ if (!err) {
+ var user = username;
+ var host = String(os.hostname()).split('.')[0];
+ var home = pathConverter.unix(self.getHomeDir());
+ var cwd = pathConverter.unix(process.cwd());
+ cwd = cwd.replace(home, '~');
+ var delimiter = user + '@' + host + ':' + cwd + '$';
+ // If we're on linux-based systems, color
+ // the prompt so we don't get confused.
+ if (os.platform().indexOf('win') === -1) {
+ delimiter = '\u001b[32m' + delimiter + '\u001b[39m';
+ }
+ vorpal.delimiter(delimiter);
+ }
+ cb(err);
+ });
+ },
+ getHomeDir: function getHomeDir() {
+ return process.env[process.platform === 'win32' ? 'USERPROFILE' : 'HOME'];
+ }
+};
35 dist/help.js
@@ -0,0 +1,35 @@
+'use strict';
+
+var pad = require('./util/pad');
+
+var commands = ['alias [-p] [name=[value]]', 'cat [-AbeEnstTv] [files ...]', 'cd [dir]', 'cp [-fnr] source ... dest', 'echo [eE] [arg ...]', 'grep [-bHhinqsvw] [-m max] [--silent] [--include pattern] pattern [files ...]', 'kill [-s sigspec | -n signum | -sigspec] pid | jobspec ... or kill -l', 'less [files ...]', 'ls [-aAdFhilQrRStUwx1] [paths ...]', 'mkdir [-pv] [directories ...]', 'mv [-fnv] source ... dest', 'pwd [files ...]', 'rm [-frR] [files ...]', 'sort [-chMnrR] [-o file] [files ...]', 'touch [-acm] [-d date] [-r ref] [--time word] file ...', 'unalias [-a] name [names ...]'];
+
+function chop(str, len) {
+ var res = String(str).slice(0, len - 2);
+ res = res.length === len - 2 ? res + '>' : res;
+ return res;
+}
+
+module.exports = function () {
+ var version = require('./../package.json').version;
+ var result = '';
+
+ result += 'Cash, version ' + version + '\n';
+ result += 'These shell commands are defined internally. Type `help\' to see this list.\n';
+ result += 'Type `help name\' to find out more about the function `name\'.\n';
+ result += 'Use `info cash\' to find out more about the shell in general.\n';
+ result += '\n';
+
+ var half = Math.floor(commands.length / 2);
+ var width = Math.floor((process.stdout.columns - 3) / 2);
+ var lhalf = Math.ceil(commands.length / 2);
+ var padding = commands.length % 2 === 1 ? 1 : 0;
+ for (var i = 0; i < lhalf; ++i) {
+ var colA = pad(chop(commands[i], width), width);
+ var colB = pad(chop(commands[half + i + padding] || '', width), width);
+ var line = i === lhalf - 1 ? '' : '\n';
+ result += ' ' + colA + ' ' + colB + line;
+ }
+
+ return result;
+};
3 dist/help/alias.js
@@ -0,0 +1,3 @@
+"use strict";
+
+module.exports = "\nUsage: alias [OPTION] [name[=value] ...]\nDefine or display aliases.\n\nWithout arguments, `alias' prints the list of aliases in the reusable\nform `alias NAME=VALUE' on standard output.\n\nOtherwise, an alias is defined for each NAME whose VALUE is given.\nA trailing space in VALUE causes the next word to be checked for\nalias substitution when the alias is expanded.\n\n -p print all defined aliases in a reusable format\n --help display this help and exit\n\nReport alias bugs to <https://github.com/dthree/cash>\nCash home page: <http://cash.js.org/>\n";
3 dist/help/cat.js
@@ -0,0 +1,3 @@
+"use strict";
+
+module.exports = "\nUsage: cat [OPTION]... [FILE]...\nConcatenate FILE(s), or standard input, to standard output.\n\n -A, --show-all equivalent to -vET\n -b, --number-nonblank number nonempty output lines, overrides -n\n -e equivalent to -vE\n -E, --show-ends display $ at end of each line\n -n, --number number all output lines\n -s, --squeeze-blank suppress repeated empty output lines\n -t equivalent to -vT\n -T, --show-tabs display TAB characters as ^I\n -v, --show-nonprinting use ^ and M- notation, except for LFD and TAB\n --help display this help and exit\n\nWith no FILE, or when FILE is -, read standard input.\n\nExamples:\n cat f - g Output f's contents, then standard input, then g's contents.\n cat Copy standard input to standard output.\n\nReport cat bugs to <https://github.com/dthree/cash>\nCash home page: <http://cash.js.org/>\n";
3 dist/help/cd.js
@@ -0,0 +1,3 @@
+"use strict";
+
+module.exports = "\nUsage: cd [DIR]...\nChange the cash working directory.\n\nChange the current directory to DIR. The default DIR is the value of the\nHOME shell variable.\n\nReport cd bugs to <https://github.com/dthree/cash>\nCash home page: <http://cash.js.org/>\n";
3 dist/help/cp.js
@@ -0,0 +1,3 @@
+"use strict";
+
+module.exports = "\nUsage: cp [OPTION]... [-T] SOURCE DEST\n or: cp [OPTION]... SOURCE... DIRECTORY\nCopy SOURCE to DEST, or multiple SOURCE(s) to DIRECTORY.\n\n -f, --force if an existing destination file cannot be\n opened, remove it and try again (this option\n is ignored when the -n option is also used)\n -n, --no-clobber do not overwrite an existing file (overrides\n a previous -i option)\n -R, -r, --recursive copy directories recursively\n --help display this help and exit\n\nReport cp bugs to <https://github.com/dthree/cash>\nCash home page: <http://cash.js.org/>\n";
3 dist/help/echo.js
@@ -0,0 +1,3 @@
+"use strict";
+
+module.exports = "\nUsage: echo [OPTION]... [ARG ...]\nWrite arguments to the standard output.\n\nDisplay the ARGs, separated by a single space character and followed by a\nnewline, on the standard output.\n\n -e enable interpretation of the following backslash escapes\n -e explicitly suppress interpretation of backslash escapes\n --help display this help and exit\n\n `echo' interprets the following backslash-escaped characters:\n \b backspace\n c suppress further output\n \n new line\n \r carriage return\n \t horizontal tab\n \\ backslash\n\nReport echo bugs to <https://github.com/dthree/cash>\nCash home page: <http://cash.js.org/>\n";
3 dist/help/grep.js
@@ -0,0 +1,3 @@
+"use strict";
+
+module.exports = "\nUsage: grep [OPTION]... PATTERN [FILE]...\nSearch for PATTERN in each FILE or standard input.\nPATTERN is, by default, a basic regular expression (BRE).\nExample: grep -i 'hello world' menu.h main.c\n\niwsvmbnHhqr\n\nRegexp selection and interpretation:\n -i, --ignore-case ignore case distinctions\n -w, --word-regexp force PATTERN to match only whole words\n\nMiscellaneous:\n -s, --no-messages suppress error messages\n -v, --invert-match select non-matching lines\n --help display this help and exit\n\nOutput control:\n -n, --line-number print line number with output lines\n -H, --with-filename print the file name for each match\n -h, --no-filename suppress the file name prefix on output\n -q, --quiet, --silent suppress all normal output\n -r, --recursive like --directories=recurse\n --include <FILE_PATTERN> search only files that match FILE_PATTERN\n\nWhen FILE is -, read standard input. With no FILE, read . if a command-line\n-r is given, - otherwise. If fewer than two FILEs are given, assume -h.\nExit status is 0 if any line is selected, 1 otherwise;\nif any error occurs and -q is not given, the exit status is 2.\n\nReport grep bugs to <https://github.com/dthree/cash>\nCash home page: <http://cash.js.org/>\n";
3 dist/help/kill.js
@@ -0,0 +1,3 @@
+"use strict";
+
+module.exports = "\nUsage: kill [OPTION] pid | jobspec ... or kill -l [sigspec]\nSend a signal to a job.\n\nSend the processes identified by PID or JOBSPEC the signal named by\nSIGSPEC or SIGNUM. If neither SIGSPEC nor SIGNUM is present, then\nSIGTERM is assumed.\n\n -s sig SIG is a signal name\n -n sig SIG is a signal number\n -l [sigspec] list the signal names; if arguments follow `-l' they\n are assumed to be signal numbers for which names\n should be listed\n --help display this help and exit\n\nExit status:\n 0 if OK,\n 1 if an invalid option is given or an error occurs.\n\nReport kill bugs to <https://github.com/dthree/cash>\nCash home page: <http://cash.js.org/>\n";
3 dist/help/ls.js
@@ -0,0 +1,3 @@
+"use strict";
+
+module.exports = "\nUsage: ls [OPTION]... [FILE]...\nList information about the FILEs (the current directory by default).\nSort entries alphabetically if none of -tSU nor --sort is specified.\n\n -a, --all do not ignore entries starting with .\n -A, --almost-all do not list implied . and ..\n -d, --directory list directory entries instead of contents,\n and do not dereference symbolic links\n -f do not sort, enable -aU, disable -ls --color\n -F, --classify append indicator (one of */=>@|) to entries\n -h, --human-readable with -l, print sizes in human readable format\n -i, --inode print the index number of each file\n -l use a long listing format\n -q, --hide-control-chars print ? instead of non graphic characters\n -r, --reverse reverse order while sorting\n -R, --recursive list subdirectories recursively\n -S sort by file size\n -t sort by modification time, newest first\n -U do not sort; list entries in directory order\n -w, --width=COLS assume screen width instead of current value\n -x list entries by lines instead of by columns\n -1 list one file per line\n --help display this help and exit\n\nExit status:\n 0 if OK,\n 1 if minor problems (e.g., cannot access subdirectory),\n 2 if serious trouble (e.g., cannot access command-line argument).\n\nReport ls bugs to <https://github.com/dthree/cash>\nCash home page: <http://cash.js.org/>\n";
3 dist/help/mkdir.js
@@ -0,0 +1,3 @@
+"use strict";
+
+module.exports = "\nUsage: mkdir [OPTION]... DIRECTORY...\nCreate the DIRECTORY(ies), if they do not already exist.\n\n -p, --parents no error if existing, make parent directories as needed\n -v, --verbose print a message for each created directory\n --help display this help and exit\n\nReport mkdir bugs to <https://github.com/dthree/cash>\nCash home page: <http://cash.js.org/>\n";
3 dist/help/mv.js
@@ -0,0 +1,3 @@
+"use strict";
+
+module.exports = "\nUsage: mv [OPTION]... [-T] SOURCE DEST\n or: mv [OPTION]... SOURCE... DIRECTORY\n or: mv [OPTION]... -t DIRECTORY SOURCE...\nRename SOURCE to DEST, or move SOURCE(s) to DIRECTORY.\n\n -f, --force do not prompt before overwriting\n -n, --no-clobber do not overwrite an existing file\n --striptrailingslashes remove any trailing slashes from each SOURCE\n argument\n -v, --verbose explain what is being done\n --help display this help and exit\n\nIf you specify -f and -n, only -f takes effect.\n\nReport mv bugs to <https://github.com/dthree/cash>\nCash home page: <http://cash.js.org/>\n";
3 dist/help/pwd.js
@@ -0,0 +1,3 @@
+"use strict";
+
+module.exports = "\nUsage: pwd [-LP]\nPrint the name of the current working directory.\n\n --help display this help and exit\n\nExit status:\n 0 if OK,\n 1 if an invalid option is given or the current directory\n cannot be read.\n\nReport pwd bugs to <https://github.com/dthree/cash>\nCash home page: <http://cash.js.org/>\n";
3 dist/help/rm.js
@@ -0,0 +1,3 @@
+"use strict";
+
+module.exports = "\nUsage: rm [OPTION]... FILE...\nRemove (unlink) the FILE(s).\n\n -f, --force ignore nonexistent files and arguments, never prompt\n -r, -R, --recursive remove directories and their contents recursively\n --help display this help and exit\n\nBy default, rm does not remove directories. Use the --recursive (-r or -R)\noption to remove each listed directory, too, along with all of its contents.\n\nTo remove a file whose name starts with a '-', for example '-foo',\nuse one of these commands:\n rm -- -foo\n rm ./-foo\n\nNote that if you use rm to remove a file, it might be possible to recover\nsome of its contents, given sufficient expertise and/or time.\n\nReport rm bugs to <https://github.com/dthree/cash>\nCash home page: <http://cash.js.org/>\n";
3 dist/help/sort.js
@@ -0,0 +1,3 @@
+"use strict";
+
+module.exports = "\nUsage: sort [OPTION]... [FILE]...\nWrite sorted concatenation of all FILE(s) to standard output.\n\nOrdering options:\n -M, --month-sort compare (unknown) < 'JAN' < ... < 'DEC'\n -h, --human-numeric-sort compare human readable numbers (e.g., 2K 1G)\n -n, --numeric-sort compare according to string numerical value\n -R, --random-sort sort by random hash of keys\n -r, --reverse reverse the result of comparisons\n\nOther options:\n -c, --check,\n --check=diagnose-first check for sorted input; do not sort\n -o, --output=FILE write result to FILE instead of standard output\n --help display this help and exit\n\nWith no FILE, or when FILE is -, read standard input.\n\nReport sort bugs to <https://github.com/dthree/cash>\nCash home page: <http://cash.js.org/>\n";
3 dist/help/touch.js
@@ -0,0 +1,3 @@
+"use strict";
+
+module.exports = "\nUsage: touch [OPTION]... FILE...\nUpdate the access and modification times of each FILE to the current time.\n\nA FILE argument that does not exist is created empty, unless -c is\nsupplied.\n\n -a change only the access time\n -c, --no-create do not create any files\n -d, --date <STRING> parse STRING and use it instead of current time\n -m change only the modification time\n -r, --reference <FILE> use this file's times instead of current time\n --time <WORD> change the specified time:\n WORD is access, atime, or use: equivalent to -a\n WORD is modify or mtime: equivalent to -m\n --help display this help and exit\n\nReport touch bugs to <https://github.com/dthree/cash>\nCash home page: <http://cash.js.org/>\n";
3 dist/help/unalias.js
@@ -0,0 +1,3 @@
+"use strict";
+
+module.exports = "\nUsage: unalias [OPTION] name ...\nRemove each name from the list of defined aliases.\n\n -a remove all alias definitions\n --help display this help and exit\n\nExit status:\n 0 if OK,\n 1 if a name is not an existing alias.\n\nReport unalias bugs to <https://github.com/dthree/cash>\nCash home page: <http://cash.js.org/>\n";
185 dist/index.js
@@ -0,0 +1,185 @@
+'use strict';
+
+var _ = require('lodash');
+var os = require('os');
+var Vorpal = require('vorpal');
+
+var commands = require('./../commands.json');
+var help = require('./help');
+var interfacer = require('./util/interfacer');
+
+var cmds = undefined;
+
+var app = {
+
+ commands: commands.commands,
+
+ importedCommands: commands.importedCommands,
+
+ vorpal: new Vorpal(),
+
+ _cwd: process.cwd(),
+
+ _fatal: false,
+
+ export: function _export(str, cbk) {
+ cbk = cbk || function () {};
+ var options = {
+ fatal: app._fatal || false
+ };
+ // Hook stdin, execute the command and
+ // then return it all.
+ var intercept = require('./util/intercept');
+ var out = '';
+ var unhook = intercept(function (str) {
+ out += str + '\n';
+ return '';
+ });
+ app.vorpal.execSync(str, options);
+ unhook();
+ return String(out).replace(/\n$/, '');
+ },
+ load: function load() {
+ var self = this;
+ self.vorpal.api = {};
+ this.commands.forEach(function (cmd) {
+ if (self.importedCommands.indexOf(cmd) > -1) {
+ return;
+ }
+ try {
+ (function () {
+ var mod = require('./commands/' + cmd + '.js');
+ var help = undefined;
+ try {
+ help = require('./help/' + cmd + '.js');
+ help = String(help).replace(/^\n|\n$/g, '');
+ } catch (e) {
+ // .. whatever
+ }
+ self.vorpal.use(mod, {
+ parent: self
+ });
+ var cmdObj = self.vorpal.find(cmd);
+ if (cmdObj && help) {
+ /* istanbul ignore next */
+ cmdObj.help(function (args, cb) {
+ cb(help);
+ });
+ }
+ })();
+ } catch (e) {
+ /* istanbul ignore next */
+ self.vorpal.log('Error loading command ' + cmd + ': ', e);
+ }
+ });
+ this.importedCommands.forEach(function (cmd) {
+ try {
+ var mod = require('vorpal-' + cmd);
+ self.vorpal.use(mod, {
+ parent: self
+ });
+ } catch (e) {
+ /* istanbul ignore next */
+ self.vorpal.log('Error loading command ' + cmd + ': ', e);
+ }
+ });
+
+ // If we're running Windows, register
+ // process spawning for Windows child processes.
+ // If on Linux, just does registers the .catch command.
+ var windows = require('./windows');
+ windows.registerCommands(self);
+
+ var _loop = function _loop(cmd) {
+ if (app.vorpal.api.hasOwnProperty(cmd)) {
+ app.export[cmd] = function (args, options, callback) {
+ callback = callback || function () {};
+ options = options || {};
+ options.vorpal = app.vorpal;
+ return interfacer.call(this, {
+ command: app.vorpal.api[cmd],
+ args: args,
+ options: options,
+ callback: callback,
+ async: app.vorpal.api[cmd].async || false,
+ silent: true
+ });
+ };
+ }
+ };
+
+ for (var cmd in app.vorpal.api) {
+ _loop(cmd);
+ }
+
+ app.vorpal.history('cash').localStorage('cash').help(help);
+
+ app.vorpal.find('exit').action(function () {
+ /* istanbul ignore next */
+ process.exit(1);
+ });
+
+ // Load aliases
+ var all = undefined;
+ try {
+ all = JSON.parse(app.vorpal.localStorage.getItem('aliases') || []);
+ } catch (e) {
+ /* istanbul ignore next */
+ all = [];
+ /* istanbul ignore next */
+ app.vorpal.localStorage.removeItem('aliases');
+ }
+ var aliases = {};
+ /* istanbul ignore next */
+ for (var i = 0; i < all.length; ++i) {
+ var item = app.vorpal.localStorage.getItem('alias|' + all[i]);
+ if (item !== undefined && item !== null) {
+ aliases[all[i]] = item;
+ }
+ }
+ app.vorpal._aliases = aliases;
+
+ // Override SIGINT to be ignored,
+ // and if the user is insistent, give
+ // a helpful message. The purpose of this
+ // is to give a full shell feel, not an
+ // application running over the shell.
+ // Skip this on linux, as its mainly
+ // for dev testing.
+ /* istanbul ignore next */
+ if (os.platform().indexOf('win') > -1) {
+ (function () {
+ var counter = 0;
+ setInterval(function () {
+ counter = counter > 0 ? 0 : counter;
+ }, 3000);
+ app.vorpal.sigint(function () {
+ counter++;
+ app.vorpal.ui.submit('');
+ if (counter > 5) {
+ app.vorpal.log('(to quit Cash, use the "exit" command)');
+ counter -= 10000;
+ }
+ return;
+ });
+ })();
+ }
+
+ app.export.vorpal = app.vorpal;
+ _.extend(app.export, cmds);
+ return this;
+ }
+};
+
+cmds = {
+ /* istanbul ignore next */
+
+ show: function show() {
+ /* istanbul ignore next */
+ app.vorpal.show();
+ }
+};
+
+app.load();
+
+module.exports = app.export;
747 dist/lib/sugar.js
@@ -0,0 +1,747 @@
+"use strict";
+
+var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol ? "symbol" : typeof obj; };
+
+/*
+ * Sugar Library v1.4.1
+ *
+ * Freely distributable and licensed under the MIT-style license.
+ * Copyright (c) 2014 Andrew Plummer
+ * http://sugarjs.com/
+ *
+ * ---------------------------- */
+/* istanbul ignore next */
+(function () {
+ function aa(a) {
+ return function () {
+ return a;
+ };
+ }
+ /* istanbul ignore next */
+ var m = Object,
+ p = Array,
+ q = RegExp,
+ r = Date,
+ s = String,
+ t = Number,
+ u = Math,
+ ba = "undefined" !== typeof global ? global : this,
+ v = m.prototype.toString,
+ da = m.prototype.hasOwnProperty,
+ ea = m.defineProperty && m.defineProperties,
+ fa = "function" === typeof q(),
+ ga = !("0" in new s("a")),
+ ia = {},
+ ja = /^\[object Date|Array|String|Number|RegExp|Boolean|Arguments\]$/,
+ w = "Boolean Number String Array Date RegExp Function".split(" "),
+ la = ka("boolean", w[0]),
+ y = ka("number", w[1]),
+ z = ka("string", w[2]),
+ A = ma(w[3]),
+ C = ma(w[4]),
+ D = ma(w[5]),
+ F = ma(w[6]);
+ /* istanbul ignore next */
+ function ma(a) {
+ var b = "Array" === a && p.isArray || function (b, d) {
+ return (d || v.call(b)) === "[object " + a + "]";
+ };return ia[a] = b;
+ }function ka(a, b) {
+ function c(c) {
+ return G(c) ? v.call(c) === "[object " + b + "]" : (typeof c === "undefined" ? "undefined" : _typeof(c)) === a;
+ }return ia[b] = c;
+ }
+ function na(a) {
+ a.SugarMethods || (oa(a, "SugarMethods", {}), H(a, !1, !0, { extend: function extend(b, c, d) {
+ H(a, !1 !== d, c, b);
+ }, sugarRestore: function sugarRestore() {
+ return pa(this, a, arguments, function (a, c, d) {
+ oa(a, c, d.method);
+ });
+ }, sugarRevert: function sugarRevert() {
+ return pa(this, a, arguments, function (a, c, d) {
+ d.existed ? oa(a, c, d.original) : delete a[c];
+ });
+ } }));
+ }function H(a, b, c, d) {
+ var e = b ? a.prototype : a;na(a);I(d, function (d, f) {
+ var h = e[d],
+ l = J(e, d);F(c) && h && (f = qa(h, f, c));!1 === c && h || oa(e, d, f);a.SugarMethods[d] = { method: f, existed: l, original: h, instance: b };
+ });
+ }
+ function K(a, b, c, d, e) {
+ var g = {};d = z(d) ? d.split(",") : d;d.forEach(function (a, b) {
+ e(g, a, b);
+ });H(a, b, c, g);
+ }function pa(a, b, c, d) {
+ var e = 0 === c.length,
+ g = L(c),
+ f = !1;I(b.SugarMethods, function (b, c) {
+ if (e || -1 !== g.indexOf(b)) f = !0, d(c.instance ? a.prototype : a, b, c);
+ });return f;
+ }function qa(a, b, c) {
+ return function (d) {
+ return c.apply(this, arguments) ? b.apply(this, arguments) : a.apply(this, arguments);
+ };
+ }function oa(a, b, c) {
+ ea ? m.defineProperty(a, b, { value: c, configurable: !0, enumerable: !1, writable: !0 }) : a[b] = c;
+ }
+ function L(a, b, c) {
+ var d = [];c = c || 0;var e;for (e = a.length; c < e; c++) {
+ d.push(a[c]), b && b.call(a, a[c], c);
+ }return d;
+ }function sa(a, b, c) {
+ var d = a[c || 0];A(d) && (a = d, c = 0);L(a, b, c);
+ }function ta(a) {
+ if (!a || !a.call) throw new TypeError("Callback is not callable");
+ }function M(a) {
+ return void 0 !== a;
+ }function N(a) {
+ return void 0 === a;
+ }function J(a, b) {
+ return !!a && da.call(a, b);
+ }function G(a) {
+ return !!a && ("object" === (typeof a === "undefined" ? "undefined" : _typeof(a)) || fa && D(a));
+ }function ua(a) {
+ var b = typeof a === "undefined" ? "undefined" : _typeof(a);return null == a || "string" === b || "number" === b || "boolean" === b;
+ }
+ function va(a, b) {
+ b = b || v.call(a);try {
+ if (a && a.constructor && !J(a, "constructor") && !J(a.constructor.prototype, "isPrototypeOf")) return !1;
+ } catch (c) {
+ return !1;
+ }return !!a && "[object Object]" === b && "hasOwnProperty" in a;
+ }function I(a, b) {
+ for (var c in a) {
+ if (J(a, c) && !1 === b.call(a, c, a[c], a)) break;
+ }
+ }function wa(a, b) {
+ for (var c = 0; c < a; c++) {
+ b(c);
+ }
+ }function xa(a, b) {
+ I(b, function (c) {
+ a[c] = b[c];
+ });return a;
+ }function ya(a) {
+ ua(a) && (a = m(a));if (ga && z(a)) for (var b = a, c = 0, d; d = b.charAt(c);) {
+ b[c++] = d;
+ }return a;
+ }function O(a) {
+ xa(this, ya(a));
+ }
+ O.prototype.constructor = m;var P = u.abs,
+ za = u.pow,
+ Aa = u.ceil,
+ Q = u.floor,
+ R = u.round,
+ Ca = u.min,
+ S = u.max;function Da(a, b, c) {
+ var d = za(10, P(b || 0));c = c || R;0 > b && (d = 1 / d);return c(a * d) / d;
+ }var Ea = 48,
+ Fa = 57,
+ Ga = 65296,
+ Ha = 65305,
+ Ia = ".",
+ Ja = "",
+ Ka = {},
+ La;function Ma() {
+ return "\t\n\u000b\f\r   ᠎             \u2028\u2029 ";
+ }function Na(a, b) {
+ var c = "";for (a = a.toString(); 0 < b;) {
+ if (b & 1 && (c += a), b >>= 1) a += a;
+ }return c;
+ }
+ function Oa(a, b) {
+ var c, d;c = a.replace(La, function (a) {
+ a = Ka[a];a === Ia && (d = !0);return a;
+ });return d ? parseFloat(c) : parseInt(c, b || 10);
+ }function T(a, b, c, d) {
+ d = P(a).toString(d || 10);d = Na("0", b - d.replace(/\.\d+/, "").length) + d;if (c || 0 > a) d = (0 > a ? "-" : "+") + d;return d;
+ }function Pa(a) {
+ if (11 <= a && 13 >= a) return "th";switch (a % 10) {case 1:
+ return "st";case 2:
+ return "nd";case 3:
+ return "rd";default:
+ return "th";}
+ }
+ function Qa(a, b) {
+ function c(a, c) {
+ if (a || -1 < b.indexOf(c)) d += c;
+ }var d = "";b = b || "";c(a.multiline, "m");c(a.ignoreCase, "i");c(a.global, "g");c(a.u, "y");return d;
+ }function Ra(a) {
+ z(a) || (a = s(a));return a.replace(/([\\/\'*+?|()\[\]{}.^$])/g, "\\$1");
+ }function U(a, b) {
+ return a["get" + (a._utc ? "UTC" : "") + b]();
+ }function Sa(a, b, c) {
+ return a["set" + (a._utc && "ISOWeek" != b ? "UTC" : "") + b](c);
+ }
+ function Ta(a, b) {
+ var c = typeof a === "undefined" ? "undefined" : _typeof(a),
+ d,
+ e,
+ g,
+ f,
+ h,
+ l,
+ n;if ("string" === c) return a;g = v.call(a);d = va(a, g);e = A(a, g);if (null != a && d || e) {
+ b || (b = []);if (1 < b.length) for (l = b.length; l--;) {
+ if (b[l] === a) return "CYC";
+ }b.push(a);d = a.valueOf() + s(a.constructor);f = e ? a : m.keys(a).sort();l = 0;for (n = f.length; l < n; l++) {
+ h = e ? l : f[l], d += h + Ta(a[h], b);
+ }b.pop();
+ } else d = -Infinity === 1 / a ? "-0" : s(a && a.valueOf ? a.valueOf() : a);return c + g + d;
+ }function Ua(a, b) {
+ return a === b ? 0 !== a || 1 / a === 1 / b : Va(a) && Va(b) ? Ta(a) === Ta(b) : !1;
+ }
+ function Va(a) {
+ var b = v.call(a);return ja.test(b) || va(a, b);
+ }function Wa(a, b, c) {
+ var d,
+ e = a.length,
+ g = b.length,
+ f = !1 !== b[g - 1];if (!(g > (f ? 1 : 2))) return Xa(a, e, b[0], f, c);d = [];L(b, function (b) {
+ if (la(b)) return !1;d.push(Xa(a, e, b, f, c));
+ });return d;
+ }function Xa(a, b, c, d, e) {
+ d && (c %= b, 0 > c && (c = b + c));return e ? a.charAt(c) : a[c];
+ }function Ya(a, b) {
+ K(b, !0, !1, a, function (a, b) {
+ a[b + ("equal" === b ? "s" : "")] = function () {
+ return m[b].apply(null, [this].concat(L(arguments)));
+ };
+ });
+ }na(m);I(w, function (a, b) {
+ na(ba[b]);
+ });var Za, $a;
+ for ($a = 0; 9 >= $a; $a++) {
+ Za = s.fromCharCode($a + Ga), Ja += Za, Ka[Za] = s.fromCharCode($a + Ea);
+ }Ka[","] = "";Ka[""] = Ia;Ka[Ia] = Ia;La = q("[" + Ja + ".," + Ia + "]", "g");
+ "use strict";H(m, !1, !1, { keys: function keys(a) {
+ var b = [];if (!G(a) && !D(a) && !F(a)) throw new TypeError("Object required");I(a, function (a) {
+ b.push(a);
+ });return b;
+ } });
+ function ab(a, b, c, d) {
+ var e = a.length,
+ g = -1 == d,
+ f = g ? e - 1 : 0;c = isNaN(c) ? f : parseInt(c >> 0);0 > c && (c = e + c);if (!g && 0 > c || g && c >= e) c = f;for (; g && 0 <= c || !g && c < e;) {
+ if (a[c] === b) return c;c += d;
+ }return -1;
+ }function bb(a, b, c, d) {
+ var e = a.length,
+ g = 0,
+ f = M(c);ta(b);if (0 != e || f) f || (c = a[d ? e - 1 : g], g++);else throw new TypeError("Reduce called on empty array with no initial value");for (; g < e;) {
+ f = d ? e - g - 1 : g, f in a && (c = b(c, a[f], f, a)), g++;
+ }return c;
+ }function cb(a) {
+ if (0 === a.length) throw new TypeError("First argument must be defined");
+ }H(p, !1, !1, { isArray: function isArray(a) {
+ return A(a);
+ } });
+ H(p, !0, !1, { every: function every(a, b) {
+ var c = this.length,
+ d = 0;for (cb(arguments); d < c;) {
+ if (d in this && !a.call(b, this[d], d, this)) return !1;d++;
+ }return !0;
+ }, some: function some(a, b) {
+ var c = this.length,
+ d = 0;for (cb(arguments); d < c;) {
+ if (d in this && a.call(b, this[d], d, this)) return !0;d++;
+ }return !1;
+ }, map: function map(a, b) {
+ b = arguments[1];var c = this.length,
+ d = 0,
+ e = Array(c);for (cb(arguments); d < c;) {
+ d in this && (e[d] = a.call(b, this[d], d, this)), d++;
+ }return e;
+ }, filter: function filter(a) {
+ var b = arguments[1],
+ c = this.length,
+ d = 0,
+ e = [];for (cb(arguments); d < c;) {
+ d in this && a.call(b, this[d], d, this) && e.push(this[d]), d++;
+ }return e;
+ }, indexOf: function indexOf(a, b) {
+ return z(this) ? this.indexOf(a, b) : ab(this, a, b, 1);
+ }, lastIndexOf: function lastIndexOf(a, b) {
+ return z(this) ? this.lastIndexOf(a, b) : ab(this, a, b, -1);
+ }, forEach: function forEach(a, b) {
+ var c = this.length,
+ d = 0;for (ta(a); d < c;) {
+ d in this && a.call(b, this[d], d, this), d++;
+ }
+ }, reduce: function reduce(a, b) {
+ return bb(this, a, b);
+ }, reduceRight: function reduceRight(a, b) {
+ return bb(this, a, b, !0);
+ } });
+ H(Function, !0, !1, { bind: function bind(a) {
+ var b = this,
+ c = L(arguments, null, 1),
+ d;if (!F(this)) throw new TypeError("Function.prototype.bind called on a non-function");d = function d() {
+ return b.apply(b.prototype && this instanceof b ? this : a, c.concat(L(arguments)));
+ };d.prototype = this.prototype;return d;
+ } });H(r, !1, !1, { now: function now() {
+ return new r().getTime();
+ } });
+ (function () {
+ var a = Ma().match(/^\s+$/);try {
+ s.prototype.trim.call([1]);
+ } catch (b) {
+ a = !1;
+ }H(s, !0, !a, { trim: function trim() {
+ return this.toString().trimLeft().trimRight();
+ }, trimLeft: function trimLeft() {
+ return this.replace(q("^[" + Ma() + "]+"), "");
+ }, trimRight: function trimRight() {
+ return this.replace(q("[" + Ma() + "]+$"), "");
+ } });
+ })();
+ (function () {
+ var a = new r(r.UTC(1999, 11, 31)),
+ a = a.toISOString && "1999-12-31T00:00:00.000Z" === a.toISOString();K(r, !0, !a, "toISOString,toJSON", function (a, c) {
+ a[c] = function () {
+ return T(this.getUTCFullYear(), 4) + "-" + T(this.getUTCMonth() + 1, 2) + "-" + T(this.getUTCDate(), 2) + "T" + T(this.getUTCHours(), 2) + ":" + T(this.getUTCMinutes(), 2) + ":" + T(this.getUTCSeconds(), 2) + "." + T(this.getUTCMilliseconds(), 3) + "Z";
+ };
+ });
+ })();
+ "use strict";
+ var W,
+ Ib,
+ Jb = "ampm hour minute second ampm utc offset_sign offset_hours offset_minutes ampm".split(" "),
+ Kb = "({t})?\\s*(\\d{1,2}(?:[,.]\\d+)?)(?:{h}([0-5]\\d(?:[,.]\\d+)?)?{m}(?::?([0-5]\\d(?:[,.]\\d+)?){s})?\\s*(?:({t})|(Z)|(?:([+-])(\\d{2,2})(?::?(\\d{2,2}))?)?)?|\\s*({t}))",
+ Lb = {},
+ Mb,
+ Nb,
+ Ob,
+ Pb = [],
+ Qb = {},
+ X = { yyyy: function yyyy(a) {
+ return U(a, "FullYear");
+ }, yy: function yy(a) {
+ return U(a, "FullYear") % 100;
+ }, ord: function ord(a) {
+ a = U(a, "Date");return a + Pa(a);
+ }, tz: function tz(a) {
+ return a.getUTCOffset();
+ }, isotz: function isotz(a) {
+ return a.getUTCOffset(!0);
+ },
+ Z: function Z(a) {
+ return a.getUTCOffset();
+ }, ZZ: function ZZ(a) {
+ return a.getUTCOffset().replace(/(\d{2})$/, ":$1");
+ } },
+ Rb = [{ name: "year", method: "FullYear", k: !0, b: function b(a) {
+ return 864E5 * (365 + (a ? a.isLeapYear() ? 1 : 0 : 0.25));
+ } }, { name: "month", error: 0.919, method: "Month", k: !0, b: function b(a, _b) {
+ var c = 30.4375,
+ d;a && (d = a.daysInMonth(), _b <= d.days() && (c = d));return 864E5 * c;
+ } }, { name: "week", method: "ISOWeek", b: aa(6048E5) }, { name: "day", error: 0.958, method: "Date", k: !0, b: aa(864E5) }, { name: "hour", method: "Hours", b: aa(36E5) }, { name: "minute",
+ method: "Minutes", b: aa(6E4) }, { name: "second", method: "Seconds", b: aa(1E3) }, { name: "millisecond", method: "Milliseconds", b: aa(1) }],
+ Sb = {};function Tb(a) {
+ xa(this, a);this.g = Pb.concat();
+ }
+ Tb.prototype = { getMonth: function getMonth(a) {
+ return y(a) ? a - 1 : this.months.indexOf(a) % 12;
+ }, getWeekday: function getWeekday(a) {
+ return this.weekdays.indexOf(a) % 7;
+ }, addFormat: function addFormat(a, b, c, d, e) {
+ var g = c || [],
+ f = this,
+ h;a = a.replace(/\s+/g, "[,. ]*");a = a.replace(/\{([^,]+?)\}/g, function (a, b) {
+ var d,
+ e,
+ h,
+ B = b.match(/\?$/);h = b.match(/^(\d+)\??$/);var k = b.match(/(\d)(?:-(\d))?/),
+ E = b.replace(/[^a-z]+$/, "");h ? d = f.tokens[h[1]] : f[E] ? d = f[E] : f[E + "s"] && (d = f[E + "s"], k && (e = [], d.forEach(function (a, b) {
+ var c = b % (f.units ? 8 : d.length);c >= k[1] && c <= (k[2] || k[1]) && e.push(a);
+ }), d = e), d = Ub(d));h ? h = "(?:" + d + ")" : (c || g.push(E), h = "(" + d + ")");B && (h += "?");return h;
+ });b ? (b = Vb(f, e), e = ["t", "[\\s\\u3000]"].concat(f.timeMarker), h = a.match(/\\d\{\d,\d\}\)+\??$/), Wb(f, "(?:" + b + ")[,\\s\\u3000]+?" + a, Jb.concat(g), d), Wb(f, a + "(?:[,\\s]*(?:" + e.join("|") + (h ? "+" : "*") + ")" + b + ")?", g.concat(Jb), d)) : Wb(f, a, g, d);
+ } };
+ function Xb(a, b, c) {
+ var d,
+ e,
+ g = b[0],
+ f = b[1],
+ h = b[2];b = a[c] || a.relative;if (F(b)) return b.call(a, g, f, h, c);e = a.units[8 * (a.plural && 1 < g ? 1 : 0) + f] || a.units[f];a.capitalizeUnit && (e = Yb(e));d = a.modifiers.filter(function (a) {
+ return "sign" == a.name && a.value == (0 < h ? 1 : -1);
+ })[0];return b.replace(/\{(.*?)\}/g, function (a, b) {
+ switch (b) {case "num":
+ return g;case "unit":
+ return e;case "sign":
+ return d.src;}
+ });
+ }function Zb(a, b) {
+ b = b || a.code;return "en" === b || "en-US" === b ? !0 : a.variant;
+ }
+ function $b(a, b) {
+ return b.replace(q(a.num, "g"), function (b) {
+ return ac(a, b) || "";
+ });
+ }function ac(a, b) {
+ var c;return y(b) ? b : b && -1 !== (c = a.numbers.indexOf(b)) ? (c + 1) % 10 : 1;
+ }function Y(a, b) {
+ var c;z(a) || (a = "");c = Sb[a] || Sb[a.slice(0, 2)];if (!1 === b && !c) throw new TypeError("Invalid locale.");return c || Ib;
+ }
+ function bc(a, b) {
+ function c(a) {
+ var b = h[a];z(b) ? h[a] = b.split(",") : b || (h[a] = []);
+ }function d(a, b) {
+ a = a.split("+").map(function (a) {
+ return a.replace(/(.+):(.+)$/, function (a, b, c) {
+ return c.split("|").map(function (a) {
+ return b + a;
+ }).join("|");
+ });
+ }).join("|");a.split("|").forEach(b);
+ }function e(a, b, c) {
+ var e = [];h[a].forEach(function (a, f) {
+ b && (a += "+" + a.slice(0, 3));d(a, function (a, b) {
+ e[b * c + f] = a.toLowerCase();
+ });
+ });h[a] = e;
+ }function g(a, b, c) {
+ a = "\\d{" + a + "," + b + "}";c && (a += "|(?:" + Ub(h.numbers) + ")+");return a;
+ }function f(a, b) {
+ h[a] = h[a] || b;
+ }var h, l;h = new Tb(b);c("modifiers");"months weekdays units numbers articles tokens timeMarker ampm timeSuffixes dateParse timeParse".split(" ").forEach(c);l = !h.monthSuffix;e("months", l, 12);e("weekdays", l, 7);e("units", !1, 8);e("numbers", !1, 10);f("code", a);f("date", g(1, 2, h.digitDate));f("year", "'\\d{2}|" + g(4, 4));f("num", function () {
+ var a = ["-?\\d+"].concat(h.articles);h.numbers && (a = a.concat(h.numbers));return Ub(a);
+ }());(function () {
+ var a = [];h.i = {};h.modifiers.push({ name: "day", src: "yesterday", value: -1 });
+ h.modifiers.push({ name: "day", src: "today", value: 0 });h.modifiers.push({ name: "day", src: "tomorrow", value: 1 });h.modifiers.forEach(function (b) {
+ var c = b.name;d(b.src, function (d) {
+ var e = h[c];h.i[d] = b;a.push({ name: c, src: d, value: b.value });h[c] = e ? e + "|" + d : d;
+ });
+ });h.day += "|" + Ub(h.weekdays);h.modifiers = a;
+ })();h.monthSuffix && (h.month = g(1, 2), h.months = "1 2 3 4 5 6 7 8 9 10 11 12".split(" ").map(function (a) {
+ return a + h.monthSuffix;
+ }));h.full_month = g(1, 2) + "|" + Ub(h.months);0 < h.timeSuffixes.length && h.addFormat(Vb(h), !1, Jb);
+ h.addFormat("{day}", !0);h.addFormat("{month}" + (h.monthSuffix || ""));h.addFormat("{year}" + (h.yearSuffix || ""));h.timeParse.forEach(function (a) {
+ h.addFormat(a, !0);
+ });h.dateParse.forEach(function (a) {
+ h.addFormat(a);
+ });return Sb[a] = h;
+ }function Wb(a, b, c, d) {
+ a.g.unshift({ r: d, locale: a, q: q("^" + b + "$", "i"), to: c });
+ }function Yb(a) {
+ return a.slice(0, 1).toUpperCase() + a.slice(1);
+ }function Ub(a) {
+ return a.filter(function (a) {
+ return !!a;
+ }).join("|");
+ }function cc() {
+ var a = r.SugarNewDate;return a ? a() : new r();
+ }
+ function dc(a, b) {
+ var c;if (G(a[0])) return a;if (y(a[0]) && !y(a[1])) return [a[0]];if (z(a[0]) && b) return [ec(a[0]), a[1]];c = {};Nb.forEach(function (b, e) {
+ c[b.name] = a[e];
+ });return [c];
+ }function ec(a) {
+ var b,
+ c = {};if (a = a.match(/^(\d+)?\s?(\w+?)s?$/i)) N(b) && (b = parseInt(a[1]) || 1), c[a[2].toLowerCase()] = b;return c;
+ }function fc(a, b, c) {
+ var d;N(c) && (c = Ob.length);for (b = b || 0; b < c && (d = Ob[b], !1 !== a(d.name, d, b)); b++) {}
+ }
+ function gc(a, b) {
+ var c = {},
+ d,
+ e;b.forEach(function (b, f) {
+ d = a[f + 1];N(d) || "" === d || ("year" === b && (c.t = d.replace(/'/, "")), e = parseFloat(d.replace(/'/, "").replace(/,/, ".")), c[b] = isNaN(e) ? d.toLowerCase() : e);
+ });return c;
+ }function hc(a) {
+ a = a.trim().replace(/^just (?=now)|\.+$/i, "");return ic(a);
+ }
+ function ic(a) {
+ return a.replace(Mb, function (a, c, d) {
+ var e = 0,
+ g = 1,
+ f,
+ h;if (c) return a;d.split("").reverse().forEach(function (a) {
+ a = Lb[a];var b = 9 < a;b ? (f && (e += g), g *= a / (h || 1), h = a) : (!1 === f && (g *= 10), e += g * a);f = b;
+ });f && (e += g);return e;
+ });
+ }
+ function jc(a, b, c, d) {
+ function e(a) {
+ vb.push(a);
+ }function g() {
+ vb.forEach(function (a) {
+ a.call();
+ });
+ }function f() {
+ var a = n.getWeekday();n.setWeekday(7 * (k.num - 1) + (a > Ba ? Ba + 7 : Ba));
+ }function h() {
+ var a = B.i[k.edge];fc(function (a) {
+ if (M(k[a])) return E = a, !1;
+ }, 4);if ("year" === E) k.e = "month";else if ("month" === E || "week" === E) k.e = "day";n[(0 > a.value ? "endOf" : "beginningOf") + Yb(E)]();-2 === a.value && n.reset();
+ }function l() {
+ var a;fc(function (b, c, d) {
+ "day" === b && (b = "date");if (M(k[b])) {
+ if (d >= wb) return n.setTime(NaN), !1;a = a || {};a[b] = k[b];
+ delete k[b];
+ }
+ });a && e(function () {
+ n.set(a, !0);
+ });
+ }var n, x, ha, vb, B, k, E, wb, Ba, ra, ca;n = cc();vb = [];n.utc(d);C(a) ? n.utc(a.isUTC()).setTime(a.getTime()) : y(a) ? n.setTime(a) : G(a) ? (n.set(a, !0), k = a) : z(a) && (ha = Y(b), a = hc(a), ha && I(ha.o ? [ha.o].concat(ha.g) : ha.g, function (c, d) {
+ var g = a.match(d.q);if (g) {
+ B = d.locale;k = gc(g, d.to);B.o = d;k.utc && n.utc();if (k.timestamp) return k = k.timestamp, !1;d.r && !z(k.month) && (z(k.date) || Zb(ha, b)) && (ca = k.month, k.month = k.date, k.date = ca);k.year && 2 === k.t.length && (k.year = 100 * R(U(cc(), "FullYear") / 100) - 100 * R(k.year / 100) + k.year);k.month && (k.month = B.getMonth(k.month), k.shift && !k.unit && (k.unit = B.units[7]));k.weekday && k.date ? delete k.weekday : k.weekday && (k.weekday = B.getWeekday(k.weekday), k.shift && !k.unit && (k.unit = B.units[5]));k.day && (ca = B.i[k.day]) ? (k.day = ca.value, n.reset(), x = !0) : k.day && -1 < (Ba = B.getWeekday(k.day)) && (delete k.day, k.num && k.month ? (e(f), k.day = 1) : k.weekday = Ba);k.date && !y(k.date) && (k.date = $b(B, k.date));k.ampm && k.ampm === B.ampm[1] && 12 > k.hour ? k.hour += 12 : k.ampm === B.ampm[0] && 12 === k.hour && (k.hour = 0);if ("offset_hours" in k || "offset_minutes" in k) n.utc(), k.offset_minutes = k.offset_minutes || 0, k.offset_minutes += 60 * k.offset_hours, "-" === k.offset_sign && (k.offset_minutes *= -1), k.minute -= k.offset_minutes;k.unit && (x = !0, ra = ac(B, k.num), wb = B.units.indexOf(k.unit) % 8, E = W.units[wb], l(), k.shift && (ra *= (ca = B.i[k.shift]) ? ca.value : 0), k.sign && (ca = B.i[k.sign]) && (ra *= ca.value), M(k.weekday) && (n.set({ weekday: k.weekday }, !0), delete k.weekday), k[E] = (k[E] || 0) + ra);k.edge && e(h);"-" === k.year_sign && (k.year *= -1);fc(function (a, b, c) {
+ b = k[a];var d = b % 1;d && (k[Ob[c - 1].name] = R(d * ("second" === a ? 1E3 : 60)), k[a] = Q(b));
+ }, 1, 4);return !1;
+ }
+ }), k ? x ? n.advance(k) : (n._utc && n.reset(), kc(n, k, !0, !1, c)) : ("now" !== a && (n = new r(a)), d && n.addMinutes(-n.getTimezoneOffset())), g(), n.utc(!1));return { c: n, set: k };
+ }function lc(a) {
+ var b,
+ c = P(a),
+ d = c,
+ e = 0;fc(function (a, f, h) {
+ b = Q(Da(c / f.b(), 1));1 <= b && (d = b, e = h);
+ }, 1);return [d, e, a];
+ }
+ function mc(a) {
+ var b = lc(a.millisecondsFromNow());if (6 === b[1] || 5 === b[1] && 4 === b[0] && a.daysFromNow() >= cc().daysInMonth()) b[0] = P(a.monthsFromNow()), b[1] = 6;return b;
+ }function nc(a, b, c) {
+ function d(a, c) {
+ var d = U(a, "Month");return Y(c).months[d + 12 * b];
+ }Z(a, d, c);Z(Yb(a), d, c, 1);
+ }function Z(a, b, c, d) {
+ X[a] = function (a, g) {
+ var f = b(a, g);c && (f = f.slice(0, c));d && (f = f.slice(0, d).toUpperCase() + f.slice(d));return f;
+ };
+ }
+ function oc(a, b, c) {
+ X[a] = b;X[a + a] = function (a, c) {
+ return T(b(a, c), 2);
+ };c && (X[a + a + a] = function (a, c) {
+ return T(b(a, c), 3);
+ }, X[a + a + a + a] = function (a, c) {
+ return T(b(a, c), 4);
+ });
+ }function pc(a) {
+ var b = a.match(/(\{\w+\})|[^{}]+/g);Qb[a] = b.map(function (a) {
+ a.replace(/\{(\w+)\}/, function (b, e) {
+ a = X[e] || e;return e;
+ });return a;
+ });
+ }
+ function qc(a, b, c, d) {
+ var e;if (!a.isValid()) return "Invalid Date";Date[b] ? b = Date[b] : F(b) && (e = mc(a), b = b.apply(a, e.concat(Y(d))));if (!b && c) return e = e || mc(a), 0 === e[1] && (e[1] = 1, e[0] = 1), a = Y(d), Xb(a, e, 0 < e[2] ? "future" : "past");b = b || "long";if ("short" === b || "long" === b || "full" === b) b = Y(d)[b];Qb[b] || pc(b);var g, f;e = "";b = Qb[b];g = 0;for (c = b.length; g < c; g++) {
+ f = b[g], e += F(f) ? f(a, d) : f;
+ }return e;
+ }
+ function rc(a, b, c, d, e) {
+ var g,
+ f,
+ h,
+ l = 0,
+ n = 0,
+ x = 0;g = jc(b, c, null, e);0 < d && (n = x = d, f = !0);if (!g.c.isValid()) return !1;if (g.set && g.set.e) {
+ Rb.forEach(function (b) {
+ b.name === g.set.e && (l = b.b(g.c, a - g.c) - 1);
+ });b = Yb(g.set.e);if (g.set.edge || g.set.shift) g.c["beginningOf" + b]();"month" === g.set.e && (h = g.c.clone()["endOf" + b]().getTime());!f && g.set.sign && "millisecond" != g.set.e && (n = 50, x = -50);
+ }f = a.getTime();b = g.c.getTime();h = sc(a, b, h || b + l);return f >= b - n && f <= h + x;
+ }
+ function sc(a, b, c) {
+ b = new r(b);a = new r(c).utc(a.isUTC());23 !== U(a, "Hours") && (b = b.getTimezoneOffset(), a = a.getTimezoneOffset(), b !== a && (c += (a - b).minutes()));return c;
+ }
+ function kc(a, b, c, d, e) {
+ function g(a) {
+ return M(b[a]) ? b[a] : b[a + "s"];
+ }function f(a) {
+ return M(g(a));
+ }var h;if (y(b) && d) b = { milliseconds: b };else if (y(b)) return a.setTime(b), a;M(b.date) && (b.day = b.date);fc(function (d, e, g) {
+ var l = "day" === d;if (f(d) || l && f("weekday")) return b.e = d, h = +g, !1;!c || "week" === d || l && f("week") || Sa(a, e.method, l ? 1 : 0);
+ });Rb.forEach(function (c) {
+ var e = c.name;c = c.method;var h;h = g(e);N(h) || (d ? ("week" === e && (h = (b.day || 0) + 7 * h, c = "Date"), h = h * d + U(a, c)) : "month" === e && f("day") && Sa(a, "Date", 15), Sa(a, c, h), d && "month" === e && (e = h, 0 > e && (e = e % 12 + 12), e % 12 != U(a, "Month") && Sa(a, "Date", 0)));
+ });d || f("day") || !f("weekday") || a.setWeekday(g("weekday"));var l;a: {
+ switch (e) {case -1:
+ l = a > cc();break a;case 1:
+ l = a < cc();break a;}l = void 0;
+ }l && fc(function (b, c) {
+ if ((c.k || "week" === b && f("weekday")) && !(f(b) || "day" === b && f("weekday"))) return a[c.j](e), !1;
+ }, h + 1);return a;
+ }
+ function Vb(a, b) {
+ var c = Kb,
+ d = { h: 0, m: 1, s: 2 },
+ e;a = a || W;return c.replace(/{([a-z])}/g, function (c, f) {
+ var h = [],
+ l = "h" === f,
+ n = l && !b;if ("t" === f) return a.ampm.join("|");l && h.push(":");(e = a.timeSuffixes[d[f]]) && h.push(e + "\\s*");return 0 === h.length ? "" : "(?:" + h.join("|") + ")" + (n ? "" : "?");
+ });
+ }function tc(a, b, c) {
+ var d, e;y(a[1]) ? d = dc(a)[0] : (d = a[0], e = a[1]);return jc(d, e, b, c).c;
+ }
+ H(r, !1, !0, { create: function create() {
+ return tc(arguments);
+ }, past: function past() {
+ return tc(arguments, -1);
+ }, future: function future() {
+ return tc(arguments, 1);
+ }, addLocale: function addLocale(a, b) {
+ return bc(a, b);
+ }, setLocale: function setLocale(a) {
+ var b = Y(a, !1);Ib = b;a && a != b.code && (b.code = a);return b;
+ }, getLocale: function getLocale(a) {
+ return a ? Y(a, !1) : Ib;
+ }, addFormat: function addFormat(a, b, c) {
+ Wb(Y(c), a, b);
+ } });
+ H(r, !0, !0, { set: function set() {
+ var a = dc(arguments);return kc(this, a[0], a[1]);
+ }, setWeekday: function setWeekday(a) {
+ if (!N(a)) return Sa(this, "Date", U(this, "Date") + a - U(this, "Day"));
+ }, setISOWeek: function setISOWeek(a) {
+ var b = U(this, "Day") || 7;if (!N(a)) return this.set({ month: 0, date: 4 }), this.set({ weekday: 1 }), 1 < a && this.addWeeks(a - 1), 1 !== b && this.advance({ days: b - 1 }), this.getTime();
+ }, getISOWeek: function getISOWeek() {
+ var a;a = this.clone();var b = U(a, "Day") || 7;a.addDays(4 - b).reset();return 1 + Q(a.daysSince(a.clone().beginningOfYear()) / 7);
+ }, beginningOfISOWeek: function beginningOfISOWeek() {
+ var a = this.getDay();0 === a ? a = -6 : 1 !== a && (a = 1);this.setWeekday(a);return this.reset();
+ }, endOfISOWeek: function endOfISOWeek() {
+ 0 !== this.getDay() && this.setWeekday(7);return this.endOfDay();
+ }, getUTCOffset: function getUTCOffset(a) {
+ var b = this._utc ? 0 : this.getTimezoneOffset(),
+ c = !0 === a ? ":" : "";return !b && a ? "Z" : T(Q(-b / 60), 2, !0) + c + T(P(b % 60), 2);
+ }, utc: function utc(a) {
+ oa(this, "_utc", !0 === a || 0 === arguments.length);return this;
+ }, isUTC: function isUTC() {
+ return !!this._utc || 0 === this.getTimezoneOffset();
+ }, advance: function advance() {
+ var a = dc(arguments, !0);return kc(this, a[0], a[1], 1);
+ }, rewind: function rewind() {
+ var a = dc(arguments, !0);return kc(this, a[0], a[1], -1);
+ }, isValid: function isValid() {
+ return !isNaN(this.getTime());
+ }, isAfter: function isAfter(a, b) {
+ return this.getTime() > r.create(a).getTime() - (b || 0);
+ }, isBefore: function isBefore(a, b) {
+ return this.getTime() < r.create(a).getTime() + (b || 0);
+ }, isBetween: function isBetween(a, b, c) {
+ var d = this.getTime();a = r.create(a).getTime();var e = r.create(b).getTime();b = Ca(a, e);a = S(a, e);c = c || 0;return b - c < d && a + c > d;
+ }, isLeapYear: function isLeapYear() {
+ var a = U(this, "FullYear");return 0 === a % 4 && 0 !== a % 100 || 0 === a % 400;
+ },
+ daysInMonth: function daysInMonth() {
+ return 32 - U(new r(U(this, "FullYear"), U(this, "Month"), 32), "Date");
+ }, format: function format(a, b) {
+ return qc(this, a, !1, b);
+ }, relative: function relative(a, b) {
+ z(a) && (b = a, a = null);return qc(this, a, !0, b);
+ }, is: function is(a, b, c) {
+ var d, e;if (this.isValid()) {
+ if (z(a)) switch (a = a.trim().toLowerCase(), e = this.clone().utc(c), !0) {case "future" === a:
+ return this.getTime() > cc().getTime();case "past" === a:
+ return this.getTime() < cc().getTime();case "weekday" === a:
+ return 0 < U(e, "Day") && 6 > U(e, "Day");case "weekend" === a:
+ return 0 === U(e, "Day") || 6 === U(e, "Day");case -1 < (d = W.weekdays.indexOf(a) % 7):
+ return U(e, "Day") === d;case -1 < (d = W.months.indexOf(a) % 12):
+ return U(e, "Month") === d;}return rc(this, a, null, b, c);
+ }
+ }, reset: function reset(a) {
+ var b = {},
+ c;a = a || "hours";"date" === a && (a = "days");c = Rb.some(function (b) {
+ return a === b.name || a === b.name + "s";
+ });b[a] = a.match(/^days?/) ? 1 : 0;return c ? this.set(b, !0) : this;
+ }, clone: function clone() {
+ var a = new r(this.getTime());a.utc(!!this._utc);return a;
+ } });
+ H(r, !0, !0, { iso: function iso() {
+ return this.toISOString();
+ }, getWeekday: r.prototype.getDay, getUTCWeekday: r.prototype.getUTCDay });function uc(a, b) {
+ function c() {
+ return R(this * b);
+ }function d() {
+ return tc(arguments)[a.j](this);
+ }function e() {
+ return tc(arguments)[a.j](-this);
+ }var g = a.name,
+ f = {};f[g] = c;f[g + "s"] = c;f[g + "Before"] = e;f[g + "sBefore"] = e;f[g + "Ago"] = e;f[g + "sAgo"] = e;f[g + "After"] = d;f[g + "sAfter"] = d;f[g + "FromNow"] = d;f[g + "sFromNow"] = d;t.extend(f);
+ }H(t, !0, !0, { duration: function duration(a) {
+ a = Y(a);return Xb(a, lc(this), "duration");
+ } });
+ W = Ib = r.addLocale("en", { plural: !0, timeMarker: "at", ampm: "am,pm", months: "January,February,March,April,May,June,July,August,September,October,November,December", weekdays: "Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday", units: "millisecond:|s,second:|s,minute:|s,hour:|s,day:|s,week:|s,month:|s,year:|s", numbers: "one,two,three,four,five,six,seven,eight,nine,ten", articles: "a,an,the", tokens: "the,st|nd|rd|th,of", "short": "{Month} {d}, {yyyy}", "long": "{Month} {d}, {yyyy} {h}:{mm}{tt}", full: "{Weekday} {Month} {d}, {yyyy} {h}:{mm}:{ss}{tt}",
+ past: "{num} {unit} {sign}", future: "{num} {unit} {sign}", duration: "{num} {unit}", modifiers: [{ name: "sign", src: "ago|before", value: -1 }, { name: "sign", src: "from now|after|from|in|later", value: 1 }, { name: "edge", src: "last day", value: -2 }, { name: "edge", src: "end", value: -1 }, { name: "edge", src: "first day|beginning", value: 1 }, { name: "shift", src: "last", value: -1 }, { name: "shift", src: "the|this", value: 0 }, { name: "shift", src: "next", value: 1 }], dateParse: ["{month} {year}", "{shift} {unit=5-7}", "{0?} {date}{1}", "{0?} {edge} of {shift?} {unit=4-7?}{month?}{year?}"],
+ timeParse: "{num} {unit} {sign};{sign} {num} {unit};{0} {num}{1} {day} of {month} {year?};{weekday?} {month} {date}{1?} {year?};{date} {month} {year};{date} {month};{shift} {weekday};{shift} week {weekday};{weekday} {2?} {shift} week;{num} {unit=4-5} {sign} {day};{0?} {date}{1} of {month};{0?}{month?} {date?}{1?} of {shift} {unit=6-7}".split(";") });Ob = Rb.concat().reverse();Nb = Rb.concat();Nb.splice(2, 1);
+ K(r, !0, !0, Rb, function (a, b, c) {
+ function d(a) {
+ a /= f;var c = a % 1,
+ d = b.error || 0.999;c && P(c % 1) > d && (a = R(a));return 0 > a ? Aa(a) : Q(a);
+ }var e = b.name,
+ g = Yb(e),
+ f = b.b(),
+ h,
+ l;b.j = "add" + g + "s";h = function h(a, b) {
+ return d(this.getTime() - r.create(a, b).getTime());
+ };l = function l(a, b) {
+ return d(r.create(a, b).getTime() - this.getTime());
+ };a[e + "sAgo"] = l;a[e + "sUntil"] = l;a[e + "sSince"] = h;a[e + "sFromNow"] = h;a[b.j] = function (a, b) {
+ var c = {};c[e] = a;return this.advance(c, b);
+ };uc(b, f);3 > c && ["Last", "This", "Next"].forEach(function (b) {
+ a["is" + b + g] = function () {
+ return rc(this, b + " " + e, "en");
+ };
+ });4 > c && (a["beginningOf" + g] = function () {
+ var a = {};switch (e) {case "year":
+ a.year = U(this, "FullYear");break;case "month":
+ a.month = U(this, "Month");break;case "day":
+ a.day = U(this, "Date");break;case "week":
+ a.weekday = 0;}return this.set(a, !0);
+ }, a["endOf" + g] = function () {
+ var a = { hours: 23, minutes: 59, seconds: 59, milliseconds: 999 };switch (e) {case "year":
+ a.month = 11;a.day = 31;break;case "month":
+ a.day = this.daysInMonth();break;case "week":
+ a.weekday = 6;}return this.set(a, !0);
+ });
+ });
+ W.addFormat("([+-])?(\\d{4,4})[-.]?{full_month}[-.]?(\\d{1,2})?", !0, ["year_sign", "year", "month", "date"], !1, !0);W.addFormat("(\\d{1,2})[-.\\/]{full_month}(?:[-.\\/](\\d{2,4}))?", !0, ["date", "month", "year"], !0);W.addFormat("{full_month}[-.](\\d{4,4})", !1, ["month", "year"]);W.addFormat("\\/Date\\((\\d+(?:[+-]\\d{4,4})?)\\)\\/", !1, ["timestamp"]);W.addFormat(Vb(W), !1, Jb);Pb = W.g.slice(0, 7).reverse();W.g = W.g.slice(7).concat(Pb);oc("f", function (a) {
+ return U(a, "Milliseconds");
+ }, !0);
+ oc("s", function (a) {
+ return U(a, "Seconds");
+ });oc("m", function (a) {
+ return U(a, "Minutes");
+ });oc("h", function (a) {
+ return U(a, "Hours") % 12 || 12;
+ });oc("H", function (a) {
+ return U(a, "Hours");
+ });oc("d", function (a) {
+ return U(a, "Date");
+ });oc("M", function (a) {
+ return U(a, "Month") + 1;
+ });(function () {
+ function a(a, c) {
+ var d = U(a, "Hours");return Y(c).ampm[Q(d / 12)] || "";
+ }Z("t", a, 1);Z("tt", a);Z("T", a, 1, 1);Z("TT", a, null, 2);
+ })();
+ /* istanbul ignore next */
+ (function () {
+ function a(a, c) {
+ var d = U(a, "Day");return Y(c).weekdays[d];
+ }Z("dow", a, 3);Z("Dow", a, 3, 1);Z("weekday", a);Z("Weekday", a, null, 1);
+ })();nc("mon", 0, 3);nc("month", 0);nc("month2", 1);nc("month3", 2);X.ms = X.f;X.milliseconds = X.f;X.seconds = X.s;X.minutes = X.m;X.hours = X.h;X["24hr"] = X.H;X["12hr"] = X.h;X.date = X.d;X.day = X.d;X.year = X.yyyy;K(r, !0, !0, "short,long,full", function (a, b) {
+ a[b] = function (a) {
+ return qc(this, b, !1, a);
+ };
+ });
+ "〇一二三四五六七八九十百千万".split("").forEach(function (a, b) {
+ 9 < b && (b = za(10, b - 9));Lb[a] = b;
+ });xa(Lb, Ka);Mb = q("([期週周])?([〇一二三四五六七八九十百千万" + Ja + "]+)(?!昨)", "g");
+ /* istanbul ignore next */
+ (function () {
+ var a = W.weekdays.slice(0, 7),
+ b = W.months.slice(0, 12);K(r, !0, !0, "today yesterday tomorrow weekday weekend future past".split(" ").concat(a).concat(b), function (a, b) {
+ a["is" + Yb(b)] = function (a) {
+ return this.is(b, 0, a);
+ };
+ });
+ })();r.utc || (r.utc = { create: function create() {
+ return tc(arguments, 0, !0);
+ }, past: function past() {
+ return tc(arguments, -1, !0);
+ }, future: function future() {
+ return tc(arguments, 1, !0);
+ } });
+ H(r, !1, !0, { RFC1123: "{Dow}, {dd} {Mon} {yyyy} {HH}:{mm}:{ss} {tz}", RFC1036: "{Weekday}, {dd}-{Mon}-{yy} {HH}:{mm}:{ss} {tz}", ISO8601_DATE: "{yyyy}-{MM}-{dd}", ISO8601_DATETIME: "{yyyy}-{MM}-{dd}T{HH}:{mm}:{ss}.{fff}{isotz}" });
+})();
34 dist/util/colorFile.js
@@ -0,0 +1,34 @@
+'use strict';
+
+var strip = require('./stripAnsi');
+
+var chalk = {};
+var map = { cyan: 36, red: 31, magenta: 35 };
+Object.keys(map).forEach(function (key, value) {
+ chalk[key] = function (str) {
+ return '\u001b[' + value + 'm' + str + '\u001b[39m';
+ };
+});
+
+/**
+ * Wraps file strings in ANSI colors
+ * based on their extension.
+ *
+ * @param {file} str
+ * @return {String}
+ * @api public
+ */
+
+module.exports = function (file) {
+ var audio = ['aac', 'au', 'flac', 'mid', 'midi', 'mka', 'mp3', 'mpc', 'ogg', 'ra', 'wav', 'axa', 'oga', 'spx', 'xspf'];
+ var archive = ['tar', 'tgz', 'arj', 'taz', 'lzh', 'lzma', 'tlz', 'txz', 'zip', 'z', 'Z', 'dz', 'gz', 'lz', 'xz', 'bz2', 'bz', 'tbz', 'tbz2', 'tz', 'deb', 'rpm', 'jar', 'rar', 'ace', 'zoo', 'cpio', '7z', 'rz'];
+ var images = ['jpg', 'jpeg', 'gif', 'bmp', 'pbm', 'pgm', 'ppm', 'tga', 'xbm', 'xpm', 'tif', 'tiff', 'png', 'svg', 'svgz', 'mng', 'pcx', 'mov', 'mpg', 'mpeg', 'm2v', 'mkv', 'ogm', 'mp4', 'm4v', 'mp4v', 'vob', 'qt', 'nuv', 'wmv', 'asf', 'rm', 'rmvb', 'flc', 'avi', 'fli', 'flv', 'gl', 'dl', 'xcf', 'xwd', 'yuv', 'cgm', 'emf', 'axv', 'anx', 'ogv', 'ogx'];
+
+ var extension = String(file).toLowerCase().trim().split('.');
+ extension = extension[extension.length - 1];
+
+ var colored = strip(file);
+ colored = audio.indexOf(extension) > -1 ? chalk.cyan(file) : archive.indexOf(extension) > -1 ? chalk.red(file) : images.indexOf(extension) > -1 ? chalk.magenta(file) : colored;
+
+ return colored;
+};
58 dist/util/columnify.js
@@ -0,0 +1,58 @@
+'use strict';
+
+var strip = require('./stripAnsi');
+var pad = require('./pad');
+
+/**
+ * Formats an array to display in a TTY
+ * in a pretty fashion.
+ *
+ * @param {Array} arr
+ * @return {String}
+ * @api public
+ */
+
+module.exports = function (arr, options) {
+ arr = arr || [];
+ options = options || {};
+ var bk = JSON.parse(JSON.stringify(arr));
+ var width = options.width && !isNaN(options.width) ? options.width : process.stdout.columns;
+ var longest = strip(bk.sort(function (a, b) {
+ return strip(b).length - strip(a).length;
+ })[0] || '').length + 2;
+ var fullWidth = strip(arr.join('')).length;
+ var fitsOneLine = fullWidth + arr.length * 2 <= width;
+ var cols = Math.floor(width / longest);
+ cols = cols < 1 ? 1 : cols;
+ if (fitsOneLine) {
+ return arr.join(' ');
+ }
+ var col = 0;
+ var lines = [];
+ var line = '';
+ for (var i = 0; i < arr.length; ++i) {
+ if (col < cols) {
+ col++;
+ } else {
+ if (String(strip(line)).trim() !== '') {
+ lines.push(line);
+ }
+ line = '';
+ col = 1;
+ }
+ if (cols === 1) {
+ // If we have files so damn
+ // long that we wrap, don't pad
+ // the lines.
+ line += arr[i];
+ } else {
+ // Pad the lines based on the
+ // longest word.
+ line += pad(arr[i], longest, ' ');
+ }
+ }
+ if (line !== '') {
+ lines.push(line);
+ }
+ return lines.join('\n');
+};
30 dist/util/converter.date.js
@@ -0,0 +1,30 @@
+'use strict';
+
+/**
+ * Date conversion utilities
+ */
+
+var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
+
+function pad(num, padding) {
+ padding = padding || '0';
+ num = parseFloat(num);
+ if (num < 10) {
+ return '' + padding + num;
+ }
+ return num;
+}
+
+module.exports = {
+ unix: function unix(dt) {
+ var date = dt;
+ var day = pad(date.getDate(), ' ');
+ var month = months[date.getMonth()];
+ var hour = pad(date.getHours());
+ var min = pad(date.getMinutes());
+ var hourMin = hour + ':' + min;
+ day = day.length === 1 ? ' ' + day : day;
+ date = month + ' ' + day + ' ' + hourMin;
+ return date;
+ }
+};
19 dist/util/converter.path.js
@@ -0,0 +1,19 @@
+'use strict';
+
+var path = require('path');
+
+/**
+ * Path conversion utilities
+ */
+
+module.exports = {
+ unix: function unix(str) {
+ var input = path.normalize(str);
+ input = input.replace(/\\/g, '\/');
+ var parts = input.split(':');
+ var drive = parts.shift();
+ var isLetter = drive.length === 1 && drive.match(/[a-z]/i);
+ var result = isLetter ? drive + parts.join(':') : input;
+ return result;
+ }
+};
39 dist/util/converter.permissions.js
@@ -0,0 +1,39 @@
+'use strict';
+
+/**
+ * Permission conversion utilities
+ */
+
+module.exports = {
+
+ listing: {
+ 0: '---',
+ 1: '--x',
+ 2: '-w-',
+ 3: '-wx',
+ 4: 'r--',
+ 5: 'r-x',
+ 6: 'rw-',
+ 7: 'rwx'
+ },
+
+ modeToRWX: function modeToRWX(mode) {
+ var octal = this.modeToOctal(mode);
+ var rwx = this.octalToRWX(octal);
+ return rwx;
+ },
+ modeToOctal: function modeToOctal(mode) {
+ var octal = '0' + (mode & 511).toString(8);
+ return octal;
+ },
+ octalToRWX: function octalToRWX(octal) {
+ if (!octal) {
+ return undefined;
+ }
+ var list = this.listing;
+ var a = list[String(octal).charAt(1)];
+ var b = list[String(octal).charAt(2)];
+ var c = list[String(octal).charAt(3)];
+ return a + b + c;
+ }
+};
29 dist/util/expand.js
@@ -0,0 +1,29 @@
+'use strict';
+
+var glob = require('glob');
+
+/**
+ * Expands wildcard files, etc. out
+ * into their full paths.
+ *
+ * @param {Array} list
+ * @return {Array}
+ * @api public
+ */
+
+module.exports = function (list) {
+ var total = list.length;
+ var files = [];
+ if (list.length < 1) {
+ return [];
+ }
+ for (var i = 0; i < total; ++i) {
+ var res = glob.sync(list[i], {});
+ files[i] = res.length > 0 ? res : list[i];
+ }
+ var out = [];
+ for (var i = 0; i < files.length; ++i) {
+ out = Array.isArray(files[i]) ? out.concat(files[i]) : out.concat([files[i]]);
+ }
+ return out;
+};
50 dist/util/fetch.js
@@ -0,0 +1,50 @@
+'use strict';
+
+var fs = require('fs');
+var path = require('path');
+
+var expand = require('./expand');
+
+/**
+ * Reads the contents of an array of
+ * files and returns the array.
+ *
+ * @param {Array} files
+ * @param {String} stdin
+ * @param {Object} options
+ * @return {Array}
+ * @api public
+ */
+
+module.exports = function (files, stdin, options) {
+ files = files || [];
+ stdin = stdin !== undefined ? stdin : [];
+ var f = expand(files);
+
+ if (!(f.length === 0 && files.length > 0)) {
+ files = f;
+ }
+
+ for (var i = 0; i < files.length; ++i) {
+ try {
+ var stat = fs.statSync(files[i]);
+ if (stat.isDirectory()) {
+ files[i] = options.onDirectory(files[i]);
+ } else {
+ files[i] = String(fs.readFileSync(path.normalize(files[i]), 'utf8'));
+ }
+ } catch (e) {
+ files[i] = options.onInvalidFile(files[i]);
+ }
+ }
+
+ var agg = files.length < 1 ? stdin : files;
+ var final = [];
+
+ for (var i = 0; i < agg.length; ++i) {
+ if (agg[i] !== undefined) {
+ final.push(agg[i]);
+ }
+ }
+ return final;
+};
17 dist/util/fileFromPath.js
@@ -0,0 +1,17 @@
+'use strict';
+
+/**
+ * Parses a path and returns just the file
+ *
+ * @param {path} str
+ * @return {String}
+ * @api public
+ */
+
+module.exports = function (path) {
+ var fileShort = String(path).split('/');
+ fileShort = fileShort[fileShort.length - 1];
+ fileShort = fileShort.split('\\');
+ fileShort = fileShort[fileShort.length - 1];
+ return fileShort;
+};
47 dist/util/intercept.js
@@ -0,0 +1,47 @@
+'use strict';
+
+var _ = require('lodash');
+
+/**
+ * Intercepts stdout, passes thru callback
+ * also pass console.error thru stdout so it goes to callback too
+ * (stdout.write and stderr.write are both refs to the same stream.write function)
+ * returns an unhook() function, call when done intercepting
+ *
+ * @param {Function} callback
+ * @return {Function}
+ */
+
+module.exports = function (callback) {
+ var oldStdoutWrite = process.stdout.write;
+ var oldConsoleError = console.error;
+ process.stdout.write = function (write) {
+ return function (string) {
+ var args = _.toArray(arguments);
+ args[0] = interceptor(string);
+ write.apply(process.stdout, args);
+ };
+ }(process.stdout.write);
+
+ console.error = function () {
+ return function () {
+ var args = _.toArray(arguments);
+ args.unshift('\x1b[31m[ERROR]\x1b[0m');
+ console.log.apply(console.log, args);
+ };
+ }(console.error);
+
+ function interceptor(string) {
+ // only intercept the string
+ var result = callback(string);
+ if (typeof result === 'string') {
+ string = result.replace(/\n$/, '') + (result && /\n$/.test(string) ? '\n' : '');
+ }
+ return string;
+ }
+ // puts back to original
+ return function unhook() {
+ process.stdout.write = oldStdoutWrite;
+ console.error = oldConsoleError;
+ };
+};
45 dist/util/interfacer.js
@@ -0,0 +1,45 @@
+'use strict';
+
+/**
+ * Simple binding interface between
+ * each command's function and the caller
+ * of the command, whether by `cash.command`
+ * or by being invoked by Vorpal.
+ * This exists to abstract complexity
+ * and create a standard in interfacing
+ * commands acorss muliple execution paths.
+ *
+ * @param {Object} opt
+ * @api public
+ */
+
+module.exports = function (opt) {
+ var self = this;
+ var stdout = '';
+ opt.options = opt.options || {};
+ opt.callback = opt.callback || function () {};
+ opt.command = opt.command || {
+ exec: function exec() {}
+ };
+
+ var logger = {
+ log: function log(out) {
+ stdout += out + '\n';
+ if (opt.silent !== true) {
+ // process.stdout.write(out) // to do - handle newline problem.
+ self.log(out);
+ }
+ }
+ };
+
+ function onResult(result) {
+ result = result === undefined ? 0 : result;
+ opt.callback(null, stdout);
+ return stdout;
+ }
+
+ if (opt.async === true) {
+ return opt.command.exec.call(logger, opt.args, opt.options, onResult);
+ }
+ return onResult(opt.command.exec.call(logger, opt.args, opt.options));
+};
20 dist/util/lpad.js
@@ -0,0 +1,20 @@
+'use strict';
+
+var strip = require('./stripAnsi');
+
+/**
+ * Pads to the left hand.
+ *
+ * @param {String} str
+ * @param {Integer} width
+ * @param {String} delimiter
+ * @return {String}
+ * @api public
+ */
+
+module.exports = function (str, width, delimiter) {
+ width = Math.floor(width);
+ delimiter = delimiter || ' ';
+ var len = Math.max(0, width - strip(str).length);
+ return Array(len + 1).join(delimiter) + str;
+};
22 dist/util/pad.js
@@ -0,0 +1,22 @@
+'use strict';
+
+var strip = require('./stripAnsi');
+
+/**
+ * Pads a value with with space or
+ * a specified delimiter to match a
+ * given width.
+ *
+ * @param {String} str
+ * @param {Integer} width
+ * @param {String} delimiter
+ * @return {String}
+ * @api public
+ */
+
+module.exports = function (str, width, delimiter) {
+ width = Math.floor(width);
+ delimiter = delimiter || ' ';
+ var len = Math.max(0, width - strip(str).length);
+ return str + Array(len + 1).join(delimiter);
+};
14 dist/util/stripAnsi.js
@@ -0,0 +1,14 @@
+'use strict';
+
+/**
+ * Removes all ansi characters.
+ *
+ * @param {String} str
+ * @return {String}
+ * @api public
+ */
+
+module.exports = function (str) {
+ var ansiRegex = /[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g;
+ return typeof str === 'string' ? str.replace(ansiRegex, '') : str;
+};
30 dist/util/unlinkSync.js
@@ -0,0 +1,30 @@
+'use strict';
+
+var fs = require('fs');
+
+/**
+ * Normalizes _unlinkSync() across
+ * platforms to match Unix behavior, i.e.
+ * file can be unlinked even its it's
+ * read only.
+ * See https://github.com/joyent/node/issues/3006
+ *
+ * @param {String} file
+ * @api public
+ */
+
+module.exports = function (file) {
+ try {
+ fs.unlinkSync(file);
+ } catch (e) {
+ // Try to override file permission
+ /* istanbul ignore if */
+ if (e.code === 'EPERM') {
+ fs.chmodSync(file, '0666');
+ fs.unlinkSync(file);
+ } else {
+ /* istanbul ignore next */
+ throw e;
+ }
+ }
+};
41 dist/util/walkDir.js
@@ -0,0 +1,41 @@
+'use strict';
+
+var fs = require('fs');
+var path = require('path');
+
+/**
+ * Walks a single directory calling
+ * a callback function for each file or
+ * folder, returning the path and results
+ * of fs.statSync.
+ *
+ * @param {String} currentDirPath
+ * @param {Function} callback
+ * @api public
+ */
+
+module.exports = function (currentDirPath, callback) {
+ function readFile(path, cbk) {
+ var stat = undefined;
+ try {
+ stat = fs.statSync(path);
+ if (stat.isFile() || stat.isDirectory()) {
+ cbk(path, stat);
+ }
+ } catch (e) {
+ // .. if we can't read the file, forget
+ // about it for now.
+ }
+ }
+ try {
+ var dirs = fs.readdirSync(currentDirPath);
+ dirs.forEach(function (name) {
+ var filePath = path.join(currentDirPath, name);
+ readFile(filePath, callback);
+ });
+ } catch (e) {
+ if (e.code === 'ENOTDIR') {
+ readFile(currentDirPath, callback);
+ }
+ }
+};
24 dist/util/walkDirRecursive.js
@@ -0,0 +1,24 @@
+'use strict';
+
+var fs = require('fs');
+var path = require('path');
+
+/**
+ * Recursively walks through and executes
+ * a callback function for each directory found.
+ *
+ * @param {String} currentDirPath
+ * @param {Function} callback
+ * @api public
+ */
+
+module.exports = function (currentDirPath, callback) {
+ fs.readdirSync(currentDirPath).forEach(function (name) {
+ var filePath = path.join(currentDirPath, name);
+ var stat = fs.statSync(filePath);
+ if (stat.isDirectory()) {
+ callback(filePath, stat);
+ module.exports(filePath, callback);
+ }
+ });
+};
120 dist/windows.js
@@ -0,0 +1,120 @@
+'use strict';
+
+var _ = require('lodash');
+var os = require('os');
+
+var commands = require('./../commands.json').windowsCommands;
+
+module.exports = {
+ registerCommands: function registerCommands(self) {
+ self.vorpal.catch('[words...]', 'Catches content').parse(function (input) {
+ // Look for aliases and translate them.
+ // Makes cash.alias and cash.unalias work.
+ var parts = String(input).split(' ');
+ var first = parts.shift();
+ var out = input;
+ var translation = self.vorpal._aliases[first];
+ if (self.vorpal._aliases && translation) {
+ /* istanbul ignore next */
+ out = translation + ' ' + parts.join(' ');
+ }
+ return out;
+ })
+ /* istanbul ignore next */
+ .autocomplete(function () {
+ /* istanbul ignore next */
+ return _.map(self.vorpal.commands, '_name');
+ }).action(function (args, cb) {
+ cb = cb || function () {};
+ var spawn = require('child_process').spawn;
+ var slf = this;
+
+ var words = args.words.join(' ');
+ var argus = undefined;
+
+ var cmd = undefined;
+ // Only register commands if on Windows.
+ /* istanbul ignore next */
+ if (os.platform() === 'win32') {
+ for (var i = 0; i < commands.length; ++i) {
+ if (String(words.slice(0, commands[i].length)).toLowerCase() === commands[i].toLowerCase()) {
+ cmd = commands[i];
+ argus = String(words.slice(commands[i].length, words.length)).trim().split(' ');
+ argus = argus.length === 1 && argus[0] === '' ? [] : argus;
+ }
+ }
+ }
+
+ // Accommodate tests for Linux.
+ if (words === 'cash-test') {
+ cmd = 'echo';
+ argus = ['hi'];
+ }
+
+ if (cmd === undefined || argus === undefined) {
+ slf.help();
+ cb();
+ return;
+ }
+
+ argus.unshift(cmd);
+ argus.unshift('/C');
+ var proc = undefined;
+ var out = '';
+ try {
+ proc = spawn('cmd', argus);
+ } catch (e) {
+ /* istanbul ignore next */
+ slf.log(e);
+ }
+
+ var closed = false;
+
+ // Properly print stdout as it's fed,
+ // waiting for line breaks before sending
+ // it to Vorpal.
+ function print() {
+ var parts = String(out).split('\n');
+ /* istanbul ignore next */
+ if (parts.length > 1) {
+ out = parts.pop();
+ var logging = String(parts.join('\n')).replace(/\r\r/g, '\r');
+ slf.log(logging);
+ }
+ /* istanbul ignore next */
+ if (closed === false) {
+ setTimeout(function () {
+ print();
+ }, 50);
+ }
+ }
+ print();
+
+ /* istanbul ignore next */
+ proc.stdout.on('data', function (data) {
+ out += data.toString('utf8');
+ });
+
+ /* istanbul ignore next */
+ proc.stderr.on('data', function (data) {
+ out += data.toString('utf8');
+ });
+
+ proc.on('close', function () {
+ closed = true;
+ if (String(out).trim() !== '') {
+ slf.log(String(out).replace(/\r\r/g, '\r'));
+ out = '';
+ }
+ /* istanbul ignore next */
+ setTimeout(function () {
+ cb();
+ }, 150);
+ });
+
+ proc.on('error', function (data) {
+ out += data.toString('utf8');
+ });
+ });
+ }
+};
127 gulpfile.js
@@ -0,0 +1,127 @@
+'use strict';
+
+const $ = require('shelljs');
+const babel = require('gulp-babel');
+const changed = require('gulp-changed');
+const eslint = require('gulp-eslint');
+const fs = require('fs');
+const gulp = require('gulp');
+
+gulp.task('lint', function () {
+ return gulp.src(['src/*.js', './*.js', './bin/*.js'])
+ .pipe(eslint())
+ .pipe(eslint.format());
+});
+gulp.task('babel', function () {
+ const bab = babel();
+ gulp.src('src/**/*.js')
+ .pipe(changed('dist'))
+ .pipe(bab)
+ .pipe(gulp.dest('dist'));
+ return;
+});
+
+gulp.task('build', function () {
+ const commands = require('./commands.json');
+ for (let i = 0; i < commands.commands.length; ++i) {
+ const command = commands.commands[i];
+ const content = `#!/usr/bin/env node\nrequire('./parser')(process.argv, '${command}');\n`;
+ fs.writeFileSync(`./bin/${command}.js`, content);
+ }
+});
+
+function getJSON(name) {
+ const dir = `./packages/${name}`;
+ let json;
+ try {
+ json = fs.readFileSync(`${dir}/package.json`, {encoding: 'utf8', force: true});
+ json = JSON.parse(json);
+ } catch (e) {
+ $.cp('-f', `./packages/template.package.json`, `${dir}/package.json`);
+ return getJSON(name);
+ }
+ return json;
+}
+
+function writeJSON(name, json) {
+ const dir = `./packages/${name}`;
+ fs.writeFileSync(`${dir}/package.json`, `${JSON.stringify(json, null, ' ')}\n`);
+}
+
+gulp.task('packages', function () {
+ const commands = require('./commands.json');
+
+ let related = '';
+ related += `- [cash](https://github.com/dthree/cash) - Main project\n`;
+ related += `- [cash-global](https://npmjs.com/package/cash-global) - Globally install all commands\n`;
+ related += `- [vorpal](https://github.com/dthree/vorpal) - Cash is built on Vorpal\n\n`;
+ related += `#### Individual commands\n\n`;
+ for (const name in commands.packages) {
+ if (commands.packages.hasOwnProperty(name)) {
+ related += `- [cash-${name}](https://npmjs.com/package/cash-${name})\n`;
+ }
+ }
+
+ related = related.replace(/\n$/g, '');
+
+ for (const name in commands.packages) {
+ if (commands.packages.hasOwnProperty(name)) {
+ const pkg = commands.packages[name];
+ const deps = pkg.dependencies;
+ const files = pkg.files;
+ const dir = `./packages/${name}`;
+ $.rm('-rf', `${dir}/dist`);
+ $.mkdir('-p', `${dir}/dist/help`);
+ $.mkdir('-p', `${dir}/dist/lib`);
+ $.mkdir('-p', `${dir}/dist/commands`);
+ $.mkdir('-p', `${dir}/dist/util`);
+ $.mkdir('-p', `${dir}/bin`);
+ const json = getJSON(name);
+ const jsonMain = require('./package.json');
+ json.dependencies = {};
+ json.devDependencies = {};
+ const main = `./dist/commands/${name}.js`;
+ const help = `./dist/help/${name}.js`;
+ const bin = `./bin/${name}.js`;
+ $.cp('-f', main, `${dir}/${main}`);
+ $.cp('-f', bin, `${dir}/${bin}`);
+ $.cp('-f', help, `${dir}/${help}`);
+ $.cp('-f', './bin/parser.js', `${dir}/bin/parser.js`);
+ $.cp('-fr', `./packages/template.README.md`, `${dir}/README.md`);
+ let readme = String($.cat(`${dir}/README.md`));
+ readme = readme.replace(/\{package\-name\}/g, `cash-${name}`);
+ readme = readme.replace(/\{command\-name\}/g, `${name}`);
+ readme = readme.replace(/\{related\}/g, related);
+ readme.to(`${dir}/README.md`);
+ for (let i = 0; i < files.length; ++i) {
+ $.cp('-f', files[i], `${dir}/${files[i]}`);
+ }
+ for (let i = 0; i < deps.length; ++i) {
+ json.dependencies[deps[i]] = jsonMain.dependencies[deps[i]];
+ if (json.dependencies[deps[i]] === undefined) {
+ throw new Error(`Sub-module dependency for "${name}" does not exist in the main package.json file.`);
+ }
+ }
+ json.files = ['dist', 'bin'];
+ json.dependencies.vorpal = jsonMain.dependencies.vorpal;
+ json.name = `cash-${name}`;
+ json.description = `Cross-platform implementation of the Unix '${name}' command.`;
+ json.main = main;
+ json.bin = json.bin || {};
+ json.bin[name] = bin;
+ writeJSON(name, json);
+ }
+ }
+ if ($.test('-e', './../cash-global/commands.json')) {
+ $.cp('./commands.json', './../cash-global/commands.json');
+ }
+});
+
+gulp.task('watch', function () {
+ gulp.watch('src/**/*.js', ['babel', 'build', 'packages']);
+ gulp.watch('commands.json', ['babel', 'build', 'packages']);
+ gulp.watch('test/**/*.js', ['babel', 'build', 'packages']);
+});
+
+gulp.task('default', ['babel', 'watch', 'build', 'packages']);
+
103 package.json
@@ -0,0 +1,103 @@
+{
+ "name": "cash",
+ "version": "0.2.1",
+ "description": "Cross-platform Linux commands in pure ES6.",
+ "main": "./lib/index.js",
+ "scripts": {
+ "test": "./node_modules/istanbul/lib/cli.js cover --root './dist' -x './dist/lib/sugar.js' _mocha -- -R spec && npm run lint",
+ "test-win": "mocha",
+ "lint": "xo ./src/*.js ./src/**/*.js ./test/*.js"
+ },
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/dthree/cash.git"
+ },
+ "keywords": [
+ "terminal",
+ "emulator",
+ "cygwin",
+ "cli",
+ "windows",
+ "linux",
+ "unix",
+ "posix",
+ "shell",
+ "shelljs",
+ "bash",
+ "cash",
+ "$",
+ "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": {
+ "babel-core": "^6.5.2",
+ "babel-preset-es2015": "^6.5.0",
+ "coveralls": "^2.11.6",
+ "gulp": "^3.9.0",
+ "gulp-babel": "^6.1.2",
+ "gulp-changed": "^1.3.0",
+ "gulp-eslint": "^2.0.0",
+ "istanbul": "^0.4.2",
+ "mocha": "^2.2.5",
+ "shelljs": "^0.6.0",
+ "should": "^7.0.3",
+ "webpack": "^1.12.13",
+ "xo": "^0.12.1"
+ },
+ "bin": {
+ "$": "./bin/cash.js",
+ "cash": "./bin/cash.js"
+ },
+ "dependencies": {
+ "chalk": "^1.1.0",
+ "filesize": "^3.1.3",
+ "fkill": "^3.1.0",
+ "fs-extra": "^0.23.1",
+ "glob": "^6.0.4",
+ "lodash": "^4.0.0",
+ "minimist": "^1.2.0",
+ "username": "^1.0.1",
+ "vorpal": "^1.9.5",
+ "vorpal-autocomplete-fs": "0.0.3",
+ "vorpal-grep": "^0.1.2",
+ "vorpal-less": "0.0.13"
+ },
+ "engines": {
+ "node": ">= 4",
+ "iojs": ">= 1.0.0"
+ },
+ "files": [
+ "commands.json",
+ "dist",
+ "bin"
+ ],
+ "xo": {
+ "envs": [
+ "node",
+ "mocha"
+ ],
+ "space": true,
+ "esnext": true,
+ "rules": {
+ "prefer-arrow-callback": 0,
+ "no-loop-func": 0,
+ "no-nested-ternary": 0,
+ "no-constant-condition": 0,
+ "no-use-extend-native/no-use-extend-native": 0,
+ "no-negated-condition": 0,
+ "no-inner-declarations": 0,
+ "prefer-reflect": 0,
+ "wrap-iife": 0,
+ "no-unused-expressions": 0,
+ "global-require": 0
+ }
+ }
+}
47 packages/cat/README.md
@@ -0,0 +1,47 @@
+# cash-cat
+
+---
+
+
+This is a cross-platform, 100% ES6 implementation of the Unix `cat` command.
+
+```bash
+npm install cash-cat -g
+```
+
+This will install `cat` globally in your system path.
+
+For help on the command, type:
+
+```bash
+> cat --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
+
+- [cash](https://github.com/dthree/cash) - Main project
+- [cash-global](https://npmjs.com/package/cash-global) - Globally install all commands
+- [vorpal](https://github.com/dthree/vorpal) - Cash is built on Vorpal
+
+#### Individual commands
+
+- [cash-cat](https://npmjs.com/package/cash-cat)
+- [cash-cp](https://npmjs.com/package/cash-cp)
+- [cash-kill](https://npmjs.com/package/cash-kill)
+- [cash-ls](https://npmjs.com/package/cash-ls)
+- [cash-mkdir](https://npmjs.com/package/cash-mkdir)
+- [cash-mv](https://npmjs.com/package/cash-mv)
+- [cash-pwd](https://npmjs.com/package/cash-pwd)
+- [cash-sort](https://npmjs.com/package/cash-sort)
+- [cash-touch](https://npmjs.com/package/cash-touch)
+- [cash-rm](https://npmjs.com/package/cash-rm)
+
+
+## License
+
+MIT © [David Caccavella](https://github.com/dthree)
2 packages/cat/bin/cat.js
@@ -0,0 +1,2 @@
+#!/usr/bin/env node
+require('./parser')(process.argv, 'cat');
50 packages/cat/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(' '));
+ }
+};
116 packages/cat/dist/commands/cat.js
@@ -0,0 +1,116 @@
+'use strict';
+
+var _ = require('lodash');
+var fsAutocomplete = require('vorpal-autocomplete-fs');
+
+var fetch = require('./../util/fetch');
+var interfacer = require('./../util/interfacer');
+var lpad = require('./../util/lpad');
+var strip = require('./../util/stripAnsi');
+
+var cat = {
+ exec: function exec(args, options) {
+ var self = this;
+
+ // Input normalization
+ if (args === undefined) {
+ args = {
+ files: []
+ };
+ } else if (_.isString(args)) {
+ args = {
+ files: [args]
+ };
+ } else if (_.isArray(args)) {
+ args = {
+ files: args
+ };
+ }
+
+ options = options || {};
+
+ // -A handler
+ if (options.showall) {
+ options.shownonprinting = true;
+ options.showends = true;
+ options.showtabs = true;
+ }
+
+ // -e handler
+ if (options.e) {
+ options.shownonprinting = true;
+ options.showends = true;
+ }
+
+ // -t handler
+ if (options.t) {
+ options.shownonprinting = true;
+ options.showtabs = true;
+ }
+
+ var stdout = '';
+ try {
+ var stdin = fetch(args.files, args.stdin, {
+ onDirectory: function onDirectory(name) {
+ return 'cat: ' + name + ': Is a directory';
+ },
+ onInvalidFile: function onInvalidFile(name) {
+ return 'cat: ' + name + ': No such file or directory';
+ }
+ });
+ var ctr = 0;
+ for (var i = 0; i < stdin.length; ++i) {
+ // If -s, squeeze double blank lines to a
+ // single line.
+ if (options.squeezeblank) {
+ stdin[i] = stdin[i].replace(/\n\n\s*\n/g, '\n\n');
+ }
+ if (options.showtabs) {
+ stdin[i] = stdin[i].replace(/\t/g, '^I');
+ }
+ // Get rid of trailing line break because
+ // node logging does it anyway.
+ stdin[i] = stdin[i].replace(/\s$/, '');
+ var parts = String(stdin[i]).split('\n');
+ for (var j = 0; j < parts.length; ++j) {
+ var blank = strip(parts[j]).trim() === '';
+ // If -b, number every non-blank line
+ // If -n, number every line
+ var numbered = !blank && options.numbernonblank || options.number && !options.numbernonblank;
+ if (numbered) {
+ ctr++;
+ }
+ var numStr = numbered ? lpad(String(ctr), 6, ' ') + ' ' : '';
+ // If -E, append a $ to each line end.
+ var dollarStr = options.showends ? '$' : '';
+ var line = numStr + parts[j] + dollarStr;
+ self.log(line);
+ stdout += line + '\n';
+ }
+ }
+ return 0;
+ } catch (e) {
+ /* istanbul ignore next */
+ self.log(e.stack);
+ /* istanbul ignore next */
+ return 1;
+ }
+ }
+};
+
+module.exports = function (vorpal) {
+ if (vorpal === undefined) {
+ return cat;
+ }
+ vorpal.api.cat = cat;
+ vorpal.command('cat [files...]').option('-A, --show-all', 'equivalent to -vET').option('-b, --number-nonblank', 'number nonempty output lines, overrides -n').option('-e', 'equivalent to -vE').option('-E, --show-ends', 'display $ at end of each line').option('-n, --number', 'number all output lines').option('-s, --squeeze-blank', 'suppress repeated empty output lines').option('-t', 'equivalent to -vT').option('-T, --show-tabs', 'display TAB characters as ^I').option('-v, --show-nonprinting', 'use ^ and M- notation, except for LFD and TAB') // this doesn't work yet...
+ .autocomplete(fsAutocomplete()).action(function (args, cb) {
+ args.options = args.options || {};
+ return interfacer.call(this, {
+ command: cat,
+ args: args,
+ options: args.options,
+ callback: cb
+ });
+ });
+};
3 packages/cat/dist/help/cat.js
@@ -0,0 +1,3 @@
+"use strict";
+
+module.exports = "\nUsage: cat [OPTION]... [FILE]...\nConcatenate FILE(s), or standard input, to standard output.\n\n -A, --show-all equivalent to -vET\n -b, --number-nonblank number nonempty output lines, overrides -n\n -e equivalent to -vE\n -E, --show-ends display $ at end of each line\n -n, --number number all output lines\n -s, --squeeze-blank suppress repeated empty output lines\n -t equivalent to -vT\n -T, --show-tabs display TAB characters as ^I\n -v, --show-nonprinting use ^ and M- notation, except for LFD and TAB\n --help display this help and exit\n\nWith no FILE, or when FILE is -, read standard input.\n\nExamples:\n cat f - g Output f's contents, then standard input, then g's contents.\n cat Copy standard input to standard output.\n\nReport cat bugs to <https://github.com/dthree/cash>\nCash home page: <http://cash.js.org/>\n";
29 packages/cat/dist/util/expand.js
@@ -0,0 +1,29 @@
+'use strict';
+
+var glob = require('glob');
+
+/**
+ * Expands wildcard files, etc. out
+ * into their full paths.
+ *
+ * @param {Array} list
+ * @return {Array}
+ * @api public
+ */
+
+module.exports = function (list) {
+ var total = list.length;
+ var files = [];
+ if (list.length < 1) {
+ return [];
+ }
+ for (var i = 0; i < total; ++i) {
+ var res = glob.sync(list[i], {});
+ files[i] = res.length > 0 ? res : list[i];
+ }
+ var out = [];
+ for (var i = 0; i < files.length; ++i) {
+ out = Array.isArray(files[i]) ? out.concat(files[i]) : out.concat([files[i]]);
+ }
+ return out;
+};
50 packages/cat/dist/util/fetch.js
@@ -0,0 +1,50 @@
+'use strict';
+
+var fs = require('fs');
+var path = require('path');
+
+var expand = require('./expand');
+
+/**
+ * Reads the contents of an array of
+ * files and returns the array.
+ *
+ * @param {Array} files
+ * @param {String} stdin
+ * @param {Object} options
+ * @return {Array}
+ * @api public
+ */
+
+module.exports = function (files, stdin, options) {
+ files = files || [];
+ stdin = stdin !== undefined ? stdin : [];
+ var f = expand(files);
+
+ if (!(f.length === 0 && files.length > 0)) {
+ files = f;
+ }
+
+ for (var i = 0; i < files.length; ++i) {
+ try {
+ var stat = fs.statSync(files[i]);
+ if (stat.isDirectory()) {
+ files[i] = options.onDirectory(files[i]);
+ } else {
+ files[i] = String(fs.readFileSync(path.normalize(files[i]), 'utf8'));
+ }
+ } catch (e) {
+ files[i] = options.onInvalidFile(files[i]);
+ }
+ }
+
+ var agg = files.length < 1 ? stdin : files;
+ var final = [];
+
+ for (var i = 0; i < agg.length; ++i) {
+ if (agg[i] !== undefined) {
+ final.push(agg[i]);
+ }
+ }
+ return final;
+};
45 packages/cat/dist/util/interfacer.js
@@ -0,0 +1,45 @@
+'use strict';
+
+/**
+ * Simple binding interface between
+ * each command's function and the caller
+ * of the command, whether by `cash.command`
+ * or by being invoked by Vorpal.
+ * This exists to abstract complexity
+ * and create a standard in interfacing
+ * commands acorss muliple execution paths.
+ *
+ * @param {Object} opt
+ * @api public
+ */
+
+module.exports = function (opt) {
+ var self = this;
+ var stdout = '';
+ opt.options = opt.options || {};
+ opt.callback = opt.callback || function () {};
+ opt.command = opt.command || {
+ exec: function exec() {}
+ };
+
+ var logger = {
+ log: function log(out) {
+ stdout += out + '\n';
+ if (opt.silent !== true) {
+ // process.stdout.write(out) // to do - handle newline problem.
+ self.log(out);
+ }
+ }
+ };
+
+ function onResult(result) {
+ result = result === undefined ? 0 : result;
+ opt.callback(null, stdout);
+ return stdout;
+ }
+
+ if (opt.async === true) {
+ return opt.command.exec.call(logger, opt.args, opt.options, onResult);
+ }
+ return onResult(opt.command.exec.call(logger, opt.args, opt.options));
+};
20 packages/cat/dist/util/lpad.js
@@ -0,0 +1,20 @@
+'use strict';
+
+var strip = require('./stripAnsi');
+
+/**
+ * Pads to the left hand.
+ *
+ * @param {String} str
+ * @param {Integer} width
+ * @param {String} delimiter
+ * @return {String}
+ * @api public
+ */
+
+module.exports = function (str, width, delimiter) {
+ width = Math.floor(width);
+ delimiter = delimiter || ' ';
+ var len = Math.max(0, width - strip(str).length);
+ return Array(len + 1).join(delimiter) + str;
+};
14 packages/cat/dist/util/stripAnsi.js
@@ -0,0 +1,14 @@
+'use strict';
+
+/**
+ * Removes all ansi characters.
+ *
+ * @param {String} str
+ * @return {String}
+ * @api public
+ */
+
+module.exports = function (str) {
+ var ansiRegex = /[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g;
+ return typeof str === 'string' ? str.replace(ansiRegex, '') : str;
+};
51 packages/cat/package.json
@@ -0,0 +1,51 @@
+{
+ "name": "cash-cat",
+ "version": "0.1.0",
+ "description": "Cross-platform implementation of the Unix 'cat' command.",
+ "main": "./dist/commands/cat.js",
+ "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": {
+ "cat": "./bin/cat.js"
+ },
+ "dependencies": {
+ "lodash": "^4.0.0",
+ "vorpal-autocomplete-fs": "0.0.3",
+ "glob": "^6.0.4",
+ "vorpal": "^1.9.5"
+ },
+ "engines": {
+ "node": ">= 0.11.16",
+ "iojs": ">= 1.0.0"
+ },
+ "files": [
+ "dist",
+ "bin"
+ ]
+}
47 packages/cp/README.md
@@ -0,0 +1,47 @@
+# cash-cp
+
+---
+
+
+This is a cross-platform, 100% ES6 implementation of the Unix `cp` command.
+
+```bash
+npm install cash-cp -g
+```
+
+This will install `cp` globally in your system path.
+
+For help on the command, type:
+
+```bash
+> cp --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
+
+- [cash](https://github.com/dthree/cash) - Main project
+- [cash-global](https://npmjs.com/package/cash-global) - Globally install all commands
+- [vorpal](https://github.com/dthree/vorpal) - Cash is built on Vorpal
+
+#### Individual commands
+
+- [cash-cat](https://npmjs.com/package/cash-cat)
+- [cash-cp](https://npmjs.com/package/cash-cp)
+- [cash-kill](https://npmjs.com/package/cash-kill)
+- [cash-ls](https://npmjs.com/package/cash-ls)
+- [cash-mkdir](https://npmjs.com/package/cash-mkdir)
+- [cash-mv](https://npmjs.com/package/cash-mv)
+- [cash-pwd](https://npmjs.com/package/cash-pwd)
+- [cash-sort](https://npmjs.com/package/cash-sort)
+- [cash-touch](https://npmjs.com/package/cash-touch)
+- [cash-rm](https://npmjs.com/package/cash-rm)
+
+
+## License
+
+MIT © [David Caccavella](https://github.com/dthree)
2 packages/cp/bin/cp.js
@@ -0,0 +1,2 @@
+#!/usr/bin/env node
+require('./parser')(process.argv, 'cp');
50 packages/cp/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(' '));
+ }
+};
207 packages/cp/dist/commands/cp.js
@@ -0,0 +1,207 @@
+'use strict';
+
+var _ = require('lodash');
+var fs = require('fs');
+var fsAutocomplete = require('vorpal-autocomplete-fs');
+var path = require('path');
+var os = require('os');
+
+var expand = require('./../util/expand');
+var interfacer = require('./../util/interfacer');
+
+var cp = {
+ exec: function exec(args, options) {
+ var self = this;
+ options = options || {};
+
+ args = args === undefined ? [] : args;
+ args = _.isArray(args) ? args : args.split(' ');
+ args = _.filter(args, function (arg) {
+ return String(arg).trim() !== '';
+ });
+
+ options.noclobber = options.force === true ? false : options.noclobber;
+ options.recursive = options.R === true ? true : options.recursive;
+
+ if (args.length < 1) {
+ this.log('cp: missing file operand\nTry \'cp --help\' for more information.');
+ return 1;
+ }
+
+ if (args.length === 1) {
+ this.log('cp: missing destination file operand after ' + args[0] + '\nTry \'cp --help\' for more information.');
+ return 1;
+ }
+
+ args = expand(args);
+
+ var dest = args.pop();
+ var sources = args;
+
+ var exists = fs.existsSync(dest);
+ var stats = exists && fs.statSync(dest);
+
+ // Dest is not existing dir, but multiple sources given
+ if ((!exists || !stats.isDirectory()) && sources.length > 1) {
+ this.log('cp: target ' + dest + ' is not a directory');
+ return 1;
+ }
+
+ // Dest is an existing file, but no -f given
+ if (exists && stats.isFile() && options.noclobber) {
+ // just dont do anything
+ return 0;
+ }
+
+ if (options.recursive) {
+ sources.forEach(function (src, i) {
+ if (src[src.length - 1] === '/') {
+ sources[i] += '*';
+ } else if (fs.statSync(src).isDirectory() && !exists) {
+ sources[i] += '/*';
+ }
+ });
+ try {
+ fs.mkdirSync(dest, parseInt('0777', 8));
+ } catch (e) {
+ // like Unix's cp, keep going even if we can't create dest dir
+ }
+ }
+
+ sources = expand(sources);
+
+ sources.forEach(function (src) {
+ if (!fs.existsSync(src)) {
+ self.log('cp: cannot stat ' + src + ': No such file or directory');
+ return;
+ }
+
+ if (fs.statSync(src).isDirectory()) {
+ if (!options.recursive) {
+ self.log('cp: omitting directory ' + src);
+ } else {
+ // 'cp /a/source dest' should create 'source' in 'dest'
+ var newDest = path.join(dest, path.basename(src));
+ var checkDir = fs.statSync(src);
+ try {
+ fs.mkdirSync(newDest, checkDir.mode);
+ } catch (e) {
+ /* istanbul ignore if */
+ if (e.code !== 'EEXIST') {
+ throw new Error();
+ }
+ }
+ cpdirSyncRecursive.call(self, src, newDest, options);
+ }
+ return;
+ }
+
+ // If here, src is a file
+ // When copying to '/path/dir', iDest = '/path/dir/file1'
+ var iDest = dest;
+ if (fs.existsSync(dest) && fs.statSync(dest).isDirectory()) {
+ iDest = path.normalize(dest + '/' + path.basename(src));
+ }
+
+ if (fs.existsSync(iDest) && options.no_force) {
+ return;
+ }
+
+ copyFileSync.call(self, src, iDest);
+ });
+ }
+};
+
+function cpdirSyncRecursive(sourceDir, destDir, options) {
+ var self = this;
+ /* istanbul ignore if */
+ if (!options) {
+ options = {};
+ }
+ var checkDir = fs.statSync(sourceDir);
+ try {
+ fs.mkdirSync(destDir, checkDir.mode);
+ } catch (e) {
+ /* istanbul ignore if */
+ if (e.code !== 'EEXIST') {
+ throw e;
+ }
+ }
+ var files = fs.readdirSync(sourceDir);
+ for (var i = 0; i < files.length; i++) {
+ var srcFile = sourceDir + '/' + files[i];
+ var destFile = destDir + '/' + files[i];
+ var srcFileStat = fs.lstatSync(srcFile);
+ if (srcFileStat.isDirectory()) {
+ // recursion this thing right on back.
+ cpdirSyncRecursive.call(self, srcFile, destFile, options);
+ } else if (srcFileStat.isSymbolicLink()) {
+ var symlinkFull = fs.readlinkSync(srcFile);
+ fs.symlinkSync(symlinkFull, destFile, os.platform() === 'win32' ? 'junction' : null);
+ // At this point, we've hit a file actually worth copying... so copy it on over.
+ } else if (fs.existsSync(destFile) && options.noclobber) {
+ // be silent
+ } else {
+ copyFileSync.call(self, srcFile, destFile);
+ }
+ }
+}
+
+function copyFileSync(src, dest) {
+ /* istanbul ignore if */
+ if (!fs.existsSync(src)) {
+ this.log('cp: cannot stat ' + src + ': No such file or directory');
+ return;
+ }
+
+ var BUF_LENGTH = 64 * 1024;
+ var buf = new Buffer(BUF_LENGTH);
+ var bytesRead = BUF_LENGTH;
+ var pos = 0;
+ var fdr = null;
+ var fdw = null;
+
+ try {
+ fdr = fs.openSync(src, 'r');
+ } catch (e) {
+ /* istanbul ignore next */
+ this.log('cp: cannot open ' + src + ': ' + e.code);
+ /* istanbul ignore next */
+ return;
+ }
+
+ try {
+ fdw = fs.openSync(dest, 'w');
+ } catch (e) {
+ /* istanbul ignore next */
+ this.log('cp: cannot write to destination file ' + dest + ': ' + e.code);
+ /* istanbul ignore next */
+ return;
+ }
+
+ while (bytesRead === BUF_LENGTH) {
+ bytesRead = fs.readSync(fdr, buf, 0, BUF_LENGTH, pos);
+ fs.writeSync(fdw, buf, 0, bytesRead);
+ pos += bytesRead;
+ }
+
+ fs.closeSync(fdr);
+ fs.closeSync(fdw);
+ fs.chmodSync(dest, fs.statSync(src).mode);
+}
+
+module.exports = function (vorpal) {
+ if (vorpal === undefined) {
+ return cp;
+ }
+ vorpal.api.cp = cp;
+ vorpal.command('cp [args...]').option('-f, --force', 'do not prompt before overwriting').option('-n, --no-clobber', 'do not overwrite an existing file').option('-r, --recursive', 'copy directories recursively').option('-R', 'copy directories recursively').autocomplete(fsAutocomplete()).action(function (args, callback) {
+ args.options = args.options || {};
+ return interfacer.call(this, {
+ command: cp,
+ args: args.args,
+ options: args.options,
+ callback: callback
+ });
+ });
+};
3 packages/cp/dist/help/cp.js
@@ -0,0 +1,3 @@
+"use strict";
+
+module.exports = "\nUsage: cp [OPTION]... [-T] SOURCE DEST\n or: cp [OPTION]... SOURCE... DIRECTORY\nCopy SOURCE to DEST, or multiple SOURCE(s) to DIRECTORY.\n\n -f, --force if an existing destination file cannot be\n opened, remove it and try again (this option\n is ignored when the -n option is also used)\n -n, --no-clobber do not overwrite an existing file (overrides\n a previous -i option)\n -R, -r, --recursive copy directories recursively\n --help display this help and exit\n\nReport cp bugs to <https://github.com/dthree/cash>\nCash home page: <http://cash.js.org/>\n";
29 packages/cp/dist/util/expand.js
@@ -0,0 +1,29 @@
+'use strict';
+
+var glob = require('glob');
+
+/**
+ * Expands wildcard files, etc. out
+ * into their full paths.
+ *
+ * @param {Array} list
+ * @return {Array}
+ * @api public
+ */
+
+module.exports = function (list) {
+ var total = list.length;
+ var files = [];
+ if (list.length < 1) {
+ return [];
+ }
+ for (var i = 0; i < total; ++i) {
+ var res = glob.sync(list[i], {});
+ files[i] = res.length > 0 ? res : list[i];
+ }
+ var out = [];
+ for (var i = 0; i < files.length; ++i) {
+ out = Array.isArray(files[i]) ? out.concat(files[i]) : out.concat([files[i]]);
+ }
+ return out;
+};
45 packages/cp/dist/util/interfacer.js
@@ -0,0 +1,45 @@
+'use strict';
+
+/**
+ * Simple binding interface between
+ * each command's function and the caller
+ * of the command, whether by `cash.command`
+ * or by being invoked by Vorpal.
+ * This exists to abstract complexity
+ * and create a standard in interfacing
+ * commands acorss muliple execution paths.
+ *
+ * @param {Object} opt
+ * @api public
+ */
+
+module.exports = function (opt) {
+ var self = this;
+ var stdout = '';
+ opt.options = opt.options || {};
+ opt.callback = opt.callback || function () {};
+ opt.command = opt.command || {
+ exec: function exec() {}
+ };
+
+ var logger = {
+ log: function log(out) {
+ stdout += out + '\n';
+ if (opt.silent !== true) {
+ // process.stdout.write(out) // to do - handle newline problem.
+ self.log(out);
+ }
+ }
+ };
+
+ function onResult(result) {
+ result = result === undefined ? 0 : result;
+ opt.callback(null, stdout);
+ return stdout;
+ }
+
+ if (opt.async === true) {
+ return opt.command.exec.call(logger, opt.args, opt.options, onResult);
+ }
+ return onResult(opt.command.exec.call(logger, opt.args, opt.options));
+};
51 packages/cp/package.json
@@ -0,0 +1,51 @@
+{
+ "name": "cash-cp",
+ "version": "0.1.0",
+ "description": "Cross-platform implementation of the Unix 'cp' command.",
+ "main": "./dist/commands/cp.js",
+ "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": {
+ "cp": "./bin/cp.js"
+ },
+ "dependencies": {
+ "lodash": "^4.0.0",
+ "vorpal-autocomplete-fs": "0.0.3",
+ "glob": "^6.0.4",
+ "vorpal": "^1.9.5"
+ },
+ "engines": {
+ "node": ">= 0.11.16",
+ "iojs": ">= 1.0.0"
+ },
+ "files": [
+ "dist",
+ "bin"
+ ]
+}
47 packages/kill/README.md
@@ -0,0 +1,47 @@
+# cash-kill
+
+---
+
+
+This is a cross-platform, 100% ES6 implementation of the Unix `kill` command.
+
+```bash
+npm install cash-kill -g
+```
+
+This will install `kill` globally in your system path.
+
+For help on the command, type:
+
+```bash
+> kill --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
+
+- [cash](https://github.com/dthree/cash) - Main project
+- [cash-global](https://npmjs.com/package/cash-global) - Globally install all commands
+- [vorpal](https://github.com/dthree/vorpal) - Cash is built on Vorpal
+
+#### Individual commands
+
+- [cash-cat](https://npmjs.com/package/cash-cat)
+- [cash-cp](https://npmjs.com/package/cash-cp)
+- [cash-kill](https://npmjs.com/package/cash-kill)
+- [cash-ls](https://npmjs.com/package/cash-ls)
+- [cash-mkdir](https://npmjs.com/package/cash-mkdir)
+- [cash-mv](https://npmjs.com/package/cash-mv)
+- [cash-pwd](https://npmjs.com/package/cash-pwd)
+- [cash-sort](https://npmjs.com/package/cash-sort)
+- [cash-touch](https://npmjs.com/package/cash-touch)
+- [cash-rm](https://npmjs.com/package/cash-rm)
+
+
+## License
+
+MIT © [David Caccavella](https://github.com/dthree)
2 packages/kill/bin/kill.js
@@ -0,0 +1,2 @@
+#!/usr/bin/env node
+require('./parser')(process.argv, 'kill');
50 packages/kill/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(' '));
+ }
+};
97 packages/kill/dist/commands/kill.js
@@ -0,0 +1,97 @@
+'use strict';
+
+var _ = require('lodash');
+var fkill = require('fkill');
+var os = require('os');
+
+var interfacer = require('./../util/interfacer');
+
+var usage = 'kill: usage: kill [-s sigspec | -n signum | -sigspec] pid | jobspec ... or kill -l [sigspec]';
+var windows = os.platform().indexOf('win') > -1;
+var signals = {
+ SIGKILL: 9,
+ SIGTERM: 15,
+ KILL: 9,
+ TERM: 15,
+ 9: 'KILL',
+ 15: 'TERM'
+};
+
+var kill = {
+ exec: function exec(args, options) {
+ options = options || {};
+
+ var procs = args;
+ procs = procs === undefined ? [] : procs;
+ procs = typeof procs === 'string' ? String(procs).split(' ') : procs;
+ procs = _.filter(procs, function (arg) {
+ return String(arg).trim() !== '';
+ });
+
+ function log(str) {
+ if (options.vorpal) {
+ options.vorpal.log(str);
+ } else {
+ /* istanbul ignore next */
+ console.log(str);
+ }
+ }
+
+ if (options.l !== undefined) {
+ if (options.l === true) {
+ this.log(' 9) SIGKILL 15) SIGTERM');
+ return 0;
+ }
+ if (signals[options.l]) {
+ this.log(signals[options.l]);
+ return 0;
+ }
+ this.log('-cash: kill: ' + options.l + ': invalid signal specification');
+ return 0;
+ }
+
+ if (procs.length < 1) {
+ this.log(usage);
+ return 0;
+ }
+
+ var forced = options['9'] === true || options.n === 9 || String(options.s).toLowerCase() === 'sigkill' || String(options.s).toLowerCase() === 'kill';
+ var opts = { force: forced };
+
+ var _loop = function _loop(i) {
+ var proc = procs[i];
+ proc = !isNaN(proc) ? parseFloat(proc) : proc;
+ proc = windows && isNaN(proc) && proc.indexOf('.') === -1 ? proc + '.exe' : proc;
+ fkill(proc, opts).then(function () {
+ // .. chill
+ }).catch(function (err) {
+ if (String(err.message).indexOf('failed') > -1) {
+ log('-cash: kill: (' + proc + ') - No such process');
+ }
+ });
+ };
+
+ for (var i = 0; i < procs.length; ++i) {
+ _loop(i);
+ }
+
+ return 0;
+ }
+};
+
+module.exports = function (vorpal) {
+ if (vorpal === undefined) {
+ return kill;
+ }
+ vorpal.api.kill = kill;
+ vorpal.command('kill [process...]').option('-9', 'sigkill').option('-s [sig]', 'sig is a signal name').option('-n [sig]', 'sig is a signal number').option('-l [sigspec]', 'list the signal names').action(function (args, callback) {
+ args.options = args.options || {};
+ args.options.vorpal = vorpal;
+ return interfacer.call(this, {
+ command: kill,
+ args: args.process,
+ options: args.options,
+ callback: callback
+ });
+ });
+};
3 packages/kill/dist/help/kill.js
@@ -0,0 +1,3 @@
+"use strict";
+
+module.exports = "\nUsage: kill [OPTION] pid | jobspec ... or kill -l [sigspec]\nSend a signal to a job.\n\nSend the processes identified by PID or JOBSPEC the signal named by\nSIGSPEC or SIGNUM. If neither SIGSPEC nor SIGNUM is present, then\nSIGTERM is assumed.\n\n -s sig SIG is a signal name\n -n sig SIG is a signal number\n -l [sigspec] list the signal names; if arguments follow `-l' they\n are assumed to be signal numbers for which names\n should be listed\n --help display this help and exit\n\nExit status:\n 0 if OK,\n 1 if an invalid option is given or an error occurs.\n\nReport kill bugs to <https://github.com/dthree/cash>\nCash home page: <http://cash.js.org/>\n";
45 packages/kill/dist/util/interfacer.js
@@ -0,0 +1,45 @@
+'use strict';
+
+/**
+ * Simple binding interface between
+ * each command's function and the caller
+ * of the command, whether by `cash.command`
+ * or by being invoked by Vorpal.
+ * This exists to abstract complexity
+ * and create a standard in interfacing
+ * commands acorss muliple execution paths.
+ *
+ * @param {Object} opt
+ * @api public
+ */
+
+module.exports = function (opt) {
+ var self = this;
+ var stdout = '';
+ opt.options = opt.options || {};
+ opt.callback = opt.callback || function () {};
+ opt.command = opt.command || {
+ exec: function exec() {}
+ };
+
+ var logger = {
+ log: function log(out) {
+ stdout += out + '\n';
+ if (opt.silent !== true) {
+ // process.stdout.write(out) // to do - handle newline problem.
+ self.log(out);
+ }
+ }
+ };
+
+ function onResult(result) {
+ result = result === undefined ? 0 : result;
+ opt.callback(null, stdout);
+ return stdout;
+ }
+
+ if (opt.async === true) {
+ return opt.command.exec.call(logger, opt.args, opt.options, onResult);
+ }
+ return onResult(opt.command.exec.call(logger, opt.args, opt.options));
+};
50 packages/kill/package.json
@@ -0,0 +1,50 @@
+{
+ "name": "cash-kill",
+ "version": "0.1.0",
+ "description": "Cross-platform implementation of the Unix 'kill' command.",
+ "main": "./dist/commands/kill.js",
+ "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": {
+ "kill": "./bin/kill.js"
+ },
+ "dependencies": {
+ "fkill": "^3.1.0",
+ "lodash": "^4.0.0",
+ "vorpal": "^1.9.5"
+ },
+ "engines": {
+ "node": ">= 0.11.16",
+ "iojs": ">= 1.0.0"
+ },
+ "files": [
+ "dist",
+ "bin"
+ ]
+}
47 packages/ls/README.md
@@ -0,0 +1,47 @@
+# cash-ls
+
+---
+
+
+This is a cross-platform, 100% ES6 implementation of the Unix `ls` command.
+
+```bash
+npm install cash-ls -g
+```
+
+This will install `ls` globally in your system path.
+
+For help on the command, type:
+
+```bash
+> ls --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
+
+- [cash](https://github.com/dthree/cash) - Main project
+- [cash-global](https://npmjs.com/package/cash-global) - Globally install all commands
+- [vorpal](https://github.com/dthree/vorpal) - Cash is built on Vorpal
+
+#### Individual commands
+
+- [cash-cat](https://npmjs.com/package/cash-cat)
+- [cash-cp](https://npmjs.com/package/cash-cp)
+- [cash-kill](https://npmjs.com/package/cash-kill)
+- [cash-ls](https://npmjs.com/package/cash-ls)
+- [cash-mkdir](https://npmjs.com/package/cash-mkdir)
+- [cash-mv](https://npmjs.com/package/cash-mv)
+- [cash-pwd](https://npmjs.com/package/cash-pwd)
+- [cash-sort](https://npmjs.com/package/cash-sort)
+- [cash-touch](https://npmjs.com/package/cash-touch)
+- [cash-rm](https://npmjs.com/package/cash-rm)
+
+
+## License
+
+MIT © [David Caccavella](https://github.com/dthree)
2 packages/ls/bin/ls.js
@@ -0,0 +1,2 @@
+#!/usr/bin/env node
+require('./parser')(process.argv, 'ls');
50 packages/ls/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(' '));
+ }
+};
353 packages/ls/dist/commands/ls.js
@@ -0,0 +1,353 @@
+'use strict';
+
+var _ = require('lodash');
+var chalk = require('chalk');
+var filesize = require('filesize');
+var fs = require('fs');
+var fsAutocomplete = require('vorpal-autocomplete-fs');
+var os = require('os');
+
+var colorFile = require('./../util/colorFile');
+var columnify = require('./../util/columnify');
+var dateConverter = require('./../util/converter.date');
+var fileFromPath = require('./../util/fileFromPath');
+var interfacer = require('./../util/interfacer');
+var pad = require('./../util/pad');
+var lpad = require('./../util/lpad');
+var permissionsConverter = require('./../util/converter.permissions');
+var strip = require('./../util/stripAnsi');
+var walkDir = require('./../util/walkDir');
+var walkDirRecursive = require('./../util/walkDirRecursive');
+
+var pads = { pad: pad, lpad: lpad };
+
+var ls = {
+
+ /**
+ * Main command execution.
+ *
+ * @param {Object} args
+ * @return {Object} { status, stdout }
+ * @api public
+ */
+
+ exec: function exec(paths, options) {
+ var self = this;
+ paths = !_.isArray(paths) && _.isObject(paths) ? paths.paths : paths;
+ paths = paths || ['.'];
+ paths = _.isArray(paths) ? paths : [paths];
+ options = options || {};
+ try {
+ var results = [];
+ for (var i = 0; i < paths.length; ++i) {
+ if (options.recursive) {
+ var result = ls.execDirRecursive(paths[i], options);
+ results = results.concat(result);
+ } else {
+ var result = ls.execDir(paths[i], options);
+ results.push(result);
+ }
+ }
+ var stdout = ls.formatAll(results, options);
+ if (strip(stdout).trim() !== '') {
+ self.log(String(stdout).replace(/\\/g, '/'));
+ }
+ return 0;
+ } catch (e) {
+ /* istanbul ignore next */
+ return ls.error.call(self, e);
+ }
+ },
+
+
+ /**
+ * Returns ls stderr and response codes
+ * for errors.
+ *
+ * @param {Error} e
+ * @return {Object} { status, stdout }
+ * @api private
+ */
+
+ error: function error(e) {
+ /* istanbul ignore next */
+ var status = undefined;
+ /* istanbul ignore next */
+ var stdout = undefined;
+ /* istanbul ignore next */
+ if (e.code === 'ENOENT' && e.syscall === 'scandir') {
+ status = 1;
+ stdout = 'ls: cannot access: No such file or directory';
+ } else {
+ /* istanbul ignore next */
+ status = 2;
+ /* istanbul ignore next */
+ stdout = e.stack;
+ }
+ /* istanbul ignore next */
+ this.log(stdout);
+ /* istanbul ignore next */
+ return status;
+ },
+
+
+ /**
+ * Recursively executes `execDir`.
+ * For use with `ls -R`.
+ *
+ * @param {String} path
+ * @param {Object} options
+ * @return {String} results
+ * @api private
+ */
+
+ execDirRecursive: function execDirRecursive(path, options) {
+ var self = this;
+ var results = [];
+ walkDirRecursive(path, function (pth) {
+ var result = self.execDir(pth, options);
+ results.push(result);
+ });
+ return results;
+ },
+
+
+ /**
+ * Executes `ls` functionality
+ * for a given directory.
+ *
+ * @param {String} path
+ * @param {Object} options
+ * @return {String} results
+ * @api private
+ */
+
+ execDir: function execDir(path, options) {
+ var files = [];
+ var rawFiles = [];
+ var totalSize = 0;
+
+ function pushFile(file, data) {
+ rawFiles.push({
+ file: file,
+ data: data
+ });
+ }
+
+ // Add in implied current and parent dirs.
+ pushFile('.', fs.statSync('.'));
+ pushFile('..', fs.statSync('..'));
+
+ // Walk the passed in directory,
+ // pushing the results into `rawFiles`.
+ walkDir(path, pushFile);
+
+ // Sort alphabetically be default,
+ // unless -U is specified, in which case
+ // we don't sort.
+ if (!options.U) {
+ rawFiles = rawFiles.sort(function (a, b) {
+ // Sort by size.
+ if (options.S) {
+ // Hack for windows - a directory lising
+ // in linux says the size is 4096, and Windows
+ // it's 0, leading to inconsistent sorts based
+ // on size, and failing tests.
+ var win = os.platform() === 'win32';
+ a.data.size = win && a.data.isDirectory() && a.data.size === 0 ? 4096 : a.data.size;
+ b.data.size = win && b.data.isDirectory() && b.data.size === 0 ? 4096 : b.data.size;
+ return a.data.size > b.data.size ? -1 : a.data.size < b.data.size ? 1 : 0;
+ }
+ if (options.t) {
+ // Sort by date modified.
+ return a.data.mtime < b.data.mtime ? 1 : b.data.mtime < a.data.mtime ? -1 : 0;
+ }
+ // Sort alphabetically - default.
+ var aFileName = fileFromPath(a.file).trim().toLowerCase().replace(/\W/g, '');
+ var bFileName = fileFromPath(b.file).trim().toLowerCase().replace(/\W/g, '');
+ return aFileName > bFileName ? 1 : aFileName < bFileName ? -1 : 0;
+ });
+ }
+
+ // Reverse whatever sort the user specified.
+ if (options.reverse) {
+ rawFiles.reverse();
+ }
+
+ var _loop = function _loop(i) {
+ var file = rawFiles[i].file;
+ var data = rawFiles[i].data;
+ var fileShort = fileFromPath(file);
+ var dotted = fileShort && fileShort.charAt(0) === '.';
+ var implied = fileShort === '..' || fileShort === '.';
+ var type = data.isDirectory() ? 'd' : '-';
+ var permissions = permissionsConverter.modeToRWX(data.mode);
+ var hardLinks = data.nlink;
+ var size = options.humanreadable ? filesize(data.size, { unix: true }) : data.size;
+ var modified = dateConverter.unix(data.mtime);
+ var owner = data.uid;
+ var group = data.gid;
+ var inode = data.ino;
+
+ totalSize += data.size;
+
+ var fileName = fileShort;
+
+ // If --classify, add '/' to end of folders.
+ fileName = options.classify && data.isDirectory() ? fileName + '/' : fileName;
+
+ // If getting --directory, give full path.
+ fileName = options.directory && file === '.' ? path : fileName;
+
+ // Color the files based on $LS_COLORS
+ fileName = data.isFile() ? colorFile(fileName) : fileName;
+
+ // If not already colored and is executable,
+ // make it green
+ var colored = strip(fileName) !== fileName;
+ if (String(permissions).indexOf('x') > -1 && !colored && data.isFile()) {
+ fileName = chalk.green(fileName);
+ }
+
+ // If --quote-name, wrap in double quotes;
+ fileName = options.quotename ? '"' + fileName + '"' : fileName;
+
+ // Make directories cyan.
+ fileName = data.isDirectory() ? chalk.cyan(fileName) : fileName;
+
+ var include = function () {
+ var directory = options.directory;
+ var all = options.all;
+ var almostAll = options.almostall;
+ var result = false;
+ if (directory && file !== '.') {
+ result = false;
+ } else if (!dotted) {
+ result = true;
+ } else if (all) {
+ result = true;
+ } else if (!implied && almostAll) {
+ result = true;
+ } else if (directory && file === '.') {
+ result = true;
+ }
+ return result;
+ }();
+
+ var details = [type + permissions, hardLinks, owner, group, size, modified, fileName];
+
+ if (options.inode) {
+ details.unshift(inode);
+ }
+
+ var result = options.l && !options.x ? details : fileName;
+
+ if (include) {
+ files.push(result);
+ }
+ };
+
+ for (var i = 0; i < rawFiles.length; ++i) {
+ _loop(i);
+ }
+
+ var result = undefined;
+
+ // If we have the detail view, draw out
+ // all of the details of each file.
+ // Otherwise, just throw the file names
+ // into columns.
+ if (_.isArray(files[0])) {
+ var longest = {};
+ for (var i = 0; i < files.length; ++i) {
+ for (var j = 0; j < files[i].length; ++j) {
+ var len = String(files[i][j]).length;
+ longest[j] = longest[j] || 0;
+ longest[j] = len > longest[j] ? len : longest[j];
+ }
+ }
+
+ var newFiles = [];
+ for (var i = 0; i < files.length; ++i) {
+ var glob = '';
+ for (var j = 0; j < files[i].length; ++j) {
+ var padFn = j === files[i].length - 1 ? 'pad' : 'lpad';
+ if (j === files[i].length - 1) {
+ glob += String(files[i][j]);
+ } else {
+ glob += pads[padFn](String(files[i][j]), longest[j], ' ') + ' ';
+ }
+ }
+ newFiles.push(String(glob));
+ }
+ result = newFiles.join('\n');
+ } else if (options['1']) {
+ result = files.join('\n');
+ } else {
+ var opt = {};
+ if (options.width) {
+ opt.width = options.width;
+ }
+ result = columnify(files, opt);
+ }
+
+ return {
+ path: path,
+ size: options.humanreadable ? filesize(totalSize, { unix: true }) : totalSize,
+ results: result
+ };
+ },
+
+
+ /**
+ * Concatenates the results of multiple
+ * `execDir` functions into their proper
+ * form based on options provided.
+ *
+ * @param {String} results
+ * @param {Object} options
+ * @return {String} stdout
+ * @api private
+ */
+
+ formatAll: function formatAll(results, options) {
+ var stdout = '';
+ if (results.length > 1) {
+ for (var i = 0; i < results.length; ++i) {
+ stdout += results[i].path + ':\n';
+ if (options.l) {
+ stdout += 'total ' + results[i].size + '\n';
+ }
+ stdout += results[i].results;
+ if (i !== results.length - 1) {
+ stdout += '\n\n';
+ }
+ }
+ } else if (results.length === 1) {
+ if (options.l && !options.x) {
+ stdout += 'total ' + results[0].size + '\n';
+ }
+ stdout += results[0].results;
+ }
+ return stdout;
+ }
+};
+
+/**
+ * Expose as a Vorpal extension.
+ */
+
+module.exports = function (vorpal) {
+ if (vorpal === undefined) {
+ return ls;
+ }
+ vorpal.api.ls = ls;
+ vorpal.command('ls [paths...]').option('-a, --all', 'do not ignore entries starting with .').option('-A, --almost-all', 'do not list implied . and ..').option('-d, --directory', 'list directory entries instead of contents, and do not dereference symbolic links').option('-F, --classify', 'append indicator (one of */=>@|) to entries').option('-h, --human-readable', 'with -l, print sizes in human readable format (e.g., 1K 234M 2G)').option('-i, --inode', 'print the index number of each file').option('-l', 'use a long listing format').option('-Q, --quote-name', 'enclose entry names in double quotes').option('-r, --reverse', 'reverse order while sorting').option('-R, --recursive', 'list subdirectories recursively').option('-S', 'sort by file size').option('-t', 'sort by modification time, newest first').option('-U', 'do not sort; list entries in directory order').option('-w, --width [COLS]', 'assume screen width instead of current value').option('-x', 'list entries by lines instead of columns').option('-1', 'list one file per line').autocomplete(fsAutocomplete()).action(function (args, cb) {
+ return interfacer.call(this, {
+ command: ls,
+ args: args.paths,
+ options: args.options,
+ callback: cb
+ });
+ });
+};
3 packages/ls/dist/help/ls.js
@@ -0,0 +1,3 @@
+"use strict";
+
+module.exports = "\nUsage: ls [OPTION]... [FILE]...\nList information about the FILEs (the current directory by default).\nSort entries alphabetically if none of -tSU nor --sort is specified.\n\n -a, --all do not ignore entries starting with .\n -A, --almost-all do not list implied . and ..\n -d, --directory list directory entries instead of contents,\n and do not dereference symbolic links\n -f do not sort, enable -aU, disable -ls --color\n -F, --classify append indicator (one of */=>@|) to entries\n -h, --human-readable with -l, print sizes in human readable format\n -i, --inode print the index number of each file\n -l use a long listing format\n -q, --hide-control-chars print ? instead of non graphic characters\n -r, --reverse reverse order while sorting\n -R, --recursive list subdirectories recursively\n -S sort by file size\n -t sort by modification time, newest first\n -U do not sort; list entries in directory order\n -w, --width=COLS assume screen width instead of current value\n -x list entries by lines instead of by columns\n -1 list one file per line\n --help display this help and exit\n\nExit status:\n 0 if OK,\n 1 if minor problems (e.g., cannot access subdirectory),\n 2 if serious trouble (e.g., cannot access command-line argument).\n\nReport ls bugs to <https://github.com/dthree/cash>\nCash home page: <http://cash.js.org/>\n";
34 packages/ls/dist/util/colorFile.js
@@ -0,0 +1,34 @@
+'use strict';
+
+var strip = require('./stripAnsi');
+
+var chalk = {};
+var map = { cyan: 36, red: 31, magenta: 35 };

Why are you overriding these?

@dthree
Owner
dthree added a note

Was trying to minimize deps per package (for the individual modules). It was such a small use of Chalk, it did it for this one.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
+Object.keys(map).forEach(function (key, value) {
+ chalk[key] = function (str) {
+ return '\u001b[' + value + 'm' + str + '\u001b[39m';
+ };
+});
+
+/**
+ * Wraps file strings in ANSI colors
+ * based on their extension.
+ *
+ * @param {file} str
+ * @return {String}
+ * @api public
+ */
+
+module.exports = function (file) {
+ var audio = ['aac', 'au', 'flac', 'mid', 'midi', 'mka', 'mp3', 'mpc', 'ogg', 'ra', 'wav', 'axa', 'oga', 'spx', 'xspf'];
+ var archive = ['tar', 'tgz', 'arj', 'taz', 'lzh', 'lzma', 'tlz', 'txz', 'zip', 'z', 'Z', 'dz', 'gz', 'lz', 'xz', 'bz2', 'bz', 'tbz', 'tbz2', 'tz', 'deb', 'rpm', 'jar', 'rar', 'ace', 'zoo', 'cpio', '7z', 'rz'];
+ var images = ['jpg', 'jpeg', 'gif', 'bmp', 'pbm', 'pgm', 'ppm', 'tga', 'xbm', 'xpm', 'tif', 'tiff', 'png', 'svg', 'svgz', 'mng', 'pcx', 'mov', 'mpg', 'mpeg', 'm2v', 'mkv', 'ogm', 'mp4', 'm4v', 'mp4v', 'vob', 'qt', 'nuv', 'wmv', 'asf', 'rm', 'rmvb', 'flc', 'avi', 'fli', 'flv', 'gl', 'dl', 'xcf', 'xwd', 'yuv', 'cgm', 'emf', 'axv', 'anx', 'ogv', 'ogx'];
+
+ var extension = String(file).toLowerCase().trim().split('.');
+ extension = extension[extension.length - 1];
+
+ var colored = strip(file);
+ colored = audio.indexOf(extension) > -1 ? chalk.cyan(file) : archive.indexOf(extension) > -1 ? chalk.red(file) : images.indexOf(extension) > -1 ? chalk.magenta(file) : colored;
+
+ return colored;
+};
58 packages/ls/dist/util/columnify.js
@@ -0,0 +1,58 @@
+'use strict';
+
+var strip = require('./stripAnsi');
+var pad = require('./pad');
+
+/**
+ * Formats an array to display in a TTY
+ * in a pretty fashion.
+ *
+ * @param {Array} arr
+ * @return {String}
+ * @api public
+ */
+
+module.exports = function (arr, options) {
+ arr = arr || [];
+ options = options || {};
+ var bk = JSON.parse(JSON.stringify(arr));
+ var width = options.width && !isNaN(options.width) ? options.width : process.stdout.columns;
+ var longest = strip(bk.sort(function (a, b) {
+ return strip(b).length - strip(a).length;
+ })[0] || '').length + 2;
+ var fullWidth = strip(arr.join('')).length;
+ var fitsOneLine = fullWidth + arr.length * 2 <= width;
+ var cols = Math.floor(width / longest);
+ cols = cols < 1 ? 1 : cols;
+ if (fitsOneLine) {
+ return arr.join(' ');
+ }
+ var col = 0;
+ var lines = [];
+ var line = '';
+ for (var i = 0; i < arr.length; ++i) {
+ if (col < cols) {
+ col++;
+ } else {
+ if (String(strip(line)).trim() !== '') {
+ lines.push(line);
+ }
+ line = '';
+ col = 1;
+ }
+ if (cols === 1) {
+ // If we have files so damn
+ // long that we wrap, don't pad
+ // the lines.
+ line += arr[i];
+ } else {
+ // Pad the lines based on the
+ // longest word.
+ line += pad(arr[i], longest, ' ');
+ }
+ }
+ if (line !== '') {
+ lines.push(line);
+ }
+ return lines.join('\n');
+};
30 packages/ls/dist/util/converter.date.js
@@ -0,0 +1,30 @@
+'use strict';
+
+/**
+ * Date conversion utilities
+ */
+
+var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
+
+function pad(num, padding) {
+ padding = padding || '0';
+ num = parseFloat(num);
+ if (num < 10) {
+ return '' + padding + num;
+ }
+ return num;
+}
+
+module.exports = {
+ unix: function unix(dt) {
+ var date = dt;
+ var day = pad(date.getDate(), ' ');
+ var month = months[date.getMonth()];
+ var hour = pad(date.getHours());
+ var min = pad(date.getMinutes());
+ var hourMin = hour + ':' + min;
+ day = day.length === 1 ? ' ' + day : day;
+ date = month + ' ' + day + ' ' + hourMin;
+ return date;
+ }
+};
39 packages/ls/dist/util/converter.permissions.js
@@ -0,0 +1,39 @@
+'use strict';
+
+/**
+ * Permission conversion utilities
+ */
+
+module.exports = {
+
+ listing: {
+ 0: '---',
+ 1: '--x',
+ 2: '-w-',
+ 3: '-wx',
+ 4: 'r--',
+ 5: 'r-x',
+ 6: 'rw-',
+ 7: 'rwx'
+ },
+
+ modeToRWX: function modeToRWX(mode) {
+ var octal = this.modeToOctal(mode);
+ var rwx = this.octalToRWX(octal);
+ return rwx;
+ },
+ modeToOctal: function modeToOctal(mode) {
+ var octal = '0' + (mode & 511).toString(8);
+ return octal;
+ },
+ octalToRWX: function octalToRWX(octal) {
+ if (!octal) {
+ return undefined;
+ }
+ var list = this.listing;
+ var a = list[String(octal).charAt(1)];
+ var b = list[String(octal).charAt(2)];
+ var c = list[String(octal).charAt(3)];
+ return a + b + c;
+ }
+};
17 packages/ls/dist/util/fileFromPath.js
@@ -0,0 +1,17 @@
+'use strict';
+
+/**
+ * Parses a path and returns just the file
+ *
+ * @param {path} str
+ * @return {String}
+ * @api public
+ */
+
+module.exports = function (path) {
+ var fileShort = String(path).split('/');
+ fileShort = fileShort[fileShort.length - 1];
+ fileShort = fileShort.split('\\');
+ fileShort = fileShort[fileShort.length - 1];
+ return fileShort;
+};
45 packages/ls/dist/util/interfacer.js
@@ -0,0 +1,45 @@
+'use strict';
+
+/**
+ * Simple binding interface between
+ * each command's function and the caller
+ * of the command, whether by `cash.command`
+ * or by being invoked by Vorpal.
+ * This exists to abstract complexity
+ * and create a standard in interfacing
+ * commands acorss muliple execution paths.
+ *
+ * @param {Object} opt
+ * @api public
+ */
+
+module.exports = function (opt) {
+ var self = this;
+ var stdout = '';
+ opt.options = opt.options || {};
+ opt.callback = opt.callback || function () {};
+ opt.command = opt.command || {
+ exec: function exec() {}
+ };
+
+ var logger = {
+ log: function log(out) {
+ stdout += out + '\n';
+ if (opt.silent !== true) {
+ // process.stdout.write(out) // to do - handle newline problem.
+ self.log(out);
+ }
+ }
+ };
+
+ function onResult(result) {
+ result = result === undefined ? 0 : result;
+ opt.callback(null, stdout);
+ return stdout;
+ }
+
+ if (opt.async === true) {
+ return opt.command.exec.call(logger, opt.args, opt.options, onResult);
+ }
+ return onResult(opt.command.exec.call(logger, opt.args, opt.options));
+};
20 packages/ls/dist/util/lpad.js
@@ -0,0 +1,20 @@
+'use strict';
+
+var strip = require('./stripAnsi');
+
+/**
+ * Pads to the left hand.
+ *
+ * @param {String} str
+ * @param {Integer} width
+ * @param {String} delimiter
+ * @return {String}
+ * @api public
+ */
+
+module.exports = function (str, width, delimiter) {
+ width = Math.floor(width);
+ delimiter = delimiter || ' ';
+ var len = Math.max(0, width - strip(str).length);
+ return Array(len + 1).join(delimiter) + str;
+};
22 packages/ls/dist/util/pad.js
@@ -0,0 +1,22 @@
+'use strict';
+
+var strip = require('./stripAnsi');
+
+/**
+ * Pads a value with with space or
+ * a specified delimiter to match a
+ * given width.
+ *
+ * @param {String} str
+ * @param {Integer} width
+ * @param {String} delimiter
+ * @return {String}
+ * @api public
+ */
+
+module.exports = function (str, width, delimiter) {
+ width = Math.floor(width);
+ delimiter = delimiter || ' ';
+ var len = Math.max(0, width - strip(str).length);
+ return str + Array(len + 1).join(delimiter);
+};
14 packages/ls/dist/util/stripAnsi.js
@@ -0,0 +1,14 @@
+'use strict';
+
+/**
+ * Removes all ansi characters.
+ *
+ * @param {String} str
+ * @return {String}
+ * @api public
+ */
+
+module.exports = function (str) {
@dthree
Owner
dthree added a note

I was trying to minimize deps in the sub-modules (individual installers), and strip is like everywhere, so I thought I'd throw it in directly. I don't mind switching back to the module, either or.

That doesn't really matter though. npm caches identical dependencies and with npm@3 it will be deduplicated too.

@dthree
Owner
dthree added a note

Good point. Will probably throw back in then.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
+ var ansiRegex = /[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g;
+ return typeof str === 'string' ? str.replace(ansiRegex, '') : str;
+};
41 packages/ls/dist/util/walkDir.js
@@ -0,0 +1,41 @@
+'use strict';
+
+var fs = require('fs');
+var path = require('path');
+
+/**
+ * Walks a single directory calling
+ * a callback function for each file or
+ * folder, returning the path and results
+ * of fs.statSync.
+ *
+ * @param {String} currentDirPath
+ * @param {Function} callback
+ * @api public
+ */
+
+module.exports = function (currentDirPath, callback) {
+ function readFile(path, cbk) {
+ var stat = undefined;
+ try {
+ stat = fs.statSync(path);
+ if (stat.isFile() || stat.isDirectory()) {
+ cbk(path, stat);
+ }
+ } catch (e) {
+ // .. if we can't read the file, forget
+ // about it for now.
+ }
+ }
+ try {
+ var dirs = fs.readdirSync(currentDirPath);
+ dirs.forEach(function (name) {
+ var filePath = path.join(currentDirPath, name);
+ readFile(filePath, callback);
+ });
+ } catch (e) {
+ if (e.code === 'ENOTDIR') {
+ readFile(currentDirPath, callback);
+ }
+ }
+};
24 packages/ls/dist/util/walkDirRecursive.js
@@ -0,0 +1,24 @@
+'use strict';
+
+var fs = require('fs');
+var path = require('path');
+
+/**
+ * Recursively walks through and executes
+ * a callback function for each directory found.
+ *
+ * @param {String} currentDirPath
+ * @param {Function} callback
+ * @api public
+ */
+
+module.exports = function (currentDirPath, callback) {
+ fs.readdirSync(currentDirPath).forEach(function (name) {
+ var filePath = path.join(currentDirPath, name);
+ var stat = fs.statSync(filePath);
+ if (stat.isDirectory()) {
+ callback(filePath, stat);
+ module.exports(filePath, callback);
+ }
+ });
+};
52 packages/ls/package.json
@@ -0,0 +1,52 @@
+{
+ "name": "cash-ls",
+ "version": "0.1.0",
+ "description": "Cross-platform implementation of the Unix 'ls' command.",
+ "main": "./dist/commands/ls.js",
+ "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": {
+ "ls": "./bin/ls.js"
+ },
+ "dependencies": {
+ "lodash": "^4.0.0",
+ "chalk": "^1.1.0",
+ "filesize": "^3.1.3",
+ "vorpal-autocomplete-fs": "0.0.3",
+ "vorpal": "^1.9.5"
+ },
+ "engines": {
+ "node": ">= 0.11.16",
+ "iojs": ">= 1.0.0"
+ },
+ "files": [
+ "dist",
+ "bin"
+ ]
+}
47 packages/mkdir/README.md
@@ -0,0 +1,47 @@
+# cash-mkdir
+
+---
+
+
+This is a cross-platform, 100% ES6 implementation of the Unix `mkdir` command.
+
+```bash
+npm install cash-mkdir -g
+```
+
+This will install `mkdir` globally in your system path.
+
+For help on the command, type:
+
+```bash
+> mkdir --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
+
+- [cash](https://github.com/dthree/cash) - Main project
+- [cash-global](https://npmjs.com/package/cash-global) - Globally install all commands
+- [vorpal](https://github.com/dthree/vorpal) - Cash is built on Vorpal
+
+#### Individual commands
+
+- [cash-cat](https://npmjs.com/package/cash-cat)
+- [cash-cp](https://npmjs.com/package/cash-cp)
+- [cash-kill](https://npmjs.com/package/cash-kill)
+- [cash-ls](https://npmjs.com/package/cash-ls)
+- [cash-mkdir](https://npmjs.com/package/cash-mkdir)
+- [cash-mv](https://npmjs.com/package/cash-mv)
+- [cash-pwd](https://npmjs.com/package/cash-pwd)
+- [cash-sort](https://npmjs.com/package/cash-sort)
+- [cash-touch](https://npmjs.com/package/cash-touch)
+- [cash-rm](https://npmjs.com/package/cash-rm)
+
+
+## License
+
+MIT © [David Caccavella](https://github.com/dthree)
2 packages/mkdir/bin/mkdir.js
@@ -0,0 +1,2 @@
+#!/usr/bin/env node
+require('./parser')(process.argv, 'mkdir');
50 packages/mkdir/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(' '));
+ }
+};
86 packages/mkdir/dist/commands/mkdir.js
@@ -0,0 +1,86 @@
+'use strict';
+
+var fs = require('fs');
+var path = require('path');
+var fsAutocomplete = require('vorpal-autocomplete-fs');
+
+var interfacer = require('./../util/interfacer');
+
+var mkdir = {
+ exec: function exec(args, options) {
+ var self = this;
+ var dirs = args || [];
+ options = options || {};
+
+ if (typeof dirs === 'string') {
+ dirs = dirs.split(' ');
+ }
+
+ dirs = dirs.filter(function (str) {
+ return String(str).trim() !== '';
+ });
+
+ if (dirs.length < 1) {
+ this.log('mkdir: missing operand\nTry \'mkdir --help\' for more information.');
+ }
+
+ dirs.forEach(function (dir) {
+ if (fs.existsSync(dir)) {
+ if (!options.parents) {
+ self.log('mkdir: cannot create directory ' + dir + ': File exists');
+ }
+ return;
+ }
+
+ // Base dir does not exist, and no -p option given
+ var baseDir = path.dirname(dir);
+ if (!fs.existsSync(baseDir) && !options.parents) {
+ self.log('mkdir: cannot create directory ' + dir + ': No such file or directory');
+ return;
+ }
+
+ if (options.parents) {
+ mkdirSyncRecursive.call(self, dir, options);
+ } else {
+ fs.mkdirSync(dir, parseInt('0777', 8));
+ if (options.verbose) {
+ self.log('mkdir: created directory ' + dir);
+ }
+ }
+ });
+ return 0;
+ }
+};
+
+function mkdirSyncRecursive(dir, options) {
+ var baseDir = path.dirname(dir);
+ if (fs.existsSync(baseDir)) {
+ fs.mkdirSync(dir, parseInt('0777', 8));
+ if (options.verbose) {
+ this.log('mkdir: created directory ' + dir);
+ }
+ return;
+ }
+ mkdirSyncRecursive.call(this, baseDir, options);
+ fs.mkdirSync(dir, parseInt('0777', 8));
+ if (options.verbose) {
+ this.log('mkdir: created directory ' + dir);
+ }
+}
+
+module.exports = function (vorpal) {
+ if (vorpal === undefined) {
+ return mkdir;
+ }
+ vorpal.api.mkdir = mkdir;
+ vorpal.command('mkdir [directory...]').option('-p, --parents', 'no error if existing, make parent directories as needed').option('-v, --verbose', 'print a message for each created directory').autocomplete(fsAutocomplete({ directory: true })).action(function (args, callback) {
+ args.options = args.options || {};
+ args.options.vorpal = vorpal;
+ return interfacer.call(this, {
+ command: mkdir,
+ args: args.directory,
+ options: args.options,
+ callback: callback
+ });
+ });
+};
3 packages/mkdir/dist/help/mkdir.js
@@ -0,0 +1,3 @@
+"use strict";
+
+module.exports = "\nUsage: mkdir [OPTION]... DIRECTORY...\nCreate the DIRECTORY(ies), if they do not already exist.\n\n -p, --parents no error if existing, make parent directories as needed\n -v, --verbose print a message for each created directory\n --help display this help and exit\n\nReport mkdir bugs to <https://github.com/dthree/cash>\nCash home page: <http://cash.js.org/>\n";
45 packages/mkdir/dist/util/interfacer.js
@@ -0,0 +1,45 @@
+'use strict';
+
+/**
+ * Simple binding interface between
+ * each command's function and the caller
+ * of the command, whether by `cash.command`
+ * or by being invoked by Vorpal.
+ * This exists to abstract complexity
+ * and create a standard in interfacing
+ * commands acorss muliple execution paths.
+ *
+ * @param {Object} opt
+ * @api public
+ */
+
+module.exports = function (opt) {
+ var self = this;
+ var stdout = '';
+ opt.options = opt.options || {};
+ opt.callback = opt.callback || function () {};
+ opt.command = opt.command || {
+ exec: function exec() {}
+ };
+
+ var logger = {
+ log: function log(out) {
+ stdout += out + '\n';
+ if (opt.silent !== true) {
+ // process.stdout.write(out) // to do - handle newline problem.
+ self.log(out);
+ }
+ }
+ };
+
+ function onResult(result) {
+ result = result === undefined ? 0 : result;
+ opt.callback(null, stdout);
+ return stdout;
+ }
+
+ if (opt.async === true) {
+ return opt.command.exec.call(logger, opt.args, opt.options, onResult);
+ }
+ return onResult(opt.command.exec.call(logger, opt.args, opt.options));
+};
49 packages/mkdir/package.json
@@ -0,0 +1,49 @@
+{
+ "name": "cash-mkdir",
+ "version": "0.1.0",
+ "description": "Cross-platform implementation of the Unix 'mkdir' command.",
+ "main": "./dist/commands/mkdir.js",
+ "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": {
+ "mkdir": "./bin/mkdir.js"
+ },
+ "dependencies": {
+ "vorpal-autocomplete-fs": "0.0.3",
+ "vorpal": "^1.9.5"
+ },
+ "engines": {
+ "node": ">= 0.11.16",
+ "iojs": ">= 1.0.0"
+ },
+ "files": [
+ "dist",
+ "bin"
+ ]
+}
47 packages/mv/README.md
@@ -0,0 +1,47 @@
+# cash-mv
+
+---
+
+
+This is a cross-platform, 100% ES6 implementation of the Unix `mv` command.
+
+```bash
+npm install cash-mv -g
+```
+
+This will install `mv` globally in your system path.
+
+For help on the command, type:
+
+```bash
+> mv --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
+
+- [cash](https://github.com/dthree/cash) - Main project
+- [cash-global](https://npmjs.com/package/cash-global) - Globally install all commands
+- [vorpal](https://github.com/dthree/vorpal) - Cash is built on Vorpal
+
+#### Individual commands
+
+- [cash-cat](https://npmjs.com/package/cash-cat)
+- [cash-cp](https://npmjs.com/package/cash-cp)
+- [cash-kill](https://npmjs.com/package/cash-kill)
+- [cash-ls](https://npmjs.com/package/cash-ls)
+- [cash-mkdir](https://npmjs.com/package/cash-mkdir)
+- [cash-mv](https://npmjs.com/package/cash-mv)
+- [cash-pwd](https://npmjs.com/package/cash-pwd)
+- [cash-sort](https://npmjs.com/package/cash-sort)
+- [cash-touch](https://npmjs.com/package/cash-touch)
+- [cash-rm](https://npmjs.com/package/cash-rm)
+
+
+## License
+
+MIT © [David Caccavella](https://github.com/dthree)
2 packages/mv/bin/mv.js
@@ -0,0 +1,2 @@
+#!/usr/bin/env node
+require('./parser')(process.argv, 'mv');
50 packages/mv/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(' '));
+ }
+};
105 packages/mv/dist/commands/mv.js
@@ -0,0 +1,105 @@
+'use strict';
+
+var _ = require('lodash');
+var fs = require('fs');
+var fsAutocomplete = require('vorpal-autocomplete-fs');
+var path = require('path');
+
+var expand = require('./../util/expand');
+var interfacer = require('./../util/interfacer');
+
+var mv = {
+ exec: function exec(args, options) {
+ var self = this;
+ options = options || {};
+
+ args = args === undefined ? [] : args;
+ args = _.isArray(args) ? args : args.split(' ');
+ args = _.filter(args, function (arg) {
+ return String(arg).trim() !== '';
+ });
+
+ options.noclobber = options.force === true ? false : options.noclobber;
+
+ if (args.length < 1) {
+ this.log('mv: missing file operand\nTry \'mv --help\' for more information.');
+ return 1;
+ }
+
+ if (args.length === 1) {
+ this.log('mv: missing destination file operand after ' + args[0] + '\nTry \'mv --help\' for more information.');
+ return 1;
+ }
+
+ args = expand(args);
+
+ var dest = args.pop();
+ var sources = args;
+
+ var exists = fs.existsSync(dest);
+ var stats = exists && fs.statSync(dest);
+
+ // Dest is not existing dir, but multiple sources given
+ if ((!exists || !stats.isDirectory()) && sources.length > 1) {
+ this.log('mv: target ' + dest + ' is not a directory');
+ return 1;
+ }
+
+ // Dest is an existing file, but no -f given
+ if (exists && stats.isFile() && options.noclobber) {
+ // just dont do anything
+ return 0;
+ }
+
+ if (options.striptrailingslashes) {
+ sources = sources.map(function (src) {
+ return String(src).replace(/\/$/g, '');
+ });
+ }
+
+ sources.forEach(function (src) {
+ if (!fs.existsSync(src)) {
+ self.log('mv: cannot stat ' + src + ': No such file or directory');
+ return;
+ }
+
+ // When copying to '/path/dir', iDest = '/path/dir/file1'
+ var iDest = dest;
+ if (exists && stats.isDirectory()) {
+ iDest = path.normalize(dest + '/' + path.basename(src));
+ }
+
+ // If the file exists and we're not clobbering, skip.
+ if (fs.existsSync(iDest) && options.noclobber) {
+ return;
+ }
+
+ if (path.resolve(src) === path.dirname(path.resolve(iDest))) {
+ self.log('mv: ' + src + ' and ' + iDest + ' are the same file');
+ return;
+ }
+
+ fs.renameSync(src, iDest);
+ if (options.verbose === true) {
+ self.log(String(src + ' -> ' + iDest).replace(/\\/g, '/'));
+ }
+ });
+ }
+};
+
+module.exports = function (vorpal) {
+ if (vorpal === undefined) {
+ return mv;
+ }
+ vorpal.api.mv = mv;
+ vorpal.command('mv [args...]').option('-f, --force', 'do not prompt before overwriting').option('-n, --no-clobber', 'do not overwrite an existing file').option('--striptrailingslashes', 'remove any trailing slashes from each source') // vorpal bug, need to add dashes between words
+ .option('-v, --verbose', 'explain what is being done').autocomplete(fsAutocomplete()).action(function (args, callback) {
+ args.options = args.options || {};
+ return interfacer.call(this, {
+ command: mv,
+ args: args.args,
+ options: args.options,
+ callback: callback
+ });
+ });
+};
3 packages/mv/dist/help/mv.js
@@ -0,0 +1,3 @@
+"use strict";
+
+module.exports = "\nUsage: mv [OPTION]... [-T] SOURCE DEST\n or: mv [OPTION]... SOURCE... DIRECTORY\n or: mv [OPTION]... -t DIRECTORY SOURCE...\nRename SOURCE to DEST, or move SOURCE(s) to DIRECTORY.\n\n -f, --force do not prompt before overwriting\n -n, --no-clobber do not overwrite an existing file\n --striptrailingslashes remove any trailing slashes from each SOURCE\n argument\n -v, --verbose explain what is being done\n --help display this help and exit\n\nIf you specify -f and -n, only -f takes effect.\n\nReport mv bugs to <https://github.com/dthree/cash>\nCash home page: <http://cash.js.org/>\n";
29 packages/mv/dist/util/expand.js
@@ -0,0 +1,29 @@
+'use strict';
+
+var glob = require('glob');
+
+/**
+ * Expands wildcard files, etc. out
+ * into their full paths.
+ *
+ * @param {Array} list
+ * @return {Array}
+ * @api public
+ */
+
+module.exports = function (list) {
+ var total = list.length;
+ var files = [];
+ if (list.length < 1) {
+ return [];
+ }
+ for (var i = 0; i < total; ++i) {
+ var res = glob.sync(list[i], {});
+ files[i] = res.length > 0 ? res : list[i];
+ }
+ var out = [];
+ for (var i = 0; i < files.length; ++i) {
+ out = Array.isArray(files[i]) ? out.concat(files[i]) : out.concat([files[i]]);
+ }
+ return out;
+};
45 packages/mv/dist/util/interfacer.js
@@ -0,0 +1,45 @@
+'use strict';
+
+/**
+ * Simple binding interface between
+ * each command's function and the caller
+ * of the command, whether by `cash.command`
+ * or by being invoked by Vorpal.
+ * This exists to abstract complexity
+ * and create a standard in interfacing
+ * commands acorss muliple execution paths.
+ *
+ * @param {Object} opt
+ * @api public
+ */
+
+module.exports = function (opt) {
+ var self = this;
+ var stdout = '';
+ opt.options = opt.options || {};
+ opt.callback = opt.callback || function () {};
+ opt.command = opt.command || {
+ exec: function exec() {}
+ };
+
+ var logger = {
+ log: function log(out) {
+ stdout += out + '\n';
+ if (opt.silent !== true) {
+ // process.stdout.write(out) // to do - handle newline problem.
+ self.log(out);
+ }
+ }
+ };
+
+ function onResult(result) {
+ result = result === undefined ? 0 : result;
+ opt.callback(null, stdout);
+ return stdout;
+ }
+
+ if (opt.async === true) {
+ return opt.command.exec.call(logger, opt.args, opt.options, onResult);
+ }
+ return onResult(opt.command.exec.call(logger, opt.args, opt.options));
+};
51 packages/mv/package.json
@@ -0,0 +1,51 @@
+{
+ "name": "cash-mv",
+ "version": "0.1.0",
+ "description": "Cross-platform implementation of the Unix 'mv' command.",
+ "main": "./dist/commands/mv.js",
+ "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": {
+ "mv": "./bin/mv.js"
+ },
+ "dependencies": {
+ "lodash": "^4.0.0",
+ "vorpal-autocomplete-fs": "0.0.3",
+ "glob": "^6.0.4",
+ "vorpal": "^1.9.5"
+ },
+ "engines": {
+ "node": ">= 0.11.16",
+ "iojs": ">= 1.0.0"
+ },
+ "files": [
+ "dist",
+ "bin"
+ ]
+}
47 packages/pwd/README.md
@@ -0,0 +1,47 @@
+# cash-pwd
+
+---
+
+
+This is a cross-platform, 100% ES6 implementation of the Unix `pwd` command.
+
+```bash
+npm install cash-pwd -g
+```
+
+This will install `pwd` globally in your system path.
+
+For help on the command, type:
+
+```bash
+> pwd --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
+
+- [cash](https://github.com/dthree/cash) - Main project
+- [cash-global](https://npmjs.com/package/cash-global) - Globally install all commands
+- [vorpal](https://github.com/dthree/vorpal) - Cash is built on Vorpal
+
+#### Individual commands
+
+- [cash-cat](https://npmjs.com/package/cash-cat)
+- [cash-cp](https://npmjs.com/package/cash-cp)
+- [cash-kill](https://npmjs.com/package/cash-kill)
+- [cash-ls](https://npmjs.com/package/cash-ls)
+- [cash-mkdir](https://npmjs.com/package/cash-mkdir)
+- [cash-mv](https://npmjs.com/package/cash-mv)
+- [cash-pwd](https://npmjs.com/package/cash-pwd)
+- [cash-sort](https://npmjs.com/package/cash-sort)
+- [cash-touch](https://npmjs.com/package/cash-touch)
+- [cash-rm](https://npmjs.com/package/cash-rm)
+
+
+## License
+
+MIT © [David Caccavella](https://github.com/dthree)
50 packages/pwd/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(' '));
+ }
+};
2 packages/pwd/bin/pwd.js
@@ -0,0 +1,2 @@
+#!/usr/bin/env node
+require('./parser')(process.argv, 'pwd');
28 packages/pwd/dist/commands/pwd.js
@@ -0,0 +1,28 @@
+'use strict';
+
+var path = require('path');
+
+var interfacer = require('./../util/interfacer');
+
+var pwd = {
+ exec: function exec() {
+ this.log(path.resolve(process.cwd()).replace(/\\/g, '/'));
+ return 0;
+ }
+};
+
+module.exports = function (vorpal) {
+ if (vorpal === undefined) {
+ return pwd;
+ }
+ vorpal.api.pwd = pwd;
+ vorpal.command('pwd [files...]').action(function (args, callback) {
+ args.options = args.options || {};
+ return interfacer.call(this, {
+ command: pwd,
+ args: args.files,
+ options: args.options,
+ callback: callback
+ });
+ });
+};
3 packages/pwd/dist/help/pwd.js
@@ -0,0 +1,3 @@
+"use strict";
+
+module.exports = "\nUsage: pwd [-LP]\nPrint the name of the current working directory.\n\n --help display this help and exit\n\nExit status:\n 0 if OK,\n 1 if an invalid option is given or the current directory\n cannot be read.\n\nReport pwd bugs to <https://github.com/dthree/cash>\nCash home page: <http://cash.js.org/>\n";
45 packages/pwd/dist/util/interfacer.js
@@ -0,0 +1,45 @@
+'use strict';
+
+/**
+ * Simple binding interface between
+ * each command's function and the caller
+ * of the command, whether by `cash.command`
+ * or by being invoked by Vorpal.
+ * This exists to abstract complexity
+ * and create a standard in interfacing
+ * commands acorss muliple execution paths.
+ *
+ * @param {Object} opt
+ * @api public
+ */
+
+module.exports = function (opt) {
+ var self = this;
+ var stdout = '';
+ opt.options = opt.options || {};
+ opt.callback = opt.callback || function () {};
+ opt.command = opt.command || {
+ exec: function exec() {}
+ };
+
+ var logger = {
+ log: function log(out) {
+ stdout += out + '\n';
+ if (opt.silent !== true) {
+ // process.stdout.write(out) // to do - handle newline problem.
+ self.log(out);
+ }
+ }
+ };
+
+ function onResult(result) {
+ result = result === undefined ? 0 : result;
+ opt.callback(null, stdout);
+ return stdout;
+ }
+
+ if (opt.async === true) {
+ return opt.command.exec.call(logger, opt.args, opt.options, onResult);
+ }
+ return onResult(opt.command.exec.call(logger, opt.args, opt.options));
+};
48 packages/pwd/package.json
@@ -0,0 +1,48 @@
+{
+ "name": "cash-pwd",
+ "version": "0.1.0",
+ "description": "Cross-platform implementation of the Unix 'pwd' command.",
+ "main": "./dist/commands/pwd.js",
+ "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": {
+ "pwd": "./bin/pwd.js"
+ },
+ "dependencies": {
+ "vorpal": "^1.9.5"
+ },
+ "engines": {
+ "node": ">= 0.11.16",
+ "iojs": ">= 1.0.0"
+ },
+ "files": [
+ "dist",
+ "bin"
+ ]
+}
47 packages/rm/README.md
@@ -0,0 +1,47 @@
+# cash-rm
+
+---
+
+
+This is a cross-platform, 100% ES6 implementation of the Unix `rm` command.
+
+```bash
+npm install cash-rm -g
+```
+
+This will install `rm` globally in your system path.
+
+For help on the command, type:
+
+```bash
+> rm --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
+
+- [cash](https://github.com/dthree/cash) - Main project
+- [cash-global](https://npmjs.com/package/cash-global) - Globally install all commands
+- [vorpal](https://github.com/dthree/vorpal) - Cash is built on Vorpal
+
+#### Individual commands
+
+- [cash-cat](https://npmjs.com/package/cash-cat)
+- [cash-cp](https://npmjs.com/package/cash-cp)
+- [cash-kill](https://npmjs.com/package/cash-kill)
+- [cash-ls](https://npmjs.com/package/cash-ls)
+- [cash-mkdir](https://npmjs.com/package/cash-mkdir)
+- [cash-mv](https://npmjs.com/package/cash-mv)
+- [cash-pwd](https://npmjs.com/package/cash-pwd)
+- [cash-sort](https://npmjs.com/package/cash-sort)
+- [cash-touch](https://npmjs.com/package/cash-touch)
+- [cash-rm](https://npmjs.com/package/cash-rm)
+
+
+## License
+
+MIT © [David Caccavella](https://github.com/dthree)
50 packages/rm/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(' '));
+ }
+};
2 packages/rm/bin/rm.js
@@ -0,0 +1,2 @@
+#!/usr/bin/env node
+require('./parser')(process.argv, 'rm');
171 packages/rm/dist/commands/rm.js
@@ -0,0 +1,171 @@
+'use strict';
+
+var fs = require('fs');
+var fsAutocomplete = require('vorpal-autocomplete-fs');
+
+var expand = require('./../util/expand');
+var interfacer = require('./../util/interfacer');
+var unlinkSync = require('./../util/unlinkSync');
+
+var rm = {
+ exec: function exec(args, options) {
+ var self = this;
+ options = options || {};
+ options.recursive = options.R ? options.R : options.recursive;
+
+ var files = args;
+ files = files === undefined ? [] : files;
+ files = typeof files === 'string' ? [files] : files;
+
+ files = expand(files);
+
+ files.forEach(function (file) {
+ if (!fs.existsSync(file)) {
+ // Path does not exist, no force flag given
+ if (!options.force) {
+ self.log('rm: cannot remove ' + file + ': No such file or directory');
+ return 2;
+ }
+ /* istanbul ignore next */
+ return 0;
+ }
+
+ var stats = fs.lstatSync(file);
+ if (stats.isFile() || stats.isSymbolicLink()) {
+ if (options.force) {
+ unlinkSync(file);
+ return 0;
+ }
+
+ if (isWriteable(file)) {
+ unlinkSync(file);
+ } else {
+ /* istanbul ignore next */
+ self.log('rm: cannot remove ' + file + ': permission denied');
+ /* istanbul ignore next */
+ return 2;
+ }
+ return 0;
+ }
+
+ // Path is an existing directory, but no -r flag given
+ if (stats.isDirectory() && !options.recursive) {
+ self.log('rm: cannot remove: path is a directory');
+ return 2;
+ }
+
+ // Recursively remove existing directory
+ if (stats.isDirectory() && options.recursive) {
+ rmdirSyncRecursive.call(self, file, options.force, options.dir);
+ }
+ });
+ }
+};
+
+function rmdirSyncRecursive(dir, force, removeEmptyDir) {
+ var self = this;
+ var files = undefined;
+ files = fs.readdirSync(dir);
+
+ // Loop through and delete everything in the sub-tree after checking it
+ for (var i = 0; i < files.length; i++) {
+ var file = dir + '/' + files[i];
+ var currFile = fs.lstatSync(file);
+
+ if (currFile.isDirectory()) {
+ // Recursive function back to the beginning
+ rmdirSyncRecursive(file, force, removeEmptyDir);
+ } else if (currFile.isSymbolicLink()) {
+ // Unlink symlinks
+ /* istanbul ignore next */
+ if (force || isWriteable(file)) {
+ try {
+ unlinkSync(file);
+ } catch (e) {
+ self.log('rm: cannot remove ' + file + ': code ' + e.code);
+ return 2;
+ }
+ }
+ } else if (force || isWriteable(file)) {
+ // Assume it's a file.
+ try {
+ unlinkSync(file);
+ } catch (e) {
+ /* istanbul ignore next */
+ self.log('rm: cannot remove ' + file + ': code ' + e.code);
+ /* istanbul ignore next */
+ return 2;
+ }
+ }
+ }
+
+ // Now that we know everything in the sub-tree has been deleted,
+ // we can delete the main directory.
+ var result = undefined;
+ try {
+ // Retry on windows, sometimes it takes a little time before all the files in the directory are gone
+ var start = Date.now();
+ while (true) {
+ try {
+ result = fs.rmdirSync(dir);
+ /* istanbul ignore next */
+ if (fs.existsSync(dir)) {
+ throw new Error('EAGAIN');
+ }
+ break;
+ } catch (er) {
+ // In addition to error codes, also check if the directory still exists and loop again if true
+ /* istanbul ignore next */
+ if (process.platform === 'win32' && (er.code === 'ENOTEMPTY' || er.code === 'EBUSY' || er.code === 'EPERM' || er.code === 'EAGAIN')) {
+ if (Date.now() - start > 1000) {
+ throw er;
+ }
+ /* istanbul ignore next */
+ } else if (er.code === 'ENOENT') {
+ // Directory did not exist, deletion was successful
+ break;
+ /* istanbul ignore next */
+ } else {
+ throw er;
+ }
+ }
+ }
+ } catch (e) {
+ /* istanbul ignore next */
+ self.log('rm: cannot remove directory ' + dir + ': code ' + e.code);
+ /* istanbul ignore next */
+ return 2;
+ }
+ return result;
+}
+
+// Hack to determine if file has write permissions for current user
+// Avoids having to check user, group, etc, but it's probably slow.
+function isWriteable(file) {
+ var writePermission = true;
+ try {
+ var __fd = fs.openSync(file, 'a');
+ fs.closeSync(__fd);
+ } catch (e) {
+ /* istanbul ignore next */
+ writePermission = false;
+ }
+
+ return writePermission;
+}
+
+module.exports = function (vorpal) {
+ if (vorpal === undefined) {
+ return rm;
+ }
+ vorpal.api.rm = rm;
+ vorpal.command('rm [files...]').option('-f, --force', 'ignore nonexistent files and arguments, never prompt').option('-r, --recursive', 'remove directories and their contents recursively').option('-R', 'remove directories and their contents recursively').autocomplete(fsAutocomplete()).action(function (args, callback) {
+ args.options = args.options || {};
+ return interfacer.call(this, {
+ command: rm,
+ args: args.files,
+ options: args.options,
+ callback: callback
+ });
+ });
+};
3 packages/rm/dist/help/rm.js
@@ -0,0 +1,3 @@
+"use strict";
+
+module.exports = "\nUsage: rm [OPTION]... FILE...\nRemove (unlink) the FILE(s).\n\n -f, --force ignore nonexistent files and arguments, never prompt\n -r, -R, --recursive remove directories and their contents recursively\n --help display this help and exit\n\nBy default, rm does not remove directories. Use the --recursive (-r or -R)\noption to remove each listed directory, too, along with all of its contents.\n\nTo remove a file whose name starts with a '-', for example '-foo',\nuse one of these commands:\n rm -- -foo\n rm ./-foo\n\nNote that if you use rm to remove a file, it might be possible to recover\nsome of its contents, given sufficient expertise and/or time.\n\nReport rm bugs to <https://github.com/dthree/cash>\nCash home page: <http://cash.js.org/>\n";
29 packages/rm/dist/util/expand.js
@@ -0,0 +1,29 @@
+'use strict';
+
+var glob = require('glob');
+
+/**
+ * Expands wildcard files, etc. out
+ * into their full paths.
+ *
+ * @param {Array} list
+ * @return {Array}
+ * @api public
+ */
+
+module.exports = function (list) {
+ var total = list.length;
+ var files = [];
+ if (list.length < 1) {
+ return [];
+ }
+ for (var i = 0; i < total; ++i) {
+ var res = glob.sync(list[i], {});
+ files[i] = res.length > 0 ? res : list[i];
+ }
+ var out = [];
+ for (var i = 0; i < files.length; ++i) {
+ out = Array.isArray(files[i]) ? out.concat(files[i]) : out.concat([files[i]]);
+ }
+ return out;
+};
45 packages/rm/dist/util/interfacer.js
@@ -0,0 +1,45 @@
+'use strict';
+
+/**
+ * Simple binding interface between
+ * each command's function and the caller
+ * of the command, whether by `cash.command`
+ * or by being invoked by Vorpal.
+ * This exists to abstract complexity
+ * and create a standard in interfacing
+ * commands acorss muliple execution paths.
+ *
+ * @param {Object} opt
+ * @api public
+ */
+
+module.exports = function (opt) {
+ var self = this;
+ var stdout = '';
+ opt.options = opt.options || {};
+ opt.callback = opt.callback || function () {};
+ opt.command = opt.command || {
+ exec: function exec() {}
+ };
+
+ var logger = {
+ log: function log(out) {
+ stdout += out + '\n';
+ if (opt.silent !== true) {
+ // process.stdout.write(out) // to do - handle newline problem.
+ self.log(out);
+ }
+ }
+ };
+
+ function onResult(result) {
+ result = result === undefined ? 0 : result;
+ opt.callback(null, stdout);
+ return stdout;
+ }
+
+ if (opt.async === true) {
+ return opt.command.exec.call(logger, opt.args, opt.options, onResult);
+ }
+ return onResult(opt.command.exec.call(logger, opt.args, opt.options));
+};
30 packages/rm/dist/util/unlinkSync.js
@@ -0,0 +1,30 @@
+'use strict';
+
+var fs = require('fs');
+
+/**
+ * Normalizes _unlinkSync() across
+ * platforms to match Unix behavior, i.e.
+ * file can be unlinked even its it's
+ * read only.
+ * See https://github.com/joyent/node/issues/3006
+ *
+ * @param {String} file
+ * @api public
+ */
+
+module.exports = function (file) {
+ try {
+ fs.unlinkSync(file);
+ } catch (e) {
+ // Try to override file permission
+ /* istanbul ignore if */
+ if (e.code === 'EPERM') {
+ fs.chmodSync(file, '0666');
+ fs.unlinkSync(file);
+ } else {
+ /* istanbul ignore next */
+ throw e;
+ }
+ }
+};
50 packages/rm/package.json
@@ -0,0 +1,50 @@
+{
+ "name": "cash-rm",
+ "version": "0.1.0",
+ "description": "Cross-platform implementation of the Unix 'rm' command.",
+ "main": "./dist/commands/rm.js",
+ "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": {
+ "rm": "./bin/rm.js"
+ },
+ "dependencies": {
+ "vorpal-autocomplete-fs": "0.0.3",
+ "glob": "^6.0.4",
+ "vorpal": "^1.9.5"
+ },
+ "engines": {
+ "node": ">= 0.11.16",
+ "iojs": ">= 1.0.0"
+ },
+ "files": [
+ "dist",
+ "bin"
+ ]
+}
47 packages/sort/README.md
@@ -0,0 +1,47 @@
+# cash-sort
+
+---
+
+
+This is a cross-platform, 100% ES6 implementation of the Unix `sort` command.
+
+```bash
+npm install cash-sort -g
+```
+
+This will install `sort` globally in your system path.
+
+For help on the command, type:
+
+```bash
+> sort --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
+
+- [cash](https://github.com/dthree/cash) - Main project
+- [cash-global](https://npmjs.com/package/cash-global) - Globally install all commands
+- [vorpal](https://github.com/dthree/vorpal) - Cash is built on Vorpal
+
+#### Individual commands
+
+- [cash-cat](https://npmjs.com/package/cash-cat)
+- [cash-cp](https://npmjs.com/package/cash-cp)
+- [cash-kill](https://npmjs.com/package/cash-kill)
+- [cash-ls](https://npmjs.com/package/cash-ls)
+- [cash-mkdir](https://npmjs.com/package/cash-mkdir)
+- [cash-mv](https://npmjs.com/package/cash-mv)
+- [cash-pwd](https://npmjs.com/package/cash-pwd)
+- [cash-sort](https://npmjs.com/package/cash-sort)
+- [cash-touch](https://npmjs.com/package/cash-touch)
+- [cash-rm](https://npmjs.com/package/cash-rm)
+
+
+## License
+
+MIT © [David Caccavella](https://github.com/dthree)
50 packages/sort/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(' '));
+ }
+};
2 packages/sort/bin/sort.js
@@ -0,0 +1,2 @@
+#!/usr/bin/env node
+require('./parser')(process.argv, 'sort');
269 packages/sort/dist/commands/sort.js
@@ -0,0 +1,269 @@
+'use strict';
+
+var _ = require('lodash');
+var fs = require('fs');
+var fsAutocomplete = require('vorpal-autocomplete-fs');
+
+var fetch = require('./../util/fetch');
+var interfacer = require('./../util/interfacer');
+var strip = require('./../util/stripAnsi');
+
+var sort = {
+
+ counter: 0,
+
+ stdin: '',
+
+ exec: function exec(args, options) {
+ var self = this;
+
+ // Hack to handle multiple calls
+ // due to fragmented stdin, such as
+ // by piping. In essence, we're waiting
+ // 100 milliseconds for all of the
+ // requests to come in, and then running
+ // sort. Only applies when sort is called
+ // through a piped command.
+ /* istanbul ignore next */
+ if (args && args.stdin && options.bypass !== true) {
+ sort.counter++;
+ sort.stdin += args.stdin + '\n';
+ if (sort.counter === 1) {
+ setTimeout(function () {
+ sort.counter = 0;
+ args.stdin = sort.stdin;
+ sort.stdin = '';
+ options.bypass = true;
+ sort.exec.call(self, args, options);
+ }, 100);
+ }
+ return;
+ }
+ sort.counter = 0;
+ sort.stdin = '';
+
+ // Input normalization
+ if (args === undefined) {
+ args = {
+ files: []
+ };
+ } else if (_.isString(args)) {
+ args = {
+ files: [args]
+ };
+ } else if (_.isArray(args)) {
+ args = {
+ files: args
+ };
+ }
+
+ options = options || {};
+
+ function log(stdout) {
+ if (options.output) {
+ if (options.output === true) {
+ self.log('sort: option \'--output\' requires an argument\nTry \'sort --help\' for more information.');
+ return 0;
+ }
+ try {
+ fs.writeFileSync(options.output, stdout);
+ return 0;
+ } catch (e) {
+ if (e.code === 'ENOENT') {
+ self.log('sort: open failed: ' + options.output + ': No such file or directory');
+ } else {
+ /* istanbul ignore next */
+ self.log('sort: open failed: ' + options.output + ': ' + e.code);
+ }
+ return 2;
+ }
+ } else {
+ self.log(stdout);
+ }
+ }
+
+ try {
+ var stdin = fetch(args.files, args.stdin, {
+ onDirectory: function onDirectory(name) {
+ /* istanbul ignore next */
+ return 'sort: read failed: ' + name + ': Is a directory';
+ },
+ onInvalidFile: function onInvalidFile(name) {
+ /* istanbul ignore next */
+ return 'sort: cannot read: ' + name + ': No such file or directory';
+ }
+ });
+
+ var combined = '';
+ for (var i = 0; i < stdin.length; ++i) {
+ // Get rid of trailing line break because
+ // node logging does it anyway.
+ combined += stdin[i];
+ }
+
+ combined = combined.replace(/\s$/, '');
+ var parts = String(combined).split('\n');
+
+ if (options.check) {
+ // Check if the thing was already sorted.
+ var original = String(combined).split('\n');
+ var disorder = undefined;
+ for (var i = 0; i < original.length; ++i) {
+ var a = original[i];
+ var b = original[i + 1];
+ if (a && b) {
+ if (!isNaN(a) && !isNaN(b) && parseFloat(a) > parseFloat(b)) {
+ /* istanbul ignore next */
+ disorder = true;
+ } else if (a > b) {
+ disorder = true;
+ }
+ if (disorder) {
+ // To do: right now, I don't say the file
+ // name of the bad sorted item - I have to
+ // figure this out as I join all the files
+ // together beforehand and lose track.
+ disorder = 'sort: -:' + (i + 2) + ': disorder: ' + b;
+ break;
+ }
+ }
+ }
+ if (disorder) {
+ log(disorder);
+ return;
+ }
+ }
+
+ parts = parts.sort(function (a, b) {
+ var aAlpha = strip(a).replace(/\W+/g, '');
+ var bAlpha = strip(b).replace(/\W+/g, '');
+ var aNumeric = strip(a).replace(/\D/g, '');
+ var bNumeric = strip(b).replace(/\D/g, '');
+ if (options.humannumericsort) {
+ var aHuman = parseHumanReadableNumbers(strip(a));
+ var bHuman = parseHumanReadableNumbers(strip(b));
+ if (aHuman.group < bHuman.group) {
+ return -1;
+ } else if (aHuman.group > bHuman.group) {
+ return 1;
+ } else if (aHuman.num < bHuman.num) {
+ return -1;
+ } else if (aHuman.num > bHuman.num) {
+ return 1;
+ }
+ return aAlpha.localeCompare(bAlpha);
+ } else if (options.monthsort) {
+ var aMonth = parseMonths(strip(a));
+ var bMonth = parseMonths(strip(b));
+ var result = aMonth - bMonth;
+ if (aMonth === bMonth) {
+ result = aAlpha.localeCompare(bAlpha);
+ }
+ return result;
+ } else if (options.numericsort) {
+ var result = aNumeric - bNumeric;
+ result = result === 0 ? aAlpha.localeCompare(bAlpha) : result;
+ return result;
+ }
+ return aAlpha.localeCompare(bAlpha);
+ });
+
+ if (options.randomsort) {
+ fisherYatesShuffle(parts);
+ }
+
+ if (options.reverse) {
+ parts.reverse();
+ }
+
+ var out = parts.join('\n');
+ if (String(out).trim() !== '') {
+ log(out);
+ }
+
+ return;
+ } catch (e) {
+ /* istanbul ignore next */
+ self.log(e.stack);
+ /* istanbul ignore next */
+ return;
+ }
+ }
+};
+
+// This shit is gnarly.
+// Per the coreutils sort.c:
+// <none/unknown> < K/k < M < G < T < P < E < Z < Y
+var humanOrdering = { '': 0, 'K': 1, 'k': 1, 'M': 2, 'G': 3, 'T': 4, 'P': 5, 'E': 6, 'Z': 7 };
+var humanReadableSort = new RegExp(/^([0-9]+)?[\.]?[0-9]+[K|k|M|G|T|P|E|Z|Y]/g);
+function parseHumanReadableNumbers(nbr) {
+ nbr = String(nbr).replace(/(\r\n|\n|\r)/gm, '');
+ if (String(nbr).match(humanReadableSort)) {
+ var num = parseFloat(String(nbr).replace(/[a-zA-Z]/g, '').trim());
+ var group = humanOrdering[String(nbr).replace(/[^a-zA-Z]/g, '').trim()] || 0;
+ return {
+ num: num,
+ group: group
+ };
+ }
+ var isNumber = String(nbr).match(/^[0-9]/);
+ var stripped = isNumber ? parseFloat(String(nbr).replace(/[^0-9.]/g, '')) : 'NaN';
+ var result = !isNaN(stripped) ? stripped : -99999999999;
+ return {
+ num: result,
+ group: 0
+ };
+}
+
+var monthOrdering = {
+ jan: 1,
+ feb: 2,
+ mar: 3,
+ apr: 4,
+ may: 5,
+ jun: 6,
+ jul: 7,
+ aug: 8,
+ sep: 9,
+ oct: 10,
+ nov: 11,
+ dec: 12
+};
+
+var months = new RegExp(/^(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)/i);
+function parseMonths(str) {
+ var match = String(str).match(months);
+ if (match) {
+ return monthOrdering[String(str.slice(0, 3).toLowerCase())];
+ }
+ return 0;
+}
+
+function fisherYatesShuffle(array) {
+ var m = array.length;
+ var t = undefined;
+ var i = undefined;
+ while (m) {
+ i = Math.floor(Math.random() * m--);
+ t = array[m];
+ array[m] = array[i];
+ array[i] = t;
+ }
+ return array;
+}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
+
+module.exports = function (vorpal) {
+ if (vorpal === undefined) {
+ return sort;
+ }
+ vorpal.api.sort = sort;
+ vorpal.command('sort [files...]').option('-M, --month-sort', 'compare (unknown) < \'JAN\' < ... < \'DEC\'').option('-h, --human-numeric-sort', 'compare human readable numbers (e.g., 2K 1G)').option('-n, --numeric-sort', 'compare according to string numerical value').option('-R, --random-sort', 'sort by random hash of keys').option('-r, --reverse', 'reverse the result of comparisons').option('-c, --check', 'check for sorted input; do not sort').option('-o, --output [file]', 'write result to file instead of standard output').autocomplete(fsAutocomplete()).action(function (args, callback) {
+ args.options = args.options || {};
+ return interfacer.call(this, {
+ command: sort,
+ args: args,
+ options: args.options,
+ callback: callback
+ });
+ });
+};
3 packages/sort/dist/help/sort.js
@@ -0,0 +1,3 @@
+"use strict";
+
+module.exports = "\nUsage: sort [OPTION]... [FILE]...\nWrite sorted concatenation of all FILE(s) to standard output.\n\nOrdering options:\n -M, --month-sort compare (unknown) < 'JAN' < ... < 'DEC'\n -h, --human-numeric-sort compare human readable numbers (e.g., 2K 1G)\n -n, --numeric-sort compare according to string numerical value\n -R, --random-sort sort by random hash of keys\n -r, --reverse reverse the result of comparisons\n\nOther options:\n -c, --check,\n --check=diagnose-first check for sorted input; do not sort\n -o, --output=FILE write result to FILE instead of standard output\n --help display this help and exit\n\nWith no FILE, or when FILE is -, read standard input.\n\nReport sort bugs to <https://github.com/dthree/cash>\nCash home page: <http://cash.js.org/>\n";
29 packages/sort/dist/util/expand.js
@@ -0,0 +1,29 @@
+'use strict';
+
+var glob = require('glob');
+
+/**
+ * Expands wildcard files, etc. out
+ * into their full paths.
+ *
+ * @param {Array} list
+ * @return {Array}
+ * @api public
+ */
+
+module.exports = function (list) {
@dthree
Owner
dthree added a note

I'll check it out. It depends on Glob, right?

Yup

@dthree
Owner
dthree added a note

Could you possibly clarify the benefit? I guess just better pattern matching? Glob seemed to comply with the same pattern matching as is expected in a bash shell command, unless I'm missing something?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
+ var total = list.length;
+ var files = [];
+ if (list.length < 1) {
+ return [];
+ }
+ for (var i = 0; i < total; ++i) {
+ var res = glob.sync(list[i], {});
+ files[i] = res.length > 0 ? res : list[i];
+ }
+ var out = [];
+ for (var i = 0; i < files.length; ++i) {
+ out = Array.isArray(files[i]) ? out.concat(files[i]) : out.concat([files[i]]);
+ }
+ return out;
+};
50 packages/sort/dist/util/fetch.js
@@ -0,0 +1,50 @@
+'use strict';
+
+var fs = require('fs');
+var path = require('path');
+
+var expand = require('./expand');
+
+/**
+ * Reads the contents of an array of
+ * files and returns the array.
+ *
+ * @param {Array} files
+ * @param {String} stdin
+ * @param {Object} options
+ * @return {Array}
+ * @api public
+ */
+
+module.exports = function (files, stdin, options) {
+ files = files || [];
+ stdin = stdin !== undefined ? stdin : [];
+ var f = expand(files);
+
+ if (!(f.length === 0 && files.length > 0)) {
+ files = f;
+ }
+
+ for (var i = 0; i < files.length; ++i) {
+ try {
+ var stat = fs.statSync(files[i]);
+ if (stat.isDirectory()) {
+ files[i] = options.onDirectory(files[i]);
+ } else {
+ files[i] = String(fs.readFileSync(path.normalize(files[i]), 'utf8'));
+ }
+ } catch (e) {
+ files[i] = options.onInvalidFile(files[i]);
+ }
+ }
+
+ var agg = files.length < 1 ? stdin : files;
+ var final = [];
+
+ for (var i = 0; i < agg.length; ++i) {
+ if (agg[i] !== undefined) {
+ final.push(agg[i]);
+ }
+ }
+ return final;
+};
45 packages/sort/dist/util/interfacer.js
@@ -0,0 +1,45 @@
+'use strict';
+
+/**
+ * Simple binding interface between
+ * each command's function and the caller
+ * of the command, whether by `cash.command`
+ * or by being invoked by Vorpal.
+ * This exists to abstract complexity
+ * and create a standard in interfacing
+ * commands acorss muliple execution paths.
+ *
+ * @param {Object} opt
+ * @api public
+ */
+
+module.exports = function (opt) {
+ var self = this;
+ var stdout = '';
+ opt.options = opt.options || {};
+ opt.callback = opt.callback || function () {};
+ opt.command = opt.command || {
+ exec: function exec() {}
+ };
+
+ var logger = {
+ log: function log(out) {
+ stdout += out + '\n';
+ if (opt.silent !== true) {
+ // process.stdout.write(out) // to do - handle newline problem.
+ self.log(out);
+ }
+ }
+ };
+
+ function onResult(result) {
+ result = result === undefined ? 0 : result;
+ opt.callback(null, stdout);
+ return stdout;
+ }
+
+ if (opt.async === true) {
+ return opt.command.exec.call(logger, opt.args, opt.options, onResult);
+ }
+ return onResult(opt.command.exec.call(logger, opt.args, opt.options));
+};
14 packages/sort/dist/util/stripAnsi.js
@@ -0,0 +1,14 @@
+'use strict';
+
+/**
+ * Removes all ansi characters.
+ *
+ * @param {String} str
+ * @return {String}
+ * @api public
+ */
+
+module.exports = function (str) {
+ var ansiRegex = /[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g;
+ return typeof str === 'string' ? str.replace(ansiRegex, '') : str;
+};
51 packages/sort/package.json
@@ -0,0 +1,51 @@
+{
+ "name": "cash-sort",
+ "version": "0.1.0",
+ "description": "Cross-platform implementation of the Unix 'sort' command.",
+ "main": "./dist/commands/sort.js",
+ "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": {
+ "sort": "./bin/sort.js"
+ },
+ "dependencies": {
+ "lodash": "^4.0.0",
+ "vorpal-autocomplete-fs": "0.0.3",
+ "glob": "^6.0.4",
+ "vorpal": "^1.9.5"
+ },
+ "engines": {
+ "node": ">= 0.11.16",
+ "iojs": ">= 1.0.0"
+ },
+ "files": [
+ "dist",
+ "bin"
+ ]
+}
32 packages/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)
44 packages/template.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"
+ ]
+}
47 packages/touch/README.md
@@ -0,0 +1,47 @@
+# cash-touch
+
+---
+
+
+This is a cross-platform, 100% ES6 implementation of the Unix `touch` command.
+
+```bash
+npm install cash-touch -g
+```
+
+This will install `touch` globally in your system path.
+
+For help on the command, type:
+
+```bash
+> touch --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
+
+- [cash](https://github.com/dthree/cash) - Main project
+- [cash-global](https://npmjs.com/package/cash-global) - Globally install all commands
+- [vorpal](https://github.com/dthree/vorpal) - Cash is built on Vorpal
+
+#### Individual commands
+
+- [cash-cat](https://npmjs.com/package/cash-cat)
+- [cash-cp](https://npmjs.com/package/cash-cp)
+- [cash-kill](https://npmjs.com/package/cash-kill)
+- [cash-ls](https://npmjs.com/package/cash-ls)
+- [cash-mkdir](https://npmjs.com/package/cash-mkdir)
+- [cash-mv](https://npmjs.com/package/cash-mv)
+- [cash-pwd](https://npmjs.com/package/cash-pwd)
+- [cash-sort](https://npmjs.com/package/cash-sort)
+- [cash-touch](https://npmjs.com/package/cash-touch)
+- [cash-rm](https://npmjs.com/package/cash-rm)
+
+
+## License
+
+MIT © [David Caccavella](https://github.com/dthree)
50 packages/touch/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(' '));
+ }
+};
2 packages/touch/bin/touch.js
@@ -0,0 +1,2 @@
+#!/usr/bin/env node
+require('./parser')(process.argv, 'touch');
151 packages/touch/dist/commands/touch.js
@@ -0,0 +1,151 @@
+'use strict';
+
+var _ = require('lodash');
+var fs = require('fs-extra');
+var fsAutocomplete = require('vorpal-autocomplete-fs');
+
+var interfacer = require('./../util/interfacer');
+require('./../lib/sugar');
+
+var touch = {
+
+ /**
+ * Main command execution.
+ *
+ * @param {Object} args
+ * @return {Object} { status, stdout }
+ * @api public
+ */
+
+ exec: function exec(files, options) {
+ var self = this;
+ files = files || ['.'];
+ files = !_.isArray(files) ? [files] : files;
+ options = options || {};
+
+ // If any version of --no-create is passed, change it to false.
+ options.create = options.create === true ? false : options.create;
+
+ // If --time is passed, ensure a valid param is called in
+ // and map it to -a or -m, as this is the equivalent of these.
+ // Throw an error if nothing valid passed.
+ if (options.time) {
+ var a = ['access', 'atime', 'use'];
+ var m = ['modify', 'mtime'];
+ var opt = a.indexOf(options.time) > -1 ? 'a' : m.indexOf(options.time) > -1 ? 'm' : undefined;
+ if (!opt) {
+ var error = 'touch: invalid argument "' + options.time + '" for "--time"\n' + 'Valid arguments are:\n' + ' - "atime", "access", "use"\n' + ' - "mtime", "modify"\n' + 'Try \'touch --help\' for more information.';
+ // I think this is the stupidest thing
+ // I've ever written.
+ try {
+ throw new Error(error);
+ } catch (e) {
+ return touch.error.call(self, e);
+ }
+ } else {
+ options[opt] = true;
+ }
+ }
+
+ try {
+ var err = false;
+ for (var i = 0; i < files.length; ++i) {
+ try {
+ touch.file(files[i], options);
+ } catch (e) {
+ err = e;
+ break;
+ }
+ }
+ if (err) {
+ return touch.error.call(self, err);
+ }
+ return 0;
+ } catch (e) {
+ return touch.error.call(self, e);
+ }
+ },
+
+ /**
+ * Returns touch stderr and response codes
+ * for errors.
+ *
+ * @param {Error} e
+ * @return {Object} { status, stdout }
+ * @api private
+ */
+
+ error: function error(e) {
+ this.log(e.message);
+ return 2;
+ },
+
+ /**
+ * Handler for a single file using touch.
+ *
+ * @param {String} path
+ * @param {Object} options
+ * @api private
+ */
+
+ file: function file(path, options) {
+ try {
+ try {
+ fs.lstatSync(path);
+ } catch (e) {
+ // If the file doesn't exist and
+ // the user doesn't want to create it,
+ // we have no purpose in life. Goodbye.
+ if (options.create === false) {
+ throw new Error(e);
+ } else {
+ fs.closeSync(fs.openSync(path, 'wx'));
+ }
+ }
+
+ var stat = fs.statSync(path);
+ var dateToSet = options.date ? Date.create(options.date) : new Date();
+
+ if (String(dateToSet) === 'Invalid Date') {
+ throw new Error('touch: invalid date format ' + options.date);
+ }
+
+ // If -m, keep access time current.
+ var atime = options.m === true ? new Date(stat.atime) : dateToSet;
+
+ // If -a, keep mod time to current.
+ var mtime = options.a === true ? new Date(stat.mtime) : dateToSet;
+
+ if (options.reference !== undefined) {
+ var reference = undefined;
+ try {
+ reference = fs.statSync(options.reference);
+ } catch (e) {
+ throw new Error('touch: failed to get attributes of ' + options.reference + ': No such file or directory');
+ }
+ atime = options.m === true ? atime : reference.atime;
+ mtime = options.a === true ? mtime : reference.mtime;
+ }
+
+ fs.utimesSync(path, atime, mtime);
+ fs.utimesSync(path, atime, mtime);
+ } catch (e) {
+ throw new Error(e);
+ }
+ }
+};
+
+module.exports = function (vorpal) {
+ if (vorpal === undefined) {
+ return touch;
+ }
+ vorpal.api.touch = touch;
+ vorpal.command('touch <files...>').option('-a', 'change only the access time').option('-c, --no-create', 'do not create any files').option('-d, --date [STRING]', 'parse STRING and use it instead of current time').option('-m', 'change only the modification time').option('-r, --reference [FILE]', 'use this file\'s times instead of current time').option('--time [WORD]', 'change the specified time: WORD is access, atime, or use: equivalent to -a WORD is modify or mtime: equivalent to -m').autocomplete(fsAutocomplete()).action(function (args, callback) {
+ return interfacer.call(this, {
+ command: touch,
+ args: args.files || [],
+ options: args.options,
+ callback: callback
+ });
+ });
+};
3 packages/touch/dist/help/touch.js
@@ -0,0 +1,3 @@
+"use strict";
+
+module.exports = "\nUsage: touch [OPTION]... FILE...\nUpdate the access and modification times of each FILE to the current time.\n\nA FILE argument that does not exist is created empty, unless -c is\nsupplied.\n\n -a change only the access time\n -c, --no-create do not create any files\n -d, --date <STRING> parse STRING and use it instead of current time\n -m change only the modification time\n -r, --reference <FILE> use this file's times instead of current time\n --time <WORD> change the specified time:\n WORD is access, atime, or use: equivalent to -a\n WORD is modify or mtime: equivalent to -m\n --help display this help and exit\n\nReport touch bugs to <https://github.com/dthree/cash>\nCash home page: <http://cash.js.org/>\n";
747 packages/touch/dist/lib/sugar.js
@@ -0,0 +1,747 @@
+"use strict";
+
+var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol ? "symbol" : typeof obj; };
+
+/*
+ * Sugar Library v1.4.1
+ *
+ * Freely distributable and licensed under the MIT-style license.
+ * Copyright (c) 2014 Andrew Plummer
+ * http://sugarjs.com/
+ *
+ * ---------------------------- */
+/* istanbul ignore next */
+(function () {
+ function aa(a) {
+ return function () {
+ return a;
+ };
+ }
+ /* istanbul ignore next */
+ var m = Object,
+ p = Array,
+ q = RegExp,
+ r = Date,
+ s = String,
+ t = Number,
+ u = Math,
+ ba = "undefined" !== typeof global ? global : this,
+ v = m.prototype.toString,
+ da = m.prototype.hasOwnProperty,
+ ea = m.defineProperty && m.defineProperties,
+ fa = "function" === typeof q(),
+ ga = !("0" in new s("a")),
+ ia = {},
+ ja = /^\[object Date|Array|String|Number|RegExp|Boolean|Arguments\]$/,
+ w = "Boolean Number String Array Date RegExp Function".split(" "),
+ la = ka("boolean", w[0]),
+ y = ka("number", w[1]),
+ z = ka("string", w[2]),
+ A = ma(w[3]),
+ C = ma(w[4]),
+ D = ma(w[5]),
+ F = ma(w[6]);
+ /* istanbul ignore next */
+ function ma(a) {
+ var b = "Array" === a && p.isArray || function (b, d) {
+ return (d || v.call(b)) === "[object " + a + "]";
+ };return ia[a] = b;
+ }function ka(a, b) {
+ function c(c) {
+ return G(c) ? v.call(c) === "[object " + b + "]" : (typeof c === "undefined" ? "undefined" : _typeof(c)) === a;
+ }return ia[b] = c;
+ }
+ function na(a) {
+ a.SugarMethods || (oa(a, "SugarMethods", {}), H(a, !1, !0, { extend: function extend(b, c, d) {
+ H(a, !1 !== d, c, b);
+ }, sugarRestore: function sugarRestore() {
+ return pa(this, a, arguments, function (a, c, d) {
+ oa(a, c, d.method);
+ });
+ }, sugarRevert: function sugarRevert() {
+ return pa(this, a, arguments, function (a, c, d) {
+ d.existed ? oa(a, c, d.original) : delete a[c];
+ });
+ } }));
+ }function H(a, b, c, d) {
+ var e = b ? a.prototype : a;na(a);I(d, function (d, f) {
+ var h = e[d],
+ l = J(e, d);F(c) && h && (f = qa(h, f, c));!1 === c && h || oa(e, d, f);a.SugarMethods[d] = { method: f, existed: l, original: h, instance: b };
+ });
+ }
+ function K(a, b, c, d, e) {
+ var g = {};d = z(d) ? d.split(",") : d;d.forEach(function (a, b) {
+ e(g, a, b);
+ });H(a, b, c, g);
+ }function pa(a, b, c, d) {
+ var e = 0 === c.length,
+ g = L(c),
+ f = !1;I(b.SugarMethods, function (b, c) {
+ if (e || -1 !== g.indexOf(b)) f = !0, d(c.instance ? a.prototype : a, b, c);
+ });return f;
+ }function qa(a, b, c) {
+ return function (d) {
+ return c.apply(this, arguments) ? b.apply(this, arguments) : a.apply(this, arguments);
+ };
+ }function oa(a, b, c) {
+ ea ? m.defineProperty(a, b, { value: c, configurable: !0, enumerable: !1, writable: !0 }) : a[b] = c;
+ }
+ function L(a, b, c) {
+ var d = [];c = c || 0;var e;for (e = a.length; c < e; c++) {
+ d.push(a[c]), b && b.call(a, a[c], c);
+ }return d;
+ }function sa(a, b, c) {
+ var d = a[c || 0];A(d) && (a = d, c = 0);L(a, b, c);
+ }function ta(a) {
+ if (!a || !a.call) throw new TypeError("Callback is not callable");
+ }function M(a) {
+ return void 0 !== a;
+ }function N(a) {
+ return void 0 === a;
+ }function J(a, b) {
+ return !!a && da.call(a, b);
+ }function G(a) {
+ return !!a && ("object" === (typeof a === "undefined" ? "undefined" : _typeof(a)) || fa && D(a));
+ }function ua(a) {
+ var b = typeof a === "undefined" ? "undefined" : _typeof(a);return null == a || "string" === b || "number" === b || "boolean" === b;
+ }
+ function va(a, b) {
+ b = b || v.call(a);try {
+ if (a && a.constructor && !J(a, "constructor") && !J(a.constructor.prototype, "isPrototypeOf")) return !1;
+ } catch (c) {
+ return !1;
+ }return !!a && "[object Object]" === b && "hasOwnProperty" in a;
+ }function I(a, b) {
+ for (var c in a) {
+ if (J(a, c) && !1 === b.call(a, c, a[c], a)) break;
+ }
+ }function wa(a, b) {
+ for (var c = 0; c < a; c++) {
+ b(c);
+ }
+ }function xa(a, b) {
+ I(b, function (c) {
+ a[c] = b[c];
+ });return a;
+ }function ya(a) {
+ ua(a) && (a = m(a));if (ga && z(a)) for (var b = a, c = 0, d; d = b.charAt(c);) {
+ b[c++] = d;
+ }return a;
+ }function O(a) {
+ xa(this, ya(a));
+ }
+ O.prototype.constructor = m;var P = u.abs,
+ za = u.pow,
+ Aa = u.ceil,
+ Q = u.floor,
+ R = u.round,
+ Ca = u.min,
+ S = u.max;function Da(a, b, c) {
+ var d = za(10, P(b || 0));c = c || R;0 > b && (d = 1 / d);return c(a * d) / d;
+ }var Ea = 48,
+ Fa = 57,
+ Ga = 65296,
+ Ha = 65305,
+ Ia = ".",
+ Ja = "",
+ Ka = {},
+ La;function Ma() {
+ return "\t\n\u000b\f\r   ᠎             \u2028\u2029 ";
+ }function Na(a, b) {
+ var c = "";for (a = a.toString(); 0 < b;) {
+ if (b & 1 && (c += a), b >>= 1) a += a;
+ }return c;
+ }
+ function Oa(a, b) {
+ var c, d;c = a.replace(La, function (a) {
+ a = Ka[a];a === Ia && (d = !0);return a;
+ });return d ? parseFloat(c) : parseInt(c, b || 10);
+ }function T(a, b, c, d) {
+ d = P(a).toString(d || 10);d = Na("0", b - d.replace(/\.\d+/, "").length) + d;if (c || 0 > a) d = (0 > a ? "-" : "+") + d;return d;
+ }function Pa(a) {
+ if (11 <= a && 13 >= a) return "th";switch (a % 10) {case 1:
+ return "st";case 2:
+ return "nd";case 3:
+ return "rd";default:
+ return "th";}
+ }
+ function Qa(a, b) {
+ function c(a, c) {
+ if (a || -1 < b.indexOf(c)) d += c;
+ }var d = "";b = b || "";c(a.multiline, "m");c(a.ignoreCase, "i");c(a.global, "g");c(a.u, "y");return d;
+ }function Ra(a) {
+ z(a) || (a = s(a));return a.replace(/([\\/\'*+?|()\[\]{}.^$])/g, "\\$1");
+ }function U(a, b) {
+ return a["get" + (a._utc ? "UTC" : "") + b]();
+ }function Sa(a, b, c) {
+ return a["set" + (a._utc && "ISOWeek" != b ? "UTC" : "") + b](c);
+ }
+ function Ta(a, b) {
+ var c = typeof a === "undefined" ? "undefined" : _typeof(a),
+ d,
+ e,
+ g,
+ f,
+ h,
+ l,
+ n;if ("string" === c) return a;g = v.call(a);d = va(a, g);e = A(a, g);if (null != a && d || e) {
+ b || (b = []);if (1 < b.length) for (l = b.length; l--;) {
+ if (b[l] === a) return "CYC";
+ }b.push(a);d = a.valueOf() + s(a.constructor);f = e ? a : m.keys(a).sort();l = 0;for (n = f.length; l < n; l++) {
+ h = e ? l : f[l], d += h + Ta(a[h], b);
+ }b.pop();
+ } else d = -Infinity === 1 / a ? "-0" : s(a && a.valueOf ? a.valueOf() : a);return c + g + d;
+ }function Ua(a, b) {
+ return a === b ? 0 !== a || 1 / a === 1 / b : Va(a) && Va(b) ? Ta(a) === Ta(b) : !1;
+ }
+ function Va(a) {
+ var b = v.call(a);return ja.test(b) || va(a, b);
+ }function Wa(a, b, c) {
+ var d,
+ e = a.length,
+ g = b.length,
+ f = !1 !== b[g - 1];if (!(g > (f ? 1 : 2))) return Xa(a, e, b[0], f, c);d = [];L(b, function (b) {
+ if (la(b)) return !1;d.push(Xa(a, e, b, f, c));
+ });return d;
+ }function Xa(a, b, c, d, e) {
+ d && (c %= b, 0 > c && (c = b + c));return e ? a.charAt(c) : a[c];
+ }function Ya(a, b) {
+ K(b, !0, !1, a, function (a, b) {
+ a[b + ("equal" === b ? "s" : "")] = function () {
+ return m[b].apply(null, [this].concat(L(arguments)));
+ };
+ });
+ }na(m);I(w, function (a, b) {
+ na(ba[b]);
+ });var Za, $a;
+ for ($a = 0; 9 >= $a; $a++) {
+ Za = s.fromCharCode($a + Ga), Ja += Za, Ka[Za] = s.fromCharCode($a + Ea);
+ }Ka[","] = "";Ka[""] = Ia;Ka[Ia] = Ia;La = q("[" + Ja + ".," + Ia + "]", "g");
+ "use strict";H(m, !1, !1, { keys: function keys(a) {
+ var b = [];if (!G(a) && !D(a) && !F(a)) throw new TypeError("Object required");I(a, function (a) {
+ b.push(a);
+ });return b;
+ } });
+ function ab(a, b, c, d) {
+ var e = a.length,
+ g = -1 == d,
+ f = g ? e - 1 : 0;c = isNaN(c) ? f : parseInt(c >> 0);0 > c && (c = e + c);if (!g && 0 > c || g && c >= e) c = f;for (; g && 0 <= c || !g && c < e;) {
+ if (a[c] === b) return c;c += d;
+ }return -1;
+ }function bb(a, b, c, d) {
+ var e = a.length,
+ g = 0,
+ f = M(c);ta(b);if (0 != e || f) f || (c = a[d ? e - 1 : g], g++);else throw new TypeError("Reduce called on empty array with no initial value");for (; g < e;) {
+ f = d ? e - g - 1 : g, f in a && (c = b(c, a[f], f, a)), g++;
+ }return c;
+ }function cb(a) {
+ if (0 === a.length) throw new TypeError("First argument must be defined");
+ }H(p, !1, !1, { isArray: function isArray(a) {
+ return A(a);
+ } });
+ H(p, !0, !1, { every: function every(a, b) {
+ var c = this.length,
+ d = 0;for (cb(arguments); d < c;) {
+ if (d in this && !a.call(b, this[d], d, this)) return !1;d++;
+ }return !0;
+ }, some: function some(a, b) {
+ var c = this.length,
+ d = 0;for (cb(arguments); d < c;) {
+ if (d in this && a.call(b, this[d], d, this)) return !0;d++;
+ }return !1;
+ }, map: function map(a, b) {
+ b = arguments[1];var c = this.length,
+ d = 0,
+ e = Array(c);for (cb(arguments); d < c;) {
+ d in this && (e[d] = a.call(b, this[d], d, this)), d++;
+ }return e;
+ }, filter: function filter(a) {
+ var b = arguments[1],
+ c = this.length,
+ d = 0,
+ e = [];for (cb(arguments); d < c;) {
+ d in this && a.call(b, this[d], d, this) && e.push(this[d]), d++;
+ }return e;
+ }, indexOf: function indexOf(a, b) {
+ return z(this) ? this.indexOf(a, b) : ab(this, a, b, 1);
+ }, lastIndexOf: function lastIndexOf(a, b) {
+ return z(this) ? this.lastIndexOf(a, b) : ab(this, a, b, -1);
+ }, forEach: function forEach(a, b) {
+ var c = this.length,
+ d = 0;for (ta(a); d < c;) {
+ d in this && a.call(b, this[d], d, this), d++;
+ }
+ }, reduce: function reduce(a, b) {
+ return bb(this, a, b);
+ }, reduceRight: function reduceRight(a, b) {
+ return bb(this, a, b, !0);
+ } });
+ H(Function, !0, !1, { bind: function bind(a) {
+ var b = this,
+ c = L(arguments, null, 1),
+ d;if (!F(this)) throw new TypeError("Function.prototype.bind called on a non-function");d = function d() {
+ return b.apply(b.prototype && this instanceof b ? this : a, c.concat(L(arguments)));
+ };d.prototype = this.prototype;return d;
+ } });H(r, !1, !1, { now: function now() {
+ return new r().getTime();
+ } });
+ (function () {
+ var a = Ma().match(/^\s+$/);try {
+ s.prototype.trim.call([1]);
+ } catch (b) {
+ a = !1;
+ }H(s, !0, !a, { trim: function trim() {
+ return this.toString().trimLeft().trimRight();
+ }, trimLeft: function trimLeft() {
+ return this.replace(q("^[" + Ma() + "]+"), "");
+ }, trimRight: function trimRight() {
+ return this.replace(q("[" + Ma() + "]+$"), "");
+ } });
+ })();
+ (function () {
+ var a = new r(r.UTC(1999, 11, 31)),
+ a = a.toISOString && "1999-12-31T00:00:00.000Z" === a.toISOString();K(r, !0, !a, "toISOString,toJSON", function (a, c) {
+ a[c] = function () {
+ return T(this.getUTCFullYear(), 4) + "-" + T(this.getUTCMonth() + 1, 2) + "-" + T(this.getUTCDate(), 2) + "T" + T(this.getUTCHours(), 2) + ":" + T(this.getUTCMinutes(), 2) + ":" + T(this.getUTCSeconds(), 2) + "." + T(this.getUTCMilliseconds(), 3) + "Z";
+ };
+ });
+ })();
+ "use strict";
+ var W,
+ Ib,
+ Jb = "ampm hour minute second ampm utc offset_sign offset_hours offset_minutes ampm".split(" "),
+ Kb = "({t})?\\s*(\\d{1,2}(?:[,.]\\d+)?)(?:{h}([0-5]\\d(?:[,.]\\d+)?)?{m}(?::?([0-5]\\d(?:[,.]\\d+)?){s})?\\s*(?:({t})|(Z)|(?:([+-])(\\d{2,2})(?::?(\\d{2,2}))?)?)?|\\s*({t}))",
+ Lb = {},
+ Mb,
+ Nb,
+ Ob,
+ Pb = [],
+ Qb = {},
+ X = { yyyy: function yyyy(a) {
+ return U(a, "FullYear");
+ }, yy: function yy(a) {
+ return U(a, "FullYear") % 100;
+ }, ord: function ord(a) {
+ a = U(a, "Date");return a + Pa(a);
+ }, tz: function tz(a) {
+ return a.getUTCOffset();
+ }, isotz: function isotz(a) {
+ return a.getUTCOffset(!0);
+ },
+ Z: function Z(a) {
+ return a.getUTCOffset();
+ }, ZZ: function ZZ(a) {
+ return a.getUTCOffset().replace(/(\d{2})$/, ":$1");
+ } },
+ Rb = [{ name: "year", method: "FullYear", k: !0, b: function b(a) {
+ return 864E5 * (365 + (a ? a.isLeapYear() ? 1 : 0 : 0.25));
+ } }, { name: "month", error: 0.919, method: "Month", k: !0, b: function b(a, _b) {
+ var c = 30.4375,
+ d;a && (d = a.daysInMonth(), _b <= d.days() && (c = d));return 864E5 * c;
+ } }, { name: "week", method: "ISOWeek", b: aa(6048E5) }, { name: "day", error: 0.958, method: "Date", k: !0, b: aa(864E5) }, { name: "hour", method: "Hours", b: aa(36E5) }, { name: "minute",
+ method: "Minutes", b: aa(6E4) }, { name: "second", method: "Seconds", b: aa(1E3) }, { name: "millisecond", method: "Milliseconds", b: aa(1) }],
+ Sb = {};function Tb(a) {
+ xa(this, a);this.g = Pb.concat();
+ }
+ Tb.prototype = { getMonth: function getMonth(a) {
+ return y(a) ? a - 1 : this.months.indexOf(a) % 12;
+ }, getWeekday: function getWeekday(a) {
+ return this.weekdays.indexOf(a) % 7;
+ }, addFormat: function addFormat(a, b, c, d, e) {
+ var g = c || [],
+ f = this,
+ h;a = a.replace(/\s+/g, "[,. ]*");a = a.replace(/\{([^,]+?)\}/g, function (a, b) {
+ var d,
+ e,
+ h,
+ B = b.match(/\?$/);h = b.match(/^(\d+)\??$/);var k = b.match(/(\d)(?:-(\d))?/),
+ E = b.replace(/[^a-z]+$/, "");h ? d = f.tokens[h[1]] : f[E] ? d = f[E] : f[E + "s"] && (d = f[E + "s"], k && (e = [], d.forEach(function (a, b) {
+ var c = b % (f.units ? 8 : d.length);c >= k[1] && c <= (k[2] || k[1]) && e.push(a);
+ }), d = e), d = Ub(d));h ? h = "(?:" + d + ")" : (c || g.push(E), h = "(" + d + ")");B && (h += "?");return h;
+ });b ? (b = Vb(f, e), e = ["t", "[\\s\\u3000]"].concat(f.timeMarker), h = a.match(/\\d\{\d,\d\}\)+\??$/), Wb(f, "(?:" + b + ")[,\\s\\u3000]+?" + a, Jb.concat(g), d), Wb(f, a + "(?:[,\\s]*(?:" + e.join("|") + (h ? "+" : "*") + ")" + b + ")?", g.concat(Jb), d)) : Wb(f, a, g, d);
+ } };
+ function Xb(a, b, c) {
+ var d,
+ e,
+ g = b[0],
+ f = b[1],
+ h = b[2];b = a[c] || a.relative;if (F(b)) return b.call(a, g, f, h, c);e = a.units[8 * (a.plural && 1 < g ? 1 : 0) + f] || a.units[f];a.capitalizeUnit && (e = Yb(e));d = a.modifiers.filter(function (a) {
+ return "sign" == a.name && a.value == (0 < h ? 1 : -1);
+ })[0];return b.replace(/\{(.*?)\}/g, function (a, b) {
+ switch (b) {case "num":
+ return g;case "unit":
+ return e;case "sign":
+ return d.src;}
+ });
+ }function Zb(a, b) {
+ b = b || a.code;return "en" === b || "en-US" === b ? !0 : a.variant;
+ }
+ function $b(a, b) {
+ return b.replace(q(a.num, "g"), function (b) {
+ return ac(a, b) || "";
+ });
+ }function ac(a, b) {
+ var c;return y(b) ? b : b && -1 !== (c = a.numbers.indexOf(b)) ? (c + 1) % 10 : 1;
+ }function Y(a, b) {
+ var c;z(a) || (a = "");c = Sb[a] || Sb[a.slice(0, 2)];if (!1 === b && !c) throw new TypeError("Invalid locale.");return c || Ib;
+ }
+ function bc(a, b) {
+ function c(a) {
+ var b = h[a];z(b) ? h[a] = b.split(",") : b || (h[a] = []);
+ }function d(a, b) {
+ a = a.split("+").map(function (a) {
+ return a.replace(/(.+):(.+)$/, function (a, b, c) {
+ return c.split("|").map(function (a) {
+ return b + a;
+ }).join("|");
+ });
+ }).join("|");a.split("|").forEach(b);
+ }function e(a, b, c) {
+ var e = [];h[a].forEach(function (a, f) {
+ b && (a += "+" + a.slice(0, 3));d(a, function (a, b) {
+ e[b * c + f] = a.toLowerCase();
+ });
+ });h[a] = e;
+ }function g(a, b, c) {
+ a = "\\d{" + a + "," + b + "}";c && (a += "|(?:" + Ub(h.numbers) + ")+");return a;
+ }function f(a, b) {
+ h[a] = h[a] || b;
+ }var h, l;h = new Tb(b);c("modifiers");"months weekdays units numbers articles tokens timeMarker ampm timeSuffixes dateParse timeParse".split(" ").forEach(c);l = !h.monthSuffix;e("months", l, 12);e("weekdays", l, 7);e("units", !1, 8);e("numbers", !1, 10);f("code", a);f("date", g(1, 2, h.digitDate));f("year", "'\\d{2}|" + g(4, 4));f("num", function () {
+ var a = ["-?\\d+"].concat(h.articles);h.numbers && (a = a.concat(h.numbers));return Ub(a);
+ }());(function () {
+ var a = [];h.i = {};h.modifiers.push({ name: "day", src: "yesterday", value: -1 });
+ h.modifiers.push({ name: "day", src: "today", value: 0 });h.modifiers.push({ name: "day", src: "tomorrow", value: 1 });h.modifiers.forEach(function (b) {
+ var c = b.name;d(b.src, function (d) {
+ var e = h[c];h.i[d] = b;a.push({ name: c, src: d, value: b.value });h[c] = e ? e + "|" + d : d;
+ });
+ });h.day += "|" + Ub(h.weekdays);h.modifiers = a;
+ })();h.monthSuffix && (h.month = g(1, 2), h.months = "1 2 3 4 5 6 7 8 9 10 11 12".split(" ").map(function (a) {
+ return a + h.monthSuffix;
+ }));h.full_month = g(1, 2) + "|" + Ub(h.months);0 < h.timeSuffixes.length && h.addFormat(Vb(h), !1, Jb);
+ h.addFormat("{day}", !0);h.addFormat("{month}" + (h.monthSuffix || ""));h.addFormat("{year}" + (h.yearSuffix || ""));h.timeParse.forEach(function (a) {
+ h.addFormat(a, !0);
+ });h.dateParse.forEach(function (a) {
+ h.addFormat(a);
+ });return Sb[a] = h;
+ }function Wb(a, b, c, d) {
+ a.g.unshift({ r: d, locale: a, q: q("^" + b + "$", "i"), to: c });
+ }function Yb(a) {
+ return a.slice(0, 1).toUpperCase() + a.slice(1);
+ }function Ub(a) {
+ return a.filter(function (a) {
+ return !!a;
+ }).join("|");
+ }function cc() {
+ var a = r.SugarNewDate;return a ? a() : new r();
+ }
+ function dc(a, b) {
+ var c;if (G(a[0])) return a;if (y(a[0]) && !y(a[1])) return [a[0]];if (z(a[0]) && b) return [ec(a[0]), a[1]];c = {};Nb.forEach(function (b, e) {
+ c[b.name] = a[e];
+ });return [c];
+ }function ec(a) {
+ var b,
+ c = {};if (a = a.match(/^(\d+)?\s?(\w+?)s?$/i)) N(b) && (b = parseInt(a[1]) || 1), c[a[2].toLowerCase()] = b;return c;
+ }function fc(a, b, c) {
+ var d;N(c) && (c = Ob.length);for (b = b || 0; b < c && (d = Ob[b], !1 !== a(d.name, d, b)); b++) {}
+ }
+ function gc(a, b) {
+ var c = {},
+ d,
+ e;b.forEach(function (b, f) {
+ d = a[f + 1];N(d) || "" === d || ("year" === b && (c.t = d.replace(/'/, "")), e = parseFloat(d.replace(/'/, "").replace(/,/, ".")), c[b] = isNaN(e) ? d.toLowerCase() : e);
+ });return c;
+ }function hc(a) {
+ a = a.trim().replace(/^just (?=now)|\.+$/i, "");return ic(a);
+ }
+ function ic(a) {
+ return a.replace(Mb, function (a, c, d) {
+ var e = 0,
+ g = 1,
+ f,
+ h;if (c) return a;d.split("").reverse().forEach(function (a) {
+ a = Lb[a];var b = 9 < a;b ? (f && (e += g), g *= a / (h || 1), h = a) : (!1 === f && (g *= 10), e += g * a);f = b;
+ });f && (e += g);return e;
+ });
+ }
+ function jc(a, b, c, d) {
+ function e(a) {
+ vb.push(a);
+ }function g() {
+ vb.forEach(function (a) {
+ a.call();
+ });
+ }function f() {
+ var a = n.getWeekday();n.setWeekday(7 * (k.num - 1) + (a > Ba ? Ba + 7 : Ba));
+ }function h() {
+ var a = B.i[k.edge];fc(function (a) {
+ if (M(k[a])) return E = a, !1;
+ }, 4);if ("year" === E) k.e = "month";else if ("month" === E || "week" === E) k.e = "day";n[(0 > a.value ? "endOf" : "beginningOf") + Yb(E)]();-2 === a.value && n.reset();
+ }function l() {
+ var a;fc(function (b, c, d) {
+ "day" === b && (b = "date");if (M(k[b])) {
+ if (d >= wb) return n.setTime(NaN), !1;a = a || {};a[b] = k[b];
+ delete k[b];
+ }
+ });a && e(function () {
+ n.set(a, !0);
+ });
+ }var n, x, ha, vb, B, k, E, wb, Ba, ra, ca;n = cc();vb = [];n.utc(d);C(a) ? n.utc(a.isUTC()).setTime(a.getTime()) : y(a) ? n.setTime(a) : G(a) ? (n.set(a, !0), k = a) : z(a) && (ha = Y(b), a = hc(a), ha && I(ha.o ? [ha.o].concat(ha.g) : ha.g, function (c, d) {
+ var g = a.match(d.q);if (g) {
+ B = d.locale;k = gc(g, d.to);B.o = d;k.utc && n.utc();if (k.timestamp) return k = k.timestamp, !1;d.r && !z(k.month) && (z(k.date) || Zb(ha, b)) && (ca = k.month, k.month = k.date, k.date = ca);k.year && 2 === k.t.length && (k.year = 100 * R(U(cc(), "FullYear") / 100) - 100 * R(k.year / 100) + k.year);k.month && (k.month = B.getMonth(k.month), k.shift && !k.unit && (k.unit = B.units[7]));k.weekday && k.date ? delete k.weekday : k.weekday && (k.weekday = B.getWeekday(k.weekday), k.shift && !k.unit && (k.unit = B.units[5]));k.day && (ca = B.i[k.day]) ? (k.day = ca.value, n.reset(), x = !0) : k.day && -1 < (Ba = B.getWeekday(k.day)) && (delete k.day, k.num && k.month ? (e(f), k.day = 1) : k.weekday = Ba);k.date && !y(k.date) && (k.date = $b(B, k.date));k.ampm && k.ampm === B.ampm[1] && 12 > k.hour ? k.hour += 12 : k.ampm === B.ampm[0] && 12 === k.hour && (k.hour = 0);if ("offset_hours" in k || "offset_minutes" in k) n.utc(), k.offset_minutes = k.offset_minutes || 0, k.offset_minutes += 60 * k.offset_hours, "-" === k.offset_sign && (k.offset_minutes *= -1), k.minute -= k.offset_minutes;k.unit && (x = !0, ra = ac(B, k.num), wb = B.units.indexOf(k.unit) % 8, E = W.units[wb], l(), k.shift && (ra *= (ca = B.i[k.shift]) ? ca.value : 0), k.sign && (ca = B.i[k.sign]) && (ra *= ca.value), M(k.weekday) && (n.set({ weekday: k.weekday }, !0), delete k.weekday), k[E] = (k[E] || 0) + ra);k.edge && e(h);"-" === k.year_sign && (k.year *= -1);fc(function (a, b, c) {
+ b = k[a];var d = b % 1;d && (k[Ob[c - 1].name] = R(d * ("second" === a ? 1E3 : 60)), k[a] = Q(b));
+ }, 1, 4);return !1;
+ }
+ }), k ? x ? n.advance(k) : (n._utc && n.reset(), kc(n, k, !0, !1, c)) : ("now" !== a && (n = new r(a)), d && n.addMinutes(-n.getTimezoneOffset())), g(), n.utc(!1));return { c: n, set: k };
+ }function lc(a) {
+ var b,
+ c = P(a),
+ d = c,
+ e = 0;fc(function (a, f, h) {
+ b = Q(Da(c / f.b(), 1));1 <= b && (d = b, e = h);
+ }, 1);return [d, e, a];
+ }
+ function mc(a) {
+ var b = lc(a.millisecondsFromNow());if (6 === b[1] || 5 === b[1] && 4 === b[0] && a.daysFromNow() >= cc().daysInMonth()) b[0] = P(a.monthsFromNow()), b[1] = 6;return b;
+ }function nc(a, b, c) {
+ function d(a, c) {
+ var d = U(a, "Month");return Y(c).months[d + 12 * b];
+ }Z(a, d, c);Z(Yb(a), d, c, 1);
+ }function Z(a, b, c, d) {
+ X[a] = function (a, g) {
+ var f = b(a, g);c && (f = f.slice(0, c));d && (f = f.slice(0, d).toUpperCase() + f.slice(d));return f;
+ };
+ }
+ function oc(a, b, c) {
+ X[a] = b;X[a + a] = function (a, c) {
+ return T(b(a, c), 2);
+ };c && (X[a + a + a] = function (a, c) {
+ return T(b(a, c), 3);
+ }, X[a + a + a + a] = function (a, c) {
+ return T(b(a, c), 4);
+ });
+ }function pc(a) {
+ var b = a.match(/(\{\w+\})|[^{}]+/g);Qb[a] = b.map(function (a) {
+ a.replace(/\{(\w+)\}/, function (b, e) {
+ a = X[e] || e;return e;
+ });return a;
+ });
+ }
+ function qc(a, b, c, d) {
+ var e;if (!a.isValid()) return "Invalid Date";Date[b] ? b = Date[b] : F(b) && (e = mc(a), b = b.apply(a, e.concat(Y(d))));if (!b && c) return e = e || mc(a), 0 === e[1] && (e[1] = 1, e[0] = 1), a = Y(d), Xb(a, e, 0 < e[2] ? "future" : "past");b = b || "long";if ("short" === b || "long" === b || "full" === b) b = Y(d)[b];Qb[b] || pc(b);var g, f;e = "";b = Qb[b];g = 0;for (c = b.length; g < c; g++) {
+ f = b[g], e += F(f) ? f(a, d) : f;
+ }return e;
+ }
+ function rc(a, b, c, d, e) {
+ var g,
+ f,
+ h,
+ l = 0,
+ n = 0,
+ x = 0;g = jc(b, c, null, e);0 < d && (n = x = d, f = !0);if (!g.c.isValid()) return !1;if (g.set && g.set.e) {
+ Rb.forEach(function (b) {
+ b.name === g.set.e && (l = b.b(g.c, a - g.c) - 1);
+ });b = Yb(g.set.e);if (g.set.edge || g.set.shift) g.c["beginningOf" + b]();"month" === g.set.e && (h = g.c.clone()["endOf" + b]().getTime());!f && g.set.sign && "millisecond" != g.set.e && (n = 50, x = -50);
+ }f = a.getTime();b = g.c.getTime();h = sc(a, b, h || b + l);return f >= b - n && f <= h + x;
+ }
+ function sc(a, b, c) {
+ b = new r(b);a = new r(c).utc(a.isUTC());23 !== U(a, "Hours") && (b = b.getTimezoneOffset(), a = a.getTimezoneOffset(), b !== a && (c += (a - b).minutes()));return c;
+ }
+ function kc(a, b, c, d, e) {
+ function g(a) {
+ return M(b[a]) ? b[a] : b[a + "s"];
+ }function f(a) {
+ return M(g(a));
+ }var h;if (y(b) && d) b = { milliseconds: b };else if (y(b)) return a.setTime(b), a;M(b.date) && (b.day = b.date);fc(function (d, e, g) {
+ var l = "day" === d;if (f(d) || l && f("weekday")) return b.e = d, h = +g, !1;!c || "week" === d || l && f("week") || Sa(a, e.method, l ? 1 : 0);
+ });Rb.forEach(function (c) {
+ var e = c.name;c = c.method;var h;h = g(e);N(h) || (d ? ("week" === e && (h = (b.day || 0) + 7 * h, c = "Date"), h = h * d + U(a, c)) : "month" === e && f("day") && Sa(a, "Date", 15), Sa(a, c, h), d && "month" === e && (e = h, 0 > e && (e = e % 12 + 12), e % 12 != U(a, "Month") && Sa(a, "Date", 0)));
+ });d || f("day") || !f("weekday") || a.setWeekday(g("weekday"));var l;a: {
+ switch (e) {case -1:
+ l = a > cc();break a;case 1:
+ l = a < cc();break a;}l = void 0;
+ }l && fc(function (b, c) {
+ if ((c.k || "week" === b && f("weekday")) && !(f(b) || "day" === b && f("weekday"))) return a[c.j](e), !1;
+ }, h + 1);return a;
+ }
+ function Vb(a, b) {
+ var c = Kb,
+ d = { h: 0, m: 1, s: 2 },
+ e;a = a || W;return c.replace(/{([a-z])}/g, function (c, f) {
+ var h = [],
+ l = "h" === f,
+ n = l && !b;if ("t" === f) return a.ampm.join("|");l && h.push(":");(e = a.timeSuffixes[d[f]]) && h.push(e + "\\s*");return 0 === h.length ? "" : "(?:" + h.join("|") + ")" + (n ? "" : "?");
+ });
+ }function tc(a, b, c) {
+ var d, e;y(a[1]) ? d = dc(a)[0] : (d = a[0], e = a[1]);return jc(d, e, b, c).c;
+ }
+ H(r, !1, !0, { create: function create() {
+ return tc(arguments);
+ }, past: function past() {
+ return tc(arguments, -1);
+ }, future: function future() {
+ return tc(arguments, 1);
+ }, addLocale: function addLocale(a, b) {
+ return bc(a, b);
+ }, setLocale: function setLocale(a) {
+ var b = Y(a, !1);Ib = b;a && a != b.code && (b.code = a);return b;
+ }, getLocale: function getLocale(a) {
+ return a ? Y(a, !1) : Ib;
+ }, addFormat: function addFormat(a, b, c) {
+ Wb(Y(c), a, b);
+ } });
+ H(r, !0, !0, { set: function set() {
+ var a = dc(arguments);return kc(this, a[0], a[1]);
+ }, setWeekday: function setWeekday(a) {
+ if (!N(a)) return Sa(this, "Date", U(this, "Date") + a - U(this, "Day"));
+ }, setISOWeek: function setISOWeek(a) {
+ var b = U(this, "Day") || 7;if (!N(a)) return this.set({ month: 0, date: 4 }), this.set({ weekday: 1 }), 1 < a && this.addWeeks(a - 1), 1 !== b && this.advance({ days: b - 1 }), this.getTime();
+ }, getISOWeek: function getISOWeek() {
+ var a;a = this.clone();var b = U(a, "Day") || 7;a.addDays(4 - b).reset();return 1 + Q(a.daysSince(a.clone().beginningOfYear()) / 7);
+ }, beginningOfISOWeek: function beginningOfISOWeek() {
+ var a = this.getDay();0 === a ? a = -6 : 1 !== a && (a = 1);this.setWeekday(a);return this.reset();
+ }, endOfISOWeek: function endOfISOWeek() {
+ 0 !== this.getDay() && this.setWeekday(7);return this.endOfDay();
+ }, getUTCOffset: function getUTCOffset(a) {
+ var b = this._utc ? 0 : this.getTimezoneOffset(),
+ c = !0 === a ? ":" : "";return !b && a ? "Z" : T(Q(-b / 60), 2, !0) + c + T(P(b % 60), 2);
+ }, utc: function utc(a) {
+ oa(this, "_utc", !0 === a || 0 === arguments.length);return this;
+ }, isUTC: function isUTC() {
+ return !!this._utc || 0 === this.getTimezoneOffset();
+ }, advance: function advance() {
+ var a = dc(arguments, !0);return kc(this, a[0], a[1], 1);
+ }, rewind: function rewind() {
+ var a = dc(arguments, !0);return kc(this, a[0], a[1], -1);
+ }, isValid: function isValid() {
+ return !isNaN(this.getTime());
+ }, isAfter: function isAfter(a, b) {
+ return this.getTime() > r.create(a).getTime() - (b || 0);
+ }, isBefore: function isBefore(a, b) {
+ return this.getTime() < r.create(a).getTime() + (b || 0);
+ }, isBetween: function isBetween(a, b, c) {
+ var d = this.getTime();a = r.create(a).getTime();var e = r.create(b).getTime();b = Ca(a, e);a = S(a, e);c = c || 0;return b - c < d && a + c > d;
+ }, isLeapYear: function isLeapYear() {
+ var a = U(this, "FullYear");return 0 === a % 4 && 0 !== a % 100 || 0 === a % 400;
+ },
+ daysInMonth: function daysInMonth() {
+ return 32 - U(new r(U(this, "FullYear"), U(this, "Month"), 32), "Date");
+ }, format: function format(a, b) {
+ return qc(this, a, !1, b);
+ }, relative: function relative(a, b) {
+ z(a) && (b = a, a = null);return qc(this, a, !0, b);
+ }, is: function is(a, b, c) {
+ var d, e;if (this.isValid()) {
+ if (z(a)) switch (a = a.trim().toLowerCase(), e = this.clone().utc(c), !0) {case "future" === a:
+ return this.getTime() > cc().getTime();case "past" === a:
+ return this.getTime() < cc().getTime();case "weekday" === a:
+ return 0 < U(e, "Day") && 6 > U(e, "Day");case "weekend" === a:
+ return 0 === U(e, "Day") || 6 === U(e, "Day");case -1 < (d = W.weekdays.indexOf(a) % 7):
+ return U(e, "Day") === d;case -1 < (d = W.months.indexOf(a) % 12):
+ return U(e, "Month") === d;}return rc(this, a, null, b, c);
+ }
+ }, reset: function reset(a) {
+ var b = {},
+ c;a = a || "hours";"date" === a && (a = "days");c = Rb.some(function (b) {
+ return a === b.name || a === b.name + "s";
+ });b[a] = a.match(/^days?/) ? 1 : 0;return c ? this.set(b, !0) : this;
+ }, clone: function clone() {
+ var a = new r(this.getTime());a.utc(!!this._utc);return a;
+ } });
+ H(r, !0, !0, { iso: function iso() {
+ return this.toISOString();
+ }, getWeekday: r.prototype.getDay, getUTCWeekday: r.prototype.getUTCDay });function uc(a, b) {
+ function c() {
+ return R(this * b);
+ }function d() {
+ return tc(arguments)[a.j](this);
+ }function e() {
+ return tc(arguments)[a.j](-this);
+ }var g = a.name,
+ f = {};f[g] = c;f[g + "s"] = c;f[g + "Before"] = e;f[g + "sBefore"] = e;f[g + "Ago"] = e;f[g + "sAgo"] = e;f[g + "After"] = d;f[g + "sAfter"] = d;f[g + "FromNow"] = d;f[g + "sFromNow"] = d;t.extend(f);
+ }H(t, !0, !0, { duration: function duration(a) {
+ a = Y(a);return Xb(a, lc(this), "duration");
+ } });
+ W = Ib = r.addLocale("en", { plural: !0, timeMarker: "at", ampm: "am,pm", months: "January,February,March,April,May,June,July,August,September,October,November,December", weekdays: "Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday", units: "millisecond:|s,second:|s,minute:|s,hour:|s,day:|s,week:|s,month:|s,year:|s", numbers: "one,two,three,four,five,six,seven,eight,nine,ten", articles: "a,an,the", tokens: "the,st|nd|rd|th,of", "short": "{Month} {d}, {yyyy}", "long": "{Month} {d}, {yyyy} {h}:{mm}{tt}", full: "{Weekday} {Month} {d}, {yyyy} {h}:{mm}:{ss}{tt}",
+ past: "{num} {unit} {sign}", future: "{num} {unit} {sign}", duration: "{num} {unit}", modifiers: [{ name: "sign", src: "ago|before", value: -1 }, { name: "sign", src: "from now|after|from|in|later", value: 1 }, { name: "edge", src: "last day", value: -2 }, { name: "edge", src: "end", value: -1 }, { name: "edge", src: "first day|beginning", value: 1 }, { name: "shift", src: "last", value: -1 }, { name: "shift", src: "the|this", value: 0 }, { name: "shift", src: "next", value: 1 }], dateParse: ["{month} {year}", "{shift} {unit=5-7}", "{0?} {date}{1}", "{0?} {edge} of {shift?} {unit=4-7?}{month?}{year?}"],
+ timeParse: "{num} {unit} {sign};{sign} {num} {unit};{0} {num}{1} {day} of {month} {year?};{weekday?} {month} {date}{1?} {year?};{date} {month} {year};{date} {month};{shift} {weekday};{shift} week {weekday};{weekday} {2?} {shift} week;{num} {unit=4-5} {sign} {day};{0?} {date}{1} of {month};{0?}{month?} {date?}{1?} of {shift} {unit=6-7}".split(";") });Ob = Rb.concat().reverse();Nb = Rb.concat();Nb.splice(2, 1);
+ K(r, !0, !0, Rb, function (a, b, c) {
+ function d(a) {
+ a /= f;var c = a % 1,
+ d = b.error || 0.999;c && P(c % 1) > d && (a = R(a));return 0 > a ? Aa(a) : Q(a);
+ }var e = b.name,
+ g = Yb(e),
+ f = b.b(),
+ h,
+ l;b.j = "add" + g + "s";h = function h(a, b) {
+ return d(this.getTime() - r.create(a, b).getTime());
+ };l = function l(a, b) {
+ return d(r.create(a, b).getTime() - this.getTime());
+ };a[e + "sAgo"] = l;a[e + "sUntil"] = l;a[e + "sSince"] = h;a[e + "sFromNow"] = h;a[b.j] = function (a, b) {
+ var c = {};c[e] = a;return this.advance(c, b);
+ };uc(b, f);3 > c && ["Last", "This", "Next"].forEach(function (b) {
+ a["is" + b + g] = function () {
+ return rc(this, b + " " + e, "en");
+ };
+ });4 > c && (a["beginningOf" + g] = function () {
+ var a = {};switch (e) {case "year":
+ a.year = U(this, "FullYear");break;case "month":
+ a.month = U(this, "Month");break;case "day":
+ a.day = U(this, "Date");break;case "week":
+ a.weekday = 0;}return this.set(a, !0);
+ }, a["endOf" + g] = function () {
+ var a = { hours: 23, minutes: 59, seconds: 59, milliseconds: 999 };switch (e) {case "year":
+ a.month = 11;a.day = 31;break;case "month":
+ a.day = this.daysInMonth();break;case "week":
+ a.weekday = 6;}return this.set(a, !0);
+ });
+ });
+ W.addFormat("([+-])?(\\d{4,4})[-.]?{full_month}[-.]?(\\d{1,2})?", !0, ["year_sign", "year", "month", "date"], !1, !0);W.addFormat("(\\d{1,2})[-.\\/]{full_month}(?:[-.\\/](\\d{2,4}))?", !0, ["date", "month", "year"], !0);W.addFormat("{full_month}[-.](\\d{4,4})", !1, ["month", "year"]);W.addFormat("\\/Date\\((\\d+(?:[+-]\\d{4,4})?)\\)\\/", !1, ["timestamp"]);W.addFormat(Vb(W), !1, Jb);Pb = W.g.slice(0, 7).reverse();W.g = W.g.slice(7).concat(Pb);oc("f", function (a) {
+ return U(a, "Milliseconds");
+ }, !0);
+ oc("s", function (a) {
+ return U(a, "Seconds");
+ });oc("m", function (a) {
+ return U(a, "Minutes");
+ });oc("h", function (a) {
+ return U(a, "Hours") % 12 || 12;
+ });oc("H", function (a) {
+ return U(a, "Hours");
+ });oc("d", function (a) {
+ return U(a, "Date");
+ });oc("M", function (a) {
+ return U(a, "Month") + 1;
+ });(function () {
+ function a(a, c) {
+ var d = U(a, "Hours");return Y(c).ampm[Q(d / 12)] || "";
+ }Z("t", a, 1);Z("tt", a);Z("T", a, 1, 1);Z("TT", a, null, 2);
+ })();
+ /* istanbul ignore next */
+ (function () {
+ function a(a, c) {
+ var d = U(a, "Day");return Y(c).weekdays[d];
+ }Z("dow", a, 3);Z("Dow", a, 3, 1);Z("weekday", a);Z("Weekday", a, null, 1);
+ })();nc("mon", 0, 3);nc("month", 0);nc("month2", 1);nc("month3", 2);X.ms = X.f;X.milliseconds = X.f;X.seconds = X.s;X.minutes = X.m;X.hours = X.h;X["24hr"] = X.H;X["12hr"] = X.h;X.date = X.d;X.day = X.d;X.year = X.yyyy;K(r, !0, !0, "short,long,full", function (a, b) {
+ a[b] = function (a) {
+ return qc(this, b, !1, a);
+ };
+ });
+ "〇一二三四五六七八九十百千万".split("").forEach(function (a, b) {
+ 9 < b && (b = za(10, b - 9));Lb[a] = b;
+ });xa(Lb, Ka);Mb = q("([期週周])?([〇一二三四五六七八九十百千万" + Ja + "]+)(?!昨)", "g");
+ /* istanbul ignore next */
+ (function () {
+ var a = W.weekdays.slice(0, 7),
+ b = W.months.slice(0, 12);K(r, !0, !0, "today yesterday tomorrow weekday weekend future past".split(" ").concat(a).concat(b), function (a, b) {
+ a["is" + Yb(b)] = function (a) {
+ return this.is(b, 0, a);
+ };
+ });
+ })();r.utc || (r.utc = { create: function create() {
+ return tc(arguments, 0, !0);
+ }, past: function past() {
+ return tc(arguments, -1, !0);
+ }, future: function future() {
+ return tc(arguments, 1, !0);
+ } });
+ H(r, !1, !0, { RFC1123: "{Dow}, {dd} {Mon} {yyyy} {HH}:{mm}:{ss} {tz}", RFC1036: "{Weekday}, {dd}-{Mon}-{yy} {HH}:{mm}:{ss} {tz}", ISO8601_DATE: "{yyyy}-{MM}-{dd}", ISO8601_DATETIME: "{yyyy}-{MM}-{dd}T{HH}:{mm}:{ss}.{fff}{isotz}" });
+})();
45 packages/touch/dist/util/interfacer.js
@@ -0,0 +1,45 @@
+'use strict';
+
+/**
+ * Simple binding interface between
+ * each command's function and the caller
+ * of the command, whether by `cash.command`
+ * or by being invoked by Vorpal.
+ * This exists to abstract complexity
+ * and create a standard in interfacing
+ * commands acorss muliple execution paths.
+ *
+ * @param {Object} opt
+ * @api public
+ */
+
+module.exports = function (opt) {
+ var self = this;
+ var stdout = '';
+ opt.options = opt.options || {};
+ opt.callback = opt.callback || function () {};
+ opt.command = opt.command || {
+ exec: function exec() {}
+ };
+
+ var logger = {
+ log: function log(out) {
+ stdout += out + '\n';
+ if (opt.silent !== true) {
+ // process.stdout.write(out) // to do - handle newline problem.
+ self.log(out);
+ }
+ }
+ };
+
+ function onResult(result) {
+ result = result === undefined ? 0 : result;
+ opt.callback(null, stdout);
+ return stdout;
+ }
+
+ if (opt.async === true) {
+ return opt.command.exec.call(logger, opt.args, opt.options, onResult);
+ }
+ return onResult(opt.command.exec.call(logger, opt.args, opt.options));
+};
51 packages/touch/package.json
@@ -0,0 +1,51 @@
+{
+ "name": "cash-touch",
+ "version": "0.1.0",
+ "description": "Cross-platform implementation of the Unix 'touch' command.",
+ "main": "./dist/commands/touch.js",
+ "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": {
+ "touch": "./bin/touch.js"
+ },
+ "dependencies": {
+ "lodash": "^4.0.0",
+ "fs-extra": "^0.23.1",
+ "vorpal-autocomplete-fs": "0.0.3",
+ "vorpal": "^1.9.5"
+ },
+ "engines": {
+ "node": ">= 0.11.16",
+ "iojs": ">= 1.0.0"
+ },
+ "files": [
+ "dist",
+ "bin"
+ ]
+}
113 src/commands/alias.js
@@ -0,0 +1,113 @@
+'use strict';
+
+const _ = require('lodash');
+
+const interfacer = require('./../util/interfacer');
+
+const alias = {
+
+ exec(args, options) {
+ args = args || [];
+ options = options || {};
+ const vorpal = options.vorpal;
+
+ if (!vorpal) {
+ throw new Error('Alias is not programatically supported.');
+ }
+
+ vorpal._aliases = vorpal._aliases || [];
+
+ if (args.length < 1) {
+ options.p = true;
+ }
+
+ if (_.isString(args)) {
+ args = [args];
+ }
+
+ // Parse incoming args. Accept either:
+ // alias foo=bar, or
+ // alias foo 'bar and so on'.
+ let key = args.join(' ');
+ let value;
+ if (String(key).indexOf('=') > -1) {
+ const parts = String(key).trim().split('=');
+ key = parts[0];
+ value = parts[1] || value;
+ } else {
+ const parts = String(key).trim().split(' ');
+ key = parts.shift();
+ value = parts.join(' ');
+ }
+
+ // Remove wrapped quotes from value.
+ if (value !== undefined) {
+ value = String(value).replace(/^[\"|\']|[\"|\']$/g, '');
+ }
+
+ // Pull list of aliases
+ let all;
+ try {
+ all = JSON.parse(vorpal.localStorage.getItem('aliases') || []);
+ } catch (e) {
+ all = [];
+ vorpal.localStorage.removeItem('aliases');
+ }
+
+ if (options.p) {
+ for (let i = 0; i < all.length; ++i) {
+ const item = vorpal.localStorage.getItem(`alias|${all[i]}`);
+ if (item !== undefined && item !== null) {
+ this.log(`alias ${all[i]}='${item}'`);
+ }
+ }
+ } else {
+ if (value) {
+ vorpal.localStorage.setItem(`alias|${key}`, value);
+ _.remove(all, function (val) {
+ return val === key;
+ });
+ all.push(key);
+ } else {
+ const item = vorpal.localStorage.getItem(`alias|${key}`);
+ if (item !== undefined && item !== null) {
+ this.log(`alias ${key}='${item}'`);
+ } else {
+ this.log(`-cash: alias: ${key}: not found`);
+ }
+ }
+
+ const aliases = {};
+ for (let i = 0; i < all.length; ++i) {
+ const item = vorpal.localStorage.getItem(`alias|${all[i]}`);
+ if (item !== undefined && item !== null) {
+ aliases[all[i]] = item;
+ }
+ }
+ vorpal._aliases = aliases;
+ }
+
+ vorpal.localStorage.setItem('aliases', JSON.stringify(all));
+ return 0;
+ }
+};
+
+module.exports = function (vorpal) {
+ if (vorpal === undefined) {
+ return alias;
+ }
+ vorpal.api.alias = alias;
+ vorpal
+ .command('alias [name...]')
+ .option('-p', 'print all defined aliases in a reusable format')
+ .action(function (args, callback) {
+ args.options = args.options || {};
+ args.options.vorpal = vorpal;
+ return interfacer.call(this, {
+ command: alias,
+ args: args.name,
+ options: args.options,
+ callback
+ });
+ });
+};
0 src/commands/boilerplate.js
Sorry, we could not display the changes to this file because there were too many other changes to display.
0 src/commands/cat.js
Sorry, we could not display the changes to this file because there were too many other changes to display.
0 src/commands/cd.js
Sorry, we could not display the changes to this file because there were too many other changes to display.
0 src/commands/cp.js
Sorry, we could not display the changes to this file because there were too many other changes to display.
0 src/commands/echo.js
Sorry, we could not display the changes to this file because there were too many other changes to display.
0 src/commands/grep.js
Sorry, we could not display the changes to this file because there were too many other changes to display.
0 src/commands/kill.js
Sorry, we could not display the changes to this file because there were too many other changes to display.
0 src/commands/less.js
Sorry, we could not display the changes to this file because there were too many other changes to display.
0 src/commands/ls.js
Sorry, we could not display the changes to this file because there were too many other changes to display.
0 src/commands/mkdir.js
Sorry, we could not display the changes to this file because there were too many other changes to display.
0 src/commands/mv.js
Sorry, we could not display the changes to this file because there were too many other changes to display.
0 src/commands/pwd.js
Sorry, we could not display the changes to this file because there were too many other changes to display.
0 src/commands/rm.js
Sorry, we could not display the changes to this file because there were too many other changes to display.
0 src/commands/sort.js
Sorry, we could not display the changes to this file because there were too many other changes to display.
0 src/commands/touch.js
Sorry, we could not display the changes to this file because there were too many other changes to display.
0 src/commands/unalias.js
Sorry, we could not display the changes to this file because there were too many other changes to display.
0 src/delimiter.js
Sorry, we could not display the changes to this file because there were too many other changes to display.
0 src/help.js
Sorry, we could not display the changes to this file because there were too many other changes to display.
0 src/help/alias.js
Sorry, we could not display the changes to this file because there were too many other changes to display.
0 src/help/cat.js
Sorry, we could not display the changes to this file because there were too many other changes to display.
0 src/help/cd.js
Sorry, we could not display the changes to this file because there were too many other changes to display.
0 src/help/cp.js
Sorry, we could not display the changes to this file because there were too many other changes to display.
0 src/help/echo.js
Sorry, we could not display the changes to this file because there were too many other changes to display.
0 src/help/grep.js
Sorry, we could not display the changes to this file because there were too many other changes to display.
0 src/help/kill.js
Sorry, we could not display the changes to this file because there were too many other changes to display.
0 src/help/ls.js
Sorry, we could not display the changes to this file because there were too many other changes to display.
0 src/help/mkdir.js
Sorry, we could not display the changes to this file because there were too many other changes to display.
0 src/help/mv.js
Sorry, we could not display the changes to this file because there were too many other changes to display.
0 src/help/pwd.js
Sorry, we could not display the changes to this file because there were too many other changes to display.
0 src/help/rm.js
Sorry, we could not display the changes to this file because there were too many other changes to display.
0 src/help/sort.js
Sorry, we could not display the changes to this file because there were too many other changes to display.
0 src/help/touch.js
Sorry, we could not display the changes to this file because there were too many other changes to display.
0 src/help/unalias.js
Sorry, we could not display the changes to this file because there were too many other changes to display.
0 src/index.js
Sorry, we could not display the changes to this file because there were too many other changes to display.
0 src/lib/sugar.js
Sorry, we could not display the changes to this file because there were too many other changes to display.
0 src/util/colorFile.js
Sorry, we could not display the changes to this file because there were too many other changes to display.
0 src/util/columnify.js
Sorry, we could not display the changes to this file because there were too many other changes to display.
0 src/util/converter.date.js
Sorry, we could not display the changes to this file because there were too many other changes to display.
0 src/util/converter.path.js
Sorry, we could not display the changes to this file because there were too many other changes to display.
0 src/util/converter.permissions.js
Sorry, we could not display the changes to this file because there were too many other changes to display.
0 src/util/expand.js
Sorry, we could not display the changes to this file because there were too many other changes to display.
0 src/util/fetch.js
Sorry, we could not display the changes to this file because there were too many other changes to display.
0 src/util/fileFromPath.js
Sorry, we could not display the changes to this file because there were too many other changes to display.
0 src/util/intercept.js
Sorry, we could not display the changes to this file because there were too many other changes to display.
0 src/util/interfacer.js
Sorry, we could not display the changes to this file because there were too many other changes to display.
0 src/util/lpad.js
Sorry, we could not display the changes to this file because there were too many other changes to display.
0 src/util/pad.js
Sorry, we could not display the changes to this file because there were too many other changes to display.
0 src/util/stripAnsi.js
Sorry, we could not display the changes to this file because there were too many other changes to display.
0 src/util/unlinkSync.js
Sorry, we could not display the changes to this file because there were too many other changes to display.
0 src/util/walkDir.js
Sorry, we could not display the changes to this file because there were too many other changes to display.
0 src/util/walkDirRecursive.js
Sorry, we could not display the changes to this file because there were too many other changes to display.
0 src/windows.js
Sorry, we could not display the changes to this file because there were too many other changes to display.
0 test/alias.js
Sorry, we could not display the changes to this file because there were too many other changes to display.
0 test/cat.js
Sorry, we could not display the changes to this file because there were too many other changes to display.
0 test/cd.js
Sorry, we could not display the changes to this file because there were too many other changes to display.
0 test/cp.js
Sorry, we could not display the changes to this file because there were too many other changes to display.
0 test/echo.js
Sorry, we could not display the changes to this file because there were too many other changes to display.
0 test/help.js
Sorry, we could not display the changes to this file because there were too many other changes to display.
0 test/kill.js
Sorry, we could not display the changes to this file because there were too many other changes to display.
0 test/ls.js
Sorry, we could not display the changes to this file because there were too many other changes to display.
0 test/mkdir.js
Sorry, we could not display the changes to this file because there were too many other changes to display.
0 test/mv.js
Sorry, we could not display the changes to this file because there were too many other changes to display.
0 test/pwd.js
Sorry, we could not display the changes to this file because there were too many other changes to display.
0 test/rm.js
Sorry, we could not display the changes to this file because there were too many other changes to display.
0 test/sort.js
Sorry, we could not display the changes to this file because there were too many other changes to display.
0 test/touch.js
Sorry, we could not display the changes to this file because there were too many other changes to display.
0 test/unalias.js
Sorry, we could not display the changes to this file because there were too many other changes to display.
0 test/util/playground.js
Sorry, we could not display the changes to this file because there were too many other changes to display.
0 test/util/util.js
Sorry, we could not display the changes to this file because there were too many other changes to display.
0 test/vorpal.js
Sorry, we could not display the changes to this file because there were too many other changes to display.
0 test/windows.js
Sorry, we could not display the changes to this file because there were too many other changes to display.

0 comments on commit a8d0eab

Please sign in to comment.
Something went wrong with that request. Please try again.