Can now add marks. Display is single-threaded, refresh on command.
Also implemented save and quit (including cases for Ctrl-D, `exit`, and `quit`)
This commit is contained in:
parent
769245b690
commit
f78cd57ec7
@ -1,4 +1,5 @@
|
|||||||
|
#Thu, 08 Aug 2013 19:52:35 -0500
|
||||||
lib.local=true
|
lib.local=true
|
||||||
name=timestamper-cli
|
name=timestamper-cli
|
||||||
version=0.1
|
version=0.1
|
||||||
build.number=0
|
build.number=29
|
||||||
|
@ -84,48 +84,95 @@ public class TimeStamperCLI {
|
|||||||
|
|
||||||
//out.println ""
|
//out.println ""
|
||||||
def currentMarker = timeline.getLastMarker(new Date())
|
def currentMarker = timeline.getLastMarker(new Date())
|
||||||
|
Reader reader = new InputStreamReader(sin)
|
||||||
|
|
||||||
boolean running = true
|
boolean running = true
|
||||||
|
|
||||||
def reader = new NonBlockingReader(sin)
|
def readNotes = {
|
||||||
def readerThread = new Thread(reader)
|
out.println(ansi().fg(YELLOW).
|
||||||
readerThread.start()
|
a("Notes (end with EOF or a blank line):").reset())
|
||||||
|
|
||||||
def blockingReadLine = {
|
String notes = ""
|
||||||
String line = null;
|
String line = null
|
||||||
while (line == null && readerThread.isAlive()) {
|
|
||||||
line = reader.readLine()
|
line = reader.readLine()
|
||||||
|
|
||||||
Thread.sleep(200) }
|
while(line != "" && line != "EOF" && line != null) {
|
||||||
|
notes += line + EOL
|
||||||
|
line = reader.readLine() }
|
||||||
|
|
||||||
return line }
|
return notes
|
||||||
|
|
||||||
String line = null
|
|
||||||
println ""
|
|
||||||
while (running && readerThread.isAlive()) {
|
|
||||||
|
|
||||||
// Refresh the display
|
|
||||||
out.print(
|
|
||||||
ansi().saveCursorPosition().
|
|
||||||
cursorUp(1).eraseLine(Erase.ALL).fgBright(CYAN).
|
|
||||||
a(Timeline.shortFormat.format(currentMarker.timestamp) + " ").
|
|
||||||
fg(GREEN).a("(" + getDuration(currentMarker) + ") ").
|
|
||||||
fg(WHITE).a(currentMarker.mark).a(EOL).restorCursorPosition()
|
|
||||||
)
|
|
||||||
|
|
||||||
// Handle user input
|
|
||||||
if ((line = reader.readLine()) != null) {
|
|
||||||
if (line =~ /quit|exit/) running = false }
|
|
||||||
|
|
||||||
Thread.sleep(200); }
|
|
||||||
|
|
||||||
if (readerThread.isAlive()) {
|
|
||||||
readerThread.interrupt();
|
|
||||||
readerThread.join(500);
|
|
||||||
if (readerThread.isAlive()) readerThread.stop(); }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected String getDuration(TimelineMarker tm) {
|
String line = null
|
||||||
|
|
||||||
|
while (running) {
|
||||||
|
|
||||||
|
out.println formatMarker(currentMarker)
|
||||||
|
out.print(ansi().fg(YELLOW).a("> ").reset())
|
||||||
|
out.flush();
|
||||||
|
|
||||||
|
// Handle user input
|
||||||
|
line = reader.readLine()
|
||||||
|
|
||||||
|
switch (line) {
|
||||||
|
|
||||||
|
case null:
|
||||||
|
case ~/quit|exit|\u0004/:
|
||||||
|
running = false;
|
||||||
|
break
|
||||||
|
|
||||||
|
case ~/r|refresh|^$/:
|
||||||
|
out.print(ansi().eraseLine().cursorUp(2).eraseLine())
|
||||||
|
break
|
||||||
|
|
||||||
|
case ~/n|new/:
|
||||||
|
|
||||||
|
// Read mark
|
||||||
|
out.println(ansi().fg(YELLOW).a("New timestamp:").reset())
|
||||||
|
String mark = reader.readLine()
|
||||||
|
|
||||||
|
// Read notes
|
||||||
|
String notes = readNotes();
|
||||||
|
|
||||||
|
// Create marker
|
||||||
|
currentMarker = new TimelineMarker(new Date(), mark, notes)
|
||||||
|
timeline.addMarker(currentMarker)
|
||||||
|
if (timelineProperties.persistOnUpdate)
|
||||||
|
timelineProperties.save()
|
||||||
|
break
|
||||||
|
|
||||||
|
case ~/h|help/:
|
||||||
|
out.println(ansi().eraseLine().
|
||||||
|
fg(RED).a("Not yet implemented."));
|
||||||
|
break
|
||||||
|
|
||||||
|
case ~/l|list|history/:
|
||||||
|
out.println(ansi().eraseLine().
|
||||||
|
fg(RED).a("Not yet implemented."));
|
||||||
|
break
|
||||||
|
|
||||||
|
case ~/s|save/:
|
||||||
|
timelineProperties.save()
|
||||||
|
break
|
||||||
|
|
||||||
|
default:
|
||||||
|
String notes = readNotes()
|
||||||
|
currentMarker = new TimelineMarker(new Date(), line, notes)
|
||||||
|
timeline.addMarker(currentMarker)
|
||||||
|
if (timelineProperties.persistOnUpdate)
|
||||||
|
timelineProperties.save()
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static String formatMarker(TimelineMarker tm) {
|
||||||
|
return ansi().fgBright(CYAN).
|
||||||
|
a(Timeline.shortFormat.format(tm.timestamp) + " ").fg(GREEN).
|
||||||
|
a("(" + getDuration(tm) + ") ").fg(WHITE).a(tm.mark).toString() }
|
||||||
|
|
||||||
|
protected static String getDuration(TimelineMarker tm) {
|
||||||
Date currentTime = new Date()
|
Date currentTime = new Date()
|
||||||
long seconds = currentTime.time - tm.timestamp.time
|
long seconds = currentTime.time - tm.timestamp.time
|
||||||
seconds /= 1000
|
seconds /= 1000
|
||||||
@ -144,23 +191,4 @@ public class TimeStamperCLI {
|
|||||||
|
|
||||||
return sb.toString() }
|
return sb.toString() }
|
||||||
|
|
||||||
class NonBlockingReader implements Runnable {
|
|
||||||
|
|
||||||
private Reader rin
|
|
||||||
private LinkedList buffer = []
|
|
||||||
|
|
||||||
public void run() {
|
|
||||||
String line = null
|
|
||||||
try {
|
|
||||||
while((line = rin.readLine()) != null &&
|
|
||||||
!Thread.currentThread().isInterrupted())
|
|
||||||
storeLine(line) }
|
|
||||||
catch (InterruptedException ie) { Thread.currentThread().interrupt() } }
|
|
||||||
|
|
||||||
public synchronized String readLine() { return buffer.poll() }
|
|
||||||
private synchronized void storeLine(String line) { buffer << line }
|
|
||||||
|
|
||||||
public NonBlockingReader(def sin) {
|
|
||||||
this.rin = new InputStreamReader(sin) }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user