Saturday, October 25, 2008

latest.sh

A bit lazy of me, but with my directories containing many entries, it's been easier to keep track of files via modification time. That's just what I've done with this script:

latest.sh

#!/bin/sh
FILE=
DATE=0
if [ $# -gt 0 ]; then
for i in "$@"
do
NDATE=`date -r "$i" '+%s'`
if [[ $NDATE -gt $DATE || -z "$FILE" ]]; then
FILE=$i
DATE=$NDATE
fi
done
echo "$FILE"
else
for i in *
do
NDATE=`date -r "$i" '+%s'`
if [[ $NDATE -gt $DATE || -z "$FILE" ]]; then
FILE=$i
DATE=$NDATE
fi
done
echo "$FILE"
fi

notedb.rb

As the number of notes I've taken for class increases, searching has become increasingly difficult. I wrote this script a little while ago, and it's made keeping track of my notes both easy and efficient.

notedb.rb

#!/usr/bin/ruby
require 'sqlite3'

def init_db(filename)
db = SQLite3::Database.new(filename)
db.execute('CREATE TABLE IF NOT EXISTS notes(id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, dir TEXT, mtime TEXT, content TEXT)')
db.execute('PRAGMA auto_vacuum = 1')
return db
end


def recurse_add(db, root)
rdir = Dir.open(root)
rdir.each do |file|
fpath = File.join(root, file)
if File.directory?(fpath)
if file != '.' and file != '..'
recurse_add(db, fpath)
end
elsif File.file?(fpath)
if file =~ /^[0-9]{4,}-[0-1][0-9]-[0-3][0-9]:.*\.tex$/
count = db.get_first_value('SELECT COUNT(*) FROM notes WHERE name = ? AND dir = ?', file, root).to_i
if count == 0
puts 'NEW: ' + file
f = File.open(fpath, 'r')
mtime = f.mtime
db.execute('INSERT INTO notes(name, dir, mtime, content) VALUES(?, ?, ?, ?)', file, root, mtime.strftime('%FT%T%z'), f.read)
f.close
else
f = File.open(fpath, 'r')
mtime = f.mtime
content = f.read
f.close
db.execute('SELECT id, content FROM notes WHERE name = ? AND dir = ?', file, root) do |info|
if info[1] != content
puts 'UPDATE: ' + file
db.execute('UPDATE notes SET content = ?, mtime = ? WHERE id = ?', content, mtime.strftime('%FT%T%z'), info[0])
end
end
end
end
else
puts 'No such file or directory: ' + file
end
end
rdir.close
end


if ARGV.length > 0 and ENV.key?('EDITOR')
db = nil
begin
db = init_db(File.join(ENV['HOME'], '.notedb'))
mode = ARGV.shift
case mode
when 'add'
if ARGV.length > 0
ARGV.each do |file|
puts file
if File.directory?(file)
recurse_add(db, File.expand_path(file))
elsif File.file?(file)
f = File.open(file, 'r')
db.execute('INSERT INTO notes(name, dir, content)', file, File.expand_path(File.dirname(file)), f.read)
f.close
else
$stderr.puts 'No such file or directory: ' + file
end
end
else
$stderr.puts 'Usage: ' + $0 + ' add f1 [ f2 .. fn ]'
end
when 'search'
if ARGV.length > 0
term = Regexp.compile(ARGV.shift)
if ARGV.length > 0
ARGV.each do |name|
db.execute('SELECT name, dir, content FROM notes WHERE dir GLOB ?', '*' + File.expand_path(name) + '*') do |row|
row[2].split(/\n/).each do |line|
if line =~ term
puts row[0] + ':' + line
end
end
end
end
else
db.execute('SELECT name, dir, content FROM notes') do |row|
row[2].split(/\n/).each do |line|
if line =~ term
puts row[0] + ':' + line
end
end
end
end
else
$stderr.puts 'Usage: ' + $0 + ' search term [ dir ]'
end
when 'get'
if ARGV.length > 1
mode = ARGV.shift
case mode
when 'name', 'iname'
qstring = ''
if mode == 'iname'
qstring = 'SELECT name, dir, mtime FROM notes WHERE name LIKE ?'
else
qstring = 'SELECT name, dir, mtime FROM notes WHERE name GLOB ?'
end
ARGV.each do |name|
if mode == 'iname'
name = '%' + name + '%'
else
name = '*' + name + '*'
end
db.execute(qstring, name) do |row|
mtime = DateTime.strptime(row[2])
printf "%-70s (modified %s)\n", row[0], mtime.strftime('%Y-%m-%d')
end
end
when 'dir', 'idir'
qstring = ''
if mode == 'idir'
qstring = 'SELECT name, dir, mtime FROM notes WHERE dir LIKE ?'
else
qstring = 'SELECT name, dir, mtime FROM notes WHERE dir GLOB ?'
end
ARGV.each do |name|
if mode == 'iname'
name = '%' + name + '%'
else
name = '*' + name + '*'
end
db.execute(qstring, name) do |row|
mtime = DateTime.strptime(row[2])
printf "%-70s (modified %s)\n", row[0], mtime.strftime('%Y-%m-%d')
end
end
when 'latest', 'ilatest', 'elatest'
pnewest = DateTime.new
rep = ''
case mode
when 'elatest'
qstring = 'SELECT name, dir, mtime FROM notes WHERE dir = ?'
when 'ilatest'
qstring = 'SELECT name, dir, mtime FROM notes WHERE dir LIKE ?'
when 'latest'
qstring = 'SELECT name, dir, mtime FROM notes WHERE dir GLOB ?'
end
ARGV.each do |name|
case mode
when 'ilatest'
name = '%' + name + '%'
when 'latest'
name = '*' + name + '*'
end
db.execute(qstring, name) do |row|
mtime = DateTime.strptime(row[2])
if mtime > pnewest
pnewest = mtime
rep = row[0]
end
end
end
if rep.length
puts rep
end
else
$stderr.puts 'Usage: ' + $0 + ' get [ name | iname | dir | idir | latest | ilatest | elatest ] match'
end
else
$stderr.puts 'Usage: ' + $0 + ' get [ name | iname | dir | idir | latest | ilatest | elatest ] match'
end
when 'list'
db.execute('SELECT name, mtime FROM notes') do |row|
mtime = DateTime.strptime(row[1])
printf "%-70s (modified %s)\n", row[0], mtime.strftime('%Y-%m-%d')
end
when 'help'
$stderr.puts 'Usage: ' + $0 + ' [ add | search | get | list ]'
$stderr.puts "\tEDITOR must be set: currently \"" + (ENV['EDITOR'] and ENV['EDITOR'] or '') + "\""
else
raise 'Unknown mode: ' + mode
end

ensure
if db
db.close
end
end
else
$stderr.puts 'Usage: ' + $0 + ' [ add | search | get | list ]'
$stderr.puts "\tEDITOR must be set: currently \"" + (ENV['EDITOR'] and ENV['EDITOR'] or '') + "\""
end

sched.rb

My first significant Ruby program was this scheduler, sched.rb. It is based on similar ideas to my unfinished Perl scheduler, but this one does work. It executes $EDITOR to edit temporary files in order to enter recurrences, events, and tasks.

sched.rb

#!/usr/bin/ruby
require 'date'
require 'sqlite3'
class Filereader
def self.read_file(filename)
ret = Hash.new
key = ""
fin = File.open(filename, 'r')

begin
while line = fin.readline.chomp
if line =~ /^([^:]+): (.*)$/
key = $1
if not ret.key?(key)
ret[key] = [$2]
else
ret[key].push($2)
end
elsif key.length > 0 and line =~ /^\t(.*$)/
ret[key][-1] << "\n" << $1
end
end
rescue
fin.close
end

return ret
end
end
class Task
attr_reader :content, :status
def initialize(content, status)
@content = content
@status = status
end
end
class Event
attr_reader :name, :location, :date
def initialize(name, location, datestring)
@name = name
@location = location
@tasks = Array.new # Task objects
@time = 0
@datestring = datestring
if datestring.class.to_s == 'DateTime'
@date = datestring
elsif datestring =~ /^([0-9]{4})-([0-1][0-9])-([0-3][0-9])T([0-2][0-9]):([0-5][0-9]):[0-5][0-9]\+[0-2][0-4]:[0-5][0-9]$/
# Stripping out excess
@datestring = sprintf('%s-%s-%sT%s:%s', $1, $2, $3, $4, $5)
@date = DateTime.strptime(@datestring, '%Y-%m-%dT%H:%M')
elsif datestring =~ /^([0-9]{4})-([0-1][0-9])-([0-3][0-9])T([0-2][0-9]):([0-5][0-9])$/
@date = DateTime.strptime(datestring, '%Y-%m-%dT%H:%M')
elsif datestring =~ /^([0-9]{4})-([0-1][0-9])-([0-3][0-9])$/
@date = DateTime.strptime(datestring, '%Y-%m-%d')
elsif datestring =~ /^([0-9]{4})-([0-1][0-9])$/
@date = DateTime.strptime(datestring, '%Y-%m')
elsif datestring =~ /^([0-9]{4})$/
@date = DateTime.strptime(datestring, '%Y')
else
raise 'Event: invalid date: ' + datestring
end
end
def self.init_from_hash(hash)
if hash.key?('Name') and hash.key?('Location') and hash.key?('Date')
if hash['Name'][0].length > 0 and hash['Location'][0].length > 0 and hash['Date'][0].length > 0
begin
ret = Event.new(hash['Name'][0], hash['Location'][0], hash['Date'][0])
if hash.key?('Task')
hash['Task'].each do |task|
if task.length > 0
ret.add_task(Task.new(task, 0))
end
end
end
if hash.key?('Task[ ]')
hash['Task[ ]'].each do |task|
if task.length > 0
ret.add_task(Task.new(task, 0))
end
end
end
if hash.key?('Task[X]')
hash['Task[X]'].each do |task|
if task.length > 0
ret.add_task(Task.new(task, 1))
end
end
end
return ret
rescue
puts 'Event: Error: ' + $!
return nil
end
else
return nil
end
else
raise 'Event: Given hash is missing some elements.'
end
end
def date_string(fmt = '%Y-%m-%dT%H:%M')
return @date.strftime(fmt)
end
def datestring()
if @datestring.class.to_s == 'DateTime'
return @datestring.strftime('%Y-%m-%dT%H:%M')
else
return @datestring
end
end
def add_task(task)
@tasks.push(task)
end
def each_task
@tasks.each {|item| yield(item)}
end
end
class Recurrence
attr_reader :name, :location
def initialize(name, location)
@name = name
@location = location
@events = []
end
def add_event(event)
@events.push(event)
end
def each_event
@events.each {|item| yield(item)}
end
def self.generate_events(name, location, dates)
ret = Recurrence.new(name, location)
dates.each {|date| ret.add_event(Event.new(name, location, date))}
return ret
end
def self.init_from_hash(hash)
# Dates: weekly 0123456 time start end
# Dates: monthly [0-3][0-9] time start end
# Dates: yearly [0-1][0-9]-[0-3][0-9] time start end
if hash.key?('Name') and hash.key?('Location') and hash.key?('Dates')
if hash['Name'][0].length > 0 and hash['Location'][0].length > 0 and hash['Dates'][0].length > 0 and hash['Dates'].length > 0
begin
dparts = hash['Dates'][0].split(/\s/)
estart = Event.new(hash['Name'][0], hash['Location'][0], dparts[3])
eend = Event.new(hash['Name'][0], hash['Location'][0], dparts[4])
time = DateTime.strptime(dparts[2], '%H:%M')
dates = []
case dparts[0]
when 'weekly'
if dparts[1] =~ /^[0-6]+$/
tmpday = estart.date
while tmpday <= eend.date
if dparts[1].include?(tmpday.wday.to_s)
dates.push(DateTime.civil(tmpday.year, tmpday.month, tmpday.mday, time.hour, time.min))
end
tmpday = tmpday.next
end
else
raise 'Invalid weekday indices: ' + dparts[1]
end
when 'monthly'
mday = dparts[1].to_i
if mday >= 1 and mday <= 31
tmpday = estart.date
while tmpday <= eend.date
if tmpday.mday == mday
dates.push(DateTime.civil(tmpday.year, tmpday.month, tmpday.mday, time.hour, time.min))
end
tmpday = tmpday.next
end
else
raise 'Invalid month day index: ' + dparts[1]
end
when 'yearly'
if dparts[1] =~ /^([0-1][0-9])-([0-3][0-9])$/
month = $1.to_i
mday = $2.to_i
tmpday = estart.date
while tmpday <= eend.date
if tmpday.mday == mday and tmpday.month == month
dates.push(DateTime.civil(tmpday.year, tmpday.month, tmpday.mday, time.hour, time.min))
end
tmpday = tmpday.next
end
raise 'Invalid month/day index: ' + dparts[1]
end
else
raise 'Invalid recurrence operator: ' + dparts[0]
end
return Recurrence.generate_events(hash['Name'][0], hash['Location'][0], dates)
rescue
puts 'Recurrence: Error: ' + $!
return nil
end
else
return nil
end
else
raise 'Event: Given hash is missing some elements.'
end
end
end
def init_db(filename)
db = SQLite3::Database.new(filename)
db.execute('PRAGMA auto_vacuum = 1')
db.execute('CREATE TABLE IF NOT EXISTS recurrences(id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, location TEXT)')
db.execute('CREATE TABLE IF NOT EXISTS events(id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, location TEXT, date TEXT, recurrence INTEGER)')
db.execute('CREATE TABLE IF NOT EXISTS tasks(id INTEGER PRIMARY KEY AUTOINCREMENT, content TEXT, status INTEGER, event INTEGER)')
return db
end
def list_events(db, selectors, glob)
query = 'SELECT * FROM events'
args = []
first = 1
if selectors.length > 0
query << ' WHERE'
end
selectors.each do |key, value|
query << (first > 0 ? ' ' : ' AND ') + key + (glob == 1 ? ' GLOB ?' : ' LIKE ?')
args.push(value)
first -= 1
end
db.execute(query, *args) do |row|
ev = Event.new(row[1], row[2], row[3])
# printf "%6d %30s %20s %15s\n", row[0], row[1], row[2], row[3]
printf "%6d %30s %20s %25s\n", row[0], row[1], row[2], ev.date_string('%H:%M on %a., %b. %d, %Y')
i = 1
db.execute('SELECT tasks.content, tasks.status FROM tasks WHERE event = ?', row[0]) do |task|
printf "\t%6d %60s %5s\n", i, task[0], (task[1].to_i == 1 ? 'Done' : 'Prog.')
i += 1
end
end
end
def list_tasks(db, selectors, glob)
query = 'SELECT tasks.id, tasks.content, tasks.status, events.date, events.name FROM tasks LEFT OUTER JOIN events ON tasks.event = events.id'
args = []
first = 1
if selectors.length > 0
query << ' WHERE'
end
selectors.each do |key, value|
query << (first > 0 ? ' ' : ' AND ') + key + (glob == 1 ? ' GLOB ?' : ' LIKE ?')
args.push(value)
first -= 1
end
db.execute(query, *args) do |row|
ev = Event.new('', '', row[3])
printf "%6d %60s %20s %5s %25s\n", row[0], row[1], row[4], (row[2].to_i == 1 ? 'Done' : 'Prog.'), ev.date_string('%H:%M on %a., %b. %d, %Y')
end
end
def parse_selectors(args)
selectors = Hash.new
svars = Hash.new
args.each do |arg|
if arg[0..1] == '--'
parts = arg[2..-1].split(/=/)
if parts.length == 1 and arg[2..-1] =~ /=/
parts << ''
end
yield(selectors, svars, parts)
else
raise 'Unknown option: ' + arg
end
end
return selectors, svars
end





if ARGV.length > 0 and ARGV[0][0..1] == '--' and ENV.key?('EDITOR')
db = nil
tmpfile = nil
begin
case ARGV[0][2..-1]
when 'create-event'
db = init_db(File.join(ENV['HOME'], '.sched_db'))
# Create tmpfile
tmpfile = %x[mktemp].chomp
f = File.open(tmpfile, 'w+')
f.print("Name: \nLocation: \nDate: \n")
f.close
# Edit tmpfile
m1 = File.mtime(tmpfile);
system(ENV['EDITOR'], tmpfile)
m2 = File.mtime(tmpfile);
if m2 != m1
# Read tmpfile
data = Filereader.read_file(tmpfile)
event = Event.init_from_hash(data)
if event
db.execute('INSERT INTO events(name, location, date) VALUES(?, ?, ?)', event.name, event.location, event.datestring)
db.execute('SELECT events.id FROM events WHERE name = ? AND location = ? AND date = ?', event.name, event.location, event.datestring) do |row|
event.each_task do |task|
db.execute('INSERT INTO tasks(content, status, event) VALUES(?, ?, ?)', task.content, task.status, row[0])
end
end
else
$stderr.puts "Null event given; skipping."
end
else
$stderr.puts "Null event given; skipping."
end
File.delete(tmpfile)
when 'create-recurrence'
db = init_db(File.join(ENV['HOME'], '.sched_db'))
# Create tmpfile
tmpfile = %x[mktemp].chomp
f = File.open(tmpfile, 'w+')
f.print("Name: \nLocation: \nDates: \n")
f.close
# Edit tmpfile
m1 = File.mtime(tmpfile);
system(ENV['EDITOR'], tmpfile)
m2 = File.mtime(tmpfile);
if m2 != m1
# Read tmpfile
data = Filereader.read_file(tmpfile)
File.delete(tmpfile)
recurrence = Recurrence.init_from_hash(data)
if recurrence
db.execute('INSERT INTO recurrences(name, location) VALUES(?, ?)', recurrence.name, recurrence.location)
db.execute('SELECT recurrences.id FROM recurrences WHERE name = ? AND location = ?', recurrence.name, recurrence.location) do |rid|

recurrence.each_event do |event|
db.execute('INSERT INTO events(name, location, date, recurrence) VALUES(?, ?, ?, ?)', event.name, event.location, event.datestring, rid)
db.execute('SELECT events.id FROM events WHERE name = ? AND location = ? AND date = ? AND recurrence = ?', event.name, event.location, event.datestring, rid) do |row|
event.each_task do |task|
db.execute('INSERT INTO tasks(content, status, event) VALUES(?, ?, ?)', task.content, task.status, row[0])
end
end
end
end
else
$stderr.puts "Null recurrence given; skipping."
end
else
$stderr.puts "Null recurrence given; skipping."
end

when 'edit-event'
db = init_db(File.join(ENV['HOME'], '.sched_db'))
selectors = Hash.new
selectors, svars = parse_selectors(ARGV[1..-1]) do |selectors, svars, parts|
option = parts[0]
value = parts[1..-1].join('=')
case option
when 'name', 'location', 'date', 'id'
selectors['events.' + option] = (value ? value : '')
else
raise 'Unknown selector: ' + option
end
end
query = 'SELECT * FROM events'
args = []
first = 1
if selectors.length > 0
query << ' WHERE'
end
selectors.each do |key, value|
query << (first > 0 ? ' ' : ' AND ') + key + ' LIKE ?'
args.push(value)
first -= 1
end
db.execute(query, *args) do |row|
# Create tmpfile
id = row[0]
tmpfile = %x[mktemp].chomp
f = File.open(tmpfile, 'w+')


first = 1
f.print 'Name: '
row[1].split(/\n/).each do |line|
if first
f.puts line
first = 0
else
f.puts "\t" + line
end
end

first = 1
f.print 'Location: '
row[2].split(/\n/).each do |line|
if first
f.puts line
first = 0
else
f.puts "\t" + line
end
end

first = 1
f.print 'Date: '
row[3].split(/\n/).each do |line|
if first
f.puts line
first = 0
else
f.puts "\t" + line
end
end

db.execute('SELECT * FROM tasks WHERE tasks.event = ?', id) do |task|
first = 1
f.print 'Task[' + (task[2].to_i == 1 ? 'X' : ' ') + ']: '
task[1].split(/\n/).each do |line|
if first
f.puts line
first = 0
else
f.puts "\t" + line
end
end
end


f.close
# Edit tmpfile
m1 = File.mtime(tmpfile);
system(ENV['EDITOR'], tmpfile)
m2 = File.mtime(tmpfile);
if m2 != m1
# Read tmpfile
data = Filereader.read_file(tmpfile)
event = Event.init_from_hash(data)
if event
db.execute('UPDATE events SET name = ?, location = ?, date = ? WHERE id = ?', event.name, event.location, event.datestring, id)
db.execute('DELETE FROM tasks WHERE tasks.event = ?', id)
event.each_task do |task|
db.execute('INSERT INTO tasks(content, status, event) VALUES(?, ?, ?)', task.content, task.status, row[0])
end
else
$stderr.puts "Null event given; skipping."
end
else
$stderr.puts "Null event given; skipping."
end
File.delete(tmpfile)
end

when 'delete-event'
db = init_db(File.join(ENV['HOME'], '.sched_db'))
selectors, svars = parse_selectors(ARGV[1..-1]) do |selectors, svars, parts|
option = parts[0]
value = parts[1..-1].join('=')
case option
when 'name', 'location', 'date', 'id'
selectors['events.' + option] = (value ? value : '')
else
raise 'Unknown selector: ' + option
end
end
query = 'SELECT events.id FROM events'
args = []
first = 1
if selectors.length > 0
query << ' WHERE'
end
selectors.each do |key, value|
query << (first > 0 ? ' ' : ' AND ') + key + ' LIKE ?'
args.push(value)
first -= 1
end
db.execute(query, *args) do |row|
db.execute('DELETE FROM events WHERE events.id = ?', row[0])
db.execute('DELETE FROM tasks WHERE tasks.event = ?', row[0])
end
when 'delete-recurrence'
db = init_db(File.join(ENV['HOME'], '.sched_db'))
selectors = Hash.new
recursive = 0
selectors, svars = parse_selectors(ARGV[1..-1]) do |selectors, svars, parts|
if parts.length >= 2
option = parts[0]
value = parts[1..-1].join('=')
case option
when 'name', 'location', 'date', 'id'
selectors['events.' + option] = (value ? value : '')
else
raise 'Unknown selector: ' + option
end
elsif parts.length == 1
option = parts[0]
case option
when 'recursive'
svars['recursive'] = 1
else
raise 'Unknown option: --' + parts.join('=')
end
end
end
query = 'SELECT recurrences.id FROM recurrences'
args = []
first = 1
if selectors.length > 0
query << ' WHERE'
end
selectors.each do |key, value|
query << (first > 0 ? ' ' : ' AND ') + key + ' LIKE ?'
args.push(value)
first -= 1
end
db.execute(query, *args) do |row|
if svars['recursive'] == 1 # Recursive deletion
db.execute('SELECT events.id FROM events WHERE events.recurrence = ?', row[0]) do |event|
db.execute('DELETE FROM events WHERE id = ?', event[0])
db.execute('DELETE FROM tasks WHERE event = ?', event[0])
end
else # Disconnects events from the recurrence
db.execute('UPDATE events SET recurrence = ? WHERE recurrence = ?', -1, row[0])
end
end

when 'list-events'
db = init_db(File.join(ENV['HOME'], '.sched_db'))
selectors, svars = parse_selectors(ARGV[1..-1]) do |selectors, svars, parts|
if parts.length >= 2
option = parts[0]
value = parts[1..-1].join('=')
case option
when 'name', 'location', 'date'
selectors['events.' + option] = (value ? value : '')
else
raise 'Unknown selector: ' + option
end
elsif parts.length == 1
option = parts[0]
case option
when 'glob'
svars['glob'] = 1
else
raise 'Unknown option: --' + parts.join('=')
end
end
end
list_events(db, selectors, svars['glob'])
when 'list-tasks'
db = init_db(File.join(ENV['HOME'], '.sched_db'))
selectors = Hash.new
glob = 0
selectors, svars = parse_selectors(ARGV[1..-1]) do |selectors, svars, parts|
if parts.length >= 2
option = parts[0]
value = parts[1..-1].join('=')
case option
when 'name', 'location', 'date'
selectors['events.' + option] = (value ? value : '')
when 'content', 'status'
selectors['tasks.' + option] = (value ? value : '')
else
raise 'Unknown selector: ' + option
end
elsif parts.length == 1
option = parts[0]
case option
when 'glob'
svars['glob'] = 1
else
raise 'Unknown option: --' + parts.join('=')
end
end
end
list_tasks(db, selectors, svars['glob'])
when 'complete-tasks'
db = init_db(File.join(ENV['HOME'], '.sched_db'))
selectors = Hash.new
glob = 0
selectors, svars = parse_selectors(ARGV[1..-1]) do |selectors, svars, parts|
if parts.length >= 2
option = parts[0]
value = parts[1..-1].join('=')
case option
when 'content', 'id', 'event'
selectors[option] = (value ? value : '')
else
raise 'Unknown selector: ' + option
end
elsif parts.length == 1
option = parts[0]
case option
when 'glob'
svars['glob'] = 1
else
raise 'Unknown option: --' + parts.join('=')
end
end
end
query = 'UPDATE tasks SET status = 1'
args = []
first = 1
if selectors.length > 0
query << ' WHERE'
end
selectors.each do |key, value|
query << (first > 0 ? ' ' : ' AND ') + key + (glob == 1 ? ' GLOB ?' : ' LIKE ?')
args.push(value)
first -= 1
end
db.execute(query, *args)
when 'list-recurrences'
db = init_db(File.join(ENV['HOME'], '.sched_db'))
else
$stderr.puts 'Unknown command: ' + ARGV[0]
end
rescue
$stderr.puts 'Error: ' + $!
ensure
if db
db.close
end
end
else
$stderr.puts 'Usage: ' + $0 + ' [ --create-event | --create-recurrence | --edit-event | --delete-event | --delete-recurrence | --list-events | --list-tasks | --list-recurrences ] ...'
$stderr.puts "\tEDITOR must be set: currently \"" + (ENV['EDITOR'] and ENV['EDITOR'] or '') + "\""
end