(archive 'newLISPer)

August 3, 2006


Filed under: newLISP — newlisper @ 00:27


The famous Hungarian-born photographer Brassai, ‘the eye of Paris’, used to time the long exposures of his night-time photographs by smoking a cigarette: after opening the shutter, he lit a cigarette, waited until it had burnt down, then closed the shutter again. He used the cheap, fast-burning Gauloise for brighter scenes and a more expensive, slower burning, brand such as Boyard for darker conditions.

I liked this story when I first heard it many years ago – something about the creative maverick genius striding around the streets of Paris at night solving problems with some casual lateral thinking, or something.

No such luck with the following, I’m afraid. It’s all strictly digital and stolidly unromantic. I wanted a timer that would wait a given number of seconds before sounding an alarm. Looking through the applications on my computer, I realised that I didn’t have such a thing installed – I’ve got plenty of alarms and calendars, but no countdown timers. I found a little dashboard widget on a web site somewhere, but that didn’t work for me. And I’m not a smoker so I didn’t have anything that would reliably take a precise number of minutes… So I thought it shouldn’t be too difficult to write a countdown timer in newLISP.

The reason it’s ended up as a Unix command-line utility is the problem of a user interface: it’s still easier for me to write a command-line program that accepts text input than to write any kind of application with a nice graphical interface. Until something suitable comes along for newLISP, this cool 1970s technology is about the only thing I can use.

(unless (main-args 2)
    (begin (println "usage: countdown duration [message]\nspecify duration in seconds or h:m:s")
(define (set-duration)
" convert input to seconds "
  (set 'duration
    (dolist (e (reverse (parse duration-input ":")))
     (if (!= "" e)
      (inc 'duration (mul (int e) ('(1 60 3600 86400) $idx)))))))
(define (seconds->hms s)
" convert seconds to h:m:s display"
    ((secs (mod s 60))
     (mins (mod (div s 60) 60))
     (hours (mod (div s 3600) 24)))
    (format "%02d:%02d:%02d" hours mins secs)))
(define (clear-screen-normans-way)
    (println "27[H27[2J"))
(define (notify announcement)
    " this is platform-specific"
    " on Mac, do some beeps and growls, and speak the supplied announcement"
    (exec (string {osascript -e 'tell application "Finder" to beep 3'}))
    (if (!= announcement nil) (exec (string [text]osascript -e 'say "[/text] announcement [text]"'[/text])))
    (exec (format "/usr/local/bin/growlnotify %s -m \"Finished count down \"" (date (date-value) 0 "%Y-%m-%d %H:%M:%S"))))
; start
(set 'duration-input (main-args 2) 'duration 0)
(set 'start-time (date-value) 'target-time (add (date-value) duration))
(set 'banner
    (string  "Started countdown of "
        (seconds->hms duration)
        " at "
        (date start-time 0 "%Y-%m-%d %H:%M:%S")
        "\nFinish time:                     " (date target-time 0 "%Y-%m-%d %H:%M:%S")))
(while (<= (date-value) target-time)
    (println banner "\n\n"
        "Elapsed: "
        (seconds->hms (- (date-value) start-time ))
        " Remaining: "
        (seconds->hms (abs (- (date-value) target-time))))
    (sleep 1000))
; finished
(println "Countdown completed at " (date (date-value) 0 "%Y-%m-%d %H:%M:%S") "\n")
(notify (main-args 3))


  1. >I like Minuteur for both countdowns and stopwatch type functionality.

    Comment by Anonymous — August 9, 2006 @ 16:45 | Reply

  2. >That’s very nice – some real programming! Pity I didn’t find it in time….

    Comment by newlisper — August 9, 2006 @ 16:50 | Reply

  3. >Your NO rooky anymore ;-) You log is so extended i think we are the rooky’s now ;-) Good work C! keep it up !

    Comment by Anonymous — August 9, 2006 @ 19:57 | Reply

  4. >I’ve copied over your countdown timer code. I like text-based interfaces. When I tried to learn programming on my Commodore 128, all I ever did was design cool ways of displaying plain text. My favorite way was a simulation of a person’s typing. With all the random pauses, spurts, and mistakes. I think I also wrote some newLISP to do this when I was first starting to learn it. If I did, maybe I can finally be able to post something to newLISPer, again! One thing I tried before actually seeing how to use your function was to use an expression for the duration: (countdown (* 60 30) “cor! ‘mullion’s countdown timer is cool.”). This seems like an acceptable modification to make. Maybe I’ll race you for the solution ;-)m i c h a e l

    Comment by m i c h a e l — August 9, 2006 @ 23:40 | Reply

  5. >Well, I suppose you could have an evaluated expression for time by inserting this line before line 7 (if (string? duration-input) (set ‘duration-input (string (eval-string duration-input))))but I can’t let you type “cor! ‘mullion’s …” because of the shell’s quotation quirkiness and bang wizardry. Which I’m sure someone can solve… :-)Your challenge: rewrite it to be more elegant!

    Comment by newlisper — August 10, 2006 @ 08:15 | Reply

  6. >Ha. Well that suggestion broke the “:” parsing, so better something like this:(if (starts-with duration-input “(“) (set ‘duration-input (string (eval-string duration-input))))- if you supply an expression in parentheses it will evaluate it first, otherwise it will get parsed as a d:h:m:s duration.

    Comment by newlisper — August 10, 2006 @ 08:53 | Reply

RSS feed for comments on this post. TrackBack URI

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Blog at WordPress.com.

%d bloggers like this: