Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

changed name of file upload setting; added documention for some parts…

… of the 'form' functionality
  • Loading branch information...
commit 9221a858d42a0625b625cb6eaa2dc1b222430111 1 parent 1819cb2
@vegashacker authored
View
6 files.scm
@@ -6,12 +6,12 @@
(provide save-uploaded-file-and-return-filename!)
-(declare-setting *PATH_TO_FILEDATA* (build-path (current-directory) "uploaded-files"))
+(declare-setting *PATH_TO_UPLOADED_FILES* (build-path (current-directory) "uploaded-files"))
(define (save-uploaded-file-and-return-filename! file-data)
(let* ((filename (fresh-filename-id (binding/string:file-filename file-data)))
(raw-file-bytes (binding/string:file-content file-data))
- (fport (open-output-file (build-path (setting *PATH_TO_FILEDATA*) filename)
+ (fport (open-output-file (build-path (setting *PATH_TO_UPLOADED_FILES*) filename)
#:exists 'error)))
(write-bytes raw-file-bytes fport)
(close-output-port fport)
@@ -19,6 +19,6 @@
(define (fresh-filename-id filename #:id-length (id-length 5))
(let ((try (string-append (random-key-string id-length) "-" filename)))
- (if (file-exists? (build-path (setting *PATH_TO_FILEDATA*) try))
+ (if (file-exists? (build-path (setting *PATH_TO_UPLOADED_FILES*) try))
(fresh-filename-id filename #:id-length id-length)
try)))
View
4 scribblings/leftparen.html
@@ -1,5 +1,5 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
-<html><head><meta http-equiv="content-type" content="text-html; charset=utf-8" /><title>LeftParen 0.4 Documentation</title><link rel="stylesheet" type="text/css" href="scribble.css" title="default" /><script type="text/javascript" src="scribble-common.js"></script></head><body><div class="tocset"><div class="tocview"><div class="tocviewlist" style="margin-bottom: 1em;"><div class="tocviewtitle"><table cellspacing="0" cellpadding="0"><tr><td style="width: 1em;"><a href="javascript:void(0);" title="Expand/Collapse" class="tocviewtoggle" onclick="TocviewToggle(this,&quot;tocview_0&quot;);">&#9658;</a></td><td></td><td><a href="file:///Users/rob/Documents/git-leftparen/scribblings/leftparen.html" class="tocviewselflink">Left<span class="mywbr"> </span>Paren 0.4 Documentation</a></td></tr></table></div><div class="tocviewsublistonly" style="display: none;" id="tocview_0"><table cellspacing="0" cellpadding="0"><tr><td align="right">1&nbsp;</td><td><a href="file:///Users/rob/Documents/git-leftparen/scribblings/leftparen.html#(part._.Installing_.Left.Paren)" class="tocviewlink">Installing Left<span class="mywbr"> </span>Paren</a></td></tr><tr><td align="right">2&nbsp;</td><td><a href="file:///Users/rob/Documents/git-leftparen/scribblings/leftparen.html#(part._tutorials)" class="tocviewlink">Tutorials</a></td></tr><tr><td align="right">3&nbsp;</td><td><a href="file:///Users/rob/Documents/git-leftparen/scribblings/leftparen.html#(part._.More_.Documentation_to_.Come)" class="tocviewlink">More Documentation to Come</a></td></tr><tr><td align="right">4&nbsp;</td><td><a href="file:///Users/rob/Documents/git-leftparen/scribblings/leftparen.html#(part._.Reference)" class="tocviewlink">Reference</a></td></tr><tr><td align="right">5&nbsp;</td><td><a href="file:///Users/rob/Documents/git-leftparen/scribblings/leftparen.html#(part._.About_.Acknowledgements)" class="tocviewlink">About/<span class="mywbr"> </span>Acknowledgements</a></td></tr></table></div></div></div><div class="tocsub"><table class="tocsublist" cellspacing="0"><tr><td><span class="tocsublinknumber">1<tt>&nbsp;</tt></span><a href="#(part._.Installing_.Left.Paren)" class="tocsubseclink">Installing Left<span class="mywbr"> </span>Paren</a></td></tr><tr><td><span class="tocsublinknumber">2<tt>&nbsp;</tt></span><a href="#(part._tutorials)" class="tocsubseclink">Tutorials</a></td></tr><tr><td><span class="tocsublinknumber">2.1<tt>&nbsp;</tt></span><a href="#(part._.Hello__.World)" class="tocsubseclink">Hello, World</a></td></tr><tr><td><span class="tocsublinknumber">2.2<tt>&nbsp;</tt></span><a href="#(part._.Blogerton_the_.Blog)" class="tocsubseclink">Blogerton the Blog</a></td></tr><tr><td><span class="tocsublinknumber">2.2.1<tt>&nbsp;</tt></span><a href="#(part._.Changes_to_app_scm)" class="tocsubseclink">Changes to <span class="stt">app.scm</span></a></td></tr><tr><td><span class="tocsublinknumber">2.2.2<tt>&nbsp;</tt></span><a href="#(part._.Changes_to_main_scm)" class="tocsubseclink">Changes to <span class="stt">main.scm</span></a></td></tr><tr><td><span class="tocsublinknumber">2.2.3<tt>&nbsp;</tt></span><a href="#(part._.Launch_.Blogerton)" class="tocsubseclink">Launch Blogerton</a></td></tr><tr><td><span class="tocsublinknumber">3<tt>&nbsp;</tt></span><a href="#(part._.More_.Documentation_to_.Come)" class="tocsubseclink">More Documentation to Come</a></td></tr><tr><td><span class="tocsublinknumber">4<tt>&nbsp;</tt></span><a href="#(part._.Reference)" class="tocsubseclink">Reference</a></td></tr><tr><td><span class="tocsublinknumber">4.1<tt>&nbsp;</tt></span><a href="#(part._.Forms)" class="tocsubseclink">Forms</a></td></tr><tr><td><span class="tocsublinknumber">4.2<tt>&nbsp;</tt></span><a href="#(part._.Sessions)" class="tocsubseclink">Sessions</a></td></tr><tr><td><span class="tocsublinknumber">4.2.1<tt>&nbsp;</tt></span><a href="#(part._.Creating_sessions)" class="tocsubseclink">Creating sessions</a></td></tr><tr><td><span class="tocsublinknumber">4.2.2<tt>&nbsp;</tt></span><a href="#(part._.Accessing_sessions)" class="tocsubseclink">Accessing sessions</a></td></tr><tr><td><span class="tocsublinknumber">5<tt>&nbsp;</tt></span><a href="#(part._.About_.Acknowledgements)" class="tocsubseclink">About/<span class="mywbr"> </span>Acknowledgements</a></td></tr><tr><td><span class="tocsublinknumber">5.1<tt>&nbsp;</tt></span><a href="#(part._.Contributors)" class="tocsubseclink">Contributors</a></td></tr></table></div></div><div class="maincolumn"><div class="main"><div class="versionbox"><span class="version">Version: 4.1.0.3</span></div><div class="navset" style="margin-bottom: 2em; border-bottom: 2px solid #e0e0c0;"><span class="navleft"><input style="width: 16em; margin: 0px; padding: 0px; background-color: #eee; color: #888; border: 1px solid #ddd; text-align: center; vertical-align: middle;" type="text" value="...search manuals..." title="Enter a search string to search the manuals" onkeypress="return DoSearchKey(event, this, &quot;4.1.0.3&quot;, &quot;&quot;);" onfocus="this.style.color=&quot;black&quot;; this.style.textAlign=&quot;left&quot;; if (this.value == &quot;...search manuals...&quot;) this.value=&quot;&quot;;" onblur="if (this.value.match(/^ *$/)) { this.style.color=&quot;#888&quot;; this.style.textAlign=&quot;center&quot;; this.value=&quot;...search manuals...&quot;; }" />&nbsp;&nbsp;</span>&nbsp;</div><h2><a name="(part._.Left.Paren_0_4_.Documentation)"></a>LeftParen 0.4 Documentation</h2><p>Website: <a href="http://leftparen.com">http://leftparen.com</a></p><p>LeftParen is a framework for quickly creating web apps. It runs on
+<html><head><meta http-equiv="content-type" content="text-html; charset=utf-8" /><title>LeftParen 0.4 Documentation</title><link rel="stylesheet" type="text/css" href="scribble.css" title="default" /><script type="text/javascript" src="scribble-common.js"></script></head><body><div class="tocset"><div class="tocview"><div class="tocviewlist" style="margin-bottom: 1em;"><div class="tocviewtitle"><table cellspacing="0" cellpadding="0"><tr><td style="width: 1em;"><a href="javascript:void(0);" title="Expand/Collapse" class="tocviewtoggle" onclick="TocviewToggle(this,&quot;tocview_0&quot;);">&#9658;</a></td><td></td><td><a href="file:///Users/rob/Documents/git-leftparen/scribblings/leftparen.html" class="tocviewselflink">Left<span class="mywbr"> </span>Paren 0.4 Documentation</a></td></tr></table></div><div class="tocviewsublistonly" style="display: none;" id="tocview_0"><table cellspacing="0" cellpadding="0"><tr><td align="right">1&nbsp;</td><td><a href="file:///Users/rob/Documents/git-leftparen/scribblings/leftparen.html#(part._.Installing_.Left.Paren)" class="tocviewlink">Installing Left<span class="mywbr"> </span>Paren</a></td></tr><tr><td align="right">2&nbsp;</td><td><a href="file:///Users/rob/Documents/git-leftparen/scribblings/leftparen.html#(part._tutorials)" class="tocviewlink">Tutorials</a></td></tr><tr><td align="right">3&nbsp;</td><td><a href="file:///Users/rob/Documents/git-leftparen/scribblings/leftparen.html#(part._.Reference)" class="tocviewlink">Reference</a></td></tr><tr><td align="right">4&nbsp;</td><td><a href="file:///Users/rob/Documents/git-leftparen/scribblings/leftparen.html#(part._.About_.Acknowledgements)" class="tocviewlink">About/<span class="mywbr"> </span>Acknowledgements</a></td></tr></table></div></div></div><div class="tocsub"><table class="tocsublist" cellspacing="0"><tr><td><span class="tocsublinknumber">1<tt>&nbsp;</tt></span><a href="#(part._.Installing_.Left.Paren)" class="tocsubseclink">Installing Left<span class="mywbr"> </span>Paren</a></td></tr><tr><td><span class="tocsublinknumber">2<tt>&nbsp;</tt></span><a href="#(part._tutorials)" class="tocsubseclink">Tutorials</a></td></tr><tr><td><span class="tocsublinknumber">2.1<tt>&nbsp;</tt></span><a href="#(part._.Hello__.World)" class="tocsubseclink">Hello, World</a></td></tr><tr><td><span class="tocsublinknumber">2.2<tt>&nbsp;</tt></span><a href="#(part._.Blogerton_the_.Blog)" class="tocsubseclink">Blogerton the Blog</a></td></tr><tr><td><span class="tocsublinknumber">2.2.1<tt>&nbsp;</tt></span><a href="#(part._.Changes_to_app_scm)" class="tocsubseclink">Changes to <span class="stt">app.scm</span></a></td></tr><tr><td><span class="tocsublinknumber">2.2.2<tt>&nbsp;</tt></span><a href="#(part._.Changes_to_main_scm)" class="tocsubseclink">Changes to <span class="stt">main.scm</span></a></td></tr><tr><td><span class="tocsublinknumber">2.2.3<tt>&nbsp;</tt></span><a href="#(part._.Launch_.Blogerton)" class="tocsubseclink">Launch Blogerton</a></td></tr><tr><td><span class="tocsublinknumber">3<tt>&nbsp;</tt></span><a href="#(part._.Reference)" class="tocsubseclink">Reference</a></td></tr><tr><td><span class="tocsublinknumber">3.1<tt>&nbsp;</tt></span><a href="#(part._.Forms)" class="tocsubseclink">Forms</a></td></tr><tr><td><span class="tocsublinknumber">3.1.1<tt>&nbsp;</tt></span><a href="#(part._.Image_uploads)" class="tocsubseclink">Image uploads</a></td></tr><tr><td><span class="tocsublinknumber">3.2<tt>&nbsp;</tt></span><a href="#(part._.Sessions)" class="tocsubseclink">Sessions</a></td></tr><tr><td><span class="tocsublinknumber">3.2.1<tt>&nbsp;</tt></span><a href="#(part._.Creating_sessions)" class="tocsubseclink">Creating sessions</a></td></tr><tr><td><span class="tocsublinknumber">3.2.2<tt>&nbsp;</tt></span><a href="#(part._.Accessing_sessions)" class="tocsubseclink">Accessing sessions</a></td></tr><tr><td><span class="tocsublinknumber">4<tt>&nbsp;</tt></span><a href="#(part._.About_.Acknowledgements)" class="tocsubseclink">About/<span class="mywbr"> </span>Acknowledgements</a></td></tr><tr><td><span class="tocsublinknumber">4.1<tt>&nbsp;</tt></span><a href="#(part._.Contributors)" class="tocsubseclink">Contributors</a></td></tr></table></div></div><div class="maincolumn"><div class="main"><div class="versionbox"><span class="version">Version: 4.1.0.3</span></div><div class="navset" style="margin-bottom: 2em; border-bottom: 2px solid #e0e0c0;"><span class="navleft"><input style="width: 16em; margin: 0px; padding: 0px; background-color: #eee; color: #888; border: 1px solid #ddd; text-align: center; vertical-align: middle;" type="text" value="...search manuals..." title="Enter a search string to search the manuals" onkeypress="return DoSearchKey(event, this, &quot;4.1.0.3&quot;, &quot;&quot;);" onfocus="this.style.color=&quot;black&quot;; this.style.textAlign=&quot;left&quot;; if (this.value == &quot;...search manuals...&quot;) this.value=&quot;&quot;;" onblur="if (this.value.match(/^ *$/)) { this.style.color=&quot;#888&quot;; this.style.textAlign=&quot;center&quot;; this.value=&quot;...search manuals...&quot;; }" />&nbsp;&nbsp;</span>&nbsp;</div><h2><a name="(part._.Left.Paren_0_4_.Documentation)"></a>LeftParen 0.4 Documentation</h2><p>Website: <a href="http://leftparen.com">http://leftparen.com</a></p><p>LeftParen is a framework for quickly creating web apps. It runs on
PLT Scheme v4.1 or greater. LeftParen is released under an <a href="http://github.com/vegashacker/leftparen/tree/master/MIT-LICENSE.txt">MIT License</a>. The source is available on <a href="http://github.com/vegashacker/leftparen/tree/master">github</a>.</p><h3>1<tt>&nbsp;</tt><a name="(part._.Installing_.Left.Paren)"></a>Installing LeftParen</h3><p>You&rsquo;ll need PLT Scheme v4.1 or greater installed.</p><p>Make sure that <span class="schemesymbol">mzscheme</span> is in your path. You should be ready
to go if you can do this:</p><p><table cellspacing="0"><tr><td><p><span class="stt"><span class="stt">% mzscheme</span></span></p></td></tr><tr><td><p><span class="stt"><span class="stt">Welcome to MzScheme v4.1...</span></span></p></td></tr><tr><td><p><span class="stt"><span class="stt">&gt;</span></span></p></td></tr></table></p><p>Installing LeftParen is done behind the scenes with a <a href="http://planet.plt-scheme.org/">PLaneT</a> <span class="schemesymbol">require</span>. See <a href="file:///Users/rob/Documents/git-leftparen/scribblings/leftparen.html#(part._tutorials)">Tutorials</a> for an example of this. When you
-first issue one of these <span class="schemesymbol">require</span> commands, you&rsquo;ll automatically download the LeftParen files to your local PLaneT cache. This can sometimes take a few moments, so be prepared to wait a bit.</p><h3>2<tt>&nbsp;</tt><a name="(part._tutorials)"></a>Tutorials</h3><h4>2.1<tt>&nbsp;</tt><a name="(part._.Hello__.World)"></a>Hello, World</h4><p>We&rsquo;re going to make a project called <span class="stt">hello-world</span>. Change to the directory that you&rsquo;d like to make the project in. Then issue</p><p><table cellspacing="0"><tr><td><p><span class="stt"><span class="stt">% mzscheme -e '(require (planet "bootstrap.scm" ("vegashacker" "leftparen.plt" 3 0)))' project hello-world</span></span></p></td></tr></table></p><p>This will create a <span class="stt">hello-world</span> project directory for you. In this directory you&rsquo;ll find the <span class="stt">script</span> directory, which contains some useful scripts. All paths are relative to this project directory, so when calling scripts, you always want to be at the project root.</p><p><table cellspacing="0"><tr><td><p><span class="stt"><span class="stt">% cd hello-world</span></span></p></td></tr></table></p><p>We need to make the scripts executable:</p><p><table cellspacing="0"><tr><td><p><span class="stt"><span class="stt">% chmod u+x script/*</span></span></p></td></tr></table></p><p>LeftParen has automatically generated everything we need to run our web app &ndash; we just need to start the server (again, you should be at the project root directory):</p><p><table cellspacing="0"><tr><td><p><span class="stt"><span class="stt">% ./script/server</span></span></p></td></tr><tr><td><p><span class="stt"><span class="stt">Web server started on port 8765</span></span></p></td></tr><tr><td><p><span class="stt"><span class="stt">Listening on IP address: 127.0.0.1</span></span></p></td></tr><tr><td><p><span class="stt"><span class="stt">Type stop to stop the server and exit</span></span></p></td></tr><tr><td><p><span class="stt"><span class="stt">Type restart to restart the server</span></span></p></td></tr></table></p><p>Point your browser to <a href="http://localhost:8765">http://localhost:8765</a> and you should see a familiar greeting:</p><p><span class="stt">Hello, World!</span></p><h4>2.2<tt>&nbsp;</tt><a name="(part._.Blogerton_the_.Blog)"></a>Blogerton the Blog</h4><p>Now let&rsquo;s try implementing the true "hello world" of web apps &ndash; a blog. First, execute the following commands from the directory in which you want to create your project directory:</p><p><table cellspacing="0"><tr><td><p><span class="stt"><span class="stt">% mzscheme -e '(require (planet "bootstrap.scm" ("vegashacker" "leftparen.plt" 3 0)))' project blogerton</span></span></p></td></tr><tr><td><p><span class="stt"><span class="stt">% cd blogerton</span></span></p></td></tr><tr><td><p><span class="stt"><span class="stt">% chmod u+x script/*</span></span></p></td></tr></table></p><h5>2.2.1<tt>&nbsp;</tt><a name="(part._.Changes_to_app_scm)"></a>Changes to <span class="stt">app.scm</span></h5><p>We need to register a couple of pages in our app. The <span class="schemesymbol">index-page</span> was already set up for you, but you&rsquo;ll need to add a page to create new posts, and one to view them. Make the <span class="schemesymbol">define-app</span> call look like this:</p><p><table cellspacing="0" class="schemeblock"><tr><td><p><span class="hspace">&nbsp;&nbsp;</span><span class="schemeparen">(</span><span class="schemesymbol">define-app</span><span class="hspace">&nbsp;</span><span class="schemesymbol">my-app</span></p></td></tr><tr><td><p><span class="schemeplain"><span class="hspace">&nbsp;&nbsp;</span></span><span class="hspace">&nbsp;&nbsp;</span><span class="schemeparen">(</span><span class="schemesymbol">index-page</span><span class="hspace">&nbsp;</span><span class="schemeparen">(</span><span class="schemesymbol">url</span><span class="hspace">&nbsp;</span><span class="schemevalue">"/"</span><span class="schemeparen">)</span><span class="schemeparen">)</span></p></td></tr><tr><td><p><span class="schemeplain"><span class="hspace">&nbsp;&nbsp;</span></span><span class="hspace">&nbsp;&nbsp;</span><span class="schemeparen">(</span><span class="schemesymbol">create-post-page</span><span class="hspace">&nbsp;</span><span class="schemeparen">(</span><span class="schemesymbol">url</span><span class="hspace">&nbsp;</span><span class="schemevalue">"/post"</span><span class="schemeparen">)</span><span class="schemeparen">)</span></p></td></tr><tr><td><p><span class="schemeplain"><span class="hspace">&nbsp;&nbsp;</span></span><span class="hspace">&nbsp;&nbsp;</span><span class="schemeparen">(</span><span class="schemesymbol">view-post-page</span><span class="hspace">&nbsp;</span><span class="schemeparen">(</span><span class="schemesymbol">url</span><span class="hspace">&nbsp;</span><span class="schemevalue">"/view/"</span><span class="hspace">&nbsp;</span><span class="schemeparen">(</span><span class="schemesymbol">string-arg</span><span class="schemeparen">)</span><span class="schemeparen">)</span><span class="schemeparen">)</span><span class="schemeparen">)</span></p></td></tr></table></p><h5>2.2.2<tt>&nbsp;</tt><a name="(part._.Changes_to_main_scm)"></a>Changes to <span class="stt">main.scm</span></h5><p>Now we need to define those pages that we declared in <span class="stt">app.scm</span>.</p><p><table cellspacing="0" class="schemeblock"><tr><td><p><span class="hspace">&nbsp;&nbsp;</span><span class="schemeparen">(</span><span class="schemesymbol">define-page</span><span class="hspace">&nbsp;</span><span class="schemeparen">(</span><span class="schemesymbol">index-page</span><span class="hspace">&nbsp;</span><span class="schemesymbol">req</span><span class="schemeparen">)</span></p></td></tr><tr><td><p><span class="schemeplain"><span class="hspace">&nbsp;&nbsp;</span></span><span class="hspace">&nbsp;&nbsp;</span><span class="schemeparen">(</span><span class="schemesymbol">**</span><span class="hspace">&nbsp;</span><span class="schemevalue">`</span><span class="schemevalue">(</span><span class="schemevalue">h1</span><span class="hspace">&nbsp;</span><span class="schemevalue">"Blogerton"</span><span class="schemevalue">)</span></p></td></tr><tr><td><p><span class="schemeplain"><span class="hspace">&nbsp;&nbsp;</span></span><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="schemevalue">`</span><span class="schemevalue">(</span><span class="schemevalue">p</span><span class="hspace">&nbsp;</span><span class="schemereader">,</span><span class="schemeparen">(</span><span class="schemesymbol">web-link</span><span class="hspace">&nbsp;</span><span class="schemevalue">"Create a new post"</span><span class="hspace">&nbsp;</span><span class="schemeparen">(</span><span class="schemesymbol">page-url</span><span class="hspace">&nbsp;</span><span class="schemesymbol">create-post-page</span><span class="schemeparen">)</span><span class="schemeparen">)</span><span class="schemevalue">)</span></p></td></tr><tr><td><p><span class="schemeplain"><span class="hspace">&nbsp;&nbsp;</span></span><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="schemevalue">`</span><span class="schemevalue">(</span><span class="schemevalue">ul</span><span class="hspace">&nbsp;</span><span class="schemereader">,@</span><span class="schemeparen">(</span><span class="schemesymbol">map</span><span class="hspace">&nbsp;</span><span class="schemeparen">(</span><span class="schemesymbol">lambda</span><span class="hspace">&nbsp;</span><span class="schemeparen">(</span><span class="schemesymbol">p</span><span class="schemeparen">)</span><span class="hspace">&nbsp;</span><span class="schemevalue">`</span><span class="schemevalue">(</span><span class="schemevalue">li</span><span class="hspace">&nbsp;</span><span class="schemereader">,</span><span class="schemeparen">(</span><span class="schemesymbol">paint-blog-post</span><span class="hspace">&nbsp;</span><span class="schemesymbol">p</span><span class="schemeparen">)</span><span class="schemevalue">)</span><span class="schemeparen">)</span></p></td></tr><tr><td><p><span class="schemeplain"><span class="hspace">&nbsp;&nbsp;</span></span><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="schemeparen">(</span><span class="schemesymbol">load-where</span><span class="hspace">&nbsp;</span><span class="schemevalue">'</span><span class="schemevalue">(</span><span class="schemevalue">(</span><span class="schemevalue">type</span><span class="hspace">&nbsp;</span><span class="schemevalue">. </span><span class="schemevalue">blog-post</span><span class="schemevalue">)</span><span class="schemevalue">)</span></p></td></tr><tr><td><p><span class="schemeplain"><span class="hspace">&nbsp;&nbsp;</span></span><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="schemeparen">#:sort-by</span><span class="hspace">&nbsp;</span><span class="schemevalue">'</span><span class="schemevalue">created-at</span><span class="hspace">&nbsp;</span><span class="schemeparen">#:compare</span><span class="hspace">&nbsp;</span><span class="schemesymbol">&gt;</span><span class="schemeparen">)</span><span class="schemeparen">)</span><span class="schemevalue">)</span><span class="schemeparen">)</span><span class="schemeparen">)</span></p></td></tr><tr><td><p><span class="schemeplain"><span class="hspace">&nbsp;&nbsp;</span></span></p></td></tr><tr><td><p><span class="schemeplain"><span class="hspace">&nbsp;&nbsp;</span></span><span class="schemeparen">(</span><span class="schemesymbol">define-page</span><span class="hspace">&nbsp;</span><span class="schemeparen">(</span><span class="schemesymbol">create-post-page</span><span class="hspace">&nbsp;</span><span class="schemesymbol">req</span><span class="schemeparen">)</span></p></td></tr><tr><td><p><span class="schemeplain"><span class="hspace">&nbsp;&nbsp;</span></span><span class="hspace">&nbsp;&nbsp;</span><span class="schemeparen">(</span><span class="schemesymbol">form</span><span class="hspace">&nbsp;</span><span class="schemevalue">'</span><span class="schemevalue">(</span><span class="schemevalue">(</span><span class="schemevalue">title</span><span class="hspace">&nbsp;</span><span class="schemevalue">"Title"</span><span class="hspace">&nbsp;</span><span class="schemevalue">text</span><span class="schemevalue">)</span><span class="hspace">&nbsp;</span><span class="schemevalue">(</span><span class="schemevalue">body</span><span class="hspace">&nbsp;</span><span class="schemevalue">"Body"</span><span class="hspace">&nbsp;</span><span class="schemevalue">long-text</span><span class="schemevalue">)</span><span class="schemevalue">)</span></p></td></tr><tr><td><p><span class="schemeplain"><span class="hspace">&nbsp;&nbsp;</span></span><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="schemeparen">#:init</span><span class="hspace">&nbsp;</span><span class="schemevalue">'</span><span class="schemevalue">(</span><span class="schemevalue">(</span><span class="schemevalue">type</span><span class="hspace">&nbsp;</span><span class="schemevalue">. </span><span class="schemevalue">blog-post</span><span class="schemevalue">)</span><span class="schemevalue">)</span></p></td></tr><tr><td><p><span class="schemeplain"><span class="hspace">&nbsp;&nbsp;</span></span><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="schemeparen">#:on-done</span><span class="hspace">&nbsp;</span><span class="schemeparen">(</span><span class="schemesymbol">lambda</span><span class="hspace">&nbsp;</span><span class="schemeparen">(</span><span class="schemesymbol">post</span><span class="schemeparen">)</span><span class="hspace">&nbsp;</span><span class="schemeparen">(</span><span class="schemesymbol">redirect-to-page</span><span class="hspace">&nbsp;</span><span class="schemesymbol">view-post-page</span><span class="hspace">&nbsp;</span><span class="schemeparen">(</span><span class="schemesymbol">rec-id</span><span class="hspace">&nbsp;</span><span class="schemesymbol">post</span><span class="schemeparen">)</span><span class="schemeparen">)</span><span class="schemeparen">)</span><span class="schemeparen">)</span><span class="schemeparen">)</span></p></td></tr><tr><td><p><span class="schemeplain"><span class="hspace">&nbsp;&nbsp;</span></span></p></td></tr><tr><td><p><span class="schemeplain"><span class="hspace">&nbsp;&nbsp;</span></span><span class="schemeparen">(</span><span class="schemesymbol">define-page</span><span class="hspace">&nbsp;</span><span class="schemeparen">(</span><span class="schemesymbol">view-post-page</span><span class="hspace">&nbsp;</span><span class="schemesymbol">req</span><span class="hspace">&nbsp;</span><span class="schemesymbol">post-id</span><span class="schemeparen">)</span></p></td></tr><tr><td><p><span class="schemeplain"><span class="hspace">&nbsp;&nbsp;</span></span><span class="hspace">&nbsp;&nbsp;</span><span class="schemeparen">(</span><span class="schemesymbol">paint-blog-post</span><span class="hspace">&nbsp;</span><span class="schemeparen">(</span><span class="schemesymbol">load-rec</span><span class="hspace">&nbsp;</span><span class="schemesymbol">post-id</span><span class="hspace">&nbsp;</span><span class="schemeparen">#:ensure</span><span class="hspace">&nbsp;</span><span class="schemevalue">'</span><span class="schemevalue">(</span><span class="schemevalue">(</span><span class="schemevalue">type</span><span class="hspace">&nbsp;</span><span class="schemevalue">. </span><span class="schemevalue">blog-post</span><span class="schemevalue">)</span><span class="schemevalue">)</span><span class="schemeparen">)</span><span class="schemeparen">)</span><span class="schemeparen">)</span></p></td></tr><tr><td><p><span class="schemeplain"><span class="hspace">&nbsp;&nbsp;</span></span></p></td></tr><tr><td><p><span class="schemeplain"><span class="hspace">&nbsp;&nbsp;</span></span><span class="schemeparen">(</span><span class="schemesymbol">define</span><span class="hspace">&nbsp;</span><span class="schemeparen">(</span><span class="schemesymbol">paint-blog-post</span><span class="hspace">&nbsp;</span><span class="schemesymbol">post</span><span class="schemeparen">)</span></p></td></tr><tr><td><p><span class="schemeplain"><span class="hspace">&nbsp;&nbsp;</span></span><span class="hspace">&nbsp;&nbsp;</span><span class="schemevalue">`</span><span class="schemevalue">(</span><span class="schemevalue">div</span><span class="hspace">&nbsp;</span><span class="schemevalue">(</span><span class="schemevalue">h2</span><span class="hspace">&nbsp;</span><span class="schemereader">,</span><span class="schemeparen">(</span><span class="schemesymbol">rec-prop</span><span class="hspace">&nbsp;</span><span class="schemesymbol">post</span><span class="hspace">&nbsp;</span><span class="schemevalue">'</span><span class="schemevalue">title</span><span class="schemeparen">)</span><span class="schemevalue">)</span></p></td></tr><tr><td><p><span class="schemeplain"><span class="hspace">&nbsp;&nbsp;</span></span><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="schemevalue">(</span><span class="schemevalue">p</span><span class="hspace">&nbsp;</span><span class="schemereader">,</span><span class="schemeparen">(</span><span class="schemesymbol">rec-prop</span><span class="hspace">&nbsp;</span><span class="schemesymbol">post</span><span class="hspace">&nbsp;</span><span class="schemevalue">'</span><span class="schemevalue">body</span><span class="schemeparen">)</span><span class="schemevalue">)</span><span class="schemevalue">)</span><span class="schemeparen">)</span></p></td></tr></table></p><h5>2.2.3<tt>&nbsp;</tt><a name="(part._.Launch_.Blogerton)"></a>Launch Blogerton</h5><p>You&rsquo;re ready for launch. Start the server with</p><p><table cellspacing="0"><tr><td><p><span class="stt"><span class="stt">% ./script/server</span></span></p></td></tr></table></p><p>and you should have a basic blogging app, with persistent data, in 19 lines of code.</p><h3>3<tt>&nbsp;</tt><a name="(part._.More_.Documentation_to_.Come)"></a>More Documentation to Come</h3><p>We need to get a full LeftParen reference up (not just simple tutorials). There&rsquo;s lots more cool stuff in LeftParen that this document doesn&rsquo;t yet address.</p><h3>4<tt>&nbsp;</tt><a name="(part._.Reference)"></a>Reference</h3><h4>4.1<tt>&nbsp;</tt><a name="(part._.Forms)"></a>Forms</h4><p>Wouldn&rsquo;t forms documentation be nice?</p><p><table cellspacing="0" class="boxed"><tr><td><p><span class="schemeparen">(</span><span class="schemesymbol">mystery</span><span class="hspace">&nbsp;</span><span class="schemevariable">a</span><span class="schemeparen">)</span><span class="hspace">&nbsp;</span>&rarr;<span class="hspace">&nbsp;</span><span class="schemesymbol">int</span></p></td></tr><tr><td><p><span class="hspace">&nbsp;&nbsp;</span><span class="schemevariable">a</span><span class="hspace">&nbsp;</span>:<span class="hspace">&nbsp;</span><span class="schemesymbol">string-dude</span></p></td></tr></table></p><h4>4.2<tt>&nbsp;</tt><a name="(part._.Sessions)"></a>Sessions</h4><p>A session is an object that allows you to easily store state about individual visitors to your web app. Sessions are stored on the server as a record with a virtually impossible-to-guess id. A cookie is left in the user&rsquo;s web browser, which contains a pointer to a particular session id. These cookies expire one month after creation and, currently, this can&rsquo;t be changed.</p><h5>4.2.1<tt>&nbsp;</tt><a name="(part._.Creating_sessions)"></a>Creating sessions</h5><p><table cellspacing="0" class="boxed"><tr><td><table cellspacing="0" class="schemeblock"><tr><td><p><span class="schemeparen">(</span><span class="schemesymbol">define-session-page</span></p></td></tr><tr><td><p><span class="hspace">&nbsp;&nbsp;</span><span class="schemeparen">(</span><span class="schemevariable">page-name</span><span class="hspace">&nbsp;</span><span class="schemevariable">request-iden</span><span class="hspace">&nbsp;</span><span class="schemevariable">session-iden</span><span class="hspace">&nbsp;</span><span class="schemevariable">page-args</span><span class="hspace">&nbsp;</span><span class="schememeta">...</span><span class="schemeparen">)</span></p></td></tr><tr><td><p><span class="hspace">&nbsp;&nbsp;</span><span class="schemevariable">body</span><span class="hspace">&nbsp;</span><span class="schememeta">...</span><span class="schemeparen">)</span></p></td></tr></table></td></tr></table></p><p>This is an alternate to <span class="schemesymbol">define-page</span>, most commonly used in <span class="schemesymbol">main.scm</span>. The only difference is that after the request identifier, you must provide a session identifier. For example, to keep a counter (unique to each user), you could write:</p><p><table cellspacing="0" class="schemeblock"><tr><td><p><span class="hspace">&nbsp;&nbsp;</span><span class="schemeparen">(</span><span class="schemesymbol">define-session-page</span><span class="hspace">&nbsp;</span><span class="schemeparen">(</span><span class="schemesymbol">foo-page</span><span class="hspace">&nbsp;</span><span class="schemesymbol">req</span><span class="hspace">&nbsp;</span><span class="schemesymbol">sesh</span><span class="schemeparen">)</span></p></td></tr><tr><td><p><span class="schemeplain"><span class="hspace">&nbsp;&nbsp;</span></span><span class="hspace">&nbsp;&nbsp;</span><span class="schemeparen">(</span><span class="schemesymbol">let</span><span class="hspace">&nbsp;</span><span class="schemeparen">(</span><span class="schemeparen">(</span><span class="schemesymbol">c</span><span class="hspace">&nbsp;</span><span class="schemeparen">(</span><span class="schemesymbol">session-get-val</span><span class="hspace">&nbsp;</span><span class="schemesymbol">sesh</span><span class="hspace">&nbsp;</span><span class="schemevalue">'</span><span class="schemevalue">counter</span><span class="hspace">&nbsp;</span><span class="schemevalue">0</span><span class="schemeparen">)</span><span class="schemeparen">)</span><span class="schemeparen">)</span></p></td></tr><tr><td><p><span class="schemeplain"><span class="hspace">&nbsp;&nbsp;</span></span><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="schemeparen">(</span><span class="schemesymbol">session-put-val!</span><span class="hspace">&nbsp;</span><span class="schemesymbol">sesh</span><span class="hspace">&nbsp;</span><span class="schemevalue">'</span><span class="schemevalue">counter</span><span class="hspace">&nbsp;</span><span class="schemeparen">(</span><span class="schemesymbol">+</span><span class="hspace">&nbsp;</span><span class="schemevalue">1</span><span class="hspace">&nbsp;</span><span class="schemesymbol">c</span><span class="schemeparen">)</span><span class="schemeparen">)</span></p></td></tr><tr><td><p><span class="schemeplain"><span class="hspace">&nbsp;&nbsp;</span></span><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="schemeparen">(</span><span class="schemesymbol">number-&gt;string</span><span class="hspace">&nbsp;</span><span class="schemesymbol">c</span><span class="schemeparen">)</span><span class="schemeparen">)</span><span class="schemeparen">)</span></p></td></tr></table></p><p>When you define a session page, the session is automatically fetched for you (and created if necessary), and bound to the session identifier you provided.</p><h5>4.2.2<tt>&nbsp;</tt><a name="(part._.Accessing_sessions)"></a>Accessing sessions</h5><p><table cellspacing="0" class="boxed"><tr><td><p><span class="schemeparen">(</span><span class="schemesymbol">session-get-val</span><span class="hspace">&nbsp;</span><span class="schemevariable">session</span><span class="hspace">&nbsp;</span><span class="schemevariable">key</span><span class="hspace">&nbsp;</span>[<span class="schemevariable">missing-val</span>]<span class="schemeparen">)</span><span class="hspace">&nbsp;</span>&rarr;<span class="hspace">&nbsp;</span><span class="schemesymbol">any</span></p></td></tr><tr><td><p><span class="hspace">&nbsp;&nbsp;</span><span class="schemevariable">session</span><span class="hspace">&nbsp;</span>:<span class="hspace">&nbsp;</span><span class="schemevariable">session</span></p></td></tr><tr><td><p><span class="hspace">&nbsp;&nbsp;</span><span class="schemevariable">key</span><span class="hspace">&nbsp;</span>:<span class="hspace">&nbsp;</span><span class="schemesymbol">symbol</span></p></td></tr><tr><td><p><span class="hspace">&nbsp;&nbsp;</span><span class="schemevariable">missing-val</span><span class="hspace">&nbsp;</span>:<span class="hspace">&nbsp;</span><span class="schemesymbol">any</span><span class="hspace">&nbsp;</span>=<span class="hspace">&nbsp;</span><span class="schemevalue">#f</span></p></td></tr></table></p><p><table cellspacing="0" class="boxed"><tr><td><p><span class="schemeparen">(</span><span class="schemesymbol">session-put-val!</span><span class="hspace">&nbsp;</span><span class="schemevariable">session</span><span class="hspace">&nbsp;</span><span class="schemevariable">key</span><span class="hspace">&nbsp;</span><span class="schemevariable">val</span><span class="schemeparen">)</span><span class="hspace">&nbsp;</span>&rarr;<span class="hspace">&nbsp;</span><span class="schemevariable">session</span></p></td></tr><tr><td><p><span class="hspace">&nbsp;&nbsp;</span><span class="schemevariable">session</span><span class="hspace">&nbsp;</span>:<span class="hspace">&nbsp;</span><span class="schemevariable">session</span></p></td></tr><tr><td><p><span class="hspace">&nbsp;&nbsp;</span><span class="schemevariable">key</span><span class="hspace">&nbsp;</span>:<span class="hspace">&nbsp;</span><span class="schemesymbol">symbol</span></p></td></tr><tr><td><p><span class="hspace">&nbsp;&nbsp;</span><span class="schemevariable">val</span><span class="hspace">&nbsp;</span>:<span class="hspace">&nbsp;</span><span class="schemesymbol">any</span></p></td></tr></table></p><h3>5<tt>&nbsp;</tt><a name="(part._.About_.Acknowledgements)"></a>About/Acknowledgements</h3><p>LeftParen was written by <a href="http://robhunter.org">Rob Hunter</a>, but it builds heavily on (and, in fact, often directly incorporates) the work of <a href="http://untyped.com/">Untyped</a> (<a href="http://planet.plt-scheme.org/display.ss?package=instaservlet.plt&amp;owner=untyped">instaservlet</a> and <a href="http://planet.plt-scheme.org/display.ss?package=dispatch.plt&amp;owner=untyped">dispatch</a>), <a href="http://scheme.dk/blog/">Jens Axel Soegaard</a> (<a href="http://planet.plt-scheme.org/display.ss?package=web.plt&amp;owner=soegaard">web.plt</a>), and of course, <a href="http://www.plt-scheme.org/">PLT Scheme</a>.</p><h4>5.1<tt>&nbsp;</tt><a name="(part._.Contributors)"></a>Contributors</h4><ul><li><p>Bill Hager</p></li><li><p>Joshua Herman</p></li></ul><div class="navset" style="margin-top: 2em; border-top: 2px solid #e0e0c0;"><span class="navleft"><input style="width: 16em; margin: 0px; padding: 0px; background-color: #eee; color: #888; border: 1px solid #ddd; text-align: center; vertical-align: middle;" type="text" value="...search manuals..." title="Enter a search string to search the manuals" onkeypress="return DoSearchKey(event, this, &quot;4.1.0.3&quot;, &quot;&quot;);" onfocus="this.style.color=&quot;black&quot;; this.style.textAlign=&quot;left&quot;; if (this.value == &quot;...search manuals...&quot;) this.value=&quot;&quot;;" onblur="if (this.value.match(/^ *$/)) { this.style.color=&quot;#888&quot;; this.style.textAlign=&quot;center&quot;; this.value=&quot;...search manuals...&quot;; }" />&nbsp;&nbsp;</span>&nbsp;</div></div></div></body></html>
+first issue one of these <span class="schemesymbol">require</span> commands, you&rsquo;ll automatically download the LeftParen files to your local PLaneT cache. This can sometimes take a few moments, so be prepared to wait a bit.</p><h3>2<tt>&nbsp;</tt><a name="(part._tutorials)"></a>Tutorials</h3><h4>2.1<tt>&nbsp;</tt><a name="(part._.Hello__.World)"></a>Hello, World</h4><p>We&rsquo;re going to make a project called <span class="stt">hello-world</span>. Change to the directory that you&rsquo;d like to make the project in. Then issue</p><p><table cellspacing="0"><tr><td><p><span class="stt"><span class="stt">% mzscheme -e '(require (planet "bootstrap.scm" ("vegashacker" "leftparen.plt" 3 0)))' project hello-world</span></span></p></td></tr></table></p><p>This will create a <span class="stt">hello-world</span> project directory for you. In this directory you&rsquo;ll find the <span class="stt">script</span> directory, which contains some useful scripts. All paths are relative to this project directory, so when calling scripts, you always want to be at the project root.</p><p><table cellspacing="0"><tr><td><p><span class="stt"><span class="stt">% cd hello-world</span></span></p></td></tr></table></p><p>We need to make the scripts executable:</p><p><table cellspacing="0"><tr><td><p><span class="stt"><span class="stt">% chmod u+x script/*</span></span></p></td></tr></table></p><p>LeftParen has automatically generated everything we need to run our web app &ndash; we just need to start the server (again, you should be at the project root directory):</p><p><table cellspacing="0"><tr><td><p><span class="stt"><span class="stt">% ./script/server</span></span></p></td></tr><tr><td><p><span class="stt"><span class="stt">Web server started on port 8765</span></span></p></td></tr><tr><td><p><span class="stt"><span class="stt">Listening on IP address: 127.0.0.1</span></span></p></td></tr><tr><td><p><span class="stt"><span class="stt">Type stop to stop the server and exit</span></span></p></td></tr><tr><td><p><span class="stt"><span class="stt">Type restart to restart the server</span></span></p></td></tr></table></p><p>Point your browser to <a href="http://localhost:8765">http://localhost:8765</a> and you should see a familiar greeting:</p><p><span class="stt">Hello, World!</span></p><h4>2.2<tt>&nbsp;</tt><a name="(part._.Blogerton_the_.Blog)"></a>Blogerton the Blog</h4><p>Now let&rsquo;s try implementing the true "hello world" of web apps &ndash; a blog. First, execute the following commands from the directory in which you want to create your project directory:</p><p><table cellspacing="0"><tr><td><p><span class="stt"><span class="stt">% mzscheme -e '(require (planet "bootstrap.scm" ("vegashacker" "leftparen.plt" 3 0)))' project blogerton</span></span></p></td></tr><tr><td><p><span class="stt"><span class="stt">% cd blogerton</span></span></p></td></tr><tr><td><p><span class="stt"><span class="stt">% chmod u+x script/*</span></span></p></td></tr></table></p><h5>2.2.1<tt>&nbsp;</tt><a name="(part._.Changes_to_app_scm)"></a>Changes to <span class="stt">app.scm</span></h5><p>We need to register a couple of pages in our app. The <span class="schemesymbol">index-page</span> was already set up for you, but you&rsquo;ll need to add a page to create new posts, and one to view them. Make the <span class="schemesymbol">define-app</span> call look like this:</p><p><table cellspacing="0" class="schemeblock"><tr><td><p><span class="hspace">&nbsp;&nbsp;</span><span class="schemeparen">(</span><span class="schemesymbol">define-app</span><span class="hspace">&nbsp;</span><span class="schemesymbol">my-app</span></p></td></tr><tr><td><p><span class="schemeplain"><span class="hspace">&nbsp;&nbsp;</span></span><span class="hspace">&nbsp;&nbsp;</span><span class="schemeparen">(</span><span class="schemesymbol">index-page</span><span class="hspace">&nbsp;</span><span class="schemeparen">(</span><span class="schemesymbol">url</span><span class="hspace">&nbsp;</span><span class="schemevalue">"/"</span><span class="schemeparen">)</span><span class="schemeparen">)</span></p></td></tr><tr><td><p><span class="schemeplain"><span class="hspace">&nbsp;&nbsp;</span></span><span class="hspace">&nbsp;&nbsp;</span><span class="schemeparen">(</span><span class="schemesymbol">create-post-page</span><span class="hspace">&nbsp;</span><span class="schemeparen">(</span><span class="schemesymbol">url</span><span class="hspace">&nbsp;</span><span class="schemevalue">"/post"</span><span class="schemeparen">)</span><span class="schemeparen">)</span></p></td></tr><tr><td><p><span class="schemeplain"><span class="hspace">&nbsp;&nbsp;</span></span><span class="hspace">&nbsp;&nbsp;</span><span class="schemeparen">(</span><span class="schemesymbol">view-post-page</span><span class="hspace">&nbsp;</span><span class="schemeparen">(</span><span class="schemesymbol">url</span><span class="hspace">&nbsp;</span><span class="schemevalue">"/view/"</span><span class="hspace">&nbsp;</span><span class="schemeparen">(</span><span class="schemesymbol">string-arg</span><span class="schemeparen">)</span><span class="schemeparen">)</span><span class="schemeparen">)</span><span class="schemeparen">)</span></p></td></tr></table></p><h5>2.2.2<tt>&nbsp;</tt><a name="(part._.Changes_to_main_scm)"></a>Changes to <span class="stt">main.scm</span></h5><p>Now we need to define those pages that we declared in <span class="stt">app.scm</span>.</p><p><table cellspacing="0" class="schemeblock"><tr><td><p><span class="hspace">&nbsp;&nbsp;</span><span class="schemeparen">(</span><span class="schemesymbol">define-page</span><span class="hspace">&nbsp;</span><span class="schemeparen">(</span><span class="schemesymbol">index-page</span><span class="hspace">&nbsp;</span><span class="schemesymbol">req</span><span class="schemeparen">)</span></p></td></tr><tr><td><p><span class="schemeplain"><span class="hspace">&nbsp;&nbsp;</span></span><span class="hspace">&nbsp;&nbsp;</span><span class="schemeparen">(</span><span class="schemesymbol">**</span><span class="hspace">&nbsp;</span><span class="schemevalue">`</span><span class="schemevalue">(</span><span class="schemevalue">h1</span><span class="hspace">&nbsp;</span><span class="schemevalue">"Blogerton"</span><span class="schemevalue">)</span></p></td></tr><tr><td><p><span class="schemeplain"><span class="hspace">&nbsp;&nbsp;</span></span><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="schemevalue">`</span><span class="schemevalue">(</span><span class="schemevalue">p</span><span class="hspace">&nbsp;</span><span class="schemereader">,</span><span class="schemeparen">(</span><span class="schemesymbol">web-link</span><span class="hspace">&nbsp;</span><span class="schemevalue">"Create a new post"</span><span class="hspace">&nbsp;</span><span class="schemeparen">(</span><span class="schemesymbol">page-url</span><span class="hspace">&nbsp;</span><span class="schemesymbol">create-post-page</span><span class="schemeparen">)</span><span class="schemeparen">)</span><span class="schemevalue">)</span></p></td></tr><tr><td><p><span class="schemeplain"><span class="hspace">&nbsp;&nbsp;</span></span><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="schemevalue">`</span><span class="schemevalue">(</span><span class="schemevalue">ul</span><span class="hspace">&nbsp;</span><span class="schemereader">,@</span><span class="schemeparen">(</span><span class="schemesymbol">map</span><span class="hspace">&nbsp;</span><span class="schemeparen">(</span><span class="schemesymbol">lambda</span><span class="hspace">&nbsp;</span><span class="schemeparen">(</span><span class="schemesymbol">p</span><span class="schemeparen">)</span><span class="hspace">&nbsp;</span><span class="schemevalue">`</span><span class="schemevalue">(</span><span class="schemevalue">li</span><span class="hspace">&nbsp;</span><span class="schemereader">,</span><span class="schemeparen">(</span><span class="schemesymbol">paint-blog-post</span><span class="hspace">&nbsp;</span><span class="schemesymbol">p</span><span class="schemeparen">)</span><span class="schemevalue">)</span><span class="schemeparen">)</span></p></td></tr><tr><td><p><span class="schemeplain"><span class="hspace">&nbsp;&nbsp;</span></span><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="schemeparen">(</span><span class="schemesymbol">load-where</span><span class="hspace">&nbsp;</span><span class="schemevalue">'</span><span class="schemevalue">(</span><span class="schemevalue">(</span><span class="schemevalue">type</span><span class="hspace">&nbsp;</span><span class="schemevalue">. </span><span class="schemevalue">blog-post</span><span class="schemevalue">)</span><span class="schemevalue">)</span></p></td></tr><tr><td><p><span class="schemeplain"><span class="hspace">&nbsp;&nbsp;</span></span><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="schemeparen">#:sort-by</span><span class="hspace">&nbsp;</span><span class="schemevalue">'</span><span class="schemevalue">created-at</span><span class="hspace">&nbsp;</span><span class="schemeparen">#:compare</span><span class="hspace">&nbsp;</span><span class="schemesymbol">&gt;</span><span class="schemeparen">)</span><span class="schemeparen">)</span><span class="schemevalue">)</span><span class="schemeparen">)</span><span class="schemeparen">)</span></p></td></tr><tr><td><p><span class="schemeplain"><span class="hspace">&nbsp;&nbsp;</span></span></p></td></tr><tr><td><p><span class="schemeplain"><span class="hspace">&nbsp;&nbsp;</span></span><span class="schemeparen">(</span><span class="schemesymbol">define-page</span><span class="hspace">&nbsp;</span><span class="schemeparen">(</span><span class="schemesymbol">create-post-page</span><span class="hspace">&nbsp;</span><span class="schemesymbol">req</span><span class="schemeparen">)</span></p></td></tr><tr><td><p><span class="schemeplain"><span class="hspace">&nbsp;&nbsp;</span></span><span class="hspace">&nbsp;&nbsp;</span><span class="schemeparen">(</span><span class="schemesymbol">form</span><span class="hspace">&nbsp;</span><span class="schemevalue">'</span><span class="schemevalue">(</span><span class="schemevalue">(</span><span class="schemevalue">title</span><span class="hspace">&nbsp;</span><span class="schemevalue">"Title"</span><span class="hspace">&nbsp;</span><span class="schemevalue">text</span><span class="schemevalue">)</span><span class="hspace">&nbsp;</span><span class="schemevalue">(</span><span class="schemevalue">body</span><span class="hspace">&nbsp;</span><span class="schemevalue">"Body"</span><span class="hspace">&nbsp;</span><span class="schemevalue">long-text</span><span class="schemevalue">)</span><span class="schemevalue">)</span></p></td></tr><tr><td><p><span class="schemeplain"><span class="hspace">&nbsp;&nbsp;</span></span><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="schemeparen">#:init</span><span class="hspace">&nbsp;</span><span class="schemevalue">'</span><span class="schemevalue">(</span><span class="schemevalue">(</span><span class="schemevalue">type</span><span class="hspace">&nbsp;</span><span class="schemevalue">. </span><span class="schemevalue">blog-post</span><span class="schemevalue">)</span><span class="schemevalue">)</span></p></td></tr><tr><td><p><span class="schemeplain"><span class="hspace">&nbsp;&nbsp;</span></span><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="schemeparen">#:on-done</span><span class="hspace">&nbsp;</span><span class="schemeparen">(</span><span class="schemesymbol">lambda</span><span class="hspace">&nbsp;</span><span class="schemeparen">(</span><span class="schemesymbol">post</span><span class="schemeparen">)</span><span class="hspace">&nbsp;</span><span class="schemeparen">(</span><span class="schemesymbol">redirect-to-page</span><span class="hspace">&nbsp;</span><span class="schemesymbol">view-post-page</span><span class="hspace">&nbsp;</span><span class="schemeparen">(</span><span class="schemesymbol">rec-id</span><span class="hspace">&nbsp;</span><span class="schemesymbol">post</span><span class="schemeparen">)</span><span class="schemeparen">)</span><span class="schemeparen">)</span><span class="schemeparen">)</span><span class="schemeparen">)</span></p></td></tr><tr><td><p><span class="schemeplain"><span class="hspace">&nbsp;&nbsp;</span></span></p></td></tr><tr><td><p><span class="schemeplain"><span class="hspace">&nbsp;&nbsp;</span></span><span class="schemeparen">(</span><span class="schemesymbol">define-page</span><span class="hspace">&nbsp;</span><span class="schemeparen">(</span><span class="schemesymbol">view-post-page</span><span class="hspace">&nbsp;</span><span class="schemesymbol">req</span><span class="hspace">&nbsp;</span><span class="schemesymbol">post-id</span><span class="schemeparen">)</span></p></td></tr><tr><td><p><span class="schemeplain"><span class="hspace">&nbsp;&nbsp;</span></span><span class="hspace">&nbsp;&nbsp;</span><span class="schemeparen">(</span><span class="schemesymbol">paint-blog-post</span><span class="hspace">&nbsp;</span><span class="schemeparen">(</span><span class="schemesymbol">load-rec</span><span class="hspace">&nbsp;</span><span class="schemesymbol">post-id</span><span class="hspace">&nbsp;</span><span class="schemeparen">#:ensure</span><span class="hspace">&nbsp;</span><span class="schemevalue">'</span><span class="schemevalue">(</span><span class="schemevalue">(</span><span class="schemevalue">type</span><span class="hspace">&nbsp;</span><span class="schemevalue">. </span><span class="schemevalue">blog-post</span><span class="schemevalue">)</span><span class="schemevalue">)</span><span class="schemeparen">)</span><span class="schemeparen">)</span><span class="schemeparen">)</span></p></td></tr><tr><td><p><span class="schemeplain"><span class="hspace">&nbsp;&nbsp;</span></span></p></td></tr><tr><td><p><span class="schemeplain"><span class="hspace">&nbsp;&nbsp;</span></span><span class="schemeparen">(</span><span class="schemesymbol">define</span><span class="hspace">&nbsp;</span><span class="schemeparen">(</span><span class="schemesymbol">paint-blog-post</span><span class="hspace">&nbsp;</span><span class="schemesymbol">post</span><span class="schemeparen">)</span></p></td></tr><tr><td><p><span class="schemeplain"><span class="hspace">&nbsp;&nbsp;</span></span><span class="hspace">&nbsp;&nbsp;</span><span class="schemevalue">`</span><span class="schemevalue">(</span><span class="schemevalue">div</span><span class="hspace">&nbsp;</span><span class="schemevalue">(</span><span class="schemevalue">h2</span><span class="hspace">&nbsp;</span><span class="schemereader">,</span><span class="schemeparen">(</span><span class="schemesymbol">rec-prop</span><span class="hspace">&nbsp;</span><span class="schemesymbol">post</span><span class="hspace">&nbsp;</span><span class="schemevalue">'</span><span class="schemevalue">title</span><span class="schemeparen">)</span><span class="schemevalue">)</span></p></td></tr><tr><td><p><span class="schemeplain"><span class="hspace">&nbsp;&nbsp;</span></span><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="schemevalue">(</span><span class="schemevalue">p</span><span class="hspace">&nbsp;</span><span class="schemereader">,</span><span class="schemeparen">(</span><span class="schemesymbol">rec-prop</span><span class="hspace">&nbsp;</span><span class="schemesymbol">post</span><span class="hspace">&nbsp;</span><span class="schemevalue">'</span><span class="schemevalue">body</span><span class="schemeparen">)</span><span class="schemevalue">)</span><span class="schemevalue">)</span><span class="schemeparen">)</span></p></td></tr></table></p><h5>2.2.3<tt>&nbsp;</tt><a name="(part._.Launch_.Blogerton)"></a>Launch Blogerton</h5><p>You&rsquo;re ready for launch. Start the server with</p><p><table cellspacing="0"><tr><td><p><span class="stt"><span class="stt">% ./script/server</span></span></p></td></tr></table></p><p>and you should have a basic blogging app, with persistent data, in 19 lines of code.</p><h3>3<tt>&nbsp;</tt><a name="(part._.Reference)"></a>Reference</h3><h4>3.1<tt>&nbsp;</tt><a name="(part._.Forms)"></a>Forms</h4><p>Most web applications make some use of web forms. The <span class="schemesymbol">form</span> function lets easily you get and process input from your users.</p><p><table cellspacing="0" class="boxed"><tr><td><p><span class="schemeparen">(</span><span class="schemesymbol">form</span><span class="hspace">&nbsp;</span><span class="schemevariable">field-specs</span><span class="schemeparen">)</span><span class="hspace">&nbsp;</span>&rarr;<span class="hspace">&nbsp;</span><span class="schemesymbol">xexpr?</span></p></td></tr><tr><td><p><span class="hspace">&nbsp;&nbsp;</span><span class="schemevariable">field-specs</span><span class="hspace">&nbsp;</span>:<span class="hspace">&nbsp;</span><span class="schemeparen">(</span><span class="schemesymbol">listof</span><span class="hspace">&nbsp;</span><span class="schemesymbol">field-spec?</span><span class="schemeparen">)</span></p></td></tr></table></p><p><table cellspacing="0" class="boxed"><tr><td><p><span class="schemesymbol">field-spec?</span><span class="hspace">&nbsp;</span>:<span class="hspace">&nbsp;</span><span class="schemeparen">(</span><span class="schemesymbol">list</span><span class="hspace">&nbsp;</span><span class="schemesymbol">symbol?</span><span class="hspace">&nbsp;</span><span class="schemesymbol">string?</span><span class="hspace">&nbsp;</span><span class="schemesymbol">field-type?</span><span class="schemeparen">)</span></p></td></tr></table></p><p><table cellspacing="0" class="boxed"><tr><td><table cellspacing="0" class="argcontract"><tr><td><p><span class="schemesymbol">field-type?</span><span class="hspace">&nbsp;</span>:<span class="hspace">&nbsp;</span></p></td><td><table cellspacing="0" class="schemeblock"><tr><td><p><span class="schemeparen">(</span><span class="schemesymbol">or/c</span><span class="hspace">&nbsp;</span><span class="schemevalue">'</span><span class="schemevalue">text</span><span class="hspace">&nbsp;</span><span class="schemevalue">'</span><span class="schemevalue">long-text</span><span class="hspace">&nbsp;</span><span class="schemevalue">'</span><span class="schemevalue">number</span><span class="hspace">&nbsp;</span><span class="schemevalue">'</span><span class="schemevalue">password</span><span class="hspace">&nbsp;</span><span class="schemevalue">'</span><span class="schemevalue">image</span><span class="hspace">&nbsp;</span><span class="schemevalue">'</span><span class="schemevalue">checkbox</span></p></td></tr><tr><td><p><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="schemevalue">'</span><span class="schemevalue">radio</span><span class="hspace">&nbsp;</span><span class="schemevalue">'</span><span class="schemevalue">drop-down</span><span class="schemeparen">)</span></p></td></tr></table></td></tr></table></td></tr></table></p><p>You create a form by listing, in order, "field specifications". For example, you might want a title field, followed by a description text box, followed by a photo upload field. Note that the many keyword arguments available to the <span class="schemesymbol">form</span> function aren&rsquo;t documented yet.</p><p>Each field spec is of the form <span class="schemeparen">(</span><span class="schemesymbol">field-name</span><span class="stt"> </span><span class="schemesymbol">label</span><span class="stt"> </span><span class="schemesymbol">field-type</span><span class="schemeparen">)</span>. For example, you create a title field, you might use the spec <span class="schemeparen">(</span><span class="schemesymbol">title</span><span class="stt"> </span><span class="schemevalue">"Enter a title"</span><span class="stt"> </span><span class="schemesymbol">text</span><span class="schemeparen">)</span>. The entire example metioned above might look like this:</p><p><table cellspacing="0" class="schemeblock"><tr><td><p><span class="hspace">&nbsp;&nbsp;</span><span class="schemeparen">(</span><span class="schemesymbol">form</span><span class="hspace">&nbsp;</span><span class="schemevalue">'</span><span class="schemevalue">(</span><span class="schemevalue">(</span><span class="schemevalue">title</span><span class="hspace">&nbsp;</span><span class="schemevalue">"Title"</span><span class="hspace">&nbsp;</span><span class="schemevalue">text</span><span class="schemevalue">)</span></p></td></tr><tr><td><p><span class="schemeplain"><span class="hspace">&nbsp;&nbsp;</span></span><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="schemevalue">(</span><span class="schemevalue">description</span><span class="hspace">&nbsp;</span><span class="schemevalue">"Description"</span><span class="hspace">&nbsp;</span><span class="schemevalue">long-text</span><span class="schemevalue">)</span></p></td></tr><tr><td><p><span class="schemeplain"><span class="hspace">&nbsp;&nbsp;</span></span><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="schemevalue">(</span><span class="schemevalue">photo</span><span class="hspace">&nbsp;</span><span class="schemevalue">"Your photo"</span><span class="hspace">&nbsp;</span><span class="schemevalue">image</span><span class="schemevalue">)</span><span class="schemevalue">)</span><span class="schemeparen">)</span></p></td></tr></table></p><h5>3.1.1<tt>&nbsp;</tt><a name="(part._.Image_uploads)"></a>Image uploads</h5><p>By default, uploaded images are stored in the <span class="stt">uploaded-files</span> directory in your project directory. You can customize this with the <span class="schemesymbol">*PATH_TO_UPLOADED_FILES*</span> setting. When images are saved, their original filenames are used with a 5-character code pre-pended to make filenames unique.</p><h4>3.2<tt>&nbsp;</tt><a name="(part._.Sessions)"></a>Sessions</h4><p>A session is an object that allows you to easily store state about individual visitors to your web app. Sessions are stored on the server as a record with a virtually impossible-to-guess id. A cookie is left in the user&rsquo;s web browser, which contains a pointer to a particular session id. These cookies expire one month after creation and, currently, this can&rsquo;t be changed.</p><h5>3.2.1<tt>&nbsp;</tt><a name="(part._.Creating_sessions)"></a>Creating sessions</h5><p><table cellspacing="0" class="boxed"><tr><td><table cellspacing="0" class="schemeblock"><tr><td><p><span class="schemeparen">(</span><span class="schemesymbol">define-session-page</span></p></td></tr><tr><td><p><span class="hspace">&nbsp;&nbsp;</span><span class="schemeparen">(</span><span class="schemevariable">page-name</span><span class="hspace">&nbsp;</span><span class="schemevariable">request-iden</span><span class="hspace">&nbsp;</span><span class="schemevariable">session-iden</span><span class="hspace">&nbsp;</span><span class="schemevariable">page-args</span><span class="hspace">&nbsp;</span><span class="schememeta">...</span><span class="schemeparen">)</span></p></td></tr><tr><td><p><span class="hspace">&nbsp;&nbsp;</span><span class="schemevariable">body</span><span class="hspace">&nbsp;</span><span class="schememeta">...</span><span class="schemeparen">)</span></p></td></tr></table></td></tr></table></p><p>This is an alternate to <span class="schemesymbol">define-page</span>, most commonly used in <span class="schemesymbol">main.scm</span>. The only difference is that after the request identifier, you must provide a session identifier. For example, to keep a counter (unique to each user), you could write:</p><p><table cellspacing="0" class="schemeblock"><tr><td><p><span class="hspace">&nbsp;&nbsp;</span><span class="schemeparen">(</span><span class="schemesymbol">define-session-page</span><span class="hspace">&nbsp;</span><span class="schemeparen">(</span><span class="schemesymbol">foo-page</span><span class="hspace">&nbsp;</span><span class="schemesymbol">req</span><span class="hspace">&nbsp;</span><span class="schemesymbol">sesh</span><span class="schemeparen">)</span></p></td></tr><tr><td><p><span class="schemeplain"><span class="hspace">&nbsp;&nbsp;</span></span><span class="hspace">&nbsp;&nbsp;</span><span class="schemeparen">(</span><span class="schemesymbol">let</span><span class="hspace">&nbsp;</span><span class="schemeparen">(</span><span class="schemeparen">(</span><span class="schemesymbol">c</span><span class="hspace">&nbsp;</span><span class="schemeparen">(</span><span class="schemesymbol">session-get-val</span><span class="hspace">&nbsp;</span><span class="schemesymbol">sesh</span><span class="hspace">&nbsp;</span><span class="schemevalue">'</span><span class="schemevalue">counter</span><span class="hspace">&nbsp;</span><span class="schemevalue">0</span><span class="schemeparen">)</span><span class="schemeparen">)</span><span class="schemeparen">)</span></p></td></tr><tr><td><p><span class="schemeplain"><span class="hspace">&nbsp;&nbsp;</span></span><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="schemeparen">(</span><span class="schemesymbol">session-put-val!</span><span class="hspace">&nbsp;</span><span class="schemesymbol">sesh</span><span class="hspace">&nbsp;</span><span class="schemevalue">'</span><span class="schemevalue">counter</span><span class="hspace">&nbsp;</span><span class="schemeparen">(</span><span class="schemesymbol">+</span><span class="hspace">&nbsp;</span><span class="schemevalue">1</span><span class="hspace">&nbsp;</span><span class="schemesymbol">c</span><span class="schemeparen">)</span><span class="schemeparen">)</span></p></td></tr><tr><td><p><span class="schemeplain"><span class="hspace">&nbsp;&nbsp;</span></span><span class="hspace">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="schemeparen">(</span><span class="schemesymbol">number-&gt;string</span><span class="hspace">&nbsp;</span><span class="schemesymbol">c</span><span class="schemeparen">)</span><span class="schemeparen">)</span><span class="schemeparen">)</span></p></td></tr></table></p><p>When you define a session page, the session is automatically fetched for you (and created if necessary), and bound to the session identifier you provided.</p><h5>3.2.2<tt>&nbsp;</tt><a name="(part._.Accessing_sessions)"></a>Accessing sessions</h5><p><table cellspacing="0" class="boxed"><tr><td><p><span class="schemeparen">(</span><span class="schemesymbol">session-get-val</span><span class="hspace">&nbsp;</span><span class="schemevariable">session</span><span class="hspace">&nbsp;</span><span class="schemevariable">key</span><span class="hspace">&nbsp;</span>[<span class="schemevariable">missing-val</span>]<span class="schemeparen">)</span><span class="hspace">&nbsp;</span>&rarr;<span class="hspace">&nbsp;</span><span class="schemesymbol">any</span></p></td></tr><tr><td><p><span class="hspace">&nbsp;&nbsp;</span><span class="schemevariable">session</span><span class="hspace">&nbsp;</span>:<span class="hspace">&nbsp;</span><span class="schemevariable">session</span></p></td></tr><tr><td><p><span class="hspace">&nbsp;&nbsp;</span><span class="schemevariable">key</span><span class="hspace">&nbsp;</span>:<span class="hspace">&nbsp;</span><span class="schemesymbol">symbol</span></p></td></tr><tr><td><p><span class="hspace">&nbsp;&nbsp;</span><span class="schemevariable">missing-val</span><span class="hspace">&nbsp;</span>:<span class="hspace">&nbsp;</span><span class="schemesymbol">any</span><span class="hspace">&nbsp;</span>=<span class="hspace">&nbsp;</span><span class="schemevalue">#f</span></p></td></tr></table></p><p><table cellspacing="0" class="boxed"><tr><td><p><span class="schemeparen">(</span><span class="schemesymbol">session-put-val!</span><span class="hspace">&nbsp;</span><span class="schemevariable">session</span><span class="hspace">&nbsp;</span><span class="schemevariable">key</span><span class="hspace">&nbsp;</span><span class="schemevariable">val</span><span class="schemeparen">)</span><span class="hspace">&nbsp;</span>&rarr;<span class="hspace">&nbsp;</span><span class="schemevariable">session</span></p></td></tr><tr><td><p><span class="hspace">&nbsp;&nbsp;</span><span class="schemevariable">session</span><span class="hspace">&nbsp;</span>:<span class="hspace">&nbsp;</span><span class="schemevariable">session</span></p></td></tr><tr><td><p><span class="hspace">&nbsp;&nbsp;</span><span class="schemevariable">key</span><span class="hspace">&nbsp;</span>:<span class="hspace">&nbsp;</span><span class="schemesymbol">symbol</span></p></td></tr><tr><td><p><span class="hspace">&nbsp;&nbsp;</span><span class="schemevariable">val</span><span class="hspace">&nbsp;</span>:<span class="hspace">&nbsp;</span><span class="schemesymbol">any</span></p></td></tr></table></p><h3>4<tt>&nbsp;</tt><a name="(part._.About_.Acknowledgements)"></a>About/Acknowledgements</h3><p>LeftParen was written by <a href="http://robhunter.org">Rob Hunter</a>, but it builds heavily on (and, in fact, often directly incorporates) the work of <a href="http://untyped.com/">Untyped</a> (<a href="http://planet.plt-scheme.org/display.ss?package=instaservlet.plt&amp;owner=untyped">instaservlet</a> and <a href="http://planet.plt-scheme.org/display.ss?package=dispatch.plt&amp;owner=untyped">dispatch</a>), <a href="http://scheme.dk/blog/">Jens Axel Soegaard</a> (<a href="http://planet.plt-scheme.org/display.ss?package=web.plt&amp;owner=soegaard">web.plt</a>), and of course, <a href="http://www.plt-scheme.org/">PLT Scheme</a>.</p><h4>4.1<tt>&nbsp;</tt><a name="(part._.Contributors)"></a>Contributors</h4><ul><li><p>Bill Hager</p></li><li><p>Joshua Herman</p></li></ul><div class="navset" style="margin-top: 2em; border-top: 2px solid #e0e0c0;"><span class="navleft"><input style="width: 16em; margin: 0px; padding: 0px; background-color: #eee; color: #888; border: 1px solid #ddd; text-align: center; vertical-align: middle;" type="text" value="...search manuals..." title="Enter a search string to search the manuals" onkeypress="return DoSearchKey(event, this, &quot;4.1.0.3&quot;, &quot;&quot;);" onfocus="this.style.color=&quot;black&quot;; this.style.textAlign=&quot;left&quot;; if (this.value == &quot;...search manuals...&quot;) this.value=&quot;&quot;;" onblur="if (this.value.match(/^ *$/)) { this.style.color=&quot;#888&quot;; this.style.textAlign=&quot;center&quot;; this.value=&quot;...search manuals...&quot;; }" />&nbsp;&nbsp;</span>&nbsp;</div></div></div></body></html>
View
26 scribblings/leftparen.scrbl
@@ -108,17 +108,31 @@ You're ready for launch. Start the server with
and you should have a basic blogging app, with persistent data, in 19 lines of code.
-@section{More Documentation to Come}
-
-We need to get a full LeftParen reference up (not just simple tutorials). There's lots more cool stuff in LeftParen that this document doesn't yet address.
-
@section{Reference}
@subsection{Forms}
-Wouldn't forms documentation be nice?
+Most web applications make some use of web forms. The @scheme[form] function lets easily you get and process input from your users.
+
+@defproc[(form (field-specs (listof field-spec?))) xexpr?]
+@defthing[field-spec? (list symbol? string? field-type?)]
+@defthing[field-type? (or/c 'text 'long-text 'number 'password 'image 'checkbox
+ 'radio 'drop-down)]
+
+You create a form by listing, in order, "field specifications". For example, you might want a title field, followed by a description text box, followed by a photo upload field. Note that the many keyword arguments available to the @scheme[form] function aren't documented yet.
+
+Each field spec is of the form @scheme[(field-name label field-type)]. For example, you create a title field, you might use the spec @scheme[(title "Enter a title" text)]. The entire example metioned above might look like this:
+
+@schemeblock[
+(form '((title "Title" text)
+ (description "Description" long-text)
+ (photo "Your photo" image)))
+]
+
+
+@subsubsection{Image uploads}
-@defproc[(mystery (a string-dude)) int]
+By default, uploaded images are stored in the @tt{uploaded-files} directory in your project directory. You can customize this with the @scheme[*PATH_TO_UPLOADED_FILES*] setting. When images are saved, their original filenames are used with a 5-character code pre-pended to make filenames unique.
@subsection{Sessions}
Please sign in to comment.
Something went wrong with that request. Please try again.