source: project/release/4/awful/extra/doc/examples @ 25608

Last change on this file since 25608 was 25608, checked in by Mario Domenech Goulart, 9 years ago

awful (doc): fixed links to screencasts

File size: 11.2 KB
Line 
1=== Examples
2
3Here are some simple examples using assorted awful features.
4
5
6==== Number guessing game
7
8A screencast showing this example is available at
9[[http://parenteses.org/mario/awful/awful-guess.ogv|http://parenteses.org/mario/awful/awful-guess.ogv]]
10
11This examples shows a simple guessing game. A random number is
12generated on the server side and the user tries to guess it.  It shows
13some basic ajax features.
14
15<enscript highlight=scheme>
16(use awful html-tags)
17
18(enable-ajax #t)
19
20(define (prompt-guess)
21  (<input> type: "text" id: "guess"))
22
23(define-page (main-page-path)
24  (lambda ()
25    (ajax "try-guess" 'guess 'change
26          (lambda ()
27            (let ((guess ($ 'guess as-number))
28                  (thinking (random 10)))
29              (<p> (if (and guess (= guess thinking))
30                       "You guessed it right!"
31                       (conc "You guessed it wrong. I'm thinking " thinking ".")))))
32            target: "verdict"
33            arguments: '((guess . "$('#guess').val()")))
34    (++ (<p> "Guess the number I'm thinking:")
35        (prompt-guess)
36        (<div> id: "verdict"))))
37</enscript>
38
39To run it, execute:
40
41  $ awful number-guess.scm
42
43(considering you saved the code above in a file called
44{{number-guess.scm}}), then access {{http://localhost:8080}}.
45
46
47
48==== Sandboxed Chicken Web REPL
49
50This example was featured in the
51[[http://gazette.call-cc.org/issues/10.html|Chicken Gazette #10]].
52
53It shows how to implement a very simple web-based Chicken REPL using a
54sandbox environment (see the
55[[http://wiki.call-cc.org/egg/sandbox|sandbox egg]] documentation) for
56safe evaluation.
57
58The idea is to have a web page with an input box. Users type the forms
59they want to evaluate and submit them to the server. The server
60evaluates the given forms in a sandbox environment and return the
61results.
62
63Here's the commented code:
64
65<enscript highlight=scheme>
66(use html-tags awful sandbox)
67
68;; Here we define the REPL page.  It uses the session to store the
69;; sandboxed environment.  By default, the `main-page-path' parameter
70;; value is "/".
71(define-session-page (main-page-path)
72  (lambda ()
73
74    ;; Create the sandbox environment (if it does not exist yet) and
75    ;; store it in the user session.
76    (unless ($session 'sandbox-env)
77      ($session-set! 'sandbox-env
78                     (make-safe-environment
79                      parent: default-safe-environment
80                      mutable: #t
81                      extendable: #t)))
82
83    ;; Here we set an ajax handler for the REPL expressions
84    ;; submission.  When users change the REPL input widget (i.e., by
85    ;; pressing ENTER), the contents of the text input field are
86    ;; submitted and handled by the procedure given as the forth
87    ;; argument to `ajax'.
88    (ajax "eval" 'repl-input 'change
89          (lambda ()
90
91            ;; This binds the variable `repl-input' from the POST
92            ;; method the the `repl-input' Scheme variable
93            (let ((repl-input ($ 'repl-input)))
94
95              ;; We'd better handle exceptions when trying to
96              ;; evaluate the expressions given by users.
97              (handle-exceptions
98               exn
99               ;; If something goes wrong, we print the error message
100               ;; and the call chain.
101               (<pre> convert-to-entities?: #t
102                      (with-output-to-string
103                        (lambda ()
104                          (print-error-message exn)
105                          (print-call-chain))))
106               ;; Here we try to evaluate the given expression in the
107               ;; sandboxed environment stored in the user session.
108               ;; The `repl-output' page div is updated with the result.
109               (<pre> convert-to-entities?: #t
110                      (safe-eval
111                       (with-input-from-string repl-input read)
112                       fuel: 100
113                       allocation-limit: 100
114                       environment: ($session 'sandbox-env))))))
115
116          ;; Here we pass the contents of the text input to the ajax
117          ;; handler.  The default HTTP method used by `ajax' is POST.
118          arguments: `((repl-input . "$('#repl-input').val()"))
119
120          ;; The output of the ajax handler updates the `repl-output'
121          ;; page div.
122          target: "repl-output")
123
124    ;; Here's what is displayed to users
125    (++ (<h1> "Sandboxed Chicken web REPL")
126        (<input> type: "text" id: "repl-input")
127        (<div> id: "repl-output")))
128
129  ;; This tells `define-session-page' to link the page to JQuery
130  use-ajax: #t)
131</enscript>
132
133To run the code above you'll need to install awful and sandbox:
134
135  $ chicken-install awful sandbox
136
137Then (considering you save the code above in a file called {{web-sandbox.scm}}), run:
138
139  $ awful web-sandbox.scm
140
141and access {{http://localhost:8080}}.
142
143
144Here are some screenshots of the code above running on Firefox:
145
146[[image:http://gazette.call-cc.org/img/10/web-sandbox.png|Screenshot of the sandboxed web REPL running on Firefox]]
147
148If you try something nasty, the sandbox will abort the evaluation and you'll get an error message and the call chain:
149
150[[image:http://gazette.call-cc.org/img/10/web-sandbox-loop.png|Screenshot of the sandboxed web REPL running on Firefox]]
151
152We can also compile the web application:
153
154 $ csc -s web-sandbox.scm
155 $ awful web-sandbox.so
156
157
158==== Color chooser
159
160Here's an example provided by
161[[http://wiki.call-cc.org/users/christian-kellermann|Christian Kellermann]] demonstrating an ajax-based color chooser:
162
163<enscript highlight=scheme>
164(use awful html-utils html-tags)
165
166(define color-table
167  '("f63353" "fead76" "107279" "10fabc" "1181bf" "120902" "129105"
168    "131848" "13a04b" "1427ee" "14a8b1" "1532d4" "15bcf7" "16671a"
169    "16c13d" "175b60" "17d583" "186fa6" "18ecc9" "1973ec"))
170
171(enable-ajax #t)
172
173(define (color-picker counter color)
174  (<div> class: "color-box" style: (conc  "background-color: " (conc "#" color))
175         (text-input (conc "change-color-" counter) value: color)))
176
177(define (make-color-chooser counter c)
178  (ajax "ajax" (conc "#change-color-" counter) 'change
179        (lambda ()
180          (let ((color (or ($ 'color) c))
181                (counter ($ 'counter)))
182            (color-picker counter color)))
183        target: (conc "color-box-" counter)
184        arguments: `((color . ,(conc  "$('#change-color-" counter "').val()"))
185                     (counter . ,counter))
186        live: #t)
187  (<div> id: (conc "color-box-" counter) (color-picker counter c)))
188
189(define-page (main-page-path)
190  (lambda ()
191    (concat (map (let ((counter -1))
192                   (lambda (c)
193                     (set! counter (add1 counter))
194                     (make-color-chooser counter c)))
195                 color-table))))
196
197</enscript>
198
199Here's a screenshot:
200
201[[image:http://parenteses.org/mario/img/awful/color-chooser.png|Awful color chooser]]
202
203To run this example (considering you save the code above in a file called {{color-chooser.scm}}):
204
205  $ awful color-chooser.scm
206
207then access {{http://localhost:8080}}.  You can change the colors by
208editing the input boxes then pressing enter.
209
210
211==== Fortune server
212
213This example is a fortune server in awful.  It demonstrates some handy
214awful features like database access and ajax.  You'll need the
215[[http://wiki.call-cc.org/egg/awful-sql-de-lite|awful-sql-de-lite]]
216egg and its dependencies (which should be automatically installed by
217{{chicken-install}}).
218
219Here are instructions to install and use it:
220
2211. Install [[http://wiki.call-cc.org/egg/awful-sql-de-lite|awful-sql-de-lite]]
222
223   $ chicken-install awful-sql-de-lite
224
225
2262. Create the fortunes database (see the code below):
227
228   $ csi -s create-database.scm
229
230
2313. Run the fortune server (see the code below):
232
233   $ awful fortune-server.scm
234
235
236Here's the code for {{create-database.scm}} which creates and populates the fortune database:
237
238<enscript highlight=scheme>
239(use sql-de-lite posix)
240
241(define fortunes
242  '(("Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it."
243     "Brian Kernighan")
244    ("In order to understand recursion, one must first understand recursion.")
245    ("If debugging is the process of removing software bugs, then programming must be the process of putting them in."
246     "Edsger Dijkstra")
247    ("Controlling complexity is the essence of computer programming."
248     "Brian Kernigan")
249    ("The function of good software is to make the complex appear to be simple."
250     "Grady Booch")
251    ("That's the thing about people who think they hate computers.  What they really hate is lousy programmers."
252     "Larry Niven")
253    ("First learn computer science and all the theory.  Next develop a programming style.  Then forget all that and just hack."
254    "George Carrette")
255    ("To iterate is human, to recurse divine."
256    "L. Peter Deutsch")
257    ("The best thing about a boolean is even if you are wrong, you are only off by a bit.")
258    ("Optimism is an occupational hazard of programming; feedback is the treatment."
259     "Kent Beck")
260    ("Simplicity is prerequisite for reliability."
261     "Edsger W. Dijkstra")
262    ("Simplicity is the ultimate sophistication."
263     "Leonardo da Vinci")
264    ("The unavoidable price of reliability is simplicity."
265     "C.A.R. Hoare")
266    ("The ability to simplify means to eliminate the unnecessary so that the necessary may speak."
267     "Hans Hoffmann")
268    ("Simplicity is hard to build, easy to use, and hard to charge for. Complexity is easy to build, hard to use, and easy to charge for."
269     "Chris Sacca")))
270
271(delete-file* "fortunes.db")
272
273(let ((db (open-database "fortunes.db")))
274  (exec (sql db "create table fortunes(sentence text, author text)"))
275  (for-each (lambda (fortune)
276              (let* ((sentence (car fortune))
277                     (author (cdr fortune))
278                     (statement
279                      (string-append
280                       "insert into fortunes (sentence, author) values (?,?)")))
281                (exec (sql db statement)
282                      sentence
283                      (if (null? author) "" (car author)))))
284            fortunes)
285  (close-database db))
286</enscript>
287
288Here's the code for the fortune server:
289
290<enscript highlight=scheme>
291(use awful html-tags awful-sql-de-lite)
292
293(enable-db)
294(db-credentials "fortunes.db")
295
296(define (random-fortune)
297  (car ($db "select sentence, author from fortunes order by random() limit 1")))
298
299(define-page (main-page-path)
300  (lambda ()
301    (ajax "new-fortune" 'new-fortune 'click
302          (lambda ()
303            (let ((fortune (random-fortune)))
304              `((sentence . ,(car fortune))
305                (author . ,(cadr fortune)))))
306          update-targets: #t)
307
308    (<div> id: "content"
309           (<div> id: "sentence" "Click the button below to get a new fortune")
310           (<div> id: "author")
311           (<button> id: "new-fortune" "New fortune")))
312
313  css: "fortune.css"
314  use-ajax: #t
315  charset: "utf-8")
316</enscript>
317
318
319The contents of the {{fortune.css}} file are:
320
321  body
322  { font-family: arial, verdana, sans-serif;
323  }
324 
325  #sentence
326  { width: 20em;
327    background-color: #DEE7EC;
328    padding: 6px;
329    min-height: 7em;
330  }
331 
332  #author
333  { width: 20em;
334    min-height: 2em;
335    padding: 6px;
336    background-color: #eee;
337  }
338
339Here's a screenshot:
340
341[[image:http://parenteses.org/mario/img/awful/fortune-server.png|Awful fortune server]]
Note: See TracBrowser for help on using the repository browser.