red-tape/reference/index.html @ 0f6bab39c0f4 default tip

adopt: Update site.
author Steve Losh <steve@stevelosh.com>
date Thu, 13 Jun 2024 13:05:28 -0400
parents 69831b3947d7
children (none)
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8"/>
        <title>Reference / Red Tape</title>
        <link rel="stylesheet" href="../_dmedia/tango.css"/>
        <link rel="stylesheet/less" type="text/css" href="../_dmedia/style.less"/>
        <script src="../_dmedia/less.js" type="text/javascript">
        </script>
    </head>
    <body class="content">
        <div class="wrap">
            <header><h1><a href="..">Red Tape</a></h1></header>
                <div class="markdown">
<h1 id="reference"><a href="">Reference</a></h1><p>The following is a list of all user-facing parts of Red Tape.</p>
<p>If there are any backwards-incompatible changes to anything listed here, they
will be noted in the changelog and the author will feel bad.</p>
<p>Anything not listed here is subject to change at any time with no warning, so
don't touch it.</p>
<div class="toc">
<ul>
<li><a href="#red-tapecore">red-tape.core</a><ul>
<li><a href="#defform">defform</a></li>
<li><a href="#form">form</a></li>
</ul>
</li>
<li><a href="#red-tapecleaners">red-tape.cleaners</a><ul>
<li><a href="#utilities">Utilities</a><ul>
<li><a href="#ensure-is">ensure-is</a></li>
<li><a href="#ensure-not">ensure-not</a></li>
</ul>
</li>
<li><a href="#string-cleaners">String Cleaners</a><ul>
<li><a href="#non-blank">non-blank</a></li>
<li><a href="#min-length">min-length</a></li>
<li><a href="#max-length">max-length</a></li>
<li><a href="#length">length</a></li>
<li><a href="#matches">matches</a></li>
</ul>
</li>
<li><a href="#numeric-cleaners">Numeric Cleaners</a><ul>
<li><a href="#to-long">to-long</a></li>
<li><a href="#to-double">to-double</a></li>
<li><a href="#positive">positive</a></li>
<li><a href="#negative">negative</a></li>
</ul>
</li>
<li><a href="#other-cleaners">Other Cleaners</a><ul>
<li><a href="#choices">choices</a></li>
<li><a href="#to-boolean">to-boolean</a></li>
</ul>
</li>
</ul>
</li>
</ul></div>
<h2 id="red-tapecore">red-tape.core</h2>
<p><code>red-tape.core</code> contains the <code>defform</code> and <code>form</code> macros you use to build forms.
Everything else in the namespace is internal.  Don't poke at it.</p>
<h3 id="defform">defform</h3>
<div class="codehilite"><pre><span class="p">(</span><span class="nf">red-tape.core/defform</span> <span class="nv">form-name</span> <span class="nv">options</span> <span class="o">&amp;</span> <span class="nv">fields</span><span class="p">)</span>
</pre></div>


<p>Define a form.</p>
<p>The first argument is the name the form will be bound to.</p>
<p>The <code>options</code> map can contain some or all of the following entries:</p>
<ul>
<li><code>:arguments</code>: a vector of symbols that the form function will take as
  arguments.  See the <a href="../form-arguments/">form arguments</a> guide for more
  information.</li>
<li><code>:initial</code>: a map of field names to expressions that will be evaluated to get
  initial data.  See the <a href="../initial-data/">initial data</a> guide for more
  information.</li>
</ul>
<p>More options may be added in the future.</p>
<p>Finally the fields are defined as pairs of <code>:field [... cleaners ...]</code>.  The
field name <code>:red-tape/form</code> is used to define <a href="../cleaners/#form-level-cleaners">form-level
cleaners</a>.</p>
<h3 id="form">form</h3>
<p><code>form</code> is like <code>defform</code> except that you don't specify a name, and it creates an
anonymous form.  In a nutshell: <code>form</code> is to <code>defform</code> as <code>fn</code> is to <code>defn</code>.</p>
<h2 id="red-tapecleaners">red-tape.cleaners</h2>
<p>Red Tape contains a number of built-in cleaners and utility functions in the
<code>red-tape.cleaners</code> namespace.</p>
<p>Most built-in cleaners take an optional <code>error-message</code> argument that you can
use to provide a custom error message if they fail (instead of the generic one
they each provide).</p>
<p>Also, remember that cleaners are just vanilla Clojure functions, which means
you'll find a lot of useful cleaners in the <code>clojure.string</code> namespace.</p>
<h3 id="utilities">Utilities</h3>
<p>The <code>ensure-is</code> and <code>ensure-not</code> macros are useful when writing your own
reusable cleaner functions.</p>
<h4 id="ensure-is">ensure-is</h4>
<div class="codehilite"><pre><span class="p">(</span><span class="nf">red-tape.cleaners/ensure-is</span> <span class="nv">value</span> <span class="nv">predicate</span> <span class="nv">message</span><span class="p">)</span>
</pre></div>


<p>Ensure the given value returns <code>true</code> for the given predicate.</p>
<p>If the value satisfies the predicate, it is returned unchanged.</p>
<p>Otherwise, the given message is thrown with Slingshot's <code>throw+</code>.</p>
<div class="codehilite"><pre><span class="p">(</span><span class="nf">ensure-is</span> <span class="mi">10</span> <span class="nb">pos? </span><span class="s">"Enter a positive number."</span><span class="p">)</span>
<span class="c1">; =&gt;</span>
<span class="mi">10</span>

<span class="p">(</span><span class="nf">ensure-is</span> <span class="mi">-10</span> <span class="nb">pos? </span><span class="s">"Enter a positive number."</span><span class="p">)</span>
<span class="c1">; =&gt;</span>
<span class="c1">; throws "Enter a positive number."</span>
</pre></div>


<h4 id="ensure-not">ensure-not</h4>
<div class="codehilite"><pre><span class="p">(</span><span class="nf">red-tape.cleaners/ensure-not</span> <span class="nv">value</span> <span class="nv">predicate</span> <span class="nv">message</span><span class="p">)</span>
</pre></div>


<p>Ensure the given value returns <code>false</code> for the given predicate.</p>
<p>If the value satisfies the predicate, it is returned unchanged.</p>
<p>Otherwise, the given message is thrown with Slingshot's <code>throw+</code>.</p>
<div class="codehilite"><pre><span class="p">(</span><span class="nf">ensure-not</span> <span class="mi">255</span> <span class="o">#</span><span class="p">(</span><span class="nb">&lt; </span><span class="nv">%</span> <span class="mi">10</span><span class="p">)</span> <span class="s">"Cannot be less than 10."</span><span class="p">)</span>
<span class="c1">; =&gt;</span>
<span class="mi">255</span>

<span class="p">(</span><span class="nf">ensure-not</span> <span class="mi">1</span> <span class="o">#</span><span class="p">(</span><span class="nb">&lt; </span><span class="nv">%</span> <span class="mi">10</span><span class="p">)</span> <span class="s">"Cannot be less than 10."</span><span class="p">)</span>
<span class="c1">; =&gt;</span>
<span class="c1">; throws "Cannot be less than 10."</span>
</pre></div>


<h3 id="string-cleaners">String Cleaners</h3>
<p>There are a number of built-in cleaners designed to be used with String data.</p>
<h4 id="non-blank">non-blank</h4>
<div class="codehilite"><pre><span class="p">(</span><span class="nf">red-tape.cleaners/non-blank</span> <span class="nv">s</span><span class="p">)</span>
<span class="p">(</span><span class="nf">red-tape.cleaners/non-blank</span> <span class="nv">s</span> <span class="nv">error-message</span><span class="p">)</span>
</pre></div>


<p>Ensure the given string is not empty.</p>
<p>Whitespace is treated like any other character -- use <code>clojure.string/trim</code> to
remove it first if you want to.</p>
<h4 id="min-length">min-length</h4>
<div class="codehilite"><pre><span class="p">(</span><span class="nf">red-tape.cleaners/min-length</span> <span class="nv">n</span> <span class="nv">s</span><span class="p">)</span>
<span class="p">(</span><span class="nf">red-tape.cleaners/min-length</span> <span class="nv">n</span> <span class="nv">s</span> <span class="nv">error-message</span><span class="p">)</span>
</pre></div>


<p>Ensure that the given string is at least <code>n</code> characters long.</p>
<h4 id="max-length">max-length</h4>
<div class="codehilite"><pre><span class="p">(</span><span class="nf">red-tape.cleaners/max-length</span> <span class="nv">n</span> <span class="nv">s</span><span class="p">)</span>
<span class="p">(</span><span class="nf">red-tape.cleaners/max-length</span> <span class="nv">n</span> <span class="nv">s</span> <span class="nv">error-message</span><span class="p">)</span>
</pre></div>


<p>Ensure that the given string is at most <code>n</code> characters long.</p>
<h4 id="length">length</h4>
<div class="codehilite"><pre><span class="p">(</span><span class="nf">red-tape.cleaners/length</span> <span class="nb">min max </span><span class="nv">s</span><span class="p">)</span>
<span class="p">(</span><span class="nf">red-tape.cleaners/length</span> <span class="nb">min max </span><span class="nv">s</span> <span class="nv">min-error</span> <span class="nv">max-error</span><span class="p">)</span>
</pre></div>


<p>Ensure that the given string is at least <code>min</code> and at most <code>max</code> characters
long.</p>
<p><code>length</code> takes two optional error message arguments, one to throw if the string
is too short and one if it's too long.</p>
<h4 id="matches">matches</h4>
<div class="codehilite"><pre><span class="p">(</span><span class="nf">red-tape.cleaners/matches</span> <span class="nv">regex</span> <span class="nv">s</span><span class="p">)</span>
<span class="p">(</span><span class="nf">red-tape.cleaners/matches</span> <span class="nv">regex</span> <span class="nv">s</span> <span class="nv">error-message</span><span class="p">)</span>
</pre></div>


<p>Ensure that the string (fully) matches the given regular expression.</p>
<p>The regex must match the <em>entire</em> string, so <code>(matches #"foo" "foo bar")</code> will
throw an error.</p>
<h3 id="numeric-cleaners">Numeric Cleaners</h3>
<p>Red Tape has a few built-in cleaners for working with numbers too.</p>
<h4 id="to-long">to-long</h4>
<div class="codehilite"><pre><span class="p">(</span><span class="nf">red-tape.cleaners/to-long</span> <span class="nv">s</span><span class="p">)</span>
<span class="p">(</span><span class="nf">red-tape.cleaners/to-long</span> <span class="nv">s</span> <span class="nv">error-message</span><span class="p">)</span>
</pre></div>


<p>Convert a String to a Long.</p>
<h4 id="to-double">to-double</h4>
<div class="codehilite"><pre><span class="p">(</span><span class="nf">red-tape.cleaners/to-double</span> <span class="nv">s</span><span class="p">)</span>
<span class="p">(</span><span class="nf">red-tape.cleaners/to-double</span> <span class="nv">s</span> <span class="nv">error-message</span><span class="p">)</span>
</pre></div>


<p>Convert a String to a Double.</p>
<h4 id="positive">positive</h4>
<div class="codehilite"><pre><span class="p">(</span><span class="nf">red-tape.cleaners/positive</span> <span class="nv">n</span><span class="p">)</span>
<span class="p">(</span><span class="nf">red-tape.cleaners/positive</span> <span class="nv">n</span> <span class="nv">error-message</span><span class="p">)</span>
</pre></div>


<p>Ensure the given number is positive.</p>
<p>This function expects a number, so use <code>to-long</code> or <code>to-double</code> first.</p>
<h4 id="negative">negative</h4>
<div class="codehilite"><pre><span class="p">(</span><span class="nf">red-tape.cleaners/negative</span> <span class="nv">n</span><span class="p">)</span>
<span class="p">(</span><span class="nf">red-tape.cleaners/negative</span> <span class="nv">n</span> <span class="nv">error-message</span><span class="p">)</span>
</pre></div>


<p>Ensure the given number is negative.</p>
<p>This function expects a number, so use <code>to-long</code> or <code>to-double</code> first.</p>
<h3 id="other-cleaners">Other Cleaners</h3>
<p>Finally, there are some other cleaners that don't fit into one of the other
categories.</p>
<h4 id="choices">choices</h4>
<div class="codehilite"><pre><span class="p">(</span><span class="nf">red-tape.cleaners/choices</span> <span class="nv">cs</span> <span class="nv">value</span><span class="p">)</span>
<span class="p">(</span><span class="nf">red-tape.cleaners/choices</span> <span class="nv">cs</span> <span class="nv">value</span> <span class="nv">error-message</span><span class="p">)</span>
</pre></div>


<p>Ensure the value is contained in the given choices.</p>
<p>Useful when you have a list of valid things for the user to choose from:</p>
<div class="codehilite"><pre><span class="p">(</span><span class="k">def </span><span class="nv">us-states</span> <span class="o">#</span><span class="p">{</span><span class="s">"NY"</span> <span class="s">"PA"</span> <span class="s">"OR"</span> <span class="nv">...</span><span class="p">})</span>

<span class="p">(</span><span class="nf">defform</span> <span class="nv">address-form</span> <span class="p">{}</span>
  <span class="nv">...</span>
  <span class="ss">:state</span> <span class="p">[</span><span class="o">#</span><span class="p">(</span><span class="nf">choices</span> <span class="nv">us-states</span> <span class="nv">%</span>
                    <span class="s">"Please enter a valid US state."</span><span class="p">)])</span>
</pre></div>


<p>Not limited to strings, so you can parse the input into something else and then
check for those with choices if you want.</p>
<p>Note that this uses <code>clojure.core/contains?</code> which is stupid about vectors, so
be careful!  Use a set if possible.</p>
<h4 id="to-boolean">to-boolean</h4>
<div class="codehilite"><pre><span class="p">(</span><span class="nf">red-tape.cleaners/to-boolean</span> <span class="nv">s</span><span class="p">)</span>
<span class="p">(</span><span class="nf">red-tape.cleaners/to-boolean</span> <span class="nv">s</span> <span class="nv">error-message</span><span class="p">)</span>
</pre></div>


<p>Convert a string to a boolean.</p>
<p>The following strings are considered true (case-insensitive):</p>
<ul>
<li><code>"1"</code></li>
<li><code>"true"</code></li>
<li><code>"t"</code></li>
</ul>
<p>The following strings are considered false (case-insensitive):</p>
<ul>
<li><code>"0"</code></li>
<li><code>"false"</code></li>
<li><code>"f"</code></li>
</ul>
<p>Anything else is an error.</p>
                </div>
            <footer><p>Made and <a href="http://sjl.bitbucket.org/d/">documented</a> with love by <a href="http://stevelosh.com">Steve
Losh</a>.</p>
<p><br/><a id="rochester-made" href="http://rochestermade.com" title="Rochester Made"><img src="http://rochestermade.com/media/images/rochester-made-dark-on-light.png" alt="Rochester Made" title="Rochester Made"/></a></p></footer>
        </div>
    </body>
</html>