Skip to content

Instantly share code, notes, and snippets.

@tomhodgins
Last active February 11, 2023 14:13
Show Gist options
  • Save tomhodgins/3d14ba60a441aae097c981b91ea9520d to your computer and use it in GitHub Desktop.
Save tomhodgins/3d14ba60a441aae097c981b91ea9520d to your computer and use it in GitHub Desktop.
This is a proof of concept, eventually I want a CLI I can use like `tasq add Buy groceries` or `tasq tag 15 work`, or `tasq check 24`; GIF: https://imgur.com/a/lkh5c9w
# tasq
function tasq
cd ~/Code/tasq/
node index.js (echo $argv)
end
// create data/
// create data/data.json
// create data/counter.txt
const fs = require('fs')
let counter = parseFloat(fs.readFileSync('data/counter.txt')) || 0
// convert number to base36
const toBase36 = number => parseInt(number).toString(36)
// convert number from base36
const fromBase36 = number => parseInt(number, 36)
// save: save current list
function save(data={}, file='data/data.json') {
fs.writeFileSync('data/counter.txt', counter)
return fs.writeFileSync(file, JSON.stringify(data))
}
// load: load from JSON
function load(file='data/data.json') {
const text = fs.readFileSync(file)
return JSON.parse(
text.length
? text
: '{}'
)
}
// help: list options
function help() {
return process.stdout.write(
`\nAvailable functions are:\n\n${
Object.entries(func)
.map(entry => `- ${entry[0]}\n`)
.join('')
}\n`
)
}
const keywords = [
'all',
'tagged',
'checked',
'unchecked'
]
// built-in functions
const func = {
// list: display all entries
list: function(term='all') {
let data = load()
let items = []
if (arguments.length > 0) {
if (keywords.includes(arguments[0])) {
switch (arguments[0]) {
case 'all':
items = Object.entries(data)
break
case 'tagged':
items = Object.entries(data)
.filter(item => item[1].tags.includes(arguments[1]))
break
case 'checked':
items = Object.entries(data)
.filter(item => item[1].status)
break
case 'unchecked':
items = Object.entries(data)
.filter(item => !item[1].status)
break
}
} else {
items = Object.entries(data)
.filter(item => item[1].tags.includes(term))
}
} else {
items = Object.entries(data)
}
return items
.map(task =>
process.stdout.write(`${
toBase36(task[0])
} ${
task[1].status
? '✔'
: '✘'
} ${
task[1].title
} ${
task[1].tags.length
? 'tagged: ' + task[1].tags.join(', ')
: ''
}\n`)
)
},
// tag: add tag to entry
tag: function(id, string) {
let data = load()
if (data[fromBase36(id)]) {
if (data[fromBase36(id)].tags.includes(string)) {
data[fromBase36(id)].tags.splice(data[fromBase36(id)].tags.indexOf(string), 1)
} else {
data[fromBase36(id)].tags.push(string)
}
}
return save(data)
},
// add: add entry
add: function(...title) {
let data = load()
data[counter] = {
title: title.join(' '),
tags: [],
status: false
}
counter++
return save(data)
},
// remove: remove entry
remove: function(term) {
let data = load()
let terms = term.split(' ')
if (keywords.includes(terms[0])) {
switch (terms[0]) {
case 'all':
data = {}
break
case 'tagged':
for (let task in data) {
if (task[1].tag.includes(terms[1])) {
delete data[task]
}
}
break
case 'checked':
for (let task in data) {
if (data[task].status) {
delete data[task]
}
}
break
case 'unchecked':
for (let task in data) {
if (!data[task].status) {
delete data[task]
}
}
break
}
} else if (data[fromBase36(term)]) {
delete data[fromBase36(term)]
}
return save(data)
},
// check: check entry
check: function(id) {
const data = load()
if (data[fromBase36(id)] && !data[fromBase36(id)].status) {
data[fromBase36(id)].status = true
}
return save(data)
},
// uncheck: uncheck entry
uncheck: function(id) {
const data = load()
if (data[fromBase36(id)] && data[fromBase36(id)].status) {
data[fromBase36(id)].status = false
}
return save(data)
},
// rename: change title of existing task
rename: function(id, ...title) {
const data = load()
if (data[fromBase36(id)] && title) {
data[fromBase36(id)].title = title.join(' ')
}
return save(data)
}
}
// Run from command-line
if (process.argv[2]) {
const cli = process.argv[2].split(' ')
if (func[cli[0]]) {
func[cli[0]](...cli.slice(1))
} else {
help()
}
} else {
help()
}
@pyrho
Copy link

pyrho commented Mar 25, 2020

Love it thanks! One question, why store the counter as base36 ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment