├── bin └── 2do.js ├── .eslintrc.js ├── .gitignore ├── .travis.yml ├── 2do.json ├── test ├── delete.js ├── tap-snapshots │ ├── delete.js-TAP.test.js │ ├── 2.delete.js-TAP.test.js │ ├── 1.add.js-TAP.test.js │ └── add.js-TAP.test.js ├── add.js ├── show.js └── util │ └── util.js ├── lib ├── check.js ├── utils.js ├── add.js ├── show.js ├── list.js ├── delete.js └── 2do.js ├── LICENSE ├── package.json └── README.md /bin/2do.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | const todo = require('../lib/2do.js').todoMain; 4 | 5 | todo(); 6 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | "extends": "airbnb-base", 3 | "env": { 4 | "node": true 5 | }, 6 | rules: { 7 | 'no-console': 'off' 8 | } 9 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Node build artifacts 2 | node_modules 3 | npm-debug.log 4 | doc 5 | 6 | # Local development 7 | *.env 8 | *.dev 9 | .DS_Store 10 | 11 | # Docker 12 | Dockerfile 13 | docker-compose.yml 14 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | os: 3 | - linux 4 | - osx 5 | cache: 6 | directories: 7 | - node_modules 8 | node_js: 9 | - "9" 10 | services: 11 | - xvfb 12 | before_script: 13 | - npm install 14 | -------------------------------------------------------------------------------- /2do.json: -------------------------------------------------------------------------------- 1 | { 2 | "add.js": { 3 | "1": { 4 | "title": "throw error when message is not set when adding a file to prevent mistakes", 5 | "status": "undone" 6 | } 7 | }, 8 | "list.js": { 9 | "1": { 10 | "title": "should remove testMode param in future", 11 | "status": "undone" 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /test/delete.js: -------------------------------------------------------------------------------- 1 | const tap = require('tap'); 2 | const rm = require('../lib/delete'); 3 | const fs = require('fs'); 4 | /* istanbul ignore file */ 5 | const { nothing, readJson, createConfig, removeConfig } = require('./util/util.js'); 6 | 7 | 8 | createConfig(); 9 | 10 | tap.test('remove', async (t) => { 11 | await t.test('wefwe', async (t) => { 12 | await rm({ 13 | fileName: 'add.js', 14 | todoNumber: 2, 15 | }, nothing); 16 | t.matchSnapshot(await readJson(), 'output remove'); 17 | t.end(); 18 | }); 19 | 20 | removeConfig(); 21 | t.end(); 22 | }); 23 | -------------------------------------------------------------------------------- /test/tap-snapshots/delete.js-TAP.test.js: -------------------------------------------------------------------------------- 1 | /* IMPORTANT 2 | * This snapshot file is auto-generated, but designed for humans. 3 | * It should be checked into source control and tracked carefully. 4 | * Re-generate by setting TAP_SNAPSHOT=1 and running tests. 5 | * Make sure to inspect the output below. Do not ignore changes! 6 | */ 7 | 'use strict' 8 | exports[`delete.js TAP remove wefwe > output remove 1`] = ` 9 | { 10 | "add.js": { 11 | "1": { 12 | "title": "throw error when message is not set when adding a file to prevent mistakes", 13 | "status": "undone" 14 | } 15 | }, 16 | "list.js": { 17 | "1": { 18 | "title": "should remove testMode param in future", 19 | "status": "undone" 20 | } 21 | } 22 | } 23 | ` 24 | -------------------------------------------------------------------------------- /test/tap-snapshots/2.delete.js-TAP.test.js: -------------------------------------------------------------------------------- 1 | /* IMPORTANT 2 | * This snapshot file is auto-generated, but designed for humans. 3 | * It should be checked into source control and tracked carefully. 4 | * Re-generate by setting TAP_SNAPSHOT=1 and running tests. 5 | * Make sure to inspect the output below. Do not ignore changes! 6 | */ 7 | 'use strict' 8 | exports[`2.delete.js TAP remove wefwe > output remove 1`] = ` 9 | { 10 | "add.js": { 11 | "1": { 12 | "title": "throw error when message is not set when adding a file to prevent mistakes", 13 | "status": "undone" 14 | } 15 | }, 16 | "list.js": { 17 | "1": { 18 | "title": "should remove testMode param in future", 19 | "status": "undone" 20 | } 21 | } 22 | } 23 | ` 24 | -------------------------------------------------------------------------------- /test/add.js: -------------------------------------------------------------------------------- 1 | const tap = require('tap'); 2 | const add = require('../lib/add'); 3 | /* istanbul ignore file */ 4 | const {nothing,readJson,createConfig,removeConfig,} = require('./util/util.js'); 5 | 6 | createConfig(); 7 | 8 | tap.test('ssefse', async (t) => { 9 | await t.test('wefwe', async (t) => { 10 | await add({ 11 | fileName: 'sooo.js', 12 | title: 'just testing the add method.', 13 | }, nothing); 14 | t.matchSnapshot(await readJson(), 'output'); 15 | t.end(); 16 | }); 17 | 18 | await t.test('should add todo to already existing name(file)', async (t) => { 19 | await add({ 20 | fileName: 'list.js', 21 | title: 'just testing the add to existing method.', 22 | }, nothing); 23 | t.matchSnapshot(await readJson(), 'output'); 24 | t.end(); 25 | }); 26 | 27 | removeConfig(); 28 | t.end(); 29 | }); 30 | -------------------------------------------------------------------------------- /test/tap-snapshots/1.add.js-TAP.test.js: -------------------------------------------------------------------------------- 1 | /* IMPORTANT 2 | * This snapshot file is auto-generated, but designed for humans. 3 | * It should be checked into source control and tracked carefully. 4 | * Re-generate by setting TAP_SNAPSHOT=1 and running tests. 5 | * Make sure to inspect the output below. Do not ignore changes! 6 | */ 7 | 'use strict' 8 | exports[`1.add.js TAP ssefse wefwe > output 1`] = ` 9 | { 10 | "add.js": { 11 | "1": { 12 | "title": "throw error when message is not set when adding a file to prevent mistakes", 13 | "status": "undone" 14 | }, 15 | "2": { 16 | "title": "second todo for tests", 17 | "status": "undone" 18 | } 19 | }, 20 | "list.js": { 21 | "1": { 22 | "title": "should remove testMode param in future", 23 | "status": "undone" 24 | } 25 | }, 26 | "sooo.js": { 27 | "1": { 28 | "title": "just testing the add method.", 29 | "status": "undone" 30 | } 31 | } 32 | } 33 | ` 34 | -------------------------------------------------------------------------------- /lib/check.js: -------------------------------------------------------------------------------- 1 | const chalk = require('chalk'); 2 | const { writeFile, readFile } = require('./utils'); 3 | 4 | /** 5 | * sets a 2do checked 6 | * @param {object} args - arguments passed in terminal 7 | * @param {function} callback - callback function (for vorpal) 8 | */ 9 | async function check2do(args, callback) { 10 | const data = await readFile('2do.json', 'UTF-8'); 11 | const todoObj = JSON.parse(data); 12 | if (todoObj[args.fileName][args.todoNumber].status === 'done') { 13 | console.log('\n 🚨 This todo has already been set to done! \n'); 14 | } else if (todoObj[args.fileName] && todoObj[args.fileName][args.todoNumber]) { 15 | todoObj[args.fileName][args.todoNumber].status = 'done'; 16 | // eslint-disable-next-line prefer-template 17 | await writeFile(todoObj, `\n 🏄‍ ${chalk.yellow.bold(args.fileName + ':' + args.todoNumber)} status set to done! \n`, callback); 18 | } else { 19 | console.log('\n 🚨 your file or your todo does not exist! \n'); 20 | } 21 | } 22 | 23 | module.exports = check2do; 24 | -------------------------------------------------------------------------------- /lib/utils.js: -------------------------------------------------------------------------------- 1 | const util = require('util'); 2 | const fs = require('fs'); 3 | 4 | // promisified readFile 5 | const readFile = util.promisify(fs.readFile); 6 | // promisified writeFile 7 | const writeFilePromise = util.promisify(fs.writeFile); 8 | 9 | /** 10 | * short way of cloning an object 11 | */ 12 | function cloneObject(obj) { 13 | return JSON.parse(JSON.stringify(obj)); 14 | } 15 | 16 | /** 17 | * renames property of an object 18 | */ 19 | function renameProp(obj, oldName, newName) { 20 | const clonedObject = cloneObject(obj); 21 | delete clonedObject[oldName]; 22 | clonedObject[newName] = { ...obj[oldName] }; 23 | console.log(clonedObject); 24 | return clonedObject; 25 | } 26 | 27 | /** 28 | * becase we use this function inside of a 29 | * async function it has to be async 30 | */ 31 | async function writeFile(obj, msg, callback) { 32 | await writeFilePromise('2do.json', JSON.stringify(obj, null, 2)); 33 | console.log(msg); 34 | callback(); 35 | } 36 | 37 | module.exports = { 38 | writeFile, 39 | readFile, 40 | renameProp, 41 | cloneObject, 42 | }; 43 | -------------------------------------------------------------------------------- /lib/add.js: -------------------------------------------------------------------------------- 1 | const { writeFile, readFile } = require('./utils'); 2 | 3 | /** 4 | * Adds a 2do to file 5 | * @param {object} args - arguments passed in terminal 6 | * @param {function} callback - callback function (for vorpal) 7 | */ 8 | async function add2do(args, callback) { 9 | const data = await readFile('2do.json', 'UTF-8'); 10 | const todoObj = JSON.parse(data); 11 | if (todoObj[args.fileName]) { 12 | const fileNameObj = todoObj[args.fileName]; 13 | const size = Object.keys(fileNameObj).length; 14 | todoObj[args.fileName][size + 1] = {}; 15 | todoObj[args.fileName][size + 1].title = args.title; 16 | todoObj[args.fileName][size + 1].status = 'undone'; 17 | await writeFile(todoObj, '\n 🏄‍ todo added successfully! \n', callback); 18 | } else { 19 | todoObj[args.fileName] = {}; 20 | todoObj[args.fileName]['1'] = {}; 21 | todoObj[args.fileName]['1'].title = args.title; 22 | todoObj[args.fileName]['1'].status = 'undone'; 23 | await writeFile(todoObj, '\n 🏄‍ todo added successfully! \n', callback); 24 | } 25 | } 26 | 27 | module.exports = add2do; 28 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (C) Hosein Barzegaran 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 13 | all 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 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "2do-cli", 3 | "version": "1.1.7", 4 | "description": "2do inside your command line", 5 | "main": "./lib/2do.js", 6 | "scripts": { 7 | "test": "cd ./test && tap ./*.js", 8 | "test:cov": "cd ./test && tap ./*.js --cov", 9 | "test:snap": "cd ./test && TAP_SNAPSHOT=1 tap ./*.js", 10 | "lint": "eslint ./lib/*.js", 11 | "lint:fix": "eslint ./*/*.js --fix" 12 | }, 13 | "author": "Hosein2398 ", 14 | "license": "MIT", 15 | "repository": { 16 | "type": "git", 17 | "url": "https://github.com/hosein2398/2do-cli" 18 | }, 19 | "bin": { 20 | "2do": "./bin/2do.js" 21 | }, 22 | "keywords": [ 23 | "todo", 24 | "task", 25 | "2do", 26 | "console" 27 | ], 28 | "dependencies": { 29 | "chalk": "^2.1.0", 30 | "cli-table3": "^0.5.1", 31 | "colors": "^1.3.2", 32 | "figlet": "^1.2.0", 33 | "inquirer": "^3.2.3", 34 | "vorpal": "^1.12.0" 35 | }, 36 | "devDependencies": { 37 | "eslint": "^4.19.1", 38 | "eslint-config-airbnb-base": "^13.0.0", 39 | "eslint-plugin-import": "^2.13.0", 40 | "tap": "^12.1.0" 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /test/show.js: -------------------------------------------------------------------------------- 1 | // const tap = require('tap'); 2 | // const add = require('../lib/show'); 3 | // /* istanbul ignore file */ 4 | // const { 5 | // nothing, 6 | // readJson, 7 | // createConfig, 8 | // removeConfig 9 | // } = require('./util/util.js'); 10 | 11 | // createConfig(); 12 | 13 | // tap.test('Show', async (t) => { 14 | 15 | // await t.test('wefwe', async (t) => { 16 | // const p = t.spawn('echo' ,['shit']); 17 | // console.log('holy') 18 | // const p = await t.spawn('node', ['-e', 'require("../lib/show.js")({fileName:"d"})']); 19 | // process.argv.forEach(function (val, index, array) { 20 | // console.log(index + ': ' + val); 21 | // }); 22 | // const e = t.stdin('oops'); 23 | // console.log('spaaaaaaaawnn'); 24 | // console.log(p); 25 | // t.equal(p, `\n 🚨 You don't have such a name in your todos: d \n`) 26 | // await add({ 27 | // fileName: 'sooo.js', 28 | // title: 'just testing the add method.', 29 | // }, nothing); 30 | // t.matchSnapshot(await readJson(), 'output'); 31 | // t.end(); 32 | // }); 33 | 34 | // removeConfig(); 35 | // t.end(); 36 | // }); -------------------------------------------------------------------------------- /test/util/util.js: -------------------------------------------------------------------------------- 1 | /* istanbul ignore file */ 2 | const fs = require('fs'); 3 | const util = require('util'); 4 | 5 | const jsonSample = ` 6 | { 7 | "add.js": { 8 | "1": { 9 | "title": "throw error when message is not set when adding a file to prevent mistakes", 10 | "status": "undone" 11 | }, 12 | "2": { 13 | "title": "second todo for tests", 14 | "status": "undone" 15 | } 16 | }, 17 | "list.js": { 18 | "1": { 19 | "title": "should remove testMode param in future", 20 | "status": "undone" 21 | } 22 | } 23 | } 24 | `; 25 | 26 | const readFile = util.promisify(fs.readFile); 27 | 28 | async function readJson() { 29 | const data = await readFile('2do.json', 'UTF-8'); 30 | return data; 31 | } 32 | 33 | function createConfig() { 34 | fs.writeFile('2do.json', jsonSample, (err) => { 35 | if (err) throw err; 36 | }); 37 | } 38 | 39 | function removeConfig() { 40 | fs.unlink('2do.json',function(e){ 41 | if(e) console.log('EEEe'+e); 42 | console.log('removedddd') 43 | }); 44 | } 45 | const nothing = () => {}; 46 | 47 | module.exports = { 48 | readJson, 49 | nothing, 50 | createConfig, 51 | removeConfig, 52 | }; 53 | -------------------------------------------------------------------------------- /lib/show.js: -------------------------------------------------------------------------------- 1 | const Table = require('cli-table3'); 2 | const chalk = require('chalk'); // todo : remove this library in future and only use colors 3 | const { readFile } = require('./utils'); 4 | 5 | /** 6 | * Shows 2do 7 | * @param {object} args - arguments passed in terminal 8 | */ 9 | async function show2doFile(args) { 10 | // since this is async function, it does not even need callback for vorpal 11 | // cause vorpal calls callback fn in async functions automatically (why?!) 12 | const data = await readFile('2do.json', 'UTF-8'); 13 | const todoObj = JSON.parse(data); 14 | const wantedFileObj = todoObj[args.fileName]; 15 | 16 | if (!wantedFileObj) { 17 | console.log(chalk.yellow(`\n 🚨 You don't have such a name in your todos: ${args.fileName} \n`)); 18 | return; 19 | } 20 | 21 | // eslint-disable-next-line prefer-template 22 | console.log(`\n ${chalk.cyanBright.bold(args.fileName + ':')}`); 23 | 24 | const table = new Table({ 25 | head: ['Number', 'Status', 'Title'], 26 | colWidths: [10, 10, 50], 27 | }); 28 | 29 | Object.keys(wantedFileObj).forEach((key, index) => { 30 | table.push( 31 | [index + 1, wantedFileObj[key].status, wantedFileObj[key].title], 32 | ); 33 | }); 34 | 35 | console.log(table.toString()); 36 | } 37 | 38 | module.exports = show2doFile; 39 | -------------------------------------------------------------------------------- /test/tap-snapshots/add.js-TAP.test.js: -------------------------------------------------------------------------------- 1 | /* IMPORTANT 2 | * This snapshot file is auto-generated, but designed for humans. 3 | * It should be checked into source control and tracked carefully. 4 | * Re-generate by setting TAP_SNAPSHOT=1 and running tests. 5 | * Make sure to inspect the output below. Do not ignore changes! 6 | */ 7 | 'use strict' 8 | exports[`add.js TAP ssefse wefwe > output 1`] = ` 9 | { 10 | "add.js": { 11 | "1": { 12 | "title": "throw error when message is not set when adding a file to prevent mistakes", 13 | "status": "undone" 14 | }, 15 | "2": { 16 | "title": "second todo for tests", 17 | "status": "undone" 18 | } 19 | }, 20 | "list.js": { 21 | "1": { 22 | "title": "should remove testMode param in future", 23 | "status": "undone" 24 | } 25 | }, 26 | "sooo.js": { 27 | "1": { 28 | "title": "just testing the add method.", 29 | "status": "undone" 30 | } 31 | } 32 | } 33 | ` 34 | 35 | exports[`add.js TAP ssefse should add todo to already existing name(file) > output 1`] = ` 36 | { 37 | "add.js": { 38 | "1": { 39 | "title": "throw error when message is not set when adding a file to prevent mistakes", 40 | "status": "undone" 41 | }, 42 | "2": { 43 | "title": "second todo for tests", 44 | "status": "undone" 45 | } 46 | }, 47 | "list.js": { 48 | "1": { 49 | "title": "should remove testMode param in future", 50 | "status": "undone" 51 | }, 52 | "2": { 53 | "title": "just testing the add to existing method.", 54 | "status": "undone" 55 | } 56 | }, 57 | "sooo.js": { 58 | "1": { 59 | "title": "just testing the add method.", 60 | "status": "undone" 61 | } 62 | } 63 | } 64 | ` 65 | -------------------------------------------------------------------------------- /lib/list.js: -------------------------------------------------------------------------------- 1 | const inquirer = require('inquirer'); 2 | const Table = require('cli-table3'); 3 | const chalk = require('chalk'); // todo : remove this library in future and only use colors 4 | const { 5 | readFile, 6 | } = require('./utils'); 7 | 8 | /** 9 | * Lists all 2dos 10 | * @param {object} args - arguments passed in terminal 11 | * @param {function} callback - callback function (for vorpal) 12 | * @param {boolean} testMode - a param to know if we are at test mode or not 13 | */ 14 | async function list2do(args, callback, testMode = false) { 15 | const data = await readFile('2do.json', 'UTF-8'); 16 | const todoObj = JSON.parse(data); 17 | const allKeys = []; 18 | Object.keys(todoObj).forEach((key) => { 19 | allKeys.push(key); 20 | }); 21 | // using inquirer to show in a list 22 | if (!testMode) { 23 | const answers = await inquirer.prompt([{ 24 | type: 'list', 25 | message: 'All available files:', 26 | name: 'selected', 27 | choices: allKeys, 28 | validate(answer) { 29 | if (answer.length < 1) { 30 | return 'You must choose at least one topping.'; 31 | } 32 | return true; 33 | }, 34 | }]); 35 | // eslint-disable-next-line prefer-template 36 | console.log(`\n ${chalk.cyanBright.bold(answers.selected + ':')}`); 37 | const wantedFileObj = todoObj[answers.selected]; 38 | const table = new Table({ 39 | head: ['Number', 'Status', 'Title'], 40 | colWidths: [10, 10, 50], 41 | }); 42 | 43 | Object.keys(wantedFileObj).forEach((key, index) => { 44 | table.push( 45 | [index + 1, wantedFileObj[key].status, wantedFileObj[key].title], 46 | ); 47 | }); 48 | 49 | console.log(table.toString()); 50 | } 51 | } 52 | 53 | module.exports = list2do; 54 | -------------------------------------------------------------------------------- /lib/delete.js: -------------------------------------------------------------------------------- 1 | const chalk = require('chalk'); 2 | const inquirer = require('inquirer'); 3 | const { 4 | writeFile, 5 | readFile, 6 | renameProp, 7 | cloneObject, 8 | } = require('./utils'); 9 | 10 | 11 | /** 12 | * Omits a 2do from the file 13 | * @param {object} args - arguments passed in terminal 14 | * @param {function} callback - callback function (for vorpal) 15 | * @param {boolean} testMode - a param to know if we are at test mode or not 16 | */ 17 | async function delete2do(args, callback, testMode = false) { 18 | // vorpal.hide(); 19 | const data = await readFile('2do.json', 'UTF-8'); 20 | const todoObj = JSON.parse(data); 21 | const wantedFileObj = todoObj[args.fileName]; 22 | if (!testMode) { 23 | // TODO: add a message to user when the inputed file does not exist 24 | if (!args.todoNumber) { 25 | const result = await inquirer.prompt({ 26 | type: 'confirm', 27 | name: 'fsd', 28 | default: false, 29 | message: `By doing this all notes related to ${chalk.blue.underline.bold(args.fileName)} will be ${chalk.red.bold('deleted')}, are you sure?`, 30 | }); 31 | if (result.fsd) { 32 | // console.log(result); // todo: why are we loggin?? 33 | delete todoObj[args.fileName]; 34 | await writeFile(todoObj, '\n 🏄‍ Deleted one 2do sucessfully! \n', () => {}); 35 | } else { 36 | console.log('\n Did not delete the file. \n'); 37 | } 38 | } 39 | } 40 | // TODO: log sth when watenfilObj is not there in the file 41 | // TODO: move this todos to 2so.json 42 | if (wantedFileObj && wantedFileObj[args.todoNumber]) { 43 | delete todoObj[args.fileName][args.todoNumber]; 44 | let newTodoObj = cloneObject(todoObj[args.fileName]); 45 | const theyKeys = Object.keys(todoObj[args.fileName]); 46 | const objSize = Object.keys(todoObj[args.fileName]).length; 47 | // eslint-disable-next-line 48 | for (let i = 0; i < objSize; i++) { 49 | if (theyKeys[i] > args.todoNumber) { 50 | // since renameProp is pure we have to reassign 51 | newTodoObj = renameProp(newTodoObj, theyKeys[i], theyKeys[i] - 1); 52 | } 53 | } 54 | todoObj[args.fileName] = newTodoObj; 55 | await writeFile(todoObj, '\n 🏄‍ Deleted one 2do sucessfully! \n', () => {}); 56 | } 57 | return callback(); 58 | } 59 | 60 | module.exports = delete2do; 61 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 2do-cli [![Build Status](https://travis-ci.org/hosein2398/2do-cli.svg?branch=master)](https://travis-ci.org/hosein2398/2do-cli) ![Download-week](https://img.shields.io/npm/dw/2do-cli.svg?style=flat-square) 2 | Commnad line todo app. 3 | 4 |
5 | 6 |
7 | 8 | ## Demo 9 |
10 | 11 |
12 | 13 | ## Installation 14 | ``` 15 | npm i -g 2do-cli 16 | ``` 17 | Or if using Yarn: 18 | ``` 19 | yarn global add 2do-cli 20 | ``` 21 | 22 | ## Usage 23 | - [Initializing](#initializing) 24 | - [Adding a file](#adding-a-file) 25 | - [Show todo](#show-todo) 26 | - [Check todo](#check-todo) 27 | - [Listing](#listing) 28 | - [Removing](#removing) 29 | 30 | --- 31 | 32 | ### Initializing 33 | Open up any repository that you want to use 2do-cli indside. 34 | Then type: 35 | ``` 36 | 2do 37 | ``` 38 | 2do-cli will start, after that write : 39 | ``` 40 | init 41 | ``` 42 | And 2do-cli will generate a 2do.json file in you repo. 43 | 44 | --- 45 | 46 | ### Adding a file 47 | To work with 2do-cli you have add a file and then todos related to that. 48 | Lets say you have a file named `main.js` and you want to add some todos for this file, to do so (after inializing 2do-cli in your repo) you have to type: 49 | ``` 50 | add main.js 'Here is my first todo for main.js' 51 | ``` 52 | After a while you might know that you want to add another todo for same file, so just use same command like: 53 | ``` 54 | add main.js 'Here is my second todo for main.js ' 55 | ``` 56 | 57 | --- 58 | 59 | ### Show todo 60 | Now if you want to see all todos of `main.js` you simply write: 61 | ``` 62 | show main.js 63 | ``` 64 | and all todos of that file will appear. 65 | 66 | --- 67 | 68 | ### Check todo 69 | So what if you want to know you have completed a todo or not. There is default `status` field for every todo, 70 | and it's value is set to `undone` by default. If you want to change it so that you know your todo is done: 71 | ``` 72 | check main.js 4 73 | ``` 74 | This will set status of fourth todo of main.js to `done`. 75 | 76 | --- 77 | 78 | ### Listing 79 | You can list all of files which have todos in current directory and select any one that you want, by typing : 80 | ``` 81 | list 82 | ``` 83 | 84 | --- 85 | 86 | ### Removing 87 | You can remove a file, which removes all of it's todos too, or you can only remove a todo of a file, to do prior one you just write: 88 | ``` 89 | delete main.js 90 | ``` 91 | And if you want to remove only second todo of this file you go like: 92 | ``` 93 | delete main.js 2 94 | ``` 95 | Above command will remove second todo of main.js . 96 | 97 | --- 98 | 99 | ### Version 100 | To get current version just type : 101 | ``` 102 | version 103 | ``` 104 | 105 | -------------------------------------------------------------------------------- /lib/2do.js: -------------------------------------------------------------------------------- 1 | const figlet = require('figlet'); 2 | const chalk = require('chalk'); // todo : remove this library in future and only use colors 3 | const fs = require('fs'); 4 | const vorpal = require('vorpal')(); 5 | const colors = require('colors'); 6 | const show2doFile = require('./show'); 7 | const list2do = require('./list'); 8 | const add2do = require('./add'); 9 | const delete2do = require('./delete'); 10 | const check2do = require('./check'); 11 | const packageJson = require('../package.json'); 12 | 13 | /* 14 | * Writes 2do file 15 | */ 16 | function write2doFile(callback) { 17 | fs.writeFile('2do.json', '{}', (err) => { 18 | if (err) throw err; 19 | console.log(chalk.green('Project started successfuly. ')); 20 | callback(); 21 | }); 22 | } 23 | 24 | /** 25 | * Main function to call at the begining 26 | */ 27 | function todoMain() { 28 | figlet('2do', (err, data) => { 29 | if (err) { 30 | console.log('Something went wrong...'); 31 | console.dir(err); 32 | return; 33 | } 34 | console.log(`${chalk.cyanBright(data)}\n \n`); 35 | console.log('Welcome to 2do-cli, for help write --help \n'); 36 | }); 37 | 38 | 39 | setTimeout(() => { 40 | /** 41 | * init command 42 | */ 43 | vorpal.command('init', 'Initializes new 2do in currnet directory. ') 44 | .action((args, callback) => { 45 | // cheking if 2do.json alrealy exists directory. 46 | fs.stat('2do.json',(err, stats) => { 47 | // if (err) console.log(err); 48 | if (stats) { 49 | console.log(colors.bgWhite.magenta('You already have a 2do in this directory.')); 50 | callback(); 51 | } else { 52 | // await w/riteFile('{}', 'The file has been saved!', callback); 53 | write2doFile(callback); 54 | } 55 | }); 56 | }); 57 | 58 | /** 59 | * --help command 60 | */ 61 | vorpal.command('--help', 'Help command') 62 | .action((args, callback) => { 63 | console.log(` 64 | Help 65 | init : Starts a new 2do inite the repositoey you are into. 66 | list : Lists all files in current directory and you can select one to show all todos. 67 | show [fileName] : Show all todos related to a file . 68 | add [fileName] [todo] : Adds a todo for a file. 69 | delete [fileName] [tosoNumber] : deletes a file's todo with given number. 70 | `); 71 | callback(); 72 | }); 73 | 74 | /** 75 | * show command 76 | */ 77 | vorpal.command('show [fileName]', 'Represents 2dos of a file. ') 78 | .action(show2doFile); 79 | 80 | /** 81 | * list command 82 | */ 83 | vorpal.command('list', 'Lists all available 2dos in current directory. ') 84 | .action(list2do); 85 | 86 | /** 87 | * check command 88 | */ 89 | vorpal.command('check [todoNumber]', 'Sets a todo status to checked') 90 | .action(check2do); 91 | 92 | /** 93 | * add command 94 | */ 95 | vorpal.command('add [title]', 'Adds new 2do for a file. ') 96 | .action(add2do); 97 | 98 | 99 | /** 100 | * delete command 101 | */ 102 | vorpal.command('delete [todoNumber]', 'Deletes a files\' 2do') 103 | .action(delete2do); 104 | 105 | 106 | vorpal.command('version', 'Logs current version. ') 107 | .action((args, callback) => { 108 | console.log(`Current version is : ${chalk.yellow(packageJson.version)}`); 109 | callback(); 110 | }); 111 | 112 | 113 | /** 114 | * replacing "chalk.js" with "colors" library, 115 | * due to the bug in issue #10 116 | */ 117 | vorpal.delimiter(`${colors.bgWhite.blue(' 2do ')} :`).show(); 118 | }, 800); 119 | } 120 | 121 | module.exports = { 122 | todoMain, 123 | // write2doFile, 124 | // show2doFile, 125 | // list2do, 126 | // add2do, 127 | // delete2do, 128 | }; 129 | --------------------------------------------------------------------------------