#!/bin/sh #-*-scheme-*- exec /home/gbenison/local-env guile -s $0 2>/dev/null # exec guile -s 2>>guile-error.txt $0 $@ !# (use-modules (srfi srfi-1) (sxml simple) (www cgi)) (define default-min-word-length 5) ; ---------- utilities ---------- (define (string-depunctuate str) (list->string (filter char-alphabetic? (string->list str)))) (define (count-occurences xs) (fold (lambda (next result) (if (and (not (null? result)) (equal? (caar result) next)) (cons (cons (caar result) (+ (cdar result) 1)) (cdr result)) (cons (cons next 1) result))) '() xs)) (define (string-not-empty? str) (> (string-length str) 0)) (define (string-longer-than? n) (lambda (str)(> (string-length str) n))) (define (word-usage msg) (count-occurences (sort (filter (string-longer-than? (- min-word-length 1)) (map string-depunctuate (string-tokenize (string-downcase msg)))) string? a b)(> (cdr a)(cdr b))) (define (top-word-usage msg n) (take-at-most (sort (word-usage msg) cdr>?) n)) (define (format-usage usage) (format #f "~a -- ~a occurrences" (car usage)(cdr usage))) (define (as-li content) `(li ,content)) ; ------ output ----------- (cgi:init) (define input (and (cgi:form-data?) (car (cgi:values "input-content")))) (define min-word-length (or (false-if-exception (string->number (car (cgi:values "min-length")))) default-min-word-length)) (display "Content-type: text/html\n\n") (sxml->xml `(html (head (title "wc demo") (link (@ (rel "stylesheet")(type "text/css")(href "style/word-usage.css")))) (body (h1 (a (@ (href ,(car (command-line)))) "Word count demo")) (p "This is a toy web application written in Scheme by " (a (@ (href "http://www.linkedin.com/in/gregorybenison"))"Greg Benison") ". I blogged about it " (a (@ (href "http://gcbenison.wordpress.com/2012/02/19/guile-vs-php"))"here") ". " "Check out the " (a (@ (href "src/word-usage")) "source code") ", or try pasting in the text of an email " "or a chapter from a favorite book below!" ) ,(if input `(p "Top words of at least " ,min-word-length " characters:" (ul ,(map as-li (map format-usage (top-word-usage input 5))))) '(p "Enter some text below, to count word usage:"))) (form (@ (method "post") (name "input-form") (action ,(car (command-line)))) (textarea (@ (name "input-content") (rows 20) (cols 60)) ,(or input "")) (p "Minimum word length: " (input (@ (type "text") (name "min-length")))) (input (@ (type "submit") (name "input-submit") (value "Determine word usage")))))))