Last active
April 6, 2020 09:08
-
-
Save typebird/be9bc2e8f84a2c94f3935b9d06176319 to your computer and use it in GitHub Desktop.
一個簡單的終端機待辦表小程式。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const rl = require("readline").createInterface({ | |
input: process.stdin, | |
output: process.stdout, | |
}) | |
const path = require("path") | |
const fs = require("fs") | |
const SAVE_PATH = path.join(__dirname, "./save.txt") | |
/** @returns {Promise<String>} */ | |
const interactive = que => | |
new Promise(resolve => rl.question(que + "\n", resolve)) | |
const File = (() => { | |
const basicMethod = { | |
/** @returns {Promise<[{id: Int, time: Int, data: String, done: Boolean}]>} */ | |
read: () => new Promise((resolve, reject) => | |
fs.readFile(SAVE_PATH, (err, data) => err | |
? reject(err) | |
: resolve(JSON.parse(data)))), | |
/** @returns {Promise<[{id: Int, time: Int, data: String, done: Boolean}]>} */ | |
write: content => new Promise(resolve => | |
fs.writeFile(SAVE_PATH, JSON.stringify(content), () => resolve(content))), | |
} | |
const append = content => { | |
const maxId = list => Math.max(...list.map(({ id }) => id)) | |
const pushToLast = val => list => [ | |
...list, (val.id = maxId(list) + 1, val) | |
] | |
return basicMethod.read() | |
.then(pushToLast(content)) | |
.then(basicMethod.write) | |
} | |
const map = func => basicMethod.read() | |
.then(list => list.map(func)) | |
.then(basicMethod.write) | |
return { | |
...basicMethod, append, map, | |
} | |
})() | |
const Data = { | |
init: val => ({ time: new Date().getTime(), data: val, done: false, }), | |
/** @returns {String} */ | |
show: fileContent => fileContent.length === 0 | |
? "Empty." | |
: fileContent | |
.map(({ time, data, done, id }) => | |
`${done ? "[v]" : "[ ]"} [${id}]: ${data}\n\tat: ${new Date(time).toLocaleString()}`) | |
.join("\n") | |
} | |
const Parm = (() => { | |
const helpIntro = ` | |
Hi, this is a simple todo list cli app. | |
Here have some function for you, try it out! | |
add <string> : add a todo in your list. | |
del <int?> : delete a todo that id is equal your parm. | |
: if didn't send any number to me, than I will delete all the list. | |
lok : display your todo list. | |
finish <int> : set a todo item are finish.` | |
const alog = todoList => Promise | |
.resolve(console.log("\n" + Data.show(todoList))) | |
const method = { | |
add: content => content | |
? Promise.resolve(Data.init(content)) | |
.then(File.append) | |
.then(alog) | |
: Promise.resolve(console.log( | |
"You didn't input any content, I can't append that for you.")), | |
del: content => content | |
? File.read() | |
.then(data => data | |
.filter(({ id }) => id !== Number(content))) | |
.then(File.write) | |
.then(alog) | |
: Promise.resolve(console.log( | |
"You realy want to delete all todo list?")) | |
.then(() => interactive("If truely, input 'y' or 'Y':")) | |
.then(input => input === "y" || input === "Y" | |
? File.write([]) | |
.then(() => console.log( | |
"Ok, now you have a new todo list.")) | |
: console.log("Ok, I willn't change anything.")), | |
lok: () => File.read() | |
.then(alog), | |
finish: val => !Number.isNaN(Number(val)) | |
? File.map(todo => todo.id === Number(val) | |
? (todo.done = true, todo) | |
: todo) | |
.then(alog) | |
: Promise.resolve(console.log( | |
"Your parm isn't a number, so I not sure what are your want.")), | |
help: () => Promise.resolve(console.log(helpIntro)), | |
} | |
return { | |
check: ([execute, ...content]) => | |
(method[execute] || method.help)(content.join(" ")) | |
} | |
})() | |
const main = (nodePath, filePath, ...userVals) => | |
Parm.check(userVals) | |
.finally(() => rl.close()) | |
main(...process.argv) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment