Created
March 9, 2009 17:50
-
-
Save kdwinter/76395 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
#!/usr/bin/env ruby19 | |
# encoding: utf-8 | |
=begin | |
Author: Gigamo <gigamo@gmail.com> | |
Inspired by Todo.txt (http://www.todotxt.com) | |
Usage: rudo <action> [<action arguments>] | |
* rudo add <some text> | |
* rudo del <tasknumber> | |
* rudo prioritize <tasknumber> [{A|B|C|X|''}] | |
* rudo append <tasknumber> [<some text to append>] | |
* rudo replace <tasknumber> [<some text to replace>] | |
* rudo list [<match>] | |
=end | |
module Rudo | |
extend self | |
# File that stores the todo items. | |
@todo_file = ENV["HOME"] + '/.todotxt/todo.txt' | |
# Main method. | |
def run | |
# Check if @todo_file exists, exit if not. | |
die "[+] #@todo_file doesn't exist" unless File.exists? @todo_file | |
# Create a new Todo instance | |
todo = Todo.new(@todo_file) | |
# Parse commandline input. | |
case ARGV.shift | |
when 'add' | |
todo.add(ARGV.join(' ')) unless ARGV.empty? | |
when 'rm', 'del', 'delete' | |
todo.delete(ARGV.shift.to_i) if ARGV.length == 1 | |
when 'prio', 'prioritize' | |
todo.prioritize(ARGV.shift.to_i, ARGV[0].nil? ? '' : ARGV[0]) | |
when 'append' | |
todo.append(ARGV.shift.to_i, ARGV.join(' ')) unless ARGV.length < 1 | |
when 'mv', 'replace' | |
todo.replace(ARGV.shift.to_i, ARGV.join(' ')) unless ARGV.length < 1 | |
when 'ls', 'list' | |
ARGV.empty? ? todo.list : todo.list(ARGV) | |
else | |
puts help | |
end | |
end | |
class Todo | |
attr_reader :file | |
def initialize(file) | |
@file = file | |
end | |
def add(text) | |
# Add a new task to @todo_file. | |
File.open(self.file, 'a') { |file| file.puts text } | |
line = IO.readlines(self.file).count.to_i | |
puts "[+] Added `#{text}' at line #{line}" | |
end | |
def append(item, text='') | |
# Append text to an existing task. | |
tasks = get_tasks | |
Rudo.die "[+] #{item}: No such todo." unless tasks.has_key? item | |
orig_text = tasks[item] | |
tasks[item] = [tasks[item], text].join(' ') | |
write_tasks tasks | |
puts "[+] Appended `#{text}' to `#{orig_text}'" | |
end | |
def replace(item, text) | |
# Replace text in a given task. | |
tasks = get_tasks | |
Rudo.die "[+] #{item}: No such todo." unless tasks.has_key? item | |
orig_text = tasks[item] | |
tasks[item] = text | |
puts "[+] Replaced `#{orig_text}' with `#{text}'" | |
write_tasks tasks | |
end | |
def delete(item) | |
# Delete a task by given tasknumber. | |
tasks = get_tasks | |
Rudo.die "[+] #{item}: No such todo." unless tasks.has_key? item | |
orig_task = tasks[item] | |
puts "[+] Delete `#{tasks[item]}' [y/n]?" | |
case $stdin.gets.chomp | |
when 'y', 'yes', 'yeah', 'yup', 'yep' | |
tasks.delete(item) | |
puts "[+] Deleted `#{orig_task}'" | |
end | |
write_tasks tasks | |
end | |
def list(patterns=nil) | |
# Print a list of all tasks found in @todo_file. | |
# Optionally accept arguments, match arguments for | |
# items in the list, and print only matching items. | |
items = [] | |
tasks = get_tasks | |
if patterns | |
tasks.each do |key, value| | |
match = true | |
patterns.each { |pattern| match = false unless value[/#{pattern}/i] } | |
items << "#{key}: #{value}" if match | |
end | |
else | |
tasks.each { |key, value| items << "#{key}: #{value}" } | |
end | |
re_pri = /.*(\([A-Z]\)).*/ | |
items.sort.each { |item| puts item.sub(re_pri, highlight_priority(item)) } | |
tasks[items.size].length.times { print '-' } | |
puts "---\nListing #{items.size} #{items.size == 1 ? 'item' : 'items'}." | |
end | |
def prioritize(item, prio='') | |
# Prioritize tasks by A, B, C, X or '' | |
prio = prio.upcase | |
tasks = get_tasks | |
Rudo.die "[+] #{item}: No such todo." unless tasks.has_key? item | |
Rudo.die "[+] #{prio}: Not recognized" unless prio[/[A-Z]/] || prio == '' | |
re_pri = /\([A-Z]?\) / | |
orig_task = tasks[item].sub(re_pri, '') | |
if prio == '' | |
tasks[item] = tasks[item].sub(re_pri, '') | |
elsif tasks[item][re_pri] | |
tasks[item] = tasks[item].gsub(re_pri, "(#{prio}) ") | |
else | |
tasks[item] = "(#{prio}) #{tasks[item]}" | |
end | |
puts "[+] Prioritized `#{orig_task}' with `#{prio == '' ? 'nothing' : prio}'" | |
write_tasks tasks | |
end | |
private | |
def get_tasks | |
# Get a hash of tasks from @todo_file. | |
count = 0 | |
tasks = {} | |
File.open(self.file).each_line do |line| | |
next if line.strip == '' | |
count += 1 | |
tasks[count] = line.chomp | |
end.close | |
return tasks | |
end | |
def write_tasks(task_dict) | |
# Write a dictionary of tasks to @todo_file. | |
keys = task_dict.keys.sort | |
File.open(self.file, 'w') do |file| | |
keys.each { |key| file.puts task_dict[key] } | |
end | |
end | |
def highlight_priority(matchobject) | |
# Colorize list's output by priority | |
yellow = "\033[0;33m" | |
green = "\033[0;32m" | |
magenta = "\033[0;35m" | |
white = "\033[0;37m" | |
default = "\033[0m" | |
case matchobject.split[1] | |
when '(A)' | |
return yellow << matchobject << default | |
when '(B)' | |
return green << matchobject << default | |
when '(C)' | |
return magenta << matchobject << default | |
else | |
return white << matchobject << default | |
end | |
end | |
end | |
def die(text) | |
# Print error and exit. | |
$stderr.puts text | |
exit 1 | |
end | |
private | |
def help | |
# Return usage located in the comments above. | |
return "Usage: " + File.read(__FILE__).match(/Usage:(.+?)=end/m)[1].strip.gsub(/rudo/, File.basename($0)) | |
end | |
end | |
Rudo.run if $0 == __FILE__ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment