├── .gitattributes ├── bin ├── run.cmd └── run ├── docs ├── res │ ├── favicon.ico │ ├── icon-256.png │ └── screenshot.png ├── css │ ├── main.css │ └── vendor │ │ └── bulma.min.css ├── js │ ├── index.js │ └── vendor │ │ └── maker-link.min.js └── index.html ├── .eslintrc ├── .npmignore ├── .gitignore ├── .travis.yml ├── .editorconfig ├── LICENSE.md ├── package.json ├── src ├── utils │ └── index.js └── index.js ├── README.md └── test └── test.js /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto 2 | *.js text eol=lf 3 | -------------------------------------------------------------------------------- /bin/run.cmd: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | node "%~dp0\run" %* 4 | -------------------------------------------------------------------------------- /docs/res/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cedricium/should-i-cli/HEAD/docs/res/favicon.ico -------------------------------------------------------------------------------- /docs/res/icon-256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cedricium/should-i-cli/HEAD/docs/res/icon-256.png -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "google", 3 | "parserOptions": { 4 | "ecmaVersion": 8 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | # Dot directories + files 2 | .editorconfig 3 | .eslintrc 4 | .gitattributes 5 | .gitignore 6 | -------------------------------------------------------------------------------- /bin/run: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | require('..').run() 4 | .catch(require('@oclif/errors/handle')) 5 | -------------------------------------------------------------------------------- /docs/res/screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cedricium/should-i-cli/HEAD/docs/res/screenshot.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *-debug.log 2 | *-error.log 3 | /.nyc_output 4 | /dist 5 | /tmp 6 | /yarn.lock 7 | node_modules 8 | bin/run.* 9 | !bin/run.cmd -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | 3 | node_js: 4 | - '8' 5 | 6 | before_install: if [[ `npm -v` != 4* ]]; then npm i -g npm@4; fi 7 | 8 | cache: 9 | directories: 10 | - node_modules 11 | 12 | sudo: false 13 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 2 6 | charset = utf-8 7 | trim_trailing_whitespace = true 8 | insert_final_newline = true 9 | 10 | [*.md] 11 | trim_trailing_whitespace = false 12 | -------------------------------------------------------------------------------- /docs/css/main.css: -------------------------------------------------------------------------------- 1 | div.notification.notification-producthunt { 2 | border-radius: 0 !important; 3 | background: #da552f; 4 | } 5 | 6 | p.install-text code { 7 | border-radius: 5px; 8 | padding: 0.75rem; 9 | } 10 | 11 | p.install-text code::before { 12 | content: '$ '; 13 | } 14 | 15 | p.install-text code:hover { 16 | cursor: text; 17 | } 18 | 19 | p.install-text code:hover span { 20 | background: pink; 21 | } 22 | 23 | .hero .hero-foot { 24 | margin-bottom: 1rem; 25 | } 26 | 27 | #madeWithBulma { 28 | vertical-align: bottom; 29 | } 30 | 31 | div.column.has-content-vcentered { 32 | display: flex; 33 | flex-direction: column; 34 | justify-content: center; 35 | } 36 | 37 | div.notification.copy-notification { 38 | position: absolute; 39 | top: 0; 40 | right: 0; 41 | z-index: 999; 42 | } 43 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Cedric Amaya 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "should-i-cli", 3 | "description": "Decision-making made easy. Ask a question to get back a yes or no answer.", 4 | "version": "2.1.1", 5 | "author": "Cedric Amaya @cedricium", 6 | "bin": { 7 | "should-i": "./bin/run" 8 | }, 9 | "bugs": "https://github.com/cedricium/should-i-cli/issues", 10 | "dependencies": { 11 | "@oclif/command": "^1.4.30", 12 | "@oclif/config": "^1.6.18", 13 | "@oclif/plugin-help": "^1.2.11", 14 | "maker-link": "^1.0.0", 15 | "ora": "^2.1.0", 16 | "update-notifier": "^2.5.0" 17 | }, 18 | "devDependencies": { 19 | "chai": "^4.1.2", 20 | "eslint": "^4.19.1", 21 | "eslint-config-google": "^0.9.1", 22 | "lodash": "^4.17.11", 23 | "mocha": "^5.2.0" 24 | }, 25 | "engines": { 26 | "node": ">=8.0.0" 27 | }, 28 | "files": [ 29 | "/bin", 30 | "/src" 31 | ], 32 | "homepage": "https://github.com/cedricium/should-i-cli", 33 | "keywords": [ 34 | "oclif", 35 | "cli", 36 | "yes-no", 37 | "decision", 38 | "should-i" 39 | ], 40 | "license": "MIT", 41 | "main": "src/index.js", 42 | "oclif": { 43 | "bin": "should-i" 44 | }, 45 | "repository": "cedricium/should-i-cli", 46 | "scripts": { 47 | "lint": "eslint . --no-eslintrc node_modules", 48 | "posttest": "npm run lint", 49 | "test": "mocha" 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/utils/index.js: -------------------------------------------------------------------------------- 1 | // List of words / phrases that should be given "no" answers every time. 2 | // Implemented by @alqahtani, pull request #2 3 | const absolutelyNo = (text) => { 4 | for (let i = 0; i < forbiddenWords.length; i++) { 5 | if ( text.includes(forbiddenWords[i])) { 6 | return true; 7 | } 8 | } 9 | return false; 10 | }; 11 | 12 | const forbiddenWords = [ 13 | 'kill myself', 14 | 'commit suicide', 15 | 'take my own life', 16 | 'rob a', 17 | ]; 18 | // End of forbidden words feature 19 | 20 | const generateYesOrNo = (fullQuestion) => { 21 | if (absolutelyNo(fullQuestion)) { 22 | return 'no'; 23 | } 24 | return Math.floor(Math.random() * 2) === 0 ? 'yes' : 'no'; 25 | }; 26 | 27 | const noSayings = [ 28 | 'go fish', 29 | 'nah', 30 | 'nay', 31 | 'negative', 32 | 'no', 33 | 'no way, Jose', 34 | 'nope', 35 | 'not in a million years', 36 | 'out of the question', 37 | 'thumbs down 👎', 38 | 'under no circumstances', 39 | ]; 40 | 41 | const yesSayings = [ 42 | '10-4', 43 | 'affirmative', 44 | 'aye', 45 | 'by all means', 46 | 'fo’ shizzle', 47 | 'go for it', 48 | 'sure', 49 | 'surely', 50 | 'totally', 51 | 'yeah', 52 | 'yes', 53 | ]; 54 | 55 | // check if the input contain letters and ends with '?' 56 | const isAQuestion = (input) => { 57 | return RegExp(/[A-z]/g).test(input) && input.endsWith('?'); 58 | }; 59 | 60 | const getRandomSaying = (answer) => { 61 | if (answer === 'yes') { 62 | return yesSayings[Math.floor(Math.random() * yesSayings.length)]; 63 | } else { 64 | return noSayings[Math.floor(Math.random() * noSayings.length)]; 65 | } 66 | }; 67 | 68 | module.exports = { 69 | generateYesOrNo, 70 | getRandomSaying, 71 | isAQuestion, 72 | yesSayings, 73 | noSayings, 74 | }; 75 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | should-i-cli 2 | ============ 3 | 4 | [![Version](https://img.shields.io/npm/v/should-i-cli.svg)](https://npmjs.org/package/should-i-cli) 5 | [![Downloads/week](https://img.shields.io/npm/dw/should-i-cli.svg)](https://npmjs.org/package/should-i-cli) 6 | [![License](https://img.shields.io/npm/l/should-i-cli.svg)](https://github.com/cedricium/should-i-cli/blob/master/package.json) 7 | 8 | Decision-making made easy. Ask a question to get back a yes or no answer. 9 | > Note: should-i and it's developers are not responsible for the actions you choose. 10 | 11 | ## Usage 12 | 13 | ```sh 14 | USAGE 15 | $ should-i QUESTION 16 | 17 | ARGUMENTS 18 | QUESTION the question you want answered 19 | 20 | OPTIONS 21 | -h, --help show CLI help 22 | -v, --version show CLI version 23 | 24 | DESCRIPTION 25 | Decision-making made easy. Ask a question to get back a yes or no answer. 26 | ``` 27 | 28 | ### Examples 29 | 30 | `should-i` has your best interest in mind (most of the time). 31 | 32 | ```sh 33 | $ should-i "go for a run tonight?" 34 | ✖ no way, Jose 35 | ``` 36 | 37 | ```sh 38 | $ should-i "eat whatever I feel like?" 39 | ✔ totally 40 | ``` 41 | 42 | ## Contributing 43 | 44 | Contributions are welcome from anyone and everyone. To contribute: 45 | 46 | 1. **Fork** the repo on GitHub 47 | 2. **Clone** the project to your own machine 48 | 3. **Commit** changes to your own branch 49 | 4. **Push** your work back up to your fork 50 | 5. Submit a **Pull request** so that we can review your changes 51 | 52 | > Note: Be sure to merge the latest from "upstream" before making a pull request! 53 | 54 | ### Contributors: 55 | 56 | Special thanks to those who have helped `should-i-cli`: 57 | 58 | - Ahmed AlQahtani ([@alqahtani](https://github.com/alqahtani)) 59 | - Anderson Joseph ([@andersonjoseph](https://github.com/andersonjoseph)) 60 | 61 | ## License 62 | [MIT](LICENSE.md) -------------------------------------------------------------------------------- /test/test.js: -------------------------------------------------------------------------------- 1 | const expect = require('chai').expect; 2 | 3 | const {generateYesOrNo, getRandomSaying, yesSayings, 4 | noSayings} = require('../src/utils/index.js'); 5 | describe('Testing answers', () => { 6 | it('should return yes or no', () => { 7 | expect(generateYesOrNo('Should I study now?')).to.match(/(yes|no)/); 8 | expect(generateYesOrNo('Should I sleep early?')).to.match(/(yes|no)/); 9 | expect(generateYesOrNo('Should I test my code before production?')) 10 | .to.match(/(yes|no)/); 11 | }); 12 | 13 | it('should derive answer from `yesSayings` list', () => { 14 | expect(yesSayings).to.include(getRandomSaying('yes')); 15 | expect(yesSayings).to.include(getRandomSaying('yes')); 16 | expect(yesSayings).to.include(getRandomSaying('yes')); 17 | }); 18 | 19 | it('should derive answer from `noSayings` list', () => { 20 | expect(noSayings).to.include(getRandomSaying('no')); 21 | expect(noSayings).to.include(getRandomSaying('no')); 22 | expect(noSayings).to.include(getRandomSaying('no')); 23 | }); 24 | }); 25 | 26 | describe('Testing forbidden questions', () => { 27 | it('should return no', () => { 28 | expect(generateYesOrNo('Should I kill myself?')).to.equal('no'); 29 | expect(generateYesOrNo('Should I rob a car?')).to.equal('no'); 30 | expect(generateYesOrNo('Should I take my own life?')).to.equal('no'); 31 | }); 32 | }); 33 | 34 | const {isAQuestion} = require('../src/utils/index.js'); 35 | describe('Testing if arg is a question', () => { 36 | it('should return true for questions', () => { 37 | expect(isAQuestion('Should I study now?')).to.be.true; 38 | expect(isAQuestion('Should I sleep early?')).to.be.true; 39 | expect(isAQuestion('Should I test my code before production?')).to.be.true; 40 | }); 41 | 42 | it('should return false for non-questions', () => { 43 | expect(isAQuestion('Should I study now')).to.be.false; // test missing ? 44 | expect(isAQuestion('423546423')).to.be.false; // test numbers 45 | expect(isAQuestion(';[]./<.;;#%#@$')).to.be.false; // testing symbols 46 | }); 47 | }); 48 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable require-jsdoc */ 2 | 3 | const ora = require('ora'); 4 | const updateNotifier = require('update-notifier'); 5 | const pkg = require('../package.json'); 6 | 7 | const {Command, flags} = require('@oclif/command'); 8 | const {generateYesOrNo, isAQuestion, getRandomSaying} = require('../src/utils'); 9 | 10 | class ShouldICliCommand extends Command { 11 | async run() { 12 | const {args} = this.parse(ShouldICliCommand); 13 | const ANSWER_DELAY = 1000; 14 | // QUESTION positional argument 15 | let question = args.question; 16 | let answer; 17 | 18 | if (!isAQuestion(question)) { 19 | return ora().warn('Well, that is not a question.'); 20 | } 21 | 22 | const fullQuestion = `should you ${question} 🤔`; 23 | 24 | const spinner = ora(fullQuestion).start(); 25 | 26 | answer = generateYesOrNo(fullQuestion); 27 | setTimeout(() => { 28 | if (answer === 'yes') { 29 | spinner.succeed(getRandomSaying(answer)); 30 | } else { 31 | spinner.fail(getRandomSaying(answer)); 32 | } 33 | }, ANSWER_DELAY); 34 | 35 | // Check for `should-i-cli` update every 3 days 36 | updateNotifier({ 37 | pkg: pkg, 38 | updateCheckInterval: 1000 * 60 * 60 * 24 * 3, 39 | }).notify(); 40 | }; 41 | 42 | // getRandomSaying(answer) { 43 | // if (answer === 'yes') { 44 | // return yesSayings[Math.floor(Math.random() * yesSayings.length)]; 45 | // } else { 46 | // return noSayings[Math.floor(Math.random() * noSayings.length)]; 47 | // } 48 | // }; 49 | }; 50 | 51 | ShouldICliCommand.description = ` 52 | Decision-making made easy. Ask a question to get back a yes or no answer. 53 | `; 54 | 55 | ShouldICliCommand.args = [ 56 | { 57 | name: 'question', 58 | required: true, 59 | description: 'the question you want answered', 60 | }, 61 | ]; 62 | 63 | ShouldICliCommand.flags = { 64 | // add --version flag to show CLI version 65 | version: flags.version({char: 'v'}), 66 | // add --help flag to show CLI version 67 | help: flags.help({char: 'h'}), 68 | }; 69 | 70 | module.exports = ShouldICliCommand; 71 | -------------------------------------------------------------------------------- /docs/js/index.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-multi-spaces, max-len */ 2 | 3 | const makerLink = new MakerLink({ 4 | author: "Cedric Amaya", 5 | photoURL: "https://pbs.twimg.com/profile_images/1163280199200280576/XVbgYr8I_400x400.jpg", 6 | redirectURL: "https://cedric.tech", 7 | brandColor: '#007bff', 8 | font: 'BlinkMacSystemFont, -apple-system, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", "Helvetica", "Arial", sans-serif', 9 | }); 10 | 11 | // `copyToClipboard()` courtesy @chalarangelo (Angelos Chalaris) 12 | // refs: https://hackernoon.com/copying-text-to-clipboard-with-javascript-df4d4988697f 13 | const copyToClipboard = (str) => { 14 | const el = document.createElement('textarea'); // Create a