pomd
Version:
Just a good old cli based Pomodoro timer with native notifactions
152 lines (126 loc) • 4.34 kB
JavaScript
const path = require('path')
const Timr = require('timrjs')
const notifier = require('node-notifier')
const vorpal = require('vorpal')()
const getStorePath = () => path.join(require('os').homedir(), '.pomd.json')
const pkg = require('./package.json')
const stats = require('piggy-bank')(getStorePath())
const clearLineAndWrite = text => {
process.stdout.clearLine()
process.stdout.cursorTo(0)
process.stdout.write(text)
}
require('update-notifier')({ pkg }).notify()
// Default args if none provided
const defaultTime = '25:00'
const chillTime = '05:00'
const defaultRepeat = 1
let timerRunning = false
let loop = false
let repeatTime = defaultRepeat
const renderTime = (time, timer, type) => {
timer.ticker(({ formattedTime }) => {
if (!timerRunning) {
timer.stop()
clearLineAndWrite('🍅 ')
} else if (loop) {
clearLineAndWrite(`🕐 ${formattedTime} - ${type} ∞`)
} else {
clearLineAndWrite(`🕐 ${formattedTime} - ${type}`)
}
})
}
const performPomodoro = (times, chills, index, cb) => {
timerRunning = true
const time = times[index] || times[repeatTime % index] || times[index % repeatTime]
const chill = chills[index] || chills[repeatTime % index] || chills[index % repeatTime]
const currentTick = `(${index + 1}/${repeatTime * times.length})`
stats.set('total', Number.parseInt(stats.get('total') || 0) + 1, { overwrite: true })
// Setup session timer
const timer = Timr(time)
const sessionCurrentTick = `Session ${currentTick}`
if (loop) {
clearLineAndWrite(`🕐 ${time} - ${sessionCurrentTick} ∞`)
} else {
clearLineAndWrite(`🕐 ${time} - ${sessionCurrentTick}`)
}
timer.start()
renderTime(time, timer, sessionCurrentTick)
// Start break when session is done
timer.finish(() => {
stats.set('completed', Number.parseInt(stats.get('completed') || 0) + 1, { overwrite: true })
notifier.notify({
title: pkg.name,
message: `Pomodoro done! ${currentTick}`,
sound: true
})
// Setup chill timer
const timer = Timr(chill)
const chillCurrentTick = `Chill ${currentTick}`
if (loop) {
clearLineAndWrite(`🕐 ${chill} - ${chillCurrentTick} ∞`)
} else {
clearLineAndWrite(`🕐 ${chill} - ${chillCurrentTick}`)
}
timer.start()
renderTime(chill, timer, chillCurrentTick)
timer.finish(() => {
clearLineAndWrite(`Done ✔︎ ${currentTick}`)
notifier.notify({
title: pkg.name,
message: `Chill done! ${currentTick}`,
sound: true
})
if (index < repeatTime - 1) {
performPomodoro(times, chills, index + 1, cb)
} else if (loop) {
performPomodoro(times, chills, 0, cb)
} else {
cb()
}
})
})
}
vorpal
.command('start', 'Start a Pomodoro')
.autocomplete(['--time', '--chill', '--repeat'])
.option('-t, --time <time>', 'Set the time of the Pomodoro. Default is 25:00 minutes.')
.option('-c, --chill <chill>', 'Set the time of chill. Default is 5:00 minutes.')
.option('-r, --repeat <repeat>', 'Repeat Pomodoro x times. Default is 1')
.option('-l, --loop', 'Run Pomodoros forever.')
.action((args = {}, cb) => {
let times = args.options.time || [defaultTime]
let chills = args.options.chill || [chillTime]
if (!Array.isArray(times)) {
times = [times]
}
if (!Array.isArray(chills)) {
chills = [chills]
}
if (times.length !== chills.length) {
console.error(
`Number of time and chill parameters must be equal. You have entered ${times.length} -t, and ${chills.length} -c.`
)
cb()
} else {
repeatTime = args.options.repeat || defaultRepeat
loop = args.options.loop || false
performPomodoro(times, chills, 0, cb)
}
})
.cancel(() => {
timerRunning = false
})
vorpal.command('stats', 'Show statistics from your Pomodoros.').action((args, cb) => {
const result = stats.get('total')
? `\nYou have completed ${stats.get('completed') || 0} out of ${stats.get('total')} Pomodoros 🎉\n\n`
: `\nYou need to have done something to have stats!\n\n`
process.stdout.write(result)
cb()
})
vorpal
.on('client_command_executed', evt => process.exit(0))
.parse(process.argv)
vorpal.delimiter('🍅 ').show()