-
Notifications
You must be signed in to change notification settings - Fork 0
/
vote.lisp
executable file
·127 lines (105 loc) · 3.87 KB
/
vote.lisp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
;#!/usr/local/bin/sbcl --script
(let ((quicklisp-init (merge-pathnames "quicklisp/setup.lisp"
(user-homedir-pathname))))
(when (probe-file quicklisp-init)
(load quicklisp-init)))
(ql:quickload "cl-who")
(ql:quickload "hunchentoot")
(ql:quickload "parenscript")
(defpackage :vote (:use :cl :cl-who :hunchentoot :parenscript))
(in-package :vote)
(hunchentoot:start (make-instance 'hunchentoot:easy-acceptor :port 8080))
(defmacro define-url-fn ((name) &body body)
`(progn
(defun ,name ()
,@body)
(push (create-prefix-dispatcher ,(format nil "/~(~a~).htm" name) ',name) *dispatch-table*)))
; VARS
(defclass counter ()
((name :initarg :name :accessor name)
(description :initarg :description :accessor description)
(votes :initform 0 :accessor votes)))
(defvar *counter-actions* nil)
(defmacro def-counter-action (name argname &body body)
`(progn
(push ,name *counter-actions*)
(hunchentoot:define-easy-handler (,(intern name) :uri ,(format nil "/~a.htm" name)) (name)
(let ((,argname (counter-by-name name)))
,@body
(redirect (format nil "/counter.htm?name=~a" (name ,argname)))))))
(defmacro render-counter-actions (counter)
`(dolist (action *counter-actions*)
(htm
(:a :href (format nil "~a.htm?name=~a" action (name ,counter)) (fmt "~a" action))
(:br))))
(def-counter-action "up vote" counter
(incf (votes counter)))
(def-counter-action "down vote" counter
(decf (votes counter)))
(defvar *counters* nil)
(defun add-counter (name description)
(push (make-instance 'counter :name name :description description) *counters*))
(defun counters ()
(copy-list *counters*))
(defun counter-by-name (name)
(find name *counters* :test #'string-equal
:key #'name))
; PAGES
(defmacro standard-page ((&key title) &body body)
`(with-html-output-to-string (*standard-output* nil :prologue t :indent t)
(:html :xmlns "http://www.w3.org/1999/xhtml"
:xml\:lang "en"
:lang "en"
(:head
(:meta :http-equiv "Content-Type"
:content "text/html;charset=utf-8")
(:title ,title))
(:body
(:div :id "header"
(:h2 :class "strapline"
"Give your vote"))
,@body))))
; HANDLERS
(define-url-fn (counter-create)
(let ((name (parameter "name"))
(description (parameter "description")))
(unless (or (null name) (zerop (length name)))
(add-counter name description))
(redirect "/")))
(define-url-fn (counter)
(let ((counter (counter-by-name (parameter "name"))))
(standard-page (:title "Vote Lisp")
(:h2 (fmt "~a" (name counter)))
(:i (fmt "~a" (description counter)))
(:p (fmt "It currently has ~d votes" (votes counter)))
(render-counter-actions counter)
(:br)
(:a :href "/" "Back"))))
(hunchentoot:define-easy-handler (index :uri "/") ()
(standard-page (:title "Vote Lisp")
(:h1 "Vote Lisp")
(:ol
(dolist (counter (counters))
(htm
(:li
(:a :href (format nil "counter.htm?name=~a" (name counter)) (fmt "~A" (name counter)))))))
(:a :href "counter-new.htm" "Add new counter")))
(hunchentoot:define-easy-handler (new :uri "/counter-new.htm") ()
(standard-page (:title "Vote Lisp")
(:h1 "Available titles")
(:form :action "/counter-create.htm" :method "post"
(:p "Title" (:br)
(:input :type "text"
:name "name"
:class "txt"))
(:p "Description" (:br)
(:input :type "text"
:name "description"
:class "txt"))
(:p (:input :type "submit"
:value "Add"
:class "btn")))))
(add-counter "Lola" "lolita")
(add-counter "Lolame" "la lola")
(add-counter "Lolitas" "las lolitas")
(read-line *query-io*)