· 8 years ago · Dec 04, 2017, 04:28 PM
1//
2// An ultra simple plaintext todo list implementation
3//
4// I have always preferred keeping todo lists in plain text files, this script allows me to keep a log of
5// the items I complete.
6//
7// Use the atom package 'save-autorun' to run this script on your list each time you save changes. ex: node ..../todoRaw.js todofile.txt
8// Completed items will be removed from the list, and stored in a sqlite database.
9//
10// Formatting is straightforward, each item should be on its own line, and use square brackets.
11// To complete an item, put a 'v' between the square brackets. Ex:
12//
13// [] Item one
14// [v] Item two (complete)
15//
16// Upon saving, the item will be removed from the text file and saved in the database with a timestamp
17//
18
19const fs = require('fs')
20const sqlite3 = require('sqlite3').verbose()
21const args = process.argv.slice(2)
22
23Array.prototype.last = function() {
24 return this[this.length - 1]
25}
26
27const f = args[0]
28const fn = f.split('/').last()
29const now = Date.now()
30
31// Exit if the file does not exist
32if (!fs.existsSync(f)) {
33 console.error('todo file does not exist')
34 process.exit(1)
35}
36
37// Read the file into a string
38let fileStr = fs.readFileSync(f, "utf8")
39
40// Completed line regex
41const completedReg = new RegExp(/^\h*\[v\]\s*(.*)\n/gm)
42
43// Build matches array
44let match
45let matches = []
46while ((match = completedReg.exec(fileStr)) !== null) matches.push(match[1])
47
48// Create object for each
49matches = matches.map(t => ({
50 completed: now,
51 fileName: fn,
52 file: f,
53 item: t
54}))
55
56// Open DB
57const db = new sqlite3.Database(__dirname + '/todoRaw.sqlite')
58
59// Create the table if it does not exist
60const tb = `CREATE TABLE IF NOT EXISTS raw(id INTEGER PRIMARY KEY,completed INTEGER,fileName TEXT,file TEXT,item TEXT)`
61db.run(tb, () => {
62
63 // Insert rows
64 matches.forEach(r => {
65 db.run(`INSERT INTO raw
66 (${Object.keys(r).join(',')})
67 VALUES(${Object.values(r).map(s => typeof s == 'string' ? `'${s}'` : s).join(',')})
68 `)
69 })
70
71 // Close the connection
72 db.close()
73})
74
75// Remove the matches from the file string
76const fileStrNew = fileStr.replace(completedReg, '')
77
78// Write the file
79fs.writeFileSync(f, fileStrNew, 'utf8')
80
81if (matches.length) console.log(`Completed ${matches.length} items!`)