object SimpleDatabase extends App { type Entry = Array[String] def asTSV(e: Entry) = e mkString "\t" def fromTSV(s: String) = s split "\t" val header = asTSV(Array("TIMESTAMP", "DESCRIPTION", "CATEGORY", "OTHER")) def read(filename: String) = try { scala.io.Source.fromFile(filename).getLines.drop(1).map(fromTSV) } catch { case e: java.io.FileNotFoundException => Nil } def write(filename: String, all: Seq[Entry]) = { import java.nio.file.{Files,Paths} import scala.collection.JavaConversions.asJavaIterable Files.write(Paths.get(filename), asJavaIterable(header +: all.map(asTSV))) all.size } def add(filename: String, description: String, category: String = "none", optional: Seq[String] = Nil) { val format = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss") val e = Array(format.format(new java.util.Date), description, category) ++ optional println(write(filename, read(filename).toBuffer :+ e) + " entries") } def print(filename: String, filter: Seq[Entry] => TraversableOnce[Entry]) = filter(read(filename).toList.sortBy(_.headOption)) map(_ mkString ",") foreach println args match { case Array(f, "latest") => print(f, _ takeRight 1) case Array(f, "latest", cat) => print(f, _ filter(_.lift(2) == Some(cat)) takeRight 1) case Array(f, "all") => print(f, _.toSeq) case Array(f, "all", "latest") => print(f, _ groupBy (_ lift 2 getOrElse "") map{case (_, cat) => cat.last}) case Array(f, "add", desc) => add(f, desc, category = "") case Array(f, "add", desc, cat, opt @ _*) => add(f, desc, cat, opt) case _ => println("Usage: SimpleDatabase filename.tsv [all [latest]| latest [CATEGORY] | add [DESCRIPTION [CATEGORY [OPTIONAL]...]]]") } }